Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

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