update brcm-2.4 to 2.4.35.4, integrate new broadcom system code, update broadcom...
[openwrt.git] / target / linux / generic-2.4 / patches / 005-mtd_flashtypes.patch
1 Index: linux-2.4.35.4/drivers/mtd/chips/Config.in
2 ===================================================================
3 --- linux-2.4.35.4.orig/drivers/mtd/chips/Config.in     2007-12-15 05:19:42.454840402 +0100
4 +++ linux-2.4.35.4/drivers/mtd/chips/Config.in  2007-12-15 05:19:50.035272385 +0100
5 @@ -45,6 +45,7 @@
6  dep_tristate '  Support for Intel/Sharp flash chips' CONFIG_MTD_CFI_INTELEXT $CONFIG_MTD_GEN_PROBE
7  dep_tristate '  Support for AMD/Fujitsu flash chips' CONFIG_MTD_CFI_AMDSTD $CONFIG_MTD_GEN_PROBE
8  dep_tristate '  Support for ST (Advanced Architecture) flash chips' CONFIG_MTD_CFI_STAA $CONFIG_MTD_GEN_PROBE
9 +dep_tristate '  Support for SST flash chips' CONFIG_MTD_CFI_SSTSTD $CONFIG_MTD_GEN_PROBE
10  
11  dep_tristate '  Support for RAM chips in bus mapping' CONFIG_MTD_RAM $CONFIG_MTD
12  dep_tristate '  Support for ROM chips in bus mapping' CONFIG_MTD_ROM $CONFIG_MTD
13 Index: linux-2.4.35.4/drivers/mtd/chips/Makefile
14 ===================================================================
15 --- linux-2.4.35.4.orig/drivers/mtd/chips/Makefile      2007-12-15 05:19:42.462840857 +0100
16 +++ linux-2.4.35.4/drivers/mtd/chips/Makefile   2007-12-15 05:19:50.039272613 +0100
17 @@ -18,6 +18,7 @@
18  obj-$(CONFIG_MTD_AMDSTD)       += amd_flash.o 
19  obj-$(CONFIG_MTD_CFI)          += cfi_probe.o
20  obj-$(CONFIG_MTD_CFI_STAA)     += cfi_cmdset_0020.o
21 +obj-$(CONFIG_MTD_CFI_SSTSTD)   += cfi_cmdset_0701.o
22  obj-$(CONFIG_MTD_CFI_AMDSTD)   += cfi_cmdset_0002.o
23  obj-$(CONFIG_MTD_CFI_INTELEXT) += cfi_cmdset_0001.o
24  obj-$(CONFIG_MTD_GEN_PROBE)    += gen_probe.o
25 Index: linux-2.4.35.4/drivers/mtd/chips/cfi_cmdset_0701.c
26 ===================================================================
27 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
28 +++ linux-2.4.35.4/drivers/mtd/chips/cfi_cmdset_0701.c  2007-12-15 05:19:50.047273069 +0100
29 @@ -0,0 +1,855 @@
30 +/*
31 + * Common Flash Interface support:
32 + *   SST Standard Vendor Command Set (ID 0x0701)
33 + *
34 + * Copyright (C) 2000 Crossnet Co. <info@crossnet.co.jp>
35 + *
36 + * 2_by_8 routines added by Simon Munton
37 + *
38 + * This code is GPL
39 + *
40 + * $Id: cfi_cmdset_0701.c,v 1.1 2005/03/16 13:50:00 wbx Exp $
41 + *
42 + */
43 +
44 +#include <linux/module.h>
45 +#include <linux/types.h>
46 +#include <linux/kernel.h>
47 +#include <linux/sched.h>
48 +#include <asm/io.h>
49 +#include <asm/byteorder.h>
50 +
51 +#include <linux/errno.h>
52 +#include <linux/slab.h>
53 +#include <linux/delay.h>
54 +#include <linux/interrupt.h>
55 +#include <linux/mtd/map.h>
56 +#include <linux/mtd/cfi.h>
57 +
58 +static int cfi_sststd_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
59 +static int cfi_sststd_write(struct mtd_info *, loff_t, size_t, size_t *, const u_char *);
60 +static int cfi_sststd_erase_onesize(struct mtd_info *, struct erase_info *);
61 +static int cfi_sststd_erase_varsize(struct mtd_info *, struct erase_info *);
62 +static void cfi_sststd_sync (struct mtd_info *);
63 +static int cfi_sststd_suspend (struct mtd_info *);
64 +static void cfi_sststd_resume (struct mtd_info *);
65 +
66 +static void cfi_sststd_destroy(struct mtd_info *);
67 +
68 +struct mtd_info *cfi_cmdset_0701(struct map_info *, int);
69 +static struct mtd_info *cfi_sststd_setup (struct map_info *);
70 +
71 +
72 +static struct mtd_chip_driver cfi_sststd_chipdrv = {
73 +       probe: NULL, /* Not usable directly */
74 +       destroy: cfi_sststd_destroy,
75 +       name: "cfi_cmdset_0701",
76 +       module: THIS_MODULE
77 +};
78 +
79 +struct mtd_info *cfi_cmdset_0701(struct map_info *map, int primary)
80 +{
81 +       struct cfi_private *cfi = map->fldrv_priv;
82 +       int ofs_factor = cfi->interleave * cfi->device_type;
83 +       int i;
84 +       __u8 major, minor;
85 +       __u32 base = cfi->chips[0].start;
86 +
87 +       if (cfi->cfi_mode==1){
88 +               __u16 adr = primary?cfi->cfiq->P_ADR:cfi->cfiq->A_ADR;
89 +
90 +               cfi_send_gen_cmd(0xAA, 0x5555, base, map, cfi, cfi->device_type, NULL);
91 +               cfi_send_gen_cmd(0x55, 0x2AAA, base, map, cfi, cfi->device_type, NULL);
92 +               cfi_send_gen_cmd(0x98, 0x5555, base, map, cfi, cfi->device_type, NULL);
93 +               
94 +               major = cfi_read_query(map, base + (adr+3)*ofs_factor);
95 +               minor = cfi_read_query(map, base + (adr+4)*ofs_factor);
96 +               
97 +               printk(" SST Query Table v%c.%c at 0x%4.4X\n",
98 +                      major, minor, adr);
99 +               cfi_send_gen_cmd(0xf0, 0x5555, base, map, cfi, cfi->device_type, NULL);
100 +               
101 +               cfi_send_gen_cmd(0xAA, 0x5555, base, map, cfi, cfi->device_type, NULL);
102 +               cfi_send_gen_cmd(0x55, 0x2AAA, base, map, cfi, cfi->device_type, NULL);
103 +               cfi_send_gen_cmd(0x90, 0x5555, base, map, cfi, cfi->device_type, NULL);
104 +               cfi->mfr = cfi_read_query(map, base);
105 +               cfi->id = cfi_read_query(map, base + ofs_factor);
106 +
107 +               cfi_send_gen_cmd(0xAA, 0x5555, base, map, cfi, cfi->device_type, NULL);
108 +               cfi_send_gen_cmd(0x55, 0x2AAA, base, map, cfi, cfi->device_type, NULL);
109 +               cfi_send_gen_cmd(0x98, 0x5555, base, map, cfi, cfi->device_type, NULL);
110 +               
111 +               switch (cfi->device_type) {
112 +               case CFI_DEVICETYPE_X16:
113 +                       cfi->addr_unlock1 = 0x5555;
114 +                       cfi->addr_unlock2 = 0x2AAA;
115 +                       break;
116 +               default:
117 +                       printk(KERN_NOTICE "Eep. Unknown cfi_cmdset_0701 device type %d\n", cfi->device_type);
118 +                       return NULL;
119 +               }
120 +       } /* CFI mode */
121 +
122 +       for (i=0; i< cfi->numchips; i++) {
123 +               cfi->chips[i].word_write_time = 1<<cfi->cfiq->WordWriteTimeoutTyp;
124 +               cfi->chips[i].buffer_write_time = 1<<cfi->cfiq->BufWriteTimeoutTyp;
125 +               cfi->chips[i].erase_time = 1<<cfi->cfiq->BlockEraseTimeoutTyp;
126 +       }               
127 +       
128 +       map->fldrv = &cfi_sststd_chipdrv;
129 +       MOD_INC_USE_COUNT;
130 +
131 +       cfi_send_gen_cmd(0xf0, 0x5555, base, map, cfi, cfi->device_type, NULL);
132 +       return cfi_sststd_setup(map);
133 +}
134 +
135 +static struct mtd_info *cfi_sststd_setup(struct map_info *map)
136 +{
137 +       struct cfi_private *cfi = map->fldrv_priv;
138 +       struct mtd_info *mtd;
139 +       unsigned long devsize = (1<<cfi->cfiq->DevSize) * cfi->interleave;
140 +
141 +       mtd = kmalloc(sizeof(*mtd), GFP_KERNEL);
142 +       printk("number of %s chips: %d\n", (cfi->cfi_mode)?"JEDEC":"CFI",cfi->numchips);
143 +
144 +       if (!mtd) {
145 +         printk("Failed to allocate memory for MTD device\n");
146 +         kfree(cfi->cmdset_priv);
147 +         return NULL;
148 +       }
149 +
150 +       memset(mtd, 0, sizeof(*mtd));
151 +       mtd->priv = map;
152 +       mtd->type = MTD_NORFLASH;
153 +       /* Also select the correct geometry setup too */ 
154 +       mtd->size = devsize * cfi->numchips;
155 +       
156 +       if (cfi->cfiq->NumEraseRegions == 1) {
157 +               /* No need to muck about with multiple erase sizes */
158 +               mtd->erasesize = ((cfi->cfiq->EraseRegionInfo[0] >> 8) & ~0xff) * cfi->interleave;
159 +       } else {
160 +               unsigned long offset = 0;
161 +               int i,j;
162 +
163 +               mtd->numeraseregions = cfi->cfiq->NumEraseRegions * cfi->numchips;
164 +               mtd->eraseregions = kmalloc(sizeof(struct mtd_erase_region_info) * mtd->numeraseregions, GFP_KERNEL);
165 +               if (!mtd->eraseregions) { 
166 +                       printk("Failed to allocate memory for MTD erase region info\n");
167 +                       kfree(cfi->cmdset_priv);
168 +                       return NULL;
169 +               }
170 +                       
171 +               for (i=0; i<cfi->cfiq->NumEraseRegions; i++) {
172 +                       unsigned long ernum, ersize;
173 +                       ersize = ((cfi->cfiq->EraseRegionInfo[i] >> 8) & ~0xff) * cfi->interleave;
174 +                       ernum = (cfi->cfiq->EraseRegionInfo[i] & 0xffff) + 1;
175 +                       
176 +                       if (mtd->erasesize < ersize) {
177 +                               mtd->erasesize = ersize;
178 +                       }
179 +                       for (j=0; j<cfi->numchips; j++) {
180 +                               mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].offset = (j*devsize)+offset;
181 +                               mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].erasesize = ersize;
182 +                               mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].numblocks = ernum;
183 +                       }
184 +                       offset += (ersize * ernum);
185 +               }
186 +
187 +               // debug
188 +               for (i=0; i<mtd->numeraseregions;i++){
189 +                       printk("%d: offset=0x%x,size=0x%x,blocks=%d\n",
190 +                              i,mtd->eraseregions[i].offset,
191 +                              mtd->eraseregions[i].erasesize,
192 +                              mtd->eraseregions[i].numblocks);
193 +               }
194 +       }
195 +
196 +       switch (CFIDEV_BUSWIDTH)
197 +       {
198 +       case 1:
199 +       case 2:
200 +       case 4:
201 +               if (mtd->numeraseregions > 1)
202 +                       mtd->erase = cfi_sststd_erase_varsize;
203 +               else
204 +                       mtd->erase = cfi_sststd_erase_onesize;
205 +               mtd->read = cfi_sststd_read;
206 +               mtd->write = cfi_sststd_write;
207 +               break;
208 +
209 +       default:
210 +               printk("Unsupported buswidth\n");
211 +               kfree(mtd);
212 +               kfree(cfi->cmdset_priv);
213 +               return NULL;
214 +               break;
215 +       }
216 +       mtd->sync = cfi_sststd_sync;
217 +       mtd->suspend = cfi_sststd_suspend;
218 +       mtd->resume = cfi_sststd_resume;
219 +       mtd->flags = MTD_CAP_NORFLASH;
220 +       map->fldrv = &cfi_sststd_chipdrv;
221 +       mtd->name = map->name;
222 +       MOD_INC_USE_COUNT;
223 +       return mtd;
224 +}
225 +
226 +static inline int do_read_onechip(struct map_info *map, struct flchip *chip, loff_t adr, size_t len, u_char *buf)
227 +{
228 +       DECLARE_WAITQUEUE(wait, current);
229 +       unsigned long timeo = jiffies + HZ;
230 +
231 + retry:
232 +       cfi_spin_lock(chip->mutex);
233 +
234 +       if (chip->state != FL_READY){
235 +               printk("Waiting for chip to read, status = %d\n", chip->state);
236 +               set_current_state(TASK_UNINTERRUPTIBLE);
237 +               add_wait_queue(&chip->wq, &wait);
238 +                
239 +               cfi_spin_unlock(chip->mutex);
240 +
241 +               schedule();
242 +               remove_wait_queue(&chip->wq, &wait);
243 +               timeo = jiffies + HZ;
244 +
245 +               goto retry;
246 +       }       
247 +
248 +       adr += chip->start;
249 +
250 +       chip->state = FL_READY;
251 +
252 +       map->copy_from(map, buf, adr, len);
253 +
254 +       wake_up(&chip->wq);
255 +       cfi_spin_unlock(chip->mutex);
256 +
257 +       return 0;
258 +}
259 +
260 +static int cfi_sststd_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf)
261 +{
262 +       struct map_info *map = mtd->priv;
263 +       struct cfi_private *cfi = map->fldrv_priv;
264 +       unsigned long ofs;
265 +       int chipnum;
266 +       int ret = 0;
267 +
268 +       /* ofs: offset within the first chip that the first read should start */
269 +
270 +       chipnum = (from >> cfi->chipshift);
271 +       ofs = from - (chipnum <<  cfi->chipshift);
272 +
273 +
274 +       *retlen = 0;
275 +
276 +       while (len) {
277 +               unsigned long thislen;
278 +
279 +               if (chipnum >= cfi->numchips)
280 +                       break;
281 +
282 +               if ((len + ofs -1) >> cfi->chipshift)
283 +                       thislen = (1<<cfi->chipshift) - ofs;
284 +               else
285 +                       thislen = len;
286 +
287 +               ret = do_read_onechip(map, &cfi->chips[chipnum], ofs, thislen, buf);
288 +               if (ret)
289 +                       break;
290 +
291 +               *retlen += thislen;
292 +               len -= thislen;
293 +               buf += thislen;
294 +
295 +               ofs = 0;
296 +               chipnum++;
297 +       }
298 +       return ret;
299 +}
300 +
301 +static int do_write_oneword(struct map_info *map, struct flchip *chip, unsigned long adr, __u32 datum, int fast)
302 +{
303 +       unsigned long timeo = jiffies + HZ;
304 +       unsigned int Last[4];
305 +       unsigned long Count = 0;
306 +       struct cfi_private *cfi = map->fldrv_priv;
307 +       DECLARE_WAITQUEUE(wait, current);
308 +       int ret = 0;
309 +
310 + retry:
311 +       cfi_spin_lock(chip->mutex);
312 +
313 +       if (chip->state != FL_READY){
314 +               printk("Waiting for chip to write, status = %d\n", chip->state);
315 +               set_current_state(TASK_UNINTERRUPTIBLE);
316 +               add_wait_queue(&chip->wq, &wait);
317 +                
318 +               cfi_spin_unlock(chip->mutex);
319 +
320 +               schedule();
321 +               remove_wait_queue(&chip->wq, &wait);
322 +               printk("Wake up to write:\n");
323 +               timeo = jiffies + HZ;
324 +
325 +               goto retry;
326 +       }       
327 +
328 +       chip->state = FL_WRITING;
329 +
330 +       adr += chip->start;
331 +       ENABLE_VPP(map);
332 +    cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X16, NULL);
333 +    cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, CFI_DEVICETYPE_X16, NULL);
334 +    cfi_send_gen_cmd(0xA0, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X16, NULL);
335 +
336 +       cfi_write(map, datum, adr);
337 +
338 +       cfi_spin_unlock(chip->mutex);
339 +       cfi_udelay(chip->word_write_time);
340 +       cfi_spin_lock(chip->mutex);
341 +
342 +       Last[0] = cfi_read(map, adr);
343 +       //      printk("Last[0] is %x\n", Last[0]);
344 +       Last[1] = cfi_read(map, adr);
345 +       //      printk("Last[1] is %x\n", Last[1]);
346 +       Last[2] = cfi_read(map, adr);
347 +       //      printk("Last[2] is %x\n", Last[2]);
348 +
349 +       for (Count = 3; Last[(Count - 1) % 4] != Last[(Count - 2) % 4] && Count < 10000; Count++){
350 +               cfi_spin_unlock(chip->mutex);
351 +               cfi_udelay(10);
352 +               cfi_spin_lock(chip->mutex);
353 +               
354 +               Last[Count % 4] = cfi_read(map, adr);
355 +               //              printk("Last[%d%%4] is %x\n", Count, Last[Count%4]);
356 +       }
357 +       
358 +       if (Last[(Count - 1) % 4] != datum){
359 +               printk("Last[%ld] is %x, datum is %x\n",(Count - 1) % 4,Last[(Count - 1) % 4],datum);
360 +               cfi_send_gen_cmd(0xF0, 0, chip->start, map, cfi, cfi->device_type, NULL);
361 +               DISABLE_VPP(map);
362 +               ret = -EIO;
363 +       }       
364 +       DISABLE_VPP(map);
365 +       chip->state = FL_READY;
366 +       wake_up(&chip->wq);
367 +       cfi_spin_unlock(chip->mutex);
368 +       
369 +       return ret;
370 +}
371 +
372 +static int cfi_sststd_write (struct mtd_info *mtd, loff_t to , size_t len, size_t *retlen, const u_char *buf)
373 +{
374 +       struct map_info *map = mtd->priv;
375 +       struct cfi_private *cfi = map->fldrv_priv;
376 +       int ret = 0;
377 +       int chipnum;
378 +       unsigned long ofs, chipstart;
379 +
380 +       *retlen = 0;
381 +       if (!len)
382 +               return 0;
383 +
384 +       chipnum = to >> cfi->chipshift;
385 +       ofs = to  - (chipnum << cfi->chipshift);
386 +       chipstart = cfi->chips[chipnum].start;
387 +
388 +       /* If it's not bus-aligned, do the first byte write */
389 +       if (ofs & (CFIDEV_BUSWIDTH-1)) {
390 +               unsigned long bus_ofs = ofs & ~(CFIDEV_BUSWIDTH-1);
391 +               int i = ofs - bus_ofs;
392 +               int n = 0;
393 +               u_char tmp_buf[4];
394 +               __u32 datum;
395 +
396 +               map->copy_from(map, tmp_buf, bus_ofs + cfi->chips[chipnum].start, CFIDEV_BUSWIDTH);
397 +               while (len && i < CFIDEV_BUSWIDTH)
398 +                       tmp_buf[i++] = buf[n++], len--;
399 +
400 +               if (cfi_buswidth_is_2()) {
401 +                       datum = *(__u16*)tmp_buf;
402 +               } else if (cfi_buswidth_is_4()) {
403 +                       datum = *(__u32*)tmp_buf;
404 +               } else {
405 +                       return -EINVAL;  /* should never happen, but be safe */
406 +               }
407 +
408 +               ret = do_write_oneword(map, &cfi->chips[chipnum], 
409 +                               bus_ofs, datum, 0);
410 +               if (ret) 
411 +                       return ret;
412 +               
413 +               ofs += n;
414 +               buf += n;
415 +               (*retlen) += n;
416 +
417 +               if (ofs >> cfi->chipshift) {
418 +                       chipnum ++; 
419 +                       ofs = 0;
420 +                       if (chipnum == cfi->numchips)
421 +                               return 0;
422 +               }
423 +       }
424 +       
425 +       /* We are now aligned, write as much as possible */
426 +       while(len >= CFIDEV_BUSWIDTH) {
427 +               __u32 datum;
428 +
429 +               if (cfi_buswidth_is_1()) {
430 +                       datum = *(__u8*)buf;
431 +               } else if (cfi_buswidth_is_2()) {
432 +                       datum = *(__u16*)buf;
433 +               } else if (cfi_buswidth_is_4()) {
434 +                       datum = *(__u32*)buf;
435 +               } else {
436 +                       return -EINVAL;
437 +               }
438 +               ret = do_write_oneword(map, &cfi->chips[chipnum],
439 +                                      ofs, datum, cfi->fast_prog);
440 +               if (ret) {
441 +                       return ret;
442 +               }
443 +
444 +               ofs += CFIDEV_BUSWIDTH;
445 +               buf += CFIDEV_BUSWIDTH;
446 +               (*retlen) += CFIDEV_BUSWIDTH;
447 +               len -= CFIDEV_BUSWIDTH;
448 +
449 +               if (ofs >> cfi->chipshift) {
450 +                       chipnum ++; 
451 +                       ofs = 0;
452 +                       if (chipnum == cfi->numchips)
453 +                               return 0;
454 +                       chipstart = cfi->chips[chipnum].start;
455 +               }
456 +       }
457 +
458 +       if (len & (CFIDEV_BUSWIDTH-1)) {
459 +               int i = 0, n = 0;
460 +               u_char tmp_buf[4];
461 +               __u32 datum;
462 +
463 +               map->copy_from(map, tmp_buf, ofs + cfi->chips[chipnum].start, CFIDEV_BUSWIDTH);
464 +               while (len--)
465 +                       tmp_buf[i++] = buf[n++];
466 +
467 +               if (cfi_buswidth_is_2()) {
468 +                       datum = *(__u16*)tmp_buf;
469 +               } else if (cfi_buswidth_is_4()) {
470 +                       datum = *(__u32*)tmp_buf;
471 +               } else {
472 +                       return -EINVAL;  /* should never happen, but be safe */
473 +               }
474 +
475 +               ret = do_write_oneword(map, &cfi->chips[chipnum], 
476 +                               ofs, datum, 0);
477 +               if (ret) 
478 +                       return ret;
479 +               
480 +               (*retlen) += n;
481 +       }
482 +
483 +       return 0;
484 +}
485 +
486 +static inline int do_erase_oneblock(struct map_info *map, struct flchip *chip, unsigned long adr)
487 +{
488 +       unsigned int status;
489 +       unsigned long timeo = jiffies + HZ;
490 +       struct cfi_private *cfi = map->fldrv_priv;
491 +       unsigned int rdy_mask;
492 +       DECLARE_WAITQUEUE(wait, current);
493 +
494 + retry:
495 +       cfi_spin_lock(chip->mutex);
496 +
497 +       if (chip->state != FL_READY){
498 +               set_current_state(TASK_UNINTERRUPTIBLE);
499 +               add_wait_queue(&chip->wq, &wait);
500 +                
501 +               cfi_spin_unlock(chip->mutex);
502 +
503 +               schedule();
504 +               remove_wait_queue(&chip->wq, &wait);
505 +               timeo = jiffies + HZ;
506 +
507 +               goto retry;
508 +       }       
509 +
510 +       chip->state = FL_ERASING;
511 +
512 +       adr += chip->start;
513 +       ENABLE_VPP(map);
514 +       cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X16, NULL);
515 +       cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, CFI_DEVICETYPE_X16, NULL);
516 +       cfi_send_gen_cmd(0x80, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X16, NULL);
517 +       cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X16, NULL);
518 +       cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, CFI_DEVICETYPE_X16, NULL);
519 +       cfi_write(map, CMD(0x30), adr);
520 +       
521 +       timeo = jiffies + (HZ*20);
522 +
523 +       cfi_spin_unlock(chip->mutex);
524 +       schedule_timeout(HZ);
525 +       cfi_spin_lock(chip->mutex);
526 +       
527 +       rdy_mask = CMD(0x80);
528 +
529 +       /* Once the state machine's known to be working I'll do that */
530 +
531 +       while ( ( (status = cfi_read(map,adr)) & rdy_mask ) != rdy_mask ) {
532 +               static int z=0;
533 +
534 +               if (chip->state != FL_ERASING) {
535 +                       /* Someone's suspended the erase. Sleep */
536 +                       set_current_state(TASK_UNINTERRUPTIBLE);
537 +                       add_wait_queue(&chip->wq, &wait);
538 +                       
539 +                       cfi_spin_unlock(chip->mutex);
540 +                       printk("erase suspended. Sleeping\n");
541 +                       
542 +                       schedule();
543 +                       remove_wait_queue(&chip->wq, &wait);
544 +                       timeo = jiffies + (HZ*2); 
545 +                       cfi_spin_lock(chip->mutex);
546 +                       continue;
547 +               }
548 +
549 +               /* OK Still waiting */
550 +               if (time_after(jiffies, timeo)) {
551 +                       chip->state = FL_READY;
552 +                       cfi_spin_unlock(chip->mutex);
553 +                       printk("waiting for erase to complete timed out.");
554 +                       DISABLE_VPP(map);
555 +                       return -EIO;
556 +               }
557 +               
558 +               /* Latency issues. Drop the lock, wait a while and retry */
559 +               cfi_spin_unlock(chip->mutex);
560 +
561 +               z++;
562 +               if ( 0 && !(z % 100 )) 
563 +                       printk("chip not ready yet after erase. looping\n");
564 +
565 +               cfi_udelay(1);
566 +               
567 +               cfi_spin_lock(chip->mutex);
568 +               continue;
569 +       }
570 +       
571 +       /* Done and happy. */
572 +       DISABLE_VPP(map);
573 +       chip->state = FL_READY;
574 +       wake_up(&chip->wq);
575 +       cfi_spin_unlock(chip->mutex);
576 +       return 0;
577 +}
578 +
579 +static int cfi_sststd_erase_varsize(struct mtd_info *mtd, struct erase_info *instr)
580 +{
581 +       struct map_info *map = mtd->priv;
582 +       struct cfi_private *cfi = map->fldrv_priv;
583 +       unsigned long adr, len;
584 +       int chipnum, ret = 0;
585 +       int i, first;
586 +       struct mtd_erase_region_info *regions = mtd->eraseregions;
587 +
588 +       if (instr->addr > mtd->size)
589 +               return -EINVAL;
590 +
591 +       if ((instr->len + instr->addr) > mtd->size)
592 +               return -EINVAL;
593 +
594 +       /* Check that both start and end of the requested erase are
595 +        * aligned with the erasesize at the appropriate addresses.
596 +        */
597 +
598 +       i = 0;
599 +
600 +       /* Skip all erase regions which are ended before the start of 
601 +          the requested erase. Actually, to save on the calculations,
602 +          we skip to the first erase region which starts after the
603 +          start of the requested erase, and then go back one.
604 +       */
605 +       
606 +       while (i < mtd->numeraseregions && instr->addr >= regions[i].offset)
607 +              i++;
608 +       i--;
609 +
610 +       /* OK, now i is pointing at the erase region in which this 
611 +          erase request starts. Check the start of the requested
612 +          erase range is aligned with the erase size which is in
613 +          effect here.
614 +       */
615 +
616 +       if (instr->addr & (regions[i].erasesize-1))
617 +               return -EINVAL;
618 +
619 +       /* Remember the erase region we start on */
620 +       first = i;
621 +
622 +       /* Next, check that the end of the requested erase is aligned
623 +        * with the erase region at that address.
624 +        */
625 +
626 +       while (i<mtd->numeraseregions && (instr->addr + instr->len) >= regions[i].offset)
627 +               i++;
628 +
629 +       /* As before, drop back one to point at the region in which
630 +          the address actually falls
631 +       */
632 +       i--;
633 +       
634 +       if ((instr->addr + instr->len) & (regions[i].erasesize-1))
635 +               return -EINVAL;
636 +       
637 +       chipnum = instr->addr >> cfi->chipshift;
638 +       adr = instr->addr - (chipnum << cfi->chipshift);
639 +       len = instr->len;
640 +
641 +       i=first;
642 +
643 +       while(len) {
644 +               ret = do_erase_oneblock(map, &cfi->chips[chipnum], adr);
645 +
646 +               if (ret)
647 +                       return ret;
648 +
649 +               adr += regions[i].erasesize;
650 +               len -= regions[i].erasesize;
651 +
652 +               if (adr % (1<< cfi->chipshift) == ((regions[i].offset + (regions[i].erasesize * regions[i].numblocks)) %( 1<< cfi->chipshift)))
653 +                       i++;
654 +
655 +               if (adr >> cfi->chipshift) {
656 +                       adr = 0;
657 +                       chipnum++;
658 +                       
659 +                       if (chipnum >= cfi->numchips)
660 +                       break;
661 +               }
662 +       }
663 +
664 +       instr->state = MTD_ERASE_DONE;
665 +       if (instr->callback)
666 +               instr->callback(instr);
667 +       
668 +       return 0;
669 +}
670 +
671 +static int cfi_sststd_erase_onesize(struct mtd_info *mtd, struct erase_info *instr)
672 +{
673 +       struct map_info *map = mtd->priv;
674 +       struct cfi_private *cfi = map->fldrv_priv;
675 +       unsigned long adr, len;
676 +       int chipnum, ret = 0;
677 +
678 +       if (instr->addr & (mtd->erasesize - 1))
679 +               return -EINVAL;
680 +
681 +       if (instr->len & (mtd->erasesize -1))
682 +               return -EINVAL;
683 +
684 +       if ((instr->len + instr->addr) > mtd->size)
685 +               return -EINVAL;
686 +
687 +       chipnum = instr->addr >> cfi->chipshift;
688 +       adr = instr->addr - (chipnum << cfi->chipshift);
689 +       len = instr->len;
690 +
691 +       while(len) {
692 +               ret = do_erase_oneblock(map, &cfi->chips[chipnum], adr);
693 +
694 +               if (ret)
695 +                       return ret;
696 +
697 +               adr += mtd->erasesize;
698 +               len -= mtd->erasesize;
699 +
700 +               if (adr >> cfi->chipshift) {
701 +                       adr = 0;
702 +                       chipnum++;
703 +                       
704 +                       if (chipnum >= cfi->numchips)
705 +                       break;
706 +               }
707 +       }
708 +               
709 +       instr->state = MTD_ERASE_DONE;
710 +       if (instr->callback)
711 +               instr->callback(instr);
712 +       
713 +       return 0;
714 +}
715 +
716 +static void cfi_sststd_sync (struct mtd_info *mtd)
717 +{
718 +       struct map_info *map = mtd->priv;
719 +       struct cfi_private *cfi = map->fldrv_priv;
720 +       int i;
721 +       struct flchip *chip;
722 +       int ret = 0;
723 +       DECLARE_WAITQUEUE(wait, current);
724 +
725 +       for (i=0; !ret && i<cfi->numchips; i++) {
726 +               chip = &cfi->chips[i];
727 +
728 +       retry:
729 +               cfi_spin_lock(chip->mutex);
730 +
731 +               switch(chip->state) {
732 +               case FL_READY:
733 +               case FL_STATUS:
734 +               case FL_CFI_QUERY:
735 +               case FL_JEDEC_QUERY:
736 +                       chip->oldstate = chip->state;
737 +                       chip->state = FL_SYNCING;
738 +                       /* No need to wake_up() on this state change - 
739 +                        * as the whole point is that nobody can do anything
740 +                        * with the chip now anyway.
741 +                        */
742 +               case FL_SYNCING:
743 +                       cfi_spin_unlock(chip->mutex);
744 +                       break;
745 +
746 +               default:
747 +                       /* Not an idle state */
748 +                       add_wait_queue(&chip->wq, &wait);
749 +                       
750 +                       cfi_spin_unlock(chip->mutex);
751 +
752 +                       schedule();
753 +
754 +                       remove_wait_queue(&chip->wq, &wait);
755 +                       
756 +                       goto retry;
757 +               }
758 +       }
759 +
760 +       /* Unlock the chips again */
761 +
762 +       for (i--; i >=0; i--) {
763 +               chip = &cfi->chips[i];
764 +
765 +               cfi_spin_lock(chip->mutex);
766 +               
767 +               if (chip->state == FL_SYNCING) {
768 +                       chip->state = chip->oldstate;
769 +                       wake_up(&chip->wq);
770 +               }
771 +               cfi_spin_unlock(chip->mutex);
772 +       }
773 +}
774 +
775 +
776 +static int cfi_sststd_suspend(struct mtd_info *mtd)
777 +{
778 +       struct map_info *map = mtd->priv;
779 +       struct cfi_private *cfi = map->fldrv_priv;
780 +       int i;
781 +       struct flchip *chip;
782 +       int ret = 0;
783 +//printk("suspend\n");
784 +
785 +       for (i=0; !ret && i<cfi->numchips; i++) {
786 +               chip = &cfi->chips[i];
787 +
788 +               cfi_spin_lock(chip->mutex);
789 +
790 +               switch(chip->state) {
791 +               case FL_READY:
792 +               case FL_STATUS:
793 +               case FL_CFI_QUERY:
794 +               case FL_JEDEC_QUERY:
795 +                       chip->oldstate = chip->state;
796 +                       chip->state = FL_PM_SUSPENDED;
797 +                       /* No need to wake_up() on this state change - 
798 +                        * as the whole point is that nobody can do anything
799 +                        * with the chip now anyway.
800 +                        */
801 +               case FL_PM_SUSPENDED:
802 +                       break;
803 +
804 +               default:
805 +                       ret = -EAGAIN;
806 +                       break;
807 +               }
808 +               cfi_spin_unlock(chip->mutex);
809 +       }
810 +
811 +       /* Unlock the chips again */
812 +
813 +       if (ret) {
814 +               for (i--; i >=0; i--) {
815 +                       chip = &cfi->chips[i];
816 +
817 +                       cfi_spin_lock(chip->mutex);
818 +               
819 +                       if (chip->state == FL_PM_SUSPENDED) {
820 +                               chip->state = chip->oldstate;
821 +                               wake_up(&chip->wq);
822 +                       }
823 +                       cfi_spin_unlock(chip->mutex);
824 +               }
825 +       }
826 +       
827 +       return ret;
828 +}
829 +
830 +static void cfi_sststd_resume(struct mtd_info *mtd)
831 +{
832 +       struct map_info *map = mtd->priv;
833 +       struct cfi_private *cfi = map->fldrv_priv;
834 +       int i;
835 +       struct flchip *chip;
836 +//printk("resume\n");
837 +
838 +       for (i=0; i<cfi->numchips; i++) {
839 +       
840 +               chip = &cfi->chips[i];
841 +
842 +               cfi_spin_lock(chip->mutex);
843 +               
844 +               if (chip->state == FL_PM_SUSPENDED) {
845 +                       chip->state = FL_READY;
846 +                       cfi_write(map, CMD(0xF0), chip->start);
847 +                       wake_up(&chip->wq);
848 +               }
849 +               else
850 +                       printk("Argh. Chip not in PM_SUSPENDED state upon resume()\n");
851 +
852 +               cfi_spin_unlock(chip->mutex);
853 +       }
854 +}
855 +
856 +static void cfi_sststd_destroy(struct mtd_info *mtd)
857 +{
858 +       struct map_info *map = mtd->priv;
859 +       struct cfi_private *cfi = map->fldrv_priv;
860 +       kfree(cfi->cmdset_priv);
861 +       kfree(cfi);
862 +}
863 +
864 +#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE)
865 +#define cfi_sststd_init init_module
866 +#define cfi_sststd_exit cleanup_module
867 +#endif
868 +
869 +static char im_name[]="cfi_cmdset_0701";
870 +
871 +mod_init_t cfi_sststd_init(void)
872 +{
873 +       inter_module_register(im_name, THIS_MODULE, &cfi_cmdset_0701);
874 +       return 0;
875 +}
876 +
877 +mod_exit_t cfi_sststd_exit(void)
878 +{
879 +       inter_module_unregister(im_name);
880 +}
881 +
882 +module_init(cfi_sststd_init);
883 +module_exit(cfi_sststd_exit);
884 +
885 Index: linux-2.4.35.4/drivers/mtd/chips/cfi_probe.c
886 ===================================================================
887 --- linux-2.4.35.4.orig/drivers/mtd/chips/cfi_probe.c   2007-12-15 05:19:42.474841541 +0100
888 +++ linux-2.4.35.4/drivers/mtd/chips/cfi_probe.c        2007-12-15 05:19:50.051273298 +0100
889 @@ -67,8 +67,15 @@
890         cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
891         cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL);
892  
893 -       if (!qry_present(map,base,cfi))
894 -               return 0;
895 +       if (!qry_present(map,base,cfi)) {
896 +               /* rather broken SST cfi probe (requires SST unlock) */
897 +               cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
898 +               cfi_send_gen_cmd(0xAA, 0x5555, base, map, cfi, cfi->device_type, NULL);
899 +               cfi_send_gen_cmd(0x55, 0x2AAA, base, map, cfi, cfi->device_type, NULL);
900 +               cfi_send_gen_cmd(0x98, 0x5555, base, map, cfi, cfi->device_type, NULL);
901 +               if (!qry_present(map,base,cfi))
902 +                       return 0;
903 +       }
904  
905         if (!cfi->numchips) {
906                 /* This is the first time we're called. Set up the CFI 
907 Index: linux-2.4.35.4/drivers/mtd/chips/gen_probe.c
908 ===================================================================
909 --- linux-2.4.35.4.orig/drivers/mtd/chips/gen_probe.c   2007-12-15 05:19:42.482841997 +0100
910 +++ linux-2.4.35.4/drivers/mtd/chips/gen_probe.c        2007-12-15 05:19:50.055273524 +0100
911 @@ -328,13 +328,18 @@
912                 return cfi_cmdset_0001(map, primary);
913  #endif
914  #ifdef CONFIG_MTD_CFI_AMDSTD
915 +       case 0x0006:
916         case 0x0002:
917                 return cfi_cmdset_0002(map, primary);
918  #endif
919  #ifdef CONFIG_MTD_CFI_STAA
920 -        case 0x0020:
921 +       case 0x0020:
922                 return cfi_cmdset_0020(map, primary);
923  #endif
924 +#ifdef CONFIG_MTD_CFI_SSTSTD
925 +       case 0x0701:
926 +               return cfi_cmdset_0701(map, primary);
927 +#endif
928         }
929  
930         return cfi_cmdset_unknown(map, primary);