66a92e8b6b7452f309a1b83df794f29e97590421
[openwrt/staging/yousong.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
4 +++ linux-2.4.35.4/drivers/mtd/chips/Config.in
5 @@ -45,6 +45,7 @@ fi
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
16 +++ linux-2.4.35.4/drivers/mtd/chips/Makefile
17 @@ -18,6 +18,7 @@ obj-$(CONFIG_MTD) += chipreg.o
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
28 +++ linux-2.4.35.4/drivers/mtd/chips/cfi_cmdset_0701.c
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
888 +++ linux-2.4.35.4/drivers/mtd/chips/cfi_probe.c
889 @@ -67,8 +67,15 @@ static int cfi_probe_chip(struct map_inf
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
910 +++ linux-2.4.35.4/drivers/mtd/chips/gen_probe.c
911 @@ -328,13 +328,18 @@ static struct mtd_info *check_cmd_set(st
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);