blob: c9cd3d21ccfaa98c64d976e29cabc0fef28ee7d0 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
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 *
Richard Purdieee2d49d2005-11-29 14:28:31 +00007 * $Id: sharp.c,v 1.17 2005/11/29 14:28:28 gleixner Exp $
Linus Torvalds1da177e2005-04-16 15:20:36 -07008 *
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/types.h>
26#include <linux/sched.h>
27#include <linux/errno.h>
28#include <linux/interrupt.h>
29#include <linux/mtd/map.h>
30#include <linux/mtd/mtd.h>
31#include <linux/mtd/cfi.h>
32#include <linux/delay.h>
33#include <linux/init.h>
Todd Poynor1da2c9a2005-08-02 21:36:09 +010034#include <linux/slab.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070035
36#define CMD_RESET 0xffffffff
37#define CMD_READ_ID 0x90909090
38#define CMD_READ_STATUS 0x70707070
39#define CMD_CLEAR_STATUS 0x50505050
40#define CMD_BLOCK_ERASE_1 0x20202020
41#define CMD_BLOCK_ERASE_2 0xd0d0d0d0
42#define CMD_BYTE_WRITE 0x40404040
43#define CMD_SUSPEND 0xb0b0b0b0
44#define CMD_RESUME 0xd0d0d0d0
45#define CMD_SET_BLOCK_LOCK_1 0x60606060
46#define CMD_SET_BLOCK_LOCK_2 0x01010101
47#define CMD_SET_MASTER_LOCK_1 0x60606060
48#define CMD_SET_MASTER_LOCK_2 0xf1f1f1f1
49#define CMD_CLEAR_BLOCK_LOCKS_1 0x60606060
50#define CMD_CLEAR_BLOCK_LOCKS_2 0xd0d0d0d0
51
52#define SR_READY 0x80808080 // 1 = ready
53#define SR_ERASE_SUSPEND 0x40404040 // 1 = block erase suspended
54#define SR_ERROR_ERASE 0x20202020 // 1 = error in block erase or clear lock bits
55#define SR_ERROR_WRITE 0x10101010 // 1 = error in byte write or set lock bit
56#define SR_VPP 0x08080808 // 1 = Vpp is low
57#define SR_WRITE_SUSPEND 0x04040404 // 1 = byte write suspended
58#define SR_PROTECT 0x02020202 // 1 = lock bit set
59#define SR_RESERVED 0x01010101
60
61#define SR_ERRORS (SR_ERROR_ERASE|SR_ERROR_WRITE|SR_VPP|SR_PROTECT)
62
63/* Configuration options */
64
65#undef AUTOUNLOCK /* automatically unlocks blocks before erasing */
66
Adrian Bunk0500abf2006-03-31 02:29:42 -080067static struct mtd_info *sharp_probe(struct map_info *);
Linus Torvalds1da177e2005-04-16 15:20:36 -070068
69static int sharp_probe_map(struct map_info *map,struct mtd_info *mtd);
70
71static int sharp_read(struct mtd_info *mtd, loff_t from, size_t len,
72 size_t *retlen, u_char *buf);
73static int sharp_write(struct mtd_info *mtd, loff_t from, size_t len,
74 size_t *retlen, const u_char *buf);
75static int sharp_erase(struct mtd_info *mtd, struct erase_info *instr);
76static void sharp_sync(struct mtd_info *mtd);
77static int sharp_suspend(struct mtd_info *mtd);
78static void sharp_resume(struct mtd_info *mtd);
79static void sharp_destroy(struct mtd_info *mtd);
80
81static int sharp_write_oneword(struct map_info *map, struct flchip *chip,
82 unsigned long adr, __u32 datum);
83static int sharp_erase_oneblock(struct map_info *map, struct flchip *chip,
84 unsigned long adr);
85#ifdef AUTOUNLOCK
86static void sharp_unlock_oneblock(struct map_info *map, struct flchip *chip,
87 unsigned long adr);
88#endif
89
90
91struct sharp_info{
92 struct flchip *chip;
93 int bogus;
94 int chipshift;
95 int numchips;
96 struct flchip chips[1];
97};
98
Linus Torvalds1da177e2005-04-16 15:20:36 -070099static void sharp_destroy(struct mtd_info *mtd);
100
101static struct mtd_chip_driver sharp_chipdrv = {
102 .probe = sharp_probe,
103 .destroy = sharp_destroy,
104 .name = "sharp",
105 .module = THIS_MODULE
106};
107
108
Adrian Bunk0500abf2006-03-31 02:29:42 -0800109static struct mtd_info *sharp_probe(struct map_info *map)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700110{
111 struct mtd_info *mtd = NULL;
112 struct sharp_info *sharp = NULL;
113 int width;
114
Burman Yan95b93a02006-11-15 21:10:29 +0200115 mtd = kzalloc(sizeof(*mtd), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700116 if(!mtd)
117 return NULL;
118
Burman Yan95b93a02006-11-15 21:10:29 +0200119 sharp = kzalloc(sizeof(*sharp), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700120 if(!sharp) {
121 kfree(mtd);
122 return NULL;
123 }
124
Linus Torvalds1da177e2005-04-16 15:20:36 -0700125 width = sharp_probe_map(map,mtd);
126 if(!width){
127 kfree(mtd);
128 kfree(sharp);
129 return NULL;
130 }
131
132 mtd->priv = map;
133 mtd->type = MTD_NORFLASH;
134 mtd->erase = sharp_erase;
135 mtd->read = sharp_read;
136 mtd->write = sharp_write;
137 mtd->sync = sharp_sync;
138 mtd->suspend = sharp_suspend;
139 mtd->resume = sharp_resume;
140 mtd->flags = MTD_CAP_NORFLASH;
Artem B. Bityutskiy783ed812006-06-14 19:53:44 +0400141 mtd->writesize = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700142 mtd->name = map->name;
143
Linus Torvalds1da177e2005-04-16 15:20:36 -0700144 sharp->chipshift = 23;
145 sharp->numchips = 1;
146 sharp->chips[0].start = 0;
147 sharp->chips[0].state = FL_READY;
148 sharp->chips[0].mutex = &sharp->chips[0]._spinlock;
149 sharp->chips[0].word_write_time = 0;
150 init_waitqueue_head(&sharp->chips[0].wq);
151 spin_lock_init(&sharp->chips[0]._spinlock);
152
153 map->fldrv = &sharp_chipdrv;
154 map->fldrv_priv = sharp;
155
156 __module_get(THIS_MODULE);
157 return mtd;
158}
159
Richard Purdieee2d49d2005-11-29 14:28:31 +0000160static inline void sharp_send_cmd(struct map_info *map, unsigned long cmd, unsigned long adr)
161{
162 map_word map_cmd;
163 map_cmd.x[0] = cmd;
164 map_write(map, map_cmd, adr);
165}
166
Linus Torvalds1da177e2005-04-16 15:20:36 -0700167static int sharp_probe_map(struct map_info *map,struct mtd_info *mtd)
168{
Richard Purdieee2d49d2005-11-29 14:28:31 +0000169 map_word tmp, read0, read4;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700170 unsigned long base = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700171 int width = 4;
172
Richard Purdieee2d49d2005-11-29 14:28:31 +0000173 tmp = map_read(map, base+0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700174
Richard Purdieee2d49d2005-11-29 14:28:31 +0000175 sharp_send_cmd(map, CMD_READ_ID, base+0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700176
Richard Purdieee2d49d2005-11-29 14:28:31 +0000177 read0 = map_read(map, base+0);
178 read4 = map_read(map, base+4);
179 if(read0.x[0] == 0x89898989){
Linus Torvalds1da177e2005-04-16 15:20:36 -0700180 printk("Looks like sharp flash\n");
Richard Purdieee2d49d2005-11-29 14:28:31 +0000181 switch(read4.x[0]){
Linus Torvalds1da177e2005-04-16 15:20:36 -0700182 case 0xaaaaaaaa:
183 case 0xa0a0a0a0:
184 /* aa - LH28F016SCT-L95 2Mx8, 32 64k blocks*/
185 /* a0 - LH28F016SCT-Z4 2Mx8, 32 64k blocks*/
186 mtd->erasesize = 0x10000 * width;
187 mtd->size = 0x200000 * width;
188 return width;
189 case 0xa6a6a6a6:
190 /* a6 - LH28F008SCT-L12 1Mx8, 16 64k blocks*/
191 /* a6 - LH28F008SCR-L85 1Mx8, 16 64k blocks*/
192 mtd->erasesize = 0x10000 * width;
193 mtd->size = 0x100000 * width;
194 return width;
195#if 0
196 case 0x00000000: /* unknown */
197 /* XX - LH28F004SCT 512kx8, 8 64k blocks*/
198 mtd->erasesize = 0x10000 * width;
199 mtd->size = 0x80000 * width;
200 return width;
201#endif
202 default:
Richard Purdieee2d49d2005-11-29 14:28:31 +0000203 printk("Sort-of looks like sharp flash, 0x%08lx 0x%08lx\n",
204 read0.x[0], read4.x[0]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700205 }
Richard Purdieee2d49d2005-11-29 14:28:31 +0000206 }else if((map_read(map, base+0).x[0] == CMD_READ_ID)){
Linus Torvalds1da177e2005-04-16 15:20:36 -0700207 /* RAM, probably */
208 printk("Looks like RAM\n");
Richard Purdieee2d49d2005-11-29 14:28:31 +0000209 map_write(map, tmp, base+0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700210 }else{
Richard Purdieee2d49d2005-11-29 14:28:31 +0000211 printk("Doesn't look like sharp flash, 0x%08lx 0x%08lx\n",
212 read0.x[0], read4.x[0]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700213 }
214
215 return 0;
216}
217
218/* This function returns with the chip->mutex lock held. */
219static int sharp_wait(struct map_info *map, struct flchip *chip)
220{
Richard Purdieee2d49d2005-11-29 14:28:31 +0000221 int i;
222 map_word status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700223 unsigned long timeo = jiffies + HZ;
224 DECLARE_WAITQUEUE(wait, current);
225 int adr = 0;
226
227retry:
228 spin_lock_bh(chip->mutex);
229
230 switch(chip->state){
231 case FL_READY:
Richard Purdieee2d49d2005-11-29 14:28:31 +0000232 sharp_send_cmd(map, CMD_READ_STATUS, adr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700233 chip->state = FL_STATUS;
234 case FL_STATUS:
Todd Poynor1da2c9a2005-08-02 21:36:09 +0100235 for(i=0;i<100;i++){
Richard Purdieee2d49d2005-11-29 14:28:31 +0000236 status = map_read(map, adr);
237 if((status.x[0] & SR_READY)==SR_READY)
Todd Poynor1da2c9a2005-08-02 21:36:09 +0100238 break;
239 udelay(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700240 }
241 break;
242 default:
243 printk("Waiting for chip\n");
244
245 set_current_state(TASK_INTERRUPTIBLE);
246 add_wait_queue(&chip->wq, &wait);
247
248 spin_unlock_bh(chip->mutex);
249
250 schedule();
251 remove_wait_queue(&chip->wq, &wait);
252
253 if(signal_pending(current))
254 return -EINTR;
255
256 timeo = jiffies + HZ;
257
258 goto retry;
259 }
260
Richard Purdieee2d49d2005-11-29 14:28:31 +0000261 sharp_send_cmd(map, CMD_RESET, adr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700262
263 chip->state = FL_READY;
264
265 return 0;
266}
267
268static void sharp_release(struct flchip *chip)
269{
270 wake_up(&chip->wq);
271 spin_unlock_bh(chip->mutex);
272}
273
274static int sharp_read(struct mtd_info *mtd, loff_t from, size_t len,
275 size_t *retlen, u_char *buf)
276{
277 struct map_info *map = mtd->priv;
278 struct sharp_info *sharp = map->fldrv_priv;
279 int chipnum;
280 int ret = 0;
281 int ofs = 0;
282
283 chipnum = (from >> sharp->chipshift);
284 ofs = from & ((1 << sharp->chipshift)-1);
285
286 *retlen = 0;
287
288 while(len){
289 unsigned long thislen;
290
291 if(chipnum>=sharp->numchips)
292 break;
293
294 thislen = len;
295 if(ofs+thislen >= (1<<sharp->chipshift))
296 thislen = (1<<sharp->chipshift) - ofs;
297
298 ret = sharp_wait(map,&sharp->chips[chipnum]);
299 if(ret<0)
300 break;
301
302 map_copy_from(map,buf,ofs,thislen);
303
304 sharp_release(&sharp->chips[chipnum]);
305
306 *retlen += thislen;
307 len -= thislen;
308 buf += thislen;
309
310 ofs = 0;
311 chipnum++;
312 }
313 return ret;
314}
315
316static int sharp_write(struct mtd_info *mtd, loff_t to, size_t len,
317 size_t *retlen, const u_char *buf)
318{
319 struct map_info *map = mtd->priv;
320 struct sharp_info *sharp = map->fldrv_priv;
321 int ret = 0;
322 int i,j;
323 int chipnum;
324 unsigned long ofs;
325 union { u32 l; unsigned char uc[4]; } tbuf;
326
327 *retlen = 0;
328
329 while(len){
330 tbuf.l = 0xffffffff;
331 chipnum = to >> sharp->chipshift;
332 ofs = to & ((1<<sharp->chipshift)-1);
333
334 j=0;
335 for(i=ofs&3;i<4 && len;i++){
336 tbuf.uc[i] = *buf;
337 buf++;
338 to++;
339 len--;
340 j++;
341 }
342 sharp_write_oneword(map, &sharp->chips[chipnum], ofs&~3, tbuf.l);
343 if(ret<0)
344 return ret;
345 (*retlen)+=j;
346 }
347
348 return 0;
349}
350
351static int sharp_write_oneword(struct map_info *map, struct flchip *chip,
352 unsigned long adr, __u32 datum)
353{
354 int ret;
355 int timeo;
356 int try;
357 int i;
Richard Purdieee2d49d2005-11-29 14:28:31 +0000358 map_word data, status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700359
Richard Purdieee2d49d2005-11-29 14:28:31 +0000360 status.x[0] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700361 ret = sharp_wait(map,chip);
362
363 for(try=0;try<10;try++){
Richard Purdieee2d49d2005-11-29 14:28:31 +0000364 sharp_send_cmd(map, CMD_BYTE_WRITE, adr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700365 /* cpu_to_le32 -> hack to fix the writel be->le conversion */
Richard Purdieee2d49d2005-11-29 14:28:31 +0000366 data.x[0] = cpu_to_le32(datum);
367 map_write(map, data, adr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700368
369 chip->state = FL_WRITING;
370
371 timeo = jiffies + (HZ/2);
372
Richard Purdieee2d49d2005-11-29 14:28:31 +0000373 sharp_send_cmd(map, CMD_READ_STATUS, adr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700374 for(i=0;i<100;i++){
Richard Purdieee2d49d2005-11-29 14:28:31 +0000375 status = map_read(map, adr);
376 if((status.x[0] & SR_READY) == SR_READY)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700377 break;
378 }
379 if(i==100){
380 printk("sharp: timed out writing\n");
381 }
382
Richard Purdieee2d49d2005-11-29 14:28:31 +0000383 if(!(status.x[0] & SR_ERRORS))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700384 break;
385
Richard Purdieee2d49d2005-11-29 14:28:31 +0000386 printk("sharp: error writing byte at addr=%08lx status=%08lx\n", adr, status.x[0]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700387
Richard Purdieee2d49d2005-11-29 14:28:31 +0000388 sharp_send_cmd(map, CMD_CLEAR_STATUS, adr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700389 }
Richard Purdieee2d49d2005-11-29 14:28:31 +0000390 sharp_send_cmd(map, CMD_RESET, adr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700391 chip->state = FL_READY;
392
393 wake_up(&chip->wq);
394 spin_unlock_bh(chip->mutex);
395
396 return 0;
397}
398
399static int sharp_erase(struct mtd_info *mtd, struct erase_info *instr)
400{
401 struct map_info *map = mtd->priv;
402 struct sharp_info *sharp = map->fldrv_priv;
403 unsigned long adr,len;
404 int chipnum, ret=0;
405
406//printk("sharp_erase()\n");
407 if(instr->addr & (mtd->erasesize - 1))
408 return -EINVAL;
409 if(instr->len & (mtd->erasesize - 1))
410 return -EINVAL;
411 if(instr->len + instr->addr > mtd->size)
412 return -EINVAL;
413
414 chipnum = instr->addr >> sharp->chipshift;
415 adr = instr->addr & ((1<<sharp->chipshift)-1);
416 len = instr->len;
417
418 while(len){
419 ret = sharp_erase_oneblock(map, &sharp->chips[chipnum], adr);
420 if(ret)return ret;
421
422 adr += mtd->erasesize;
423 len -= mtd->erasesize;
424 if(adr >> sharp->chipshift){
425 adr = 0;
426 chipnum++;
427 if(chipnum>=sharp->numchips)
428 break;
429 }
430 }
431
432 instr->state = MTD_ERASE_DONE;
433 mtd_erase_callback(instr);
434
435 return 0;
436}
437
438static int sharp_do_wait_for_ready(struct map_info *map, struct flchip *chip,
439 unsigned long adr)
440{
441 int ret;
442 unsigned long timeo;
Richard Purdieee2d49d2005-11-29 14:28:31 +0000443 map_word status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700444 DECLARE_WAITQUEUE(wait, current);
445
Richard Purdieee2d49d2005-11-29 14:28:31 +0000446 sharp_send_cmd(map, CMD_READ_STATUS, adr);
447 status = map_read(map, adr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700448
449 timeo = jiffies + HZ;
450
451 while(time_before(jiffies, timeo)){
Richard Purdieee2d49d2005-11-29 14:28:31 +0000452 sharp_send_cmd(map, CMD_READ_STATUS, adr);
453 status = map_read(map, adr);
454 if((status.x[0] & SR_READY)==SR_READY){
Linus Torvalds1da177e2005-04-16 15:20:36 -0700455 ret = 0;
456 goto out;
457 }
458 set_current_state(TASK_INTERRUPTIBLE);
459 add_wait_queue(&chip->wq, &wait);
460
461 //spin_unlock_bh(chip->mutex);
462
463 schedule_timeout(1);
464 schedule();
465 remove_wait_queue(&chip->wq, &wait);
466
467 //spin_lock_bh(chip->mutex);
Thomas Gleixner1f948b42005-11-07 11:15:37 +0000468
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469 if (signal_pending(current)){
470 ret = -EINTR;
471 goto out;
472 }
Thomas Gleixner1f948b42005-11-07 11:15:37 +0000473
Linus Torvalds1da177e2005-04-16 15:20:36 -0700474 }
475 ret = -ETIME;
476out:
477 return ret;
478}
479
480static int sharp_erase_oneblock(struct map_info *map, struct flchip *chip,
481 unsigned long adr)
482{
483 int ret;
484 //int timeo;
Richard Purdieee2d49d2005-11-29 14:28:31 +0000485 map_word status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700486 //int i;
487
488//printk("sharp_erase_oneblock()\n");
489
490#ifdef AUTOUNLOCK
491 /* This seems like a good place to do an unlock */
492 sharp_unlock_oneblock(map,chip,adr);
493#endif
494
Richard Purdieee2d49d2005-11-29 14:28:31 +0000495 sharp_send_cmd(map, CMD_BLOCK_ERASE_1, adr);
496 sharp_send_cmd(map, CMD_BLOCK_ERASE_2, adr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700497
498 chip->state = FL_ERASING;
499
500 ret = sharp_do_wait_for_ready(map,chip,adr);
501 if(ret<0)return ret;
502
Richard Purdieee2d49d2005-11-29 14:28:31 +0000503 sharp_send_cmd(map, CMD_READ_STATUS, adr);
504 status = map_read(map, adr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700505
Richard Purdieee2d49d2005-11-29 14:28:31 +0000506 if(!(status.x[0] & SR_ERRORS)){
507 sharp_send_cmd(map, CMD_RESET, adr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700508 chip->state = FL_READY;
509 //spin_unlock_bh(chip->mutex);
510 return 0;
511 }
512
Richard Purdieee2d49d2005-11-29 14:28:31 +0000513 printk("sharp: error erasing block at addr=%08lx status=%08lx\n", adr, status.x[0]);
514 sharp_send_cmd(map, CMD_CLEAR_STATUS, adr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700515
516 //spin_unlock_bh(chip->mutex);
517
518 return -EIO;
519}
520
521#ifdef AUTOUNLOCK
522static void sharp_unlock_oneblock(struct map_info *map, struct flchip *chip,
523 unsigned long adr)
524{
525 int i;
Richard Purdieee2d49d2005-11-29 14:28:31 +0000526 map_word status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700527
Richard Purdieee2d49d2005-11-29 14:28:31 +0000528 sharp_send_cmd(map, CMD_CLEAR_BLOCK_LOCKS_1, adr);
529 sharp_send_cmd(map, CMD_CLEAR_BLOCK_LOCKS_2, adr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700530
531 udelay(100);
532
Richard Purdieee2d49d2005-11-29 14:28:31 +0000533 status = map_read(map, adr);
534 printk("status=%08lx\n", status.x[0]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700535
536 for(i=0;i<1000;i++){
Richard Purdieee2d49d2005-11-29 14:28:31 +0000537 //sharp_send_cmd(map, CMD_READ_STATUS, adr);
538 status = map_read(map, adr);
539 if((status.x[0] & SR_READY) == SR_READY)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700540 break;
541 udelay(100);
542 }
543 if(i==1000){
544 printk("sharp: timed out unlocking block\n");
545 }
546
Richard Purdieee2d49d2005-11-29 14:28:31 +0000547 if(!(status.x[0] & SR_ERRORS)){
548 sharp_send_cmd(map, CMD_RESET, adr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700549 chip->state = FL_READY;
550 return;
551 }
552
Richard Purdieee2d49d2005-11-29 14:28:31 +0000553 printk("sharp: error unlocking block at addr=%08lx status=%08lx\n", adr, status.x[0]);
554 sharp_send_cmd(map, CMD_CLEAR_STATUS, adr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700555}
556#endif
557
558static void sharp_sync(struct mtd_info *mtd)
559{
560 //printk("sharp_sync()\n");
561}
562
563static int sharp_suspend(struct mtd_info *mtd)
564{
565 printk("sharp_suspend()\n");
566 return -EINVAL;
567}
568
569static void sharp_resume(struct mtd_info *mtd)
570{
571 printk("sharp_resume()\n");
Thomas Gleixner1f948b42005-11-07 11:15:37 +0000572
Linus Torvalds1da177e2005-04-16 15:20:36 -0700573}
574
575static void sharp_destroy(struct mtd_info *mtd)
576{
577 printk("sharp_destroy()\n");
578
579}
580
Adrian Bunk0500abf2006-03-31 02:29:42 -0800581static int __init sharp_probe_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700582{
583 printk("MTD Sharp chip driver <ds@lineo.com>\n");
584
585 register_mtd_chip_driver(&sharp_chipdrv);
586
587 return 0;
588}
589
590static void __exit sharp_probe_exit(void)
591{
592 unregister_mtd_chip_driver(&sharp_chipdrv);
593}
594
595module_init(sharp_probe_init);
596module_exit(sharp_probe_exit);
597
598
599MODULE_LICENSE("GPL");
600MODULE_AUTHOR("David Schleef <ds@schleef.org>");
601MODULE_DESCRIPTION("Old MTD chip driver for pre-CFI Sharp flash chips");