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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [char/] [nwflash.c] - Blame information for rev 1774

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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