de72d0d14b9161931ca7f7802e1afe185b568673
[linux-flexiantxendom0-3.2.10.git] / drivers / sbus / char / jsflash.c
1 /*
2  * drivers/sbus/char/jsflash.c
3  *
4  *  Copyright (C) 1991, 1992  Linus Torvalds    (drivers/char/mem.c)
5  *  Copyright (C) 1997  Eddie C. Dost           (drivers/sbus/char/flash.c)
6  *  Copyright (C) 1997-2000 Pavel Machek <pavel@ucw.cz>   (drivers/block/nbd.c)
7  *  Copyright (C) 1999-2000 Pete Zaitcev
8  *
9  * This driver is used to program OS into a Flash SIMM on
10  * Krups and Espresso platforms.
11  *
12  * TODO: do not allow erase/programming if file systems are mounted.
13  * TODO: Erase/program both banks of a 8MB SIMM.
14  *
15  * It is anticipated that programming an OS Flash will be a routine
16  * procedure. In the same time it is exeedingly dangerous because
17  * a user can program its OBP flash with OS image and effectively
18  * kill the machine.
19  *
20  * This driver uses an interface different from Eddie's flash.c
21  * as a silly safeguard.
22  *
23  * XXX The flash.c manipulates page caching characteristics in a certain
24  * dubious way; also it assumes that remap_page_range() can remap
25  * PCI bus locations, which may be false. ioremap() must be used
26  * instead. We should discuss this.
27  */
28
29 #include <linux/module.h>
30 #include <linux/types.h>
31 #include <linux/errno.h>
32 #include <linux/miscdevice.h>
33 #include <linux/slab.h>
34 #include <linux/fcntl.h>
35 #include <linux/poll.h>
36 #include <linux/init.h>
37 #include <linux/string.h>
38 #include <linux/smp_lock.h>
39 #include <linux/genhd.h>
40
41 #define MAJOR_NR        JSFD_MAJOR
42
43 #include <asm/uaccess.h>
44 #include <asm/pgtable.h>
45 #include <asm/io.h>
46 #include <asm/pcic.h>
47 #include <asm/oplib.h>
48
49 #include <asm/jsflash.h>                /* ioctl arguments. <linux/> ?? */
50 #define JSFIDSZ         (sizeof(struct jsflash_ident_arg))
51 #define JSFPRGSZ        (sizeof(struct jsflash_program_arg))
52
53 /*
54  * Our device numbers have no business in system headers.
55  * The only thing a user knows is the device name /dev/jsflash.
56  *
57  * Block devices are laid out like this:
58  *   minor+0    - Bootstrap, for 8MB SIMM 0x20400000[0x800000]
59  *   minor+1    - Filesystem to mount, normally 0x20400400[0x7ffc00]
60  *   minor+2    - Whole flash area for any case... 0x20000000[0x01000000]
61  * Total 3 minors per flash device.
62  *
63  * It is easier to have static size vectors, so we define
64  * a total minor range JSF_MAX, which must cover all minors.
65  */
66 /* character device */
67 #define JSF_MINOR       178     /* 178 is registered with hpa */
68 /* block device */
69 #define JSF_MAX          3      /* 3 minors wasted total so far. */
70 #define JSF_NPART        3      /* 3 minors per flash device */
71 #define JSF_PART_BITS    2      /* 2 bits of minors to cover JSF_NPART */
72 #define JSF_PART_MASK    0x3    /* 2 bits mask */
73
74 /*
75  * Access functions.
76  * We could ioremap(), but it's easier this way.
77  */
78 static unsigned int jsf_inl(unsigned long addr)
79 {
80         unsigned long retval;
81
82         __asm__ __volatile__("lda [%1] %2, %0\n\t" :
83                                 "=r" (retval) :
84                                 "r" (addr), "i" (ASI_M_BYPASS));
85         return retval;
86 }
87
88 static void jsf_outl(unsigned long addr, __u32 data)
89 {
90
91         __asm__ __volatile__("sta %0, [%1] %2\n\t" : :
92                                 "r" (data), "r" (addr), "i" (ASI_M_BYPASS) :
93                                 "memory");
94 }
95
96 /*
97  * soft carrier
98  */
99
100 struct jsfd_part {
101         unsigned long dbase;
102         unsigned long dsize;
103 };
104
105 struct jsflash {
106         unsigned long base;
107         unsigned long size;
108         unsigned long busy;             /* In use? */
109         struct jsflash_ident_arg id;
110         /* int mbase; */                /* Minor base, typically zero */
111         struct jsfd_part dv[JSF_NPART];
112 };
113
114 /*
115  * We do not map normal memory or obio as a safety precaution.
116  * But offsets are real, for ease of userland programming.
117  */
118 #define JSF_BASE_TOP    0x30000000
119 #define JSF_BASE_ALL    0x20000000
120
121 #define JSF_BASE_JK     0x20400000
122
123 /*
124  */
125 static struct gendisk *jsfd_disk[JSF_MAX];
126
127 /*
128  * Let's pretend we may have several of these...
129  */
130 static struct jsflash jsf0;
131
132 /*
133  * Wait for AMD to finish its embedded algorithm.
134  * We use the Toggle bit DQ6 (0x40) because it does not
135  * depend on the data value as /DATA bit DQ7 does.
136  *
137  * XXX Do we need any timeout here? So far it never hanged, beware broken hw.
138  */
139 static void jsf_wait(unsigned long p) {
140         unsigned int x1, x2;
141
142         for (;;) {
143                 x1 = jsf_inl(p);
144                 x2 = jsf_inl(p);
145                 if ((x1 & 0x40404040) == (x2 & 0x40404040)) return;
146         }
147 }
148
149 /*
150  * Programming will only work if Flash is clean,
151  * we leave it to the programmer application.
152  *
153  * AMD must be programmed one byte at a time;
154  * thus, Simple Tech SIMM must be written 4 bytes at a time.
155  *
156  * Write waits for the chip to become ready after the write
157  * was finished. This is done so that application would read
158  * consistent data after the write is done.
159  */
160 static void jsf_write4(unsigned long fa, u32 data) {
161
162         jsf_outl(fa, 0xAAAAAAAA);               /* Unlock 1 Write 1 */
163         jsf_outl(fa, 0x55555555);               /* Unlock 1 Write 2 */
164         jsf_outl(fa, 0xA0A0A0A0);               /* Byte Program */
165         jsf_outl(fa, data);
166
167         jsf_wait(fa);
168 }
169
170 /*
171  */
172 static void jsfd_read(char *buf, unsigned long p, size_t togo) {
173         union byte4 {
174                 char s[4];
175                 unsigned int n;
176         } b;
177
178         while (togo >= 4) {
179                 togo -= 4;
180                 b.n = jsf_inl(p);
181                 memcpy(buf, b.s, 4);
182                 p += 4;
183                 buf += 4;
184         }
185 }
186
187 static void jsfd_do_request(request_queue_t *q)
188 {
189         struct request *req;
190         
191         while ((req = elv_next_request(q)) != NULL) {
192                 struct jsfd_part *jdp = req->rq_disk->private_data;
193                 unsigned long offset = req->sector << 9;
194                 size_t len = req->current_nr_sectors << 9;
195
196                 if ((offset + len) > jdp->dsize) {
197                         end_request(req, 0);
198                         continue;
199                 }
200
201                 if (req->cmd == WRITE) {
202                         printk(KERN_ERR "jsfd: write\n");
203                         end_request(req, 0);
204                         continue;
205                 }
206                 if (req->cmd != READ) {
207                         printk(KERN_ERR "jsfd: bad req->cmd %d\n", req->cmd);
208                         end_request(req, 0);
209                         continue;
210                 }
211
212                 if ((jdp->dbase & 0xff000000) != 0x20000000) {
213                         printk(KERN_ERR "jsfd: bad base %x\n", (int)jdp->dbase);
214                         end_request(req, 0);
215                         continue;
216                 }
217
218 /* printk("%s: read buf %p off %x len %x\n", req->rq_disk->disk_name, req->buffer, (int)offset, (int)len); */ /* P3 */
219                 jsfd_read(req->buffer, jdp->dbase + offset, len);
220
221                 end_request(req, 1);
222         }
223 }
224
225 /*
226  * The memory devices use the full 32/64 bits of the offset, and so we cannot
227  * check against negative addresses: they are ok. The return value is weird,
228  * though, in that case (0).
229  *
230  * also note that seeking relative to the "end of file" isn't supported:
231  * it has no meaning, so it returns -EINVAL.
232  */
233 static loff_t jsf_lseek(struct file * file, loff_t offset, int orig)
234 {
235         loff_t ret;
236
237         lock_kernel();
238         switch (orig) {
239                 case 0:
240                         file->f_pos = offset;
241                         ret = file->f_pos;
242                         break;
243                 case 1:
244                         file->f_pos += offset;
245                         ret = file->f_pos;
246                         break;
247                 default:
248                         ret = -EINVAL;
249         }
250         unlock_kernel();
251         return ret;
252 }
253
254 /*
255  * OS SIMM Cannot be read in other size but a 32bits word.
256  */
257 static ssize_t jsf_read(struct file * file, char * buf, 
258     size_t togo, loff_t *ppos)
259 {
260         unsigned long p = *ppos;
261         char *tmp = buf;
262
263         union byte4 {
264                 char s[4];
265                 unsigned int n;
266         } b;
267
268         if (verify_area(VERIFY_WRITE, buf, togo))
269                 return -EFAULT; 
270
271         if (p < JSF_BASE_ALL || p >= JSF_BASE_TOP) {
272                 return 0;
273         }
274
275         if ((p + togo) < p      /* wrap */
276            || (p + togo) >= JSF_BASE_TOP) {
277                 togo = JSF_BASE_TOP - p;
278         }
279
280         if (p < JSF_BASE_ALL && togo != 0) {
281 #if 0 /* __bzero XXX */
282                 size_t x = JSF_BASE_ALL - p;
283                 if (x > togo) x = togo;
284                 clear_user(tmp, x);
285                 tmp += x;
286                 p += x;
287                 togo -= x;
288 #else
289                 /*
290                  * Implementation of clear_user() calls __bzero
291                  * without regard to modversions,
292                  * so we cannot build a module.
293                  */
294                 return 0;
295 #endif
296         }
297
298         while (togo >= 4) {
299                 togo -= 4;
300                 b.n = jsf_inl(p);
301                 copy_to_user(tmp, b.s, 4);
302                 tmp += 4;
303                 p += 4;
304         }
305
306         /*
307          * XXX Small togo may remain if 1 byte is ordered.
308          * It would be nice if we did a word size read and unpacked it.
309          */
310
311         *ppos = p;
312         return tmp-buf;
313 }
314
315 static ssize_t jsf_write(struct file * file, const char * buf,
316     size_t count, loff_t *ppos)
317 {
318         return -ENOSPC;
319 }
320
321 /*
322  */
323 static int jsf_ioctl_erase(unsigned long arg)
324 {
325         unsigned long p;
326
327         /* p = jsf0.base;       hits wrong bank */
328         p = 0x20400000;
329
330         jsf_outl(p, 0xAAAAAAAA);                /* Unlock 1 Write 1 */
331         jsf_outl(p, 0x55555555);                /* Unlock 1 Write 2 */
332         jsf_outl(p, 0x80808080);                /* Erase setup */
333         jsf_outl(p, 0xAAAAAAAA);                /* Unlock 2 Write 1 */
334         jsf_outl(p, 0x55555555);                /* Unlock 2 Write 2 */
335         jsf_outl(p, 0x10101010);                /* Chip erase */
336
337 #if 0
338         /*
339          * This code is ok, except that counter based timeout
340          * has no place in this world. Let's just drop timeouts...
341          */
342         {
343                 int i;
344                 __u32 x;
345                 for (i = 0; i < 1000000; i++) {
346                         x = jsf_inl(p);
347                         if ((x & 0x80808080) == 0x80808080) break;
348                 }
349                 if ((x & 0x80808080) != 0x80808080) {
350                         printk("jsf0: erase timeout with 0x%08x\n", x);
351                 } else {
352                         printk("jsf0: erase done with 0x%08x\n", x);
353                 }
354         }
355 #else
356         jsf_wait(p);
357 #endif
358
359         return 0;
360 }
361
362 /*
363  * Program a block of flash.
364  * Very simple because we can do it byte by byte anyway.
365  */
366 static int jsf_ioctl_program(unsigned long arg)
367 {
368         struct jsflash_program_arg abuf;
369         char *uptr;
370         unsigned long p;
371         unsigned int togo;
372         union {
373                 unsigned int n;
374                 char s[4];
375         } b;
376
377         if (verify_area(VERIFY_READ, (void *)arg, JSFPRGSZ))
378                 return -EFAULT; 
379         copy_from_user(&abuf, (char *)arg, JSFPRGSZ);
380         p = abuf.off;
381         togo = abuf.size;
382         if ((togo & 3) || (p & 3)) return -EINVAL;
383
384         uptr = (char *) (unsigned long) abuf.data;
385         if (verify_area(VERIFY_READ, uptr, togo))
386                 return -EFAULT;
387         while (togo != 0) {
388                 togo -= 4;
389                 copy_from_user(&b.s[0], uptr, 4);
390                 jsf_write4(p, b.n);
391                 p += 4;
392                 uptr += 4;
393         }
394
395         return 0;
396 }
397
398 static int jsf_ioctl(struct inode *inode, struct file *f, unsigned int cmd,
399     unsigned long arg)
400 {
401         int error = -ENOTTY;
402
403         if (!capable(CAP_SYS_ADMIN))
404                 return -EPERM;
405         switch (cmd) {
406         case JSFLASH_IDENT:
407                 if (verify_area(VERIFY_WRITE, (void *)arg, JSFIDSZ))
408                         return -EFAULT; 
409                 copy_to_user(arg, &jsf0.id, JSFIDSZ);
410                 error = 0;
411                 break;
412         case JSFLASH_ERASE:
413                 error = jsf_ioctl_erase(arg);
414                 break;
415         case JSFLASH_PROGRAM:
416                 error = jsf_ioctl_program(arg);
417                 break;
418         }
419
420         return error;
421 }
422
423 static int jsf_mmap(struct file * file, struct vm_area_struct * vma)
424 {
425         return -ENXIO;
426 }
427
428 static int jsf_open(struct inode * inode, struct file * filp)
429 {
430
431         if (jsf0.base == 0) return -ENXIO;
432         if (test_and_set_bit(0, (void *)&jsf0.busy) != 0)
433                 return -EBUSY;
434
435         return 0;       /* XXX What security? */
436 }
437
438 static int jsf_release(struct inode *inode, struct file *file)
439 {
440         jsf0.busy = 0;
441         return 0;
442 }
443
444 static struct file_operations jsf_fops = {
445         .owner =        THIS_MODULE,
446         .llseek =       jsf_lseek,
447         .read =         jsf_read,
448         .write =        jsf_write,
449         .ioctl =        jsf_ioctl,
450         .mmap =         jsf_mmap,
451         .open =         jsf_open,
452         .release =      jsf_release,
453 };
454
455 static struct miscdevice jsf_dev = { JSF_MINOR, "jsflash", &jsf_fops };
456
457 static struct block_device_operations jsfd_fops = {
458         .owner =        THIS_MODULE,
459 };
460
461 static int jsflash_init(void)
462 {
463         int rc;
464         struct jsflash *jsf;
465         int node;
466         char banner[128];
467         struct linux_prom_registers reg0;
468
469         node = prom_getchild(prom_root_node);
470         node = prom_searchsiblings(node, "flash-memory");
471         if (node != 0 && node != -1) {
472                 if (prom_getproperty(node, "reg",
473                     (char *)&reg0, sizeof(reg0)) == -1) {
474                         printk("jsflash: no \"reg\" property\n");
475                         return -ENXIO;
476                 }
477                 if (reg0.which_io != 0) {
478                         printk("jsflash: bus number nonzero: 0x%x:%x\n",
479                             reg0.which_io, reg0.phys_addr);
480                         return -ENXIO;
481                 }
482                 /*
483                  * Flash may be somewhere else, for instance on Ebus.
484                  * So, don't do the following check for IIep flash space.
485                  */
486 #if 0
487                 if ((reg0.phys_addr >> 24) != 0x20) {
488                         printk("jsflash: suspicious address: 0x%x:%x\n",
489                             reg0.which_io, reg0.phys_addr);
490                         return -ENXIO;
491                 }
492 #endif
493                 if ((int)reg0.reg_size <= 0) {
494                         printk("jsflash: bad size 0x%x\n", (int)reg0.reg_size);
495                         return -ENXIO;
496                 }
497         } else {
498                 /* XXX Remove this code once PROLL ID12 got widespread */
499                 printk("jsflash: no /flash-memory node, use PROLL >= 12\n");
500                 prom_getproperty(prom_root_node, "banner-name", banner, 128);
501                 if (strcmp (banner, "JavaStation-NC") != 0 &&
502                     strcmp (banner, "JavaStation-E") != 0) {
503                         return -ENXIO;
504                 }
505                 reg0.which_io = 0;
506                 reg0.phys_addr = 0x20400000;
507                 reg0.reg_size  = 0x00800000;
508         }
509
510         /* Let us be really paranoid for modifications to probing code. */
511         /* extern enum sparc_cpu sparc_cpu_model; */ /* in <asm/system.h> */
512         if (sparc_cpu_model != sun4m) {
513                 /* We must be on sun4m because we use MMU Bypass ASI. */
514                 return -ENXIO;
515         }
516
517         if (jsf0.base == 0) {
518                 jsf = &jsf0;
519
520                 jsf->base = reg0.phys_addr;
521                 jsf->size = reg0.reg_size;
522
523                 /* XXX Redo the userland interface. */
524                 jsf->id.off = JSF_BASE_ALL;
525                 jsf->id.size = 0x01000000;      /* 16M - all segments */
526                 strcpy(jsf->id.name, "Krups_all");
527
528                 jsf->dv[0].dbase = jsf->base;
529                 jsf->dv[0].dsize = jsf->size;
530                 jsf->dv[1].dbase = jsf->base + 1024;
531                 jsf->dv[1].dsize = jsf->size - 1024;
532                 jsf->dv[2].dbase = JSF_BASE_ALL;
533                 jsf->dv[2].dsize = 0x01000000;
534
535                 printk("Espresso Flash @0x%lx [%d MB]\n", jsf->base,
536                     (int) (jsf->size / (1024*1024)));
537         }
538
539         if ((rc = misc_register(&jsf_dev)) != 0) {
540                 printk(KERN_ERR "jsf: unable to get misc minor %d\n",
541                     JSF_MINOR);
542                 jsf0.base = 0;
543                 return rc;
544         }
545
546         return 0;
547 }
548
549 static struct request_queue jsf_queue;
550
551 static int jsfd_init(void)
552 {
553         static spinlock_t lock = SPIN_LOCK_UNLOCKED;
554         struct jsflash *jsf;
555         struct jsfd_part *jdp;
556         int err;
557         int i;
558
559         if (jsf0.base == 0)
560                 return -ENXIO;
561
562         err = -ENOMEM;
563         for (i = 0; i < JSF_MAX; i++) {
564                 struct gendisk *disk = alloc_disk(1);
565                 if (!disk)
566                         goto out;
567                 jsfd_disk[i] = disk;
568         }
569
570         if (register_blkdev(JSFD_MAJOR, "jsfd")) {
571                 err = -EIO;
572                 goto out;
573         }
574
575         blk_init_queue(&jsf_queue, jsfd_do_request, &lock);
576         for (i = 0; i < JSF_MAX; i++) {
577                 struct gendisk *disk = jsfd_disk[i];
578                 if ((i & JSF_PART_MASK) >= JSF_NPART) continue;
579                 jsf = &jsf0;    /* actually, &jsfv[i >> JSF_PART_BITS] */
580                 jdp = &jsf->dv[i&JSF_PART_MASK];
581
582                 disk->major = JSFD_MAJOR;
583                 disk->first_minor = i;
584                 sprintf(disk->disk_name, "jsfd%d", i);
585                 disk->fops = &jsfd_fops;
586                 set_capacity(disk, jdp->dsize >> 9);
587                 disk->private_data = jdp;
588                 disk->queue = &jsf_queue;
589                 add_disk(disk);
590                 set_disk_ro(disk, 1);
591         }
592         return 0;
593 out:
594         while (i--)
595                 put_disk(jsfd_disk[i]);
596         return err;
597 }
598
599 MODULE_LICENSE("GPL");
600
601 static int __init jsflash_init_module(void) {
602         int rc;
603
604         if ((rc = jsflash_init()) == 0) {
605                 jsfd_init();
606                 return 0;
607         }
608         return rc;
609 }
610
611 static void __exit jsflash_cleanup_module(void)
612 {
613         int i;
614
615         for (i = 0; i < JSF_MAX; i++) {
616                 if ((i & JSF_PART_MASK) >= JSF_NPART) continue;
617                 del_gendisk(jsfd_disk[i]);
618                 put_disk(jsfd_disk[i]);
619         }
620         if (jsf0.busy)
621                 printk("jsf0: cleaning busy unit\n");
622         jsf0.base = 0;
623         jsf0.busy = 0;
624
625         misc_deregister(&jsf_dev);
626         if (unregister_blkdev(JSFD_MAJOR, "jsfd") != 0)
627                 printk("jsfd: cleanup_module failed\n");
628         blk_cleanup_queue(&jsf_queue);
629 }
630
631 module_init(jsflash_init_module);
632 module_exit(jsflash_cleanup_module);