Merge branch 'org.openembedded.dev' of git@git.openembedded.net:openembedded into...
[vuplus_openembedded] / packages / linux / linux-2.6.28 / collie / 0006-add-collie-flash-hack.patch
1 From 6b663bce31fb1e1a78dbca22190e98251628fd4f Mon Sep 17 00:00:00 2001
2 From: Thomas Kunze <thommycheck@gmx.de>
3 Date: Mon, 20 Oct 2008 17:48:10 +0200
4 Subject: [PATCH 06/23] add collie flash hack
5
6 ---
7  arch/arm/mach-sa1100/collie.c |    2 +-
8  drivers/mtd/chips/Kconfig     |    8 +
9  drivers/mtd/chips/Makefile    |    1 +
10  drivers/mtd/chips/sharp.c     |  645 +++++++++++++++++++++++++++++++++++++++++
11  drivers/mtd/maps/Kconfig      |    2 +-
12  5 files changed, 656 insertions(+), 2 deletions(-)
13  create mode 100644 drivers/mtd/chips/sharp.c
14
15 diff --git a/arch/arm/mach-sa1100/collie.c b/arch/arm/mach-sa1100/collie.c
16 index 8cf267f..ec673b8 100644
17 --- a/arch/arm/mach-sa1100/collie.c
18 +++ b/arch/arm/mach-sa1100/collie.c
19 @@ -222,7 +222,7 @@ static void collie_flash_exit(void)
20         gpio_free(COLLIE_GPIO_VPEN);
21  }
22  static struct flash_platform_data collie_flash_data = {
23 -       .map_name       = "cfi_probe",
24 +       .map_name       = "sharp",
25         .init           = collie_flash_init,
26         .set_vpp        = collie_set_vpp,
27         .exit           = collie_flash_exit,
28 diff --git a/drivers/mtd/chips/Kconfig b/drivers/mtd/chips/Kconfig
29 index 9408099..2dcbd03 100644
30 --- a/drivers/mtd/chips/Kconfig
31 +++ b/drivers/mtd/chips/Kconfig
32 @@ -241,5 +241,13 @@ config MTD_XIP
33           used for XIP purposes.  If you're not sure what this is all about
34           then say N.
35  
36 +config MTD_SHARP
37 +        tristate "pre-CFI Sharp chip support"
38 +        depends on MTD
39 +        help
40 +          This option enables support for flash chips using Sharp-compatible
41 +          commands, including some which are not CFI-compatible and hence
42 +          cannot be used with the CONFIG_MTD_CFI_INTELxxx options.
43 +
44  endmenu
45  
46 diff --git a/drivers/mtd/chips/Makefile b/drivers/mtd/chips/Makefile
47 index 3658241..7283c57 100644
48 --- a/drivers/mtd/chips/Makefile
49 +++ b/drivers/mtd/chips/Makefile
50 @@ -12,4 +12,5 @@ obj-$(CONFIG_MTD_GEN_PROBE)   += gen_probe.o
51  obj-$(CONFIG_MTD_JEDECPROBE)   += jedec_probe.o
52  obj-$(CONFIG_MTD_RAM)          += map_ram.o
53  obj-$(CONFIG_MTD_ROM)          += map_rom.o
54 +obj-$(CONFIG_MTD_SHARP)         += sharp.o
55  obj-$(CONFIG_MTD_ABSENT)       += map_absent.o
56 diff --git a/drivers/mtd/chips/sharp.c b/drivers/mtd/chips/sharp.c
57 new file mode 100644
58 index 0000000..046b964
59 --- /dev/null
60 +++ b/drivers/mtd/chips/sharp.c
61 @@ -0,0 +1,645 @@
62 +/*
63 + * MTD chip driver for pre-CFI Sharp flash chips
64 + *
65 + * Copyright 2000,2001 David A. Schleef <ds@schleef.org>
66 + *           2000,2001 Lineo, Inc.
67 + *
68 + * $Id: sharp.c,v 1.17 2005/11/29 14:28:28 gleixner Exp $
69 + *
70 + * Devices supported:
71 + *   LH28F016SCT Symmetrical block flash memory, 2Mx8
72 + *   LH28F008SCT Symmetrical block flash memory, 1Mx8
73 + *
74 + * Documentation:
75 + *   http://www.sharpmeg.com/datasheets/memic/flashcmp/
76 + *   http://www.sharpmeg.com/datasheets/memic/flashcmp/01symf/16m/016sctl9.pdf
77 + *   016sctl9.pdf
78 + *
79 + * Limitations:
80 + *   This driver only supports 4x1 arrangement of chips.
81 + *   Not tested on anything but PowerPC.
82 + */
83 +
84 +#include <linux/kernel.h>
85 +#include <linux/module.h>
86 +#include <linux/types.h>
87 +#include <linux/sched.h>
88 +#include <linux/errno.h>
89 +#include <linux/init.h>
90 +#include <linux/interrupt.h>
91 +#include <linux/mtd/map.h>
92 +#include <linux/mtd/mtd.h>
93 +#include <linux/mtd/cfi.h>
94 +#include <linux/delay.h>
95 +#include <linux/init.h>
96 +
97 +#define CMD_RESET              0xffffffff
98 +#define CMD_READ_ID            0x90909090
99 +#define CMD_READ_STATUS                0x70707070
100 +#define CMD_CLEAR_STATUS       0x50505050
101 +#define CMD_BLOCK_ERASE_1      0x20202020
102 +#define CMD_BLOCK_ERASE_2      0xd0d0d0d0
103 +#define CMD_BYTE_WRITE         0x40404040
104 +#define CMD_SUSPEND            0xb0b0b0b0
105 +#define CMD_RESUME             0xd0d0d0d0
106 +#define CMD_SET_BLOCK_LOCK_1   0x60606060
107 +#define CMD_SET_BLOCK_LOCK_2   0x01010101
108 +#define CMD_SET_MASTER_LOCK_1  0x60606060
109 +#define CMD_SET_MASTER_LOCK_2  0xf1f1f1f1
110 +#define CMD_CLEAR_BLOCK_LOCKS_1        0x60606060
111 +#define CMD_CLEAR_BLOCK_LOCKS_2        0xd0d0d0d0
112 +
113 +#define SR_READY               0x80808080 // 1 = ready
114 +#define SR_ERASE_SUSPEND       0x40404040 // 1 = block erase suspended
115 +#define SR_ERROR_ERASE         0x20202020 // 1 = error in block erase or clear lock bits
116 +#define SR_ERROR_WRITE         0x10101010 // 1 = error in byte write or set lock bit
117 +#define        SR_VPP                  0x08080808 // 1 = Vpp is low
118 +#define SR_WRITE_SUSPEND       0x04040404 // 1 = byte write suspended
119 +#define SR_PROTECT             0x02020202 // 1 = lock bit set
120 +#define SR_RESERVED            0x01010101
121 +
122 +#define SR_ERRORS (SR_ERROR_ERASE|SR_ERROR_WRITE|SR_VPP|SR_PROTECT)
123 +
124 +#define BLOCK_MASK             0xfffe0000
125 +
126 +/* Configuration options */
127 +
128 +#define AUTOUNLOCK  /* automatically unlocks blocks before erasing */
129 +
130 +static struct mtd_info *sharp_probe(struct map_info *);
131 +
132 +static int sharp_probe_map(struct map_info *map, struct mtd_info *mtd);
133 +
134 +static int sharp_read(struct mtd_info *mtd, loff_t from, size_t len,
135 +       size_t *retlen, u_char *buf);
136 +static int sharp_write(struct mtd_info *mtd, loff_t from, size_t len,
137 +       size_t *retlen, const u_char *buf);
138 +static int sharp_erase(struct mtd_info *mtd, struct erase_info *instr);
139 +static void sharp_sync(struct mtd_info *mtd);
140 +static int sharp_suspend(struct mtd_info *mtd);
141 +static void sharp_resume(struct mtd_info *mtd);
142 +static void sharp_destroy(struct mtd_info *mtd);
143 +
144 +static int sharp_write_oneword(struct map_info *map, struct flchip *chip,
145 +       unsigned long adr, __u32 datum);
146 +static int sharp_erase_oneblock(struct map_info *map, struct flchip *chip,
147 +       unsigned long adr);
148 +#ifdef AUTOUNLOCK
149 +static inline void sharp_unlock_oneblock(struct map_info *map, struct flchip *chip,
150 +       unsigned long adr);
151 +#endif
152 +
153 +
154 +struct sharp_info{
155 +       struct flchip *chip;
156 +       int bogus;
157 +       int chipshift;
158 +       int numchips;
159 +       struct flchip chips[1];
160 +};
161 +
162 +static void sharp_destroy(struct mtd_info *mtd);
163 +
164 +static struct mtd_chip_driver sharp_chipdrv = {
165 +       .probe          = sharp_probe,
166 +       .destroy        = sharp_destroy,
167 +       .name           = "sharp",
168 +       .module         = THIS_MODULE
169 +};
170 +
171 +static void sharp_udelay(unsigned long i) {
172 +       if (in_interrupt()) {
173 +               udelay(i);
174 +       } else {
175 +               schedule();
176 +       }
177 +}
178 +
179 +static struct mtd_info *sharp_probe(struct map_info *map)
180 +{
181 +       struct mtd_info *mtd = NULL;
182 +       struct sharp_info *sharp = NULL;
183 +       int width;
184 +
185 +       mtd = kzalloc(sizeof(*mtd), GFP_KERNEL);
186 +       if(!mtd)
187 +               return NULL;
188 +
189 +       sharp = kzalloc(sizeof(*sharp), GFP_KERNEL);
190 +       if(!sharp) {
191 +               kfree(mtd);
192 +               return NULL;
193 +       }
194 +
195 +       width = sharp_probe_map(map,mtd);
196 +       if(!width){
197 +               kfree(mtd);
198 +               kfree(sharp);
199 +               return NULL;
200 +       }
201 +
202 +       mtd->priv = map;
203 +       mtd->type = MTD_NORFLASH;
204 +       mtd->erase = sharp_erase;
205 +       mtd->read = sharp_read;
206 +       mtd->write = sharp_write;
207 +       mtd->sync = sharp_sync;
208 +       mtd->suspend = sharp_suspend;
209 +       mtd->resume = sharp_resume;
210 +       mtd->flags = MTD_CAP_NORFLASH;
211 +       mtd->writesize = 1;
212 +       mtd->name = map->name;
213 +
214 +       sharp->chipshift = 24;
215 +       sharp->numchips = 1;
216 +       sharp->chips[0].start = 0;
217 +       sharp->chips[0].state = FL_READY;
218 +       sharp->chips[0].mutex = &sharp->chips[0]._spinlock;
219 +       sharp->chips[0].word_write_time = 0;
220 +       init_waitqueue_head(&sharp->chips[0].wq);
221 +       spin_lock_init(&sharp->chips[0]._spinlock);
222 +
223 +       map->fldrv = &sharp_chipdrv;
224 +       map->fldrv_priv = sharp;
225 +
226 +       __module_get(THIS_MODULE);
227 +       return mtd;
228 +}
229 +
230 +static inline void sharp_send_cmd(struct map_info *map, unsigned long cmd, unsigned long adr)
231 +{
232 +       map_word map_cmd;
233 +       map_cmd.x[0] = cmd;
234 +       map_write(map, map_cmd, adr);
235 +}
236 +
237 +static int sharp_probe_map(struct map_info *map,struct mtd_info *mtd)
238 +{
239 +       map_word tmp, read0, read4;
240 +       unsigned long base = 0;
241 +       int width = 4;
242 +
243 +       tmp = map_read(map, base+0);
244 +
245 +       sharp_send_cmd(map, CMD_READ_ID, base+0);
246 +
247 +       read0 = map_read(map, base+0);
248 +       read4 = map_read(map, base+4);
249 +       if (read0.x[0] == 0x00b000b0) {
250 +               printk("Sharp chip, %lx, %lx, width = %d\n", read0.x[0], read4.x[0], width);
251 +               /* Prints b000b0, b000b0, width = 4 on collie */
252 +               switch(read4.x[0]){
253 +               case 0xaaaaaaaa:
254 +               case 0xa0a0a0a0:
255 +                       /* aa - LH28F016SCT-L95 2Mx8, 32 64k blocks*/
256 +                       /* a0 - LH28F016SCT-Z4  2Mx8, 32 64k blocks*/
257 +                       mtd->erasesize = 0x10000 * width;
258 +                       mtd->size = 0x200000 * width;
259 +                       return width;
260 +               case 0xa6a6a6a6:
261 +                       /* a6 - LH28F008SCT-L12 1Mx8, 16 64k blocks*/
262 +                       /* a6 - LH28F008SCR-L85 1Mx8, 16 64k blocks*/
263 +                       mtd->erasesize = 0x10000 * width;
264 +                       mtd->size = 0x100000 * width;
265 +                       return width;
266 +               case 0x00b000b0:
267 +                       /* a6 - LH28F640BFHE 8 64k * 2 chip blocks*/
268 +                       mtd->erasesize = 0x10000 * width / 2;
269 +                       mtd->size = 0x800000 * width / 2;
270 +                       return width;
271 +               default:
272 +                       printk("Sort-of looks like sharp flash, 0x%08lx 0x%08lx\n",
273 +                               read0.x[0], read4.x[0]);
274 +               }
275 +       } else if ((map_read(map, base+0).x[0] == CMD_READ_ID)){
276 +               /* RAM, probably */
277 +               printk("Looks like RAM\n");
278 +               map_write(map, tmp, base+0);
279 +       }else{
280 +               printk("Doesn't look like sharp flash, 0x%08lx 0x%08lx\n",
281 +                       read0.x[0], read4.x[0]);
282 +       }
283 +
284 +       return 0;
285 +}
286 +
287 +/* This function returns with the chip->mutex lock held. */
288 +static int sharp_wait(struct map_info *map, struct flchip *chip)
289 +{
290 +       map_word status;
291 +       unsigned long timeo = jiffies + HZ;
292 +       DECLARE_WAITQUEUE(wait, current);
293 +       int adr = 0;
294 +
295 +retry:
296 +       spin_lock_bh(chip->mutex);
297 +
298 +       switch (chip->state) {
299 +       case FL_READY:
300 +               sharp_send_cmd(map, CMD_READ_STATUS, adr);
301 +               chip->state = FL_STATUS;
302 +       case FL_STATUS:
303 +               status = map_read(map, adr);
304 +               if ((status.x[0] & SR_READY) == SR_READY)
305 +                       break;
306 +               spin_unlock_bh(chip->mutex);
307 +               if (time_after(jiffies, timeo)) {
308 +                       printk("Waiting for chip to be ready timed out in erase\n");
309 +                       return -EIO;
310 +               }
311 +               sharp_udelay(1);
312 +               goto retry;
313 +       default:
314 +               set_current_state(TASK_INTERRUPTIBLE);
315 +               add_wait_queue(&chip->wq, &wait);
316 +
317 +               spin_unlock_bh(chip->mutex);
318 +
319 +               sharp_udelay(1);
320 +
321 +               set_current_state(TASK_RUNNING);
322 +               remove_wait_queue(&chip->wq, &wait);
323 +
324 +               if(signal_pending(current))
325 +                       return -EINTR;
326 +
327 +               timeo = jiffies + HZ;
328 +
329 +               goto retry;
330 +       }
331 +
332 +       sharp_send_cmd(map, CMD_RESET, adr);
333 +
334 +       chip->state = FL_READY;
335 +
336 +       return 0;
337 +}
338 +
339 +static void sharp_release(struct flchip *chip)
340 +{
341 +       wake_up(&chip->wq);
342 +       spin_unlock_bh(chip->mutex);
343 +}
344 +
345 +static int sharp_read(struct mtd_info *mtd, loff_t from, size_t len,
346 +       size_t *retlen, u_char *buf)
347 +{
348 +       struct map_info *map = mtd->priv;
349 +       struct sharp_info *sharp = map->fldrv_priv;
350 +       int chipnum;
351 +       int ret = 0;
352 +       int ofs = 0;
353 +
354 +       chipnum = (from >> sharp->chipshift);
355 +       ofs = from & ((1 << sharp->chipshift)-1);
356 +
357 +       *retlen = 0;
358 +
359 +       while(len){
360 +               unsigned long thislen;
361 +
362 +               if(chipnum>=sharp->numchips)
363 +                       break;
364 +
365 +               thislen = len;
366 +               if(ofs+thislen >= (1<<sharp->chipshift))
367 +                       thislen = (1<<sharp->chipshift) - ofs;
368 +
369 +               ret = sharp_wait(map,&sharp->chips[chipnum]);
370 +               if(ret<0)
371 +                       break;
372 +
373 +               map_copy_from(map,buf,ofs,thislen);
374 +
375 +               sharp_release(&sharp->chips[chipnum]);
376 +
377 +               *retlen += thislen;
378 +               len -= thislen;
379 +               buf += thislen;
380 +
381 +               ofs = 0;
382 +               chipnum++;
383 +       }
384 +       return ret;
385 +}
386 +
387 +static int sharp_write(struct mtd_info *mtd, loff_t to, size_t len,
388 +       size_t *retlen, const u_char *buf)
389 +{
390 +       struct map_info *map = mtd->priv;
391 +       struct sharp_info *sharp = map->fldrv_priv;
392 +       int ret = 0;
393 +       int i,j;
394 +       int chipnum;
395 +       unsigned long ofs;
396 +       union { u32 l; unsigned char uc[4]; } tbuf;
397 +
398 +       *retlen = 0;
399 +
400 +       while(len){
401 +               tbuf.l = 0xffffffff;
402 +               chipnum = to >> sharp->chipshift;
403 +               ofs = to & ((1<<sharp->chipshift)-1);
404 +
405 +               j=0;
406 +               for(i=ofs&3;i<4 && len;i++){
407 +                       tbuf.uc[i] = *buf;
408 +                       buf++;
409 +                       to++;
410 +                       len--;
411 +                       j++;
412 +               }
413 +               sharp_write_oneword(map, &sharp->chips[chipnum], ofs&~3, tbuf.l);
414 +               if(ret<0)
415 +                       return ret;
416 +               (*retlen)+=j;
417 +       }
418 +
419 +       return 0;
420 +}
421 +
422 +static int sharp_write_oneword(struct map_info *map, struct flchip *chip,
423 +       unsigned long adr, __u32 datum)
424 +{
425 +       int ret;
426 +       int try;
427 +       int i;
428 +       map_word data, status;
429 +
430 +       status.x[0] = 0;
431 +       ret = sharp_wait(map,chip);
432 +       if (ret < 0)
433 +               return ret;
434 +
435 +       for (try=0; try<10; try++) {
436 +               long timeo;
437 +
438 +               sharp_send_cmd(map, CMD_BYTE_WRITE, adr);
439 +               /* cpu_to_le32 -> hack to fix the writel be->le conversion */
440 +               data.x[0] = cpu_to_le32(datum);
441 +               map_write(map, data, adr);
442 +
443 +               chip->state = FL_WRITING;
444 +               timeo = jiffies + (HZ/2);
445 +
446 +               sharp_send_cmd(map, CMD_READ_STATUS, adr);
447 +               for(i=0;i<100;i++){
448 +                       status = map_read(map, adr);
449 +                       if((status.x[0] & SR_READY) == SR_READY)
450 +                               break;
451 +               }
452 +#ifdef AUTOUNLOCK
453 +               if (status.x[0] & SR_PROTECT) { /* lock block */
454 +                       sharp_send_cmd(map, CMD_CLEAR_STATUS, adr);
455 +                       sharp_unlock_oneblock(map,chip,adr);
456 +                       sharp_send_cmd(map, CMD_CLEAR_STATUS, adr);
457 +                       sharp_send_cmd(map, CMD_RESET, adr);
458 +                       continue;
459 +               }
460 +#endif
461 +               if(i==100){
462 +                       printk("sharp: timed out writing\n");
463 +               }
464 +
465 +               if (!(status.x[0] & SR_ERRORS))
466 +                       break;
467 +
468 +               printk("sharp: error writing byte at addr=%08lx status=%08lx\n", adr, status.x[0]);
469 +
470 +               sharp_send_cmd(map, CMD_CLEAR_STATUS, adr);
471 +       }
472 +       sharp_send_cmd(map, CMD_RESET, adr);
473 +       chip->state = FL_READY;
474 +
475 +       sharp_release(chip);
476 +
477 +       return 0;
478 +}
479 +
480 +static int sharp_erase(struct mtd_info *mtd, struct erase_info *instr)
481 +{
482 +       struct map_info *map = mtd->priv;
483 +       struct sharp_info *sharp = map->fldrv_priv;
484 +       unsigned long adr,len;
485 +       int chipnum, ret=0;
486 +
487 +       if(instr->addr & (mtd->erasesize - 1))
488 +               return -EINVAL;
489 +       if(instr->len & (mtd->erasesize - 1))
490 +               return -EINVAL;
491 +       if(instr->len + instr->addr > mtd->size)
492 +               return -EINVAL;
493 +
494 +       chipnum = instr->addr >> sharp->chipshift;
495 +       adr = instr->addr & ((1<<sharp->chipshift)-1);
496 +       len = instr->len;
497 +
498 +       while(len){
499 +               ret = sharp_erase_oneblock(map, &sharp->chips[chipnum], adr);
500 +               if(ret)return ret;
501 +
502 +               if (adr >= 0xfe0000) {
503 +                       adr += mtd->erasesize / 8;
504 +                       len -= mtd->erasesize / 8;
505 +               } else {
506 +                       adr += mtd->erasesize;
507 +                       len -= mtd->erasesize;
508 +               }
509 +               if(adr >> sharp->chipshift){
510 +                       adr = 0;
511 +                       chipnum++;
512 +                       if(chipnum>=sharp->numchips)
513 +                               break;
514 +               }
515 +       }
516 +
517 +       instr->state = MTD_ERASE_DONE;
518 +       mtd_erase_callback(instr);
519 +
520 +       return 0;
521 +}
522 +
523 +static inline int sharp_do_wait_for_ready(struct map_info *map, struct flchip *chip,
524 +       unsigned long adr)
525 +{
526 +       int ret;
527 +       unsigned long timeo;
528 +       map_word status;
529 +       DECLARE_WAITQUEUE(wait, current);
530 +
531 +       sharp_send_cmd(map, CMD_READ_STATUS, adr);
532 +       status = map_read(map, adr);
533 +
534 +       timeo = jiffies + HZ * 10;
535 +
536 +       while (time_before(jiffies, timeo)) {
537 +               sharp_send_cmd(map, CMD_READ_STATUS, adr);
538 +               status = map_read(map, adr);
539 +               if ((status.x[0] & SR_READY) == SR_READY) {
540 +                       ret = 0;
541 +                       goto out;
542 +               }
543 +               set_current_state(TASK_INTERRUPTIBLE);
544 +               add_wait_queue(&chip->wq, &wait);
545 +
546 +               spin_unlock_bh(chip->mutex);
547 +
548 +               schedule_timeout(1);
549 +               schedule();
550 +
551 +               spin_lock_bh(chip->mutex);
552 +
553 +               remove_wait_queue(&chip->wq, &wait);
554 +               set_current_state(TASK_RUNNING);
555 +       }
556 +       ret = -ETIME;
557 +out:
558 +       return ret;
559 +}
560 +
561 +static int sharp_erase_oneblock(struct map_info *map, struct flchip *chip,
562 +       unsigned long adr)
563 +{
564 +       int ret;
565 +       map_word status;
566 +
567 +       ret = sharp_wait(map,chip);
568 +       if (ret < 0)
569 +               return ret;
570 +
571 +#ifdef AUTOUNLOCK
572 +       /* This seems like a good place to do an unlock */
573 +       sharp_unlock_oneblock(map,chip,adr);
574 +#endif
575 +
576 +       sharp_send_cmd(map, CMD_BLOCK_ERASE_1, adr);
577 +       sharp_send_cmd(map, CMD_BLOCK_ERASE_2, adr);
578 +
579 +       chip->state = FL_ERASING;
580 +
581 +       ret = sharp_do_wait_for_ready(map,chip,adr);
582 +       if(ret<0) {
583 +               spin_unlock_bh(chip->mutex);
584 +               return ret;
585 +       }
586 +
587 +       sharp_send_cmd(map, CMD_READ_STATUS, adr);
588 +       status = map_read(map, adr);
589 +
590 +       if (!(status.x[0] & SR_ERRORS)) {
591 +               sharp_send_cmd(map, CMD_RESET, adr);
592 +               chip->state = FL_READY;
593 +               spin_unlock_bh(chip->mutex);
594 +               return 0;
595 +       }
596 +
597 +       printk("sharp: error erasing block at addr=%08lx status=%08lx\n", adr, status.x[0]);
598 +       sharp_send_cmd(map, CMD_CLEAR_STATUS, adr);
599 +
600 +       sharp_release(chip);
601 +
602 +       return -EIO;
603 +}
604 +
605 +#ifdef AUTOUNLOCK
606 +static inline void sharp_unlock_oneblock(struct map_info *map, struct flchip *chip,
607 +       unsigned long adr)
608 +{
609 +       map_word status;
610 +
611 +       sharp_send_cmd(map, CMD_CLEAR_BLOCK_LOCKS_1, adr & BLOCK_MASK);
612 +       sharp_send_cmd(map, CMD_CLEAR_BLOCK_LOCKS_2, adr & BLOCK_MASK);
613 +
614 +       sharp_do_wait_for_ready(map,chip,adr);
615 +
616 +       status = map_read(map, adr);
617 +
618 +       if (!(status.x[0] & SR_ERRORS)) {
619 +               sharp_send_cmd(map, CMD_RESET, adr);
620 +               chip->state = FL_READY;
621 +               return;
622 +       }
623 +
624 +       printk("sharp: error unlocking block at addr=%08lx status=%08lx\n", adr, status.x[0]);
625 +       sharp_send_cmd(map, CMD_CLEAR_STATUS, adr);
626 +}
627 +#endif
628 +
629 +static void sharp_sync(struct mtd_info *mtd)
630 +{
631 +}
632 +
633 +static int sharp_suspend(struct mtd_info *mtd)
634 +{
635 +       struct map_info *map = mtd->priv;
636 +       struct sharp_info *sharp = map->fldrv_priv;
637 +       int i;
638 +       struct flchip *chip;
639 +       int ret = 0;
640 +
641 +       for (i = 0; !ret && i < sharp->numchips; i++) {
642 +               chip = &sharp->chips[i];
643 +               ret = sharp_wait(map,chip);
644 +
645 +               if (ret) {
646 +                       ret = -EAGAIN;
647 +               } else {
648 +                       chip->state = FL_PM_SUSPENDED;
649 +                       spin_unlock_bh(chip->mutex);
650 +               }
651 +       }
652 +       return ret;
653 +}
654 +
655 +static void sharp_resume(struct mtd_info *mtd)
656 +{
657 +       struct map_info *map = mtd->priv;
658 +       struct sharp_info *sharp = map->fldrv_priv;
659 +       int i;
660 +       struct flchip *chip;
661 +
662 +       for (i = 0; i < sharp->numchips; i++) {
663 +               chip = &sharp->chips[i];
664 +
665 +               spin_lock_bh(chip->mutex);
666 +
667 +               if (chip->state == FL_PM_SUSPENDED) {
668 +                       /* We need to force it back to a known state */
669 +                       sharp_send_cmd(map, CMD_RESET, chip->start);
670 +                       chip->state = FL_READY;
671 +                       wake_up(&chip->wq);
672 +               }
673 +
674 +               spin_unlock_bh(chip->mutex);
675 +       }
676 +}
677 +
678 +static void sharp_destroy(struct mtd_info *mtd)
679 +{
680 +       struct map_info *map = mtd->priv;
681 +       struct sharp_info *sharp = map->fldrv_priv;
682 +
683 +       kfree(sharp);
684 +}
685 +
686 +static int __init sharp_probe_init(void)
687 +{
688 +       printk("MTD Sharp chip driver <ds@lineo.com>\n");
689 +
690 +       register_mtd_chip_driver(&sharp_chipdrv);
691 +
692 +       return 0;
693 +}
694 +
695 +static void __exit sharp_probe_exit(void)
696 +{
697 +       unregister_mtd_chip_driver(&sharp_chipdrv);
698 +}
699 +
700 +module_init(sharp_probe_init);
701 +module_exit(sharp_probe_exit);
702 +
703 +
704 +MODULE_LICENSE("GPL");
705 +MODULE_AUTHOR("David Schleef <ds@schleef.org>");
706 +MODULE_DESCRIPTION("Old MTD chip driver for pre-CFI Sharp flash chips");
707 diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig
708 index 5ea1693..d523464 100644
709 --- a/drivers/mtd/maps/Kconfig
710 +++ b/drivers/mtd/maps/Kconfig
711 @@ -360,7 +360,7 @@ config MTD_CDB89712
712  
713  config MTD_SA1100
714         tristate "CFI Flash device mapped on StrongARM SA11x0"
715 -       depends on MTD_CFI && ARCH_SA1100 && MTD_PARTITIONS
716 +       depends on (MTD_CFI || MTD_SHARP) && ARCH_SA1100 && MTD_PARTITIONS
717         help
718           This enables access to the flash chips on most platforms based on
719           the SA1100 and SA1110, including the Assabet and the Compaq iPAQ.
720 -- 
721 1.5.6.5
722