OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [char/] [nwflash.c] - Blame information for rev 62

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.