Root/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
42static DEFINE_MUTEX(flash_mutex);
43static void kick_open(void);
44static int get_flash_id(void);
45static int erase_block(int nBlock);
46static 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
53static bool flashdebug; //if set - we will display progress msgs
54
55static int gbWriteEnable;
56static int gbWriteBase64Enable;
57static volatile unsigned char *FLASH_BASE;
58static int gbFlashSize = KFLASH_SIZE;
59static DEFINE_MUTEX(nwflash_mutex);
60
61static 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
96static 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
123static 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
143static 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 */
280static 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
329static 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 */
439static 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
612static 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
630static 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
639static struct miscdevice flash_miscdev =
640{
641    FLASH_MINOR,
642    "nwflash",
643    &flash_fops
644};
645
646static 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    }
673out:
674    return ret;
675}
676
677static void __exit nwflash_exit(void)
678{
679    misc_deregister(&flash_miscdev);
680    iounmap((void *)FLASH_BASE);
681}
682
683MODULE_LICENSE("GPL");
684
685module_param(flashdebug, bool, 0644);
686
687module_init(nwflash_init);
688module_exit(nwflash_exit);
689

Archive Download this file



interactive