Remove all #inclusions of asm/system.h
[linux-flexiantxendom0-3.2.10.git] / drivers / char / nwflash.c
1 /*
2  * Flash memory interface rev.5 driver for the Intel
3  * Flash chips used on the NetWinder.
4  *
5  * 20/08/2000   RMK     use __ioremap to map flash into virtual memory
6  *                      make a few more places use "volatile"
7  * 22/05/2001   RMK     - Lock read against write
8  *                      - merge printk level changes (with mods) from Alan Cox.
9  *                      - use *ppos as the file position, not file->f_pos.
10  *                      - fix check for out of range pos and r/w size
11  *
12  * Please note that we are tampering with the only flash chip in the
13  * machine, which contains the bootup code.  We therefore have the
14  * power to convert these machines into doorstops...
15  */
16
17 #include <linux/module.h>
18 #include <linux/types.h>
19 #include <linux/fs.h>
20 #include <linux/errno.h>
21 #include <linux/mm.h>
22 #include <linux/delay.h>
23 #include <linux/proc_fs.h>
24 #include <linux/miscdevice.h>
25 #include <linux/spinlock.h>
26 #include <linux/rwsem.h>
27 #include <linux/init.h>
28 #include <linux/mutex.h>
29 #include <linux/jiffies.h>
30
31 #include <asm/hardware/dec21285.h>
32 #include <asm/io.h>
33 #include <asm/leds.h>
34 #include <asm/mach-types.h>
35 #include <asm/uaccess.h>
36
37 /*****************************************************************************/
38 #include <asm/nwflash.h>
39
40 #define NWFLASH_VERSION "6.4"
41
42 static DEFINE_MUTEX(flash_mutex);
43 static void kick_open(void);
44 static int get_flash_id(void);
45 static int erase_block(int nBlock);
46 static int write_block(unsigned long p, const char __user *buf, int count);
47
48 #define KFLASH_SIZE     1024*1024       //1 Meg
49 #define KFLASH_SIZE4    4*1024*1024     //4 Meg
50 #define KFLASH_ID       0x89A6          //Intel flash
51 #define KFLASH_ID4      0xB0D4          //Intel flash 4Meg
52
53 static bool flashdebug;         //if set - we will display progress msgs
54
55 static int gbWriteEnable;
56 static int gbWriteBase64Enable;
57 static volatile unsigned char *FLASH_BASE;
58 static int gbFlashSize = KFLASH_SIZE;
59 static DEFINE_MUTEX(nwflash_mutex);
60
61 static int get_flash_id(void)
62 {
63         volatile unsigned int c1, c2;
64
65         /*
66          * try to get flash chip ID
67          */
68         kick_open();
69         c2 = inb(0x80);
70         *(volatile unsigned char *) (FLASH_BASE + 0x8000) = 0x90;
71         udelay(15);
72         c1 = *(volatile unsigned char *) FLASH_BASE;
73         c2 = inb(0x80);
74
75         /*
76          * on 4 Meg flash the second byte is actually at offset 2...
77          */
78         if (c1 == 0xB0)
79                 c2 = *(volatile unsigned char *) (FLASH_BASE + 2);
80         else
81                 c2 = *(volatile unsigned char *) (FLASH_BASE + 1);
82
83         c2 += (c1 << 8);
84
85         /*
86          * set it back to read mode
87          */
88         *(volatile unsigned char *) (FLASH_BASE + 0x8000) = 0xFF;
89
90         if (c2 == KFLASH_ID4)
91                 gbFlashSize = KFLASH_SIZE4;
92
93         return c2;
94 }
95
96 static long flash_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
97 {
98         mutex_lock(&flash_mutex);
99         switch (cmd) {
100         case CMD_WRITE_DISABLE:
101                 gbWriteBase64Enable = 0;
102                 gbWriteEnable = 0;
103                 break;
104
105         case CMD_WRITE_ENABLE:
106                 gbWriteEnable = 1;
107                 break;
108
109         case CMD_WRITE_BASE64K_ENABLE:
110                 gbWriteBase64Enable = 1;
111                 break;
112
113         default:
114                 gbWriteBase64Enable = 0;
115                 gbWriteEnable = 0;
116                 mutex_unlock(&flash_mutex);
117                 return -EINVAL;
118         }
119         mutex_unlock(&flash_mutex);
120         return 0;
121 }
122
123 static ssize_t flash_read(struct file *file, char __user *buf, size_t size,
124                           loff_t *ppos)
125 {
126         ssize_t ret;
127
128         if (flashdebug)
129                 printk(KERN_DEBUG "flash_read: flash_read: offset=0x%llx, "
130                        "buffer=%p, count=0x%zx.\n", *ppos, buf, size);
131         /*
132          * We now lock against reads and writes. --rmk
133          */
134         if (mutex_lock_interruptible(&nwflash_mutex))
135                 return -ERESTARTSYS;
136
137         ret = simple_read_from_buffer(buf, size, ppos, (void *)FLASH_BASE, gbFlashSize);
138         mutex_unlock(&nwflash_mutex);
139
140         return ret;
141 }
142
143 static ssize_t flash_write(struct file *file, const char __user *buf,
144                            size_t size, loff_t * ppos)
145 {
146         unsigned long p = *ppos;
147         unsigned int count = size;
148         int written;
149         int nBlock, temp, rc;
150         int i, j;
151
152         if (flashdebug)
153                 printk("flash_write: offset=0x%lX, buffer=0x%p, count=0x%X.\n",
154                        p, buf, count);
155
156         if (!gbWriteEnable)
157                 return -EINVAL;
158
159         if (p < 64 * 1024 && (!gbWriteBase64Enable))
160                 return -EINVAL;
161
162         /*
163          * check for out of range pos or count
164          */
165         if (p >= gbFlashSize)
166                 return count ? -ENXIO : 0;
167
168         if (count > gbFlashSize - p)
169                 count = gbFlashSize - p;
170                         
171         if (!access_ok(VERIFY_READ, buf, count))
172                 return -EFAULT;
173
174         /*
175          * We now lock against reads and writes. --rmk
176          */
177         if (mutex_lock_interruptible(&nwflash_mutex))
178                 return -ERESTARTSYS;
179
180         written = 0;
181
182         leds_event(led_claim);
183         leds_event(led_green_on);
184
185         nBlock = (int) p >> 16; //block # of 64K bytes
186
187         /*
188          * # of 64K blocks to erase and write
189          */
190         temp = ((int) (p + count) >> 16) - nBlock + 1;
191
192         /*
193          * write ends at exactly 64k boundary?
194          */
195         if (((int) (p + count) & 0xFFFF) == 0)
196                 temp -= 1;
197
198         if (flashdebug)
199                 printk(KERN_DEBUG "flash_write: writing %d block(s) "
200                         "starting at %d.\n", temp, nBlock);
201
202         for (; temp; temp--, nBlock++) {
203                 if (flashdebug)
204                         printk(KERN_DEBUG "flash_write: erasing block %d.\n", nBlock);
205
206                 /*
207                  * first we have to erase the block(s), where we will write...
208                  */
209                 i = 0;
210                 j = 0;
211           RetryBlock:
212                 do {
213                         rc = erase_block(nBlock);
214                         i++;
215                 } while (rc && i < 10);
216
217                 if (rc) {
218                         printk(KERN_ERR "flash_write: erase error %x\n", rc);
219                         break;
220                 }
221                 if (flashdebug)
222                         printk(KERN_DEBUG "flash_write: writing offset %lX, "
223                                "from buf %p, bytes left %X.\n", p, buf,
224                                count - written);
225
226                 /*
227                  * write_block will limit write to space left in this block
228                  */
229                 rc = write_block(p, buf, count - written);
230                 j++;
231
232                 /*
233                  * if somehow write verify failed? Can't happen??
234                  */
235                 if (!rc) {
236                         /*
237                          * retry up to 10 times
238                          */
239                         if (j < 10)
240                                 goto RetryBlock;
241                         else
242                                 /*
243                                  * else quit with error...
244                                  */
245                                 rc = -1;
246
247                 }
248                 if (rc < 0) {
249                         printk(KERN_ERR "flash_write: write error %X\n", rc);
250                         break;
251                 }
252                 p += rc;
253                 buf += rc;
254                 written += rc;
255                 *ppos += rc;
256
257                 if (flashdebug)
258                         printk(KERN_DEBUG "flash_write: written 0x%X bytes OK.\n", written);
259         }
260
261         /*
262          * restore reg on exit
263          */
264         leds_event(led_release);
265
266         mutex_unlock(&nwflash_mutex);
267
268         return written;
269 }
270
271
272 /*
273  * The memory devices use the full 32/64 bits of the offset, and so we cannot
274  * check against negative addresses: they are ok. The return value is weird,
275  * though, in that case (0).
276  *
277  * also note that seeking relative to the "end of file" isn't supported:
278  * it has no meaning, so it returns -EINVAL.
279  */
280 static loff_t flash_llseek(struct file *file, loff_t offset, int orig)
281 {
282         loff_t ret;
283
284         mutex_lock(&flash_mutex);
285         if (flashdebug)
286                 printk(KERN_DEBUG "flash_llseek: offset=0x%X, orig=0x%X.\n",
287                        (unsigned int) offset, orig);
288
289         switch (orig) {
290         case 0:
291                 if (offset < 0) {
292                         ret = -EINVAL;
293                         break;
294                 }
295
296                 if ((unsigned int) offset > gbFlashSize) {
297                         ret = -EINVAL;
298                         break;
299                 }
300
301                 file->f_pos = (unsigned int) offset;
302                 ret = file->f_pos;
303                 break;
304         case 1:
305                 if ((file->f_pos + offset) > gbFlashSize) {
306                         ret = -EINVAL;
307                         break;
308                 }
309                 if ((file->f_pos + offset) < 0) {
310                         ret = -EINVAL;
311                         break;
312                 }
313                 file->f_pos += offset;
314                 ret = file->f_pos;
315                 break;
316         default:
317                 ret = -EINVAL;
318         }
319         mutex_unlock(&flash_mutex);
320         return ret;
321 }
322
323
324 /*
325  * assume that main Write routine did the parameter checking...
326  * so just go ahead and erase, what requested!
327  */
328
329 static int erase_block(int nBlock)
330 {
331         volatile unsigned int c1;
332         volatile unsigned char *pWritePtr;
333         unsigned long timeout;
334         int temp, temp1;
335
336         /*
337          * orange LED == erase
338          */
339         leds_event(led_amber_on);
340
341         /*
342          * reset footbridge to the correct offset 0 (...0..3)
343          */
344         *CSR_ROMWRITEREG = 0;
345
346         /*
347          * dummy ROM read
348          */
349         c1 = *(volatile unsigned char *) (FLASH_BASE + 0x8000);
350
351         kick_open();
352         /*
353          * reset status if old errors
354          */
355         *(volatile unsigned char *) (FLASH_BASE + 0x8000) = 0x50;
356
357         /*
358          * erase a block...
359          * aim at the middle of a current block...
360          */
361         pWritePtr = (unsigned char *) ((unsigned int) (FLASH_BASE + 0x8000 + (nBlock << 16)));
362         /*
363          * dummy read
364          */
365         c1 = *pWritePtr;
366
367         kick_open();
368         /*
369          * erase
370          */
371         *(volatile unsigned char *) pWritePtr = 0x20;
372
373         /*
374          * confirm
375          */
376         *(volatile unsigned char *) pWritePtr = 0xD0;
377
378         /*
379          * wait 10 ms
380          */
381         msleep(10);
382
383         /*
384          * wait while erasing in process (up to 10 sec)
385          */
386         timeout = jiffies + 10 * HZ;
387         c1 = 0;
388         while (!(c1 & 0x80) && time_before(jiffies, timeout)) {
389                 msleep(10);
390                 /*
391                  * read any address
392                  */
393                 c1 = *(volatile unsigned char *) (pWritePtr);
394                 //              printk("Flash_erase: status=%X.\n",c1);
395         }
396
397         /*
398          * set flash for normal read access
399          */
400         kick_open();
401 //      *(volatile unsigned char*)(FLASH_BASE+0x8000) = 0xFF;
402         *(volatile unsigned char *) pWritePtr = 0xFF;   //back to normal operation
403
404         /*
405          * check if erase errors were reported
406          */
407         if (c1 & 0x20) {
408                 printk(KERN_ERR "flash_erase: err at %p\n", pWritePtr);
409
410                 /*
411                  * reset error
412                  */
413                 *(volatile unsigned char *) (FLASH_BASE + 0x8000) = 0x50;
414                 return -2;
415         }
416
417         /*
418          * just to make sure - verify if erased OK...
419          */
420         msleep(10);
421
422         pWritePtr = (unsigned char *) ((unsigned int) (FLASH_BASE + (nBlock << 16)));
423
424         for (temp = 0; temp < 16 * 1024; temp++, pWritePtr += 4) {
425                 if ((temp1 = *(volatile unsigned int *) pWritePtr) != 0xFFFFFFFF) {
426                         printk(KERN_ERR "flash_erase: verify err at %p = %X\n",
427                                pWritePtr, temp1);
428                         return -1;
429                 }
430         }
431
432         return 0;
433
434 }
435
436 /*
437  * write_block will limit number of bytes written to the space in this block
438  */
439 static int write_block(unsigned long p, const char __user *buf, int count)
440 {
441         volatile unsigned int c1;
442         volatile unsigned int c2;
443         unsigned char *pWritePtr;
444         unsigned int uAddress;
445         unsigned int offset;
446         unsigned long timeout;
447         unsigned long timeout1;
448
449         /*
450          * red LED == write
451          */
452         leds_event(led_amber_off);
453         leds_event(led_red_on);
454
455         pWritePtr = (unsigned char *) ((unsigned int) (FLASH_BASE + p));
456
457         /*
458          * check if write will end in this block....
459          */
460         offset = p & 0xFFFF;
461
462         if (offset + count > 0x10000)
463                 count = 0x10000 - offset;
464
465         /*
466          * wait up to 30 sec for this block
467          */
468         timeout = jiffies + 30 * HZ;
469
470         for (offset = 0; offset < count; offset++, pWritePtr++) {
471                 uAddress = (unsigned int) pWritePtr;
472                 uAddress &= 0xFFFFFFFC;
473                 if (__get_user(c2, buf + offset))
474                         return -EFAULT;
475
476           WriteRetry:
477                 /*
478                  * dummy read
479                  */
480                 c1 = *(volatile unsigned char *) (FLASH_BASE + 0x8000);
481
482                 /*
483                  * kick open the write gate
484                  */
485                 kick_open();
486
487                 /*
488                  * program footbridge to the correct offset...0..3
489                  */
490                 *CSR_ROMWRITEREG = (unsigned int) pWritePtr & 3;
491
492                 /*
493                  * write cmd
494                  */
495                 *(volatile unsigned char *) (uAddress) = 0x40;
496
497                 /*
498                  * data to write
499                  */
500                 *(volatile unsigned char *) (uAddress) = c2;
501
502                 /*
503                  * get status
504                  */
505                 *(volatile unsigned char *) (FLASH_BASE + 0x10000) = 0x70;
506
507                 c1 = 0;
508
509                 /*
510                  * wait up to 1 sec for this byte
511                  */
512                 timeout1 = jiffies + 1 * HZ;
513
514                 /*
515                  * while not ready...
516                  */
517                 while (!(c1 & 0x80) && time_before(jiffies, timeout1))
518                         c1 = *(volatile unsigned char *) (FLASH_BASE + 0x8000);
519
520                 /*
521                  * if timeout getting status
522                  */
523                 if (time_after_eq(jiffies, timeout1)) {
524                         kick_open();
525                         /*
526                          * reset err
527                          */
528                         *(volatile unsigned char *) (FLASH_BASE + 0x8000) = 0x50;
529
530                         goto WriteRetry;
531                 }
532                 /*
533                  * switch on read access, as a default flash operation mode
534                  */
535                 kick_open();
536                 /*
537                  * read access
538                  */
539                 *(volatile unsigned char *) (FLASH_BASE + 0x8000) = 0xFF;
540
541                 /*
542                  * if hardware reports an error writing, and not timeout - 
543                  * reset the chip and retry
544                  */
545                 if (c1 & 0x10) {
546                         kick_open();
547                         /*
548                          * reset err
549                          */
550                         *(volatile unsigned char *) (FLASH_BASE + 0x8000) = 0x50;
551
552                         /*
553                          * before timeout?
554                          */
555                         if (time_before(jiffies, timeout)) {
556                                 if (flashdebug)
557                                         printk(KERN_DEBUG "write_block: Retrying write at 0x%X)n",
558                                                pWritePtr - FLASH_BASE);
559
560                                 /*
561                                  * no LED == waiting
562                                  */
563                                 leds_event(led_amber_off);
564                                 /*
565                                  * wait couple ms
566                                  */
567                                 msleep(10);
568                                 /*
569                                  * red LED == write
570                                  */
571                                 leds_event(led_red_on);
572
573                                 goto WriteRetry;
574                         } else {
575                                 printk(KERN_ERR "write_block: timeout at 0x%X\n",
576                                        pWritePtr - FLASH_BASE);
577                                 /*
578                                  * return error -2
579                                  */
580                                 return -2;
581
582                         }
583                 }
584         }
585
586         /*
587          * green LED == read/verify
588          */
589         leds_event(led_amber_off);
590         leds_event(led_green_on);
591
592         msleep(10);
593
594         pWritePtr = (unsigned char *) ((unsigned int) (FLASH_BASE + p));
595
596         for (offset = 0; offset < count; offset++) {
597                 char c, c1;
598                 if (__get_user(c, buf))
599                         return -EFAULT;
600                 buf++;
601                 if ((c1 = *pWritePtr++) != c) {
602                         printk(KERN_ERR "write_block: verify error at 0x%X (%02X!=%02X)\n",
603                                pWritePtr - FLASH_BASE, c1, c);
604                         return 0;
605                 }
606         }
607
608         return count;
609 }
610
611
612 static void kick_open(void)
613 {
614         unsigned long flags;
615
616         /*
617          * we want to write a bit pattern XXX1 to Xilinx to enable
618          * the write gate, which will be open for about the next 2ms.
619          */
620         spin_lock_irqsave(&nw_gpio_lock, flags);
621         nw_cpld_modify(CPLD_FLASH_WR_ENABLE, CPLD_FLASH_WR_ENABLE);
622         spin_unlock_irqrestore(&nw_gpio_lock, flags);
623
624         /*
625          * let the ISA bus to catch on...
626          */
627         udelay(25);
628 }
629
630 static const struct file_operations flash_fops =
631 {
632         .owner          = THIS_MODULE,
633         .llseek         = flash_llseek,
634         .read           = flash_read,
635         .write          = flash_write,
636         .unlocked_ioctl = flash_ioctl,
637 };
638
639 static struct miscdevice flash_miscdev =
640 {
641         FLASH_MINOR,
642         "nwflash",
643         &flash_fops
644 };
645
646 static int __init nwflash_init(void)
647 {
648         int ret = -ENODEV;
649
650         if (machine_is_netwinder()) {
651                 int id;
652
653                 FLASH_BASE = ioremap(DC21285_FLASH, KFLASH_SIZE4);
654                 if (!FLASH_BASE)
655                         goto out;
656
657                 id = get_flash_id();
658                 if ((id != KFLASH_ID) && (id != KFLASH_ID4)) {
659                         ret = -ENXIO;
660                         iounmap((void *)FLASH_BASE);
661                         printk("Flash: incorrect ID 0x%04X.\n", id);
662                         goto out;
663                 }
664
665                 printk("Flash ROM driver v.%s, flash device ID 0x%04X, size %d Mb.\n",
666                        NWFLASH_VERSION, id, gbFlashSize / (1024 * 1024));
667
668                 ret = misc_register(&flash_miscdev);
669                 if (ret < 0) {
670                         iounmap((void *)FLASH_BASE);
671                 }
672         }
673 out:
674         return ret;
675 }
676
677 static void __exit nwflash_exit(void)
678 {
679         misc_deregister(&flash_miscdev);
680         iounmap((void *)FLASH_BASE);
681 }
682
683 MODULE_LICENSE("GPL");
684
685 module_param(flashdebug, bool, 0644);
686
687 module_init(nwflash_init);
688 module_exit(nwflash_exit);