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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [mtd/] [chips/] [sharp.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 * MTD chip driver for pre-CFI Sharp flash chips
3
 *
4
 * Copyright 2000,2001 David A. Schleef <ds@schleef.org>
5
 *           2000,2001 Lineo, Inc.
6
 *
7
 * $Id: sharp.c,v 1.1.1.1 2004-04-15 01:52:07 phoenix Exp $
8
 *
9
 * Devices supported:
10
 *   LH28F016SCT Symmetrical block flash memory, 2Mx8
11
 *   LH28F008SCT Symmetrical block flash memory, 1Mx8
12
 *
13
 * Documentation:
14
 *   http://www.sharpmeg.com/datasheets/memic/flashcmp/
15
 *   http://www.sharpmeg.com/datasheets/memic/flashcmp/01symf/16m/016sctl9.pdf
16
 *   016sctl9.pdf
17
 *
18
 * Limitations:
19
 *   This driver only supports 4x1 arrangement of chips.
20
 *   Not tested on anything but PowerPC.
21
 */
22
 
23
#include <linux/kernel.h>
24
#include <linux/module.h>
25
#include <linux/version.h>
26
#include <linux/types.h>
27
#include <linux/sched.h>
28
#include <linux/errno.h>
29
#include <linux/interrupt.h>
30
#include <linux/mtd/map.h>
31
#include <linux/mtd/cfi.h>
32
#include <linux/delay.h>
33
 
34
#define CMD_RESET               0xffffffff
35
#define CMD_READ_ID             0x90909090
36
#define CMD_READ_STATUS         0x70707070
37
#define CMD_CLEAR_STATUS        0x50505050
38
#define CMD_BLOCK_ERASE_1       0x20202020
39
#define CMD_BLOCK_ERASE_2       0xd0d0d0d0
40
#define CMD_BYTE_WRITE          0x40404040
41
#define CMD_SUSPEND             0xb0b0b0b0
42
#define CMD_RESUME              0xd0d0d0d0
43
#define CMD_SET_BLOCK_LOCK_1    0x60606060
44
#define CMD_SET_BLOCK_LOCK_2    0x01010101
45
#define CMD_SET_MASTER_LOCK_1   0x60606060
46
#define CMD_SET_MASTER_LOCK_2   0xf1f1f1f1
47
#define CMD_CLEAR_BLOCK_LOCKS_1 0x60606060
48
#define CMD_CLEAR_BLOCK_LOCKS_2 0xd0d0d0d0
49
 
50
#define SR_READY                0x80808080 // 1 = ready
51
#define SR_ERASE_SUSPEND        0x40404040 // 1 = block erase suspended
52
#define SR_ERROR_ERASE          0x20202020 // 1 = error in block erase or clear lock bits
53
#define SR_ERROR_WRITE          0x10101010 // 1 = error in byte write or set lock bit
54
#define SR_VPP                  0x08080808 // 1 = Vpp is low
55
#define SR_WRITE_SUSPEND        0x04040404 // 1 = byte write suspended
56
#define SR_PROTECT              0x02020202 // 1 = lock bit set
57
#define SR_RESERVED             0x01010101
58
 
59
#define SR_ERRORS (SR_ERROR_ERASE|SR_ERROR_WRITE|SR_VPP|SR_PROTECT)
60
 
61
/* Configuration options */
62
 
63
#undef AUTOUNLOCK  /* automatically unlocks blocks before erasing */
64
 
65
struct mtd_info *sharp_probe(struct map_info *);
66
 
67
static int sharp_probe_map(struct map_info *map,struct mtd_info *mtd);
68
 
69
static int sharp_read(struct mtd_info *mtd, loff_t from, size_t len,
70
        size_t *retlen, u_char *buf);
71
static int sharp_write(struct mtd_info *mtd, loff_t from, size_t len,
72
        size_t *retlen, const u_char *buf);
73
static int sharp_erase(struct mtd_info *mtd, struct erase_info *instr);
74
static void sharp_sync(struct mtd_info *mtd);
75
static int sharp_suspend(struct mtd_info *mtd);
76
static void sharp_resume(struct mtd_info *mtd);
77
static void sharp_destroy(struct mtd_info *mtd);
78
 
79
static int sharp_write_oneword(struct map_info *map, struct flchip *chip,
80
        unsigned long adr, __u32 datum);
81
static int sharp_erase_oneblock(struct map_info *map, struct flchip *chip,
82
        unsigned long adr);
83
#ifdef AUTOUNLOCK
84
static void sharp_unlock_oneblock(struct map_info *map, struct flchip *chip,
85
        unsigned long adr);
86
#endif
87
 
88
 
89
struct sharp_info{
90
        struct flchip *chip;
91
        int bogus;
92
        int chipshift;
93
        int numchips;
94
        struct flchip chips[1];
95
};
96
 
97
struct mtd_info *sharp_probe(struct map_info *map);
98
static void sharp_destroy(struct mtd_info *mtd);
99
 
100
static struct mtd_chip_driver sharp_chipdrv = {
101
        probe: sharp_probe,
102
        destroy: sharp_destroy,
103
        name: "sharp",
104
        module: THIS_MODULE
105
};
106
 
107
 
108
struct mtd_info *sharp_probe(struct map_info *map)
109
{
110
        struct mtd_info *mtd = NULL;
111
        struct sharp_info *sharp = NULL;
112
        int width;
113
 
114
        mtd = kmalloc(sizeof(*mtd), GFP_KERNEL);
115
        if(!mtd)
116
                return NULL;
117
 
118
        sharp = kmalloc(sizeof(*sharp), GFP_KERNEL);
119
        if(!sharp)
120
                return NULL;
121
 
122
        memset(mtd, 0, sizeof(*mtd));
123
 
124
        width = sharp_probe_map(map,mtd);
125
        if(!width){
126
                kfree(mtd);
127
                kfree(sharp);
128
                return NULL;
129
        }
130
 
131
        mtd->priv = map;
132
        mtd->type = MTD_NORFLASH;
133
        mtd->erase = sharp_erase;
134
        mtd->read = sharp_read;
135
        mtd->write = sharp_write;
136
        mtd->sync = sharp_sync;
137
        mtd->suspend = sharp_suspend;
138
        mtd->resume = sharp_resume;
139
        mtd->flags = MTD_CAP_NORFLASH;
140
        mtd->name = map->name;
141
 
142
        memset(sharp, 0, sizeof(*sharp));
143
        sharp->chipshift = 23;
144
        sharp->numchips = 1;
145
        sharp->chips[0].start = 0;
146
        sharp->chips[0].state = FL_READY;
147
        sharp->chips[0].mutex = &sharp->chips[0]._spinlock;
148
        sharp->chips[0].word_write_time = 0;
149
        init_waitqueue_head(&sharp->chips[0].wq);
150
        spin_lock_init(&sharp->chips[0]._spinlock);
151
 
152
        map->fldrv = &sharp_chipdrv;
153
        map->fldrv_priv = sharp;
154
 
155
        MOD_INC_USE_COUNT;
156
        return mtd;
157
}
158
 
159
static int sharp_probe_map(struct map_info *map,struct mtd_info *mtd)
160
{
161
        unsigned long tmp;
162
        unsigned long base = 0;
163
        u32 read0, read4;
164
        int width = 4;
165
 
166
        tmp = map->read32(map, base+0);
167
 
168
        map->write32(map, CMD_READ_ID, base+0);
169
 
170
        read0=map->read32(map, base+0);
171
        read4=map->read32(map, base+4);
172
        if(read0 == 0x89898989){
173
                printk("Looks like sharp flash\n");
174
                switch(read4){
175
                case 0xaaaaaaaa:
176
                case 0xa0a0a0a0:
177
                        /* aa - LH28F016SCT-L95 2Mx8, 32 64k blocks*/
178
                        /* a0 - LH28F016SCT-Z4  2Mx8, 32 64k blocks*/
179
                        mtd->erasesize = 0x10000 * width;
180
                        mtd->size = 0x200000 * width;
181
                        return width;
182
                case 0xa6a6a6a6:
183
                        /* a6 - LH28F008SCT-L12 1Mx8, 16 64k blocks*/
184
                        /* a6 - LH28F008SCR-L85 1Mx8, 16 64k blocks*/
185
                        mtd->erasesize = 0x10000 * width;
186
                        mtd->size = 0x100000 * width;
187
                        return width;
188
#if 0
189
                case 0x00000000: /* unknown */
190
                        /* XX - LH28F004SCT 512kx8, 8 64k blocks*/
191
                        mtd->erasesize = 0x10000 * width;
192
                        mtd->size = 0x80000 * width;
193
                        return width;
194
#endif
195
                default:
196
                        printk("Sort-of looks like sharp flash, 0x%08x 0x%08x\n",
197
                                read0,read4);
198
                }
199
        }else if((map->read32(map, base+0) == CMD_READ_ID)){
200
                /* RAM, probably */
201
                printk("Looks like RAM\n");
202
                map->write32(map, tmp, base+0);
203
        }else{
204
                printk("Doesn't look like sharp flash, 0x%08x 0x%08x\n",
205
                        read0,read4);
206
        }
207
 
208
        return 0;
209
}
210
 
211
/* This function returns with the chip->mutex lock held. */
212
static int sharp_wait(struct map_info *map, struct flchip *chip)
213
{
214
        __u16 status;
215
        unsigned long timeo = jiffies + HZ;
216
        DECLARE_WAITQUEUE(wait, current);
217
        int adr = 0;
218
 
219
retry:
220
        spin_lock_bh(chip->mutex);
221
 
222
        switch(chip->state){
223
        case FL_READY:
224
                map->write32(map,CMD_READ_STATUS,adr);
225
                chip->state = FL_STATUS;
226
        case FL_STATUS:
227
                status = map->read32(map,adr);
228
//printk("status=%08x\n",status);
229
 
230
                udelay(100);
231
                if((status & SR_READY)!=SR_READY){
232
//printk(".status=%08x\n",status);
233
                        udelay(100);
234
                }
235
                break;
236
        default:
237
                printk("Waiting for chip\n");
238
 
239
                set_current_state(TASK_INTERRUPTIBLE);
240
                add_wait_queue(&chip->wq, &wait);
241
 
242
                spin_unlock_bh(chip->mutex);
243
 
244
                schedule();
245
                remove_wait_queue(&chip->wq, &wait);
246
 
247
                if(signal_pending(current))
248
                        return -EINTR;
249
 
250
                timeo = jiffies + HZ;
251
 
252
                goto retry;
253
        }
254
 
255
        map->write32(map,CMD_RESET, adr);
256
 
257
        chip->state = FL_READY;
258
 
259
        return 0;
260
}
261
 
262
static void sharp_release(struct flchip *chip)
263
{
264
        wake_up(&chip->wq);
265
        spin_unlock_bh(chip->mutex);
266
}
267
 
268
static int sharp_read(struct mtd_info *mtd, loff_t from, size_t len,
269
        size_t *retlen, u_char *buf)
270
{
271
        struct map_info *map = mtd->priv;
272
        struct sharp_info *sharp = map->fldrv_priv;
273
        int chipnum;
274
        int ret = 0;
275
        int ofs = 0;
276
 
277
        chipnum = (from >> sharp->chipshift);
278
        ofs = from & ((1 << sharp->chipshift)-1);
279
 
280
        *retlen = 0;
281
 
282
        while(len){
283
                unsigned long thislen;
284
 
285
                if(chipnum>=sharp->numchips)
286
                        break;
287
 
288
                thislen = len;
289
                if(ofs+thislen >= (1<<sharp->chipshift))
290
                        thislen = (1<<sharp->chipshift) - ofs;
291
 
292
                ret = sharp_wait(map,&sharp->chips[chipnum]);
293
                if(ret<0)
294
                        break;
295
 
296
                map->copy_from(map,buf,ofs,thislen);
297
 
298
                sharp_release(&sharp->chips[chipnum]);
299
 
300
                *retlen += thislen;
301
                len -= thislen;
302
                buf += thislen;
303
 
304
                ofs = 0;
305
                chipnum++;
306
        }
307
        return ret;
308
}
309
 
310
static int sharp_write(struct mtd_info *mtd, loff_t to, size_t len,
311
        size_t *retlen, const u_char *buf)
312
{
313
        struct map_info *map = mtd->priv;
314
        struct sharp_info *sharp = map->fldrv_priv;
315
        int ret = 0;
316
        int i,j;
317
        int chipnum;
318
        unsigned long ofs;
319
        union { u32 l; unsigned char uc[4]; } tbuf;
320
 
321
        *retlen = 0;
322
 
323
        while(len){
324
                tbuf.l = 0xffffffff;
325
                chipnum = to >> sharp->chipshift;
326
                ofs = to & ((1<<sharp->chipshift)-1);
327
 
328
                j=0;
329
                for(i=ofs&3;i<4 && len;i++){
330
                        tbuf.uc[i] = *buf;
331
                        buf++;
332
                        to++;
333
                        len--;
334
                        j++;
335
                }
336
                sharp_write_oneword(map, &sharp->chips[chipnum], ofs&~3, tbuf.l);
337
                if(ret<0)
338
                        return ret;
339
                (*retlen)+=j;
340
        }
341
 
342
        return 0;
343
}
344
 
345
static int sharp_write_oneword(struct map_info *map, struct flchip *chip,
346
        unsigned long adr, __u32 datum)
347
{
348
        int ret;
349
        int timeo;
350
        int try;
351
        int i;
352
        int status = 0;
353
 
354
        ret = sharp_wait(map,chip);
355
 
356
        for(try=0;try<10;try++){
357
                map->write32(map,CMD_BYTE_WRITE,adr);
358
                /* cpu_to_le32 -> hack to fix the writel be->le conversion */
359
                map->write32(map,cpu_to_le32(datum),adr);
360
 
361
                chip->state = FL_WRITING;
362
 
363
                timeo = jiffies + (HZ/2);
364
 
365
                map->write32(map,CMD_READ_STATUS,adr);
366
                for(i=0;i<100;i++){
367
                        status = map->read32(map,adr);
368
                        if((status & SR_READY)==SR_READY)
369
                                break;
370
                }
371
                if(i==100){
372
                        printk("sharp: timed out writing\n");
373
                }
374
 
375
                if(!(status&SR_ERRORS))
376
                        break;
377
 
378
                printk("sharp: error writing byte at addr=%08lx status=%08x\n",adr,status);
379
 
380
                map->write32(map,CMD_CLEAR_STATUS,adr);
381
        }
382
        map->write32(map,CMD_RESET,adr);
383
        chip->state = FL_READY;
384
 
385
        wake_up(&chip->wq);
386
        spin_unlock_bh(chip->mutex);
387
 
388
        return 0;
389
}
390
 
391
static int sharp_erase(struct mtd_info *mtd, struct erase_info *instr)
392
{
393
        struct map_info *map = mtd->priv;
394
        struct sharp_info *sharp = map->fldrv_priv;
395
        unsigned long adr,len;
396
        int chipnum, ret=0;
397
 
398
//printk("sharp_erase()\n");
399
        if(instr->addr & (mtd->erasesize - 1))
400
                return -EINVAL;
401
        if(instr->len & (mtd->erasesize - 1))
402
                return -EINVAL;
403
        if(instr->len + instr->addr > mtd->size)
404
                return -EINVAL;
405
 
406
        chipnum = instr->addr >> sharp->chipshift;
407
        adr = instr->addr & ((1<<sharp->chipshift)-1);
408
        len = instr->len;
409
 
410
        while(len){
411
                ret = sharp_erase_oneblock(map, &sharp->chips[chipnum], adr);
412
                if(ret)return ret;
413
 
414
                adr += mtd->erasesize;
415
                len -= mtd->erasesize;
416
                if(adr >> sharp->chipshift){
417
                        adr = 0;
418
                        chipnum++;
419
                        if(chipnum>=sharp->numchips)
420
                                break;
421
                }
422
        }
423
 
424
        instr->state = MTD_ERASE_DONE;
425
        if(instr->callback)
426
                instr->callback(instr);
427
 
428
        return 0;
429
}
430
 
431
static int sharp_do_wait_for_ready(struct map_info *map, struct flchip *chip,
432
        unsigned long adr)
433
{
434
        int ret;
435
        int timeo;
436
        int status;
437
        DECLARE_WAITQUEUE(wait, current);
438
 
439
        map->write32(map,CMD_READ_STATUS,adr);
440
        status = map->read32(map,adr);
441
 
442
        timeo = jiffies + HZ;
443
 
444
        while(time_before(jiffies, timeo)){
445
                map->write32(map,CMD_READ_STATUS,adr);
446
                status = map->read32(map,adr);
447
                if((status & SR_READY)==SR_READY){
448
                        ret = 0;
449
                        goto out;
450
                }
451
                set_current_state(TASK_INTERRUPTIBLE);
452
                add_wait_queue(&chip->wq, &wait);
453
 
454
                //spin_unlock_bh(chip->mutex);
455
 
456
                schedule_timeout(1);
457
                schedule();
458
                remove_wait_queue(&chip->wq, &wait);
459
 
460
                //spin_lock_bh(chip->mutex);
461
 
462
                if (signal_pending(current)){
463
                        ret = -EINTR;
464
                        goto out;
465
                }
466
 
467
        }
468
        ret = -ETIME;
469
out:
470
        return ret;
471
}
472
 
473
static int sharp_erase_oneblock(struct map_info *map, struct flchip *chip,
474
        unsigned long adr)
475
{
476
        int ret;
477
        //int timeo;
478
        int status;
479
        //int i;
480
 
481
//printk("sharp_erase_oneblock()\n");
482
 
483
#ifdef AUTOUNLOCK
484
        /* This seems like a good place to do an unlock */
485
        sharp_unlock_oneblock(map,chip,adr);
486
#endif
487
 
488
        map->write32(map,CMD_BLOCK_ERASE_1,adr);
489
        map->write32(map,CMD_BLOCK_ERASE_2,adr);
490
 
491
        chip->state = FL_ERASING;
492
 
493
        ret = sharp_do_wait_for_ready(map,chip,adr);
494
        if(ret<0)return ret;
495
 
496
        map->write32(map,CMD_READ_STATUS,adr);
497
        status = map->read32(map,adr);
498
 
499
        if(!(status&SR_ERRORS)){
500
                map->write32(map,CMD_RESET,adr);
501
                chip->state = FL_READY;
502
                //spin_unlock_bh(chip->mutex);
503
                return 0;
504
        }
505
 
506
        printk("sharp: error erasing block at addr=%08lx status=%08x\n",adr,status);
507
        map->write32(map,CMD_CLEAR_STATUS,adr);
508
 
509
        //spin_unlock_bh(chip->mutex);
510
 
511
        return -EIO;
512
}
513
 
514
#ifdef AUTOUNLOCK
515
static void sharp_unlock_oneblock(struct map_info *map, struct flchip *chip,
516
        unsigned long adr)
517
{
518
        int i;
519
        int status;
520
 
521
        map->write32(map,CMD_CLEAR_BLOCK_LOCKS_1,adr);
522
        map->write32(map,CMD_CLEAR_BLOCK_LOCKS_2,adr);
523
 
524
        udelay(100);
525
 
526
        status = map->read32(map,adr);
527
        printk("status=%08x\n",status);
528
 
529
        for(i=0;i<1000;i++){
530
                //map->write32(map,CMD_READ_STATUS,adr);
531
                status = map->read32(map,adr);
532
                if((status & SR_READY)==SR_READY)
533
                        break;
534
                udelay(100);
535
        }
536
        if(i==1000){
537
                printk("sharp: timed out unlocking block\n");
538
        }
539
 
540
        if(!(status&SR_ERRORS)){
541
                map->write32(map,CMD_RESET,adr);
542
                chip->state = FL_READY;
543
                return;
544
        }
545
 
546
        printk("sharp: error unlocking block at addr=%08lx status=%08x\n",adr,status);
547
        map->write32(map,CMD_CLEAR_STATUS,adr);
548
}
549
#endif
550
 
551
static void sharp_sync(struct mtd_info *mtd)
552
{
553
        //printk("sharp_sync()\n");
554
}
555
 
556
static int sharp_suspend(struct mtd_info *mtd)
557
{
558
        printk("sharp_suspend()\n");
559
        return -EINVAL;
560
}
561
 
562
static void sharp_resume(struct mtd_info *mtd)
563
{
564
        printk("sharp_resume()\n");
565
 
566
}
567
 
568
static void sharp_destroy(struct mtd_info *mtd)
569
{
570
        printk("sharp_destroy()\n");
571
 
572
}
573
 
574
int __init sharp_probe_init(void)
575
{
576
        printk("MTD Sharp chip driver <ds@lineo.com>\n");
577
 
578
        register_mtd_chip_driver(&sharp_chipdrv);
579
 
580
        return 0;
581
}
582
 
583
static void __exit sharp_probe_exit(void)
584
{
585
        unregister_mtd_chip_driver(&sharp_chipdrv);
586
}
587
 
588
module_init(sharp_probe_init);
589
module_exit(sharp_probe_exit);
590
 
591
 
592
MODULE_LICENSE("GPL");
593
MODULE_AUTHOR("David Schleef <ds@schleef.org>");
594
MODULE_DESCRIPTION("Old MTD chip driver for pre-CFI Sharp flash chips");

powered by: WebSVN 2.1.0

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