1
2 /* JEDEC Flash Interface.
3 * This is an older type of interface for self programming flash. It is
4 * commonly use in older AMD chips and is obsolete compared with CFI.
5 * It is called JEDEC because the JEDEC association distributes the ID codes
6 * for the chips.
7 *
8 * See the AMD flash databook for information on how to operate the interface.
9 *
10 * This code does not support anything wider than 8 bit flash chips, I am
11 * not going to guess how to send commands to them, plus I expect they will
12 * all speak CFI..
13 *
14 * $Id: jedec.c,v 1.1 2000/07/04 07:21:57 jgg Exp $
15 */
16
17 #include <linux/mtd/jedec.h>
18
19 struct mtd_info *jedec_probe(struct map_info *);
20 int jedec_probe8(struct map_info *map,unsigned long base,
21 struct jedec_private *priv);
22 int jedec_probe16(struct map_info *map,unsigned long base,
23 struct jedec_private *priv);
24 int jedec_probe32(struct map_info *map,unsigned long base,
25 struct jedec_private *priv);
26 static void jedec_flash_chip_scan(struct jedec_private *priv,unsigned long start,
27 unsigned long len);
28 static int flash_erase(struct mtd_info *mtd, struct erase_info *instr);
29 static int flash_write(struct mtd_info *mtd, loff_t start, size_t len,
30 size_t *retlen, const u_char *buf);
31
32 EXPORT_SYMBOL(jedec_probe);
33
34 /* Listing of parts and sizes. We need this table to learn the sector
35 size of the chip and the total length */
36 static const struct JEDECTable JEDEC_table[] =
37 {{0x01AD,"AMD Am29F016",2*1024*1024,64*1024,MTD_CAP_NORFLASH},
38 {0x01D5,"AMD Am29F080",1*1024*1024,64*1024,MTD_CAP_NORFLASH},
39 {0x01A4,"AMD Am29F040",512*1024,64*1024,MTD_CAP_NORFLASH},
40 {}};
41
42 static void jedec_sync(struct mtd_info *mtd) {};
43 static int jedec_read(struct mtd_info *mtd, loff_t from, size_t len,
44 size_t *retlen, u_char *buf);
45 static int jedec_read_banked(struct mtd_info *mtd, loff_t from, size_t len,
46 size_t *retlen, u_char *buf);
47
48 /* Probe entry point */
49 struct jedec_private priv;
50 struct mtd_info __MTD;
51 struct mtd_info *jedec_probe(struct map_info *map)
52 {
53 struct mtd_info *MTD = &__MTD;
54 unsigned long Base;
55 unsigned long SectorSize;
56 unsigned count;
57 unsigned I,Uniq;
58 char Part[200];
59 memset(&priv,0,sizeof(priv));
60
61 if (map->bank_size == 0)
62 map->bank_size = map->size;
63
64 if (map->size/map->bank_size > MAX_JEDEC_CHIPS)
65 {
66 printk("mtd: Increase MAX_JEDEC_CHIPS, too many banks.\n");
67 return 0;
68 }
69
70 for (Base = 0; Base < map->size; Base += map->bank_size)
71 {
72 // Perhaps zero could designate all tests?
73 if (map->bus_width == 0)
74 map->bus_width = 8;
75
76 if (map->bus_width == 8)
77 jedec_probe8(map,Base,&priv);
78 if (map->bus_width == 16)
79 jedec_probe16(map,Base,&priv);
80 if (map->bus_width == 32)
81 jedec_probe32(map,Base,&priv);
82 }
83
84 // Get the biggest sector size
85 SectorSize = 0;
86 for (I = 0; priv.chips[I].jedec != 0 && I < MAX_JEDEC_CHIPS; I++)
87 {
88 if (priv.chips[I].sectorsize > SectorSize)
89 SectorSize = priv.chips[I].sectorsize;
90 }
91
92 // Quickly ensure that the other sector sizes are factors of the largest
93 for (I = 0; priv.chips[I].jedec != 0 && I < MAX_JEDEC_CHIPS; I++)
94 {
95 if ((SectorSize/priv.chips[I].sectorsize)*priv.chips[I].sectorsize != SectorSize)
96 {
97 printk("mtd: Failed. Device has incompatible mixed sector sizes\n");
98 return 0;
99 }
100 }
101
102 /* Generate a part name that includes the number of different chips and
103 other configuration information */
104 count = 1;
105 strncpy(Part,map->name,sizeof(Part)-10);
106 Part[sizeof(Part)-11] = 0;
107 strcat(Part," ");
108 Uniq = 0;
109 for (I = 0; priv.chips[I].jedec != 0 && I < MAX_JEDEC_CHIPS; I++)
110 {
111 const struct JEDECTable *JEDEC;
112
113 if (priv.chips[I+1].jedec == priv.chips[I].jedec)
114 {
115 count++;
116 continue;
117 }
118
119 // Locate the chip in the jedec table
120 JEDEC = jedec_idtoinf(priv.chips[I].jedec >> 8,priv.chips[I].jedec);
121 if (JEDEC == 0)
122 {
123 printk("mtd: Internal Error, JEDEC not set\n");
124 return 0;
125 }
126
127 if (Uniq != 0)
128 strcat(Part,",");
129 Uniq++;
130
131 if (count != 1)
132 sprintf(Part+strlen(Part),"%x*[%s]",count,JEDEC->name);
133 else
134 sprintf(Part+strlen(Part),"%s",JEDEC->name);
135 if (strlen(Part) > sizeof(Part)*2/3)
136 break;
137 count = 1;
138 }
139
140 /* Determine if the chips are organized in a linear fashion, or if there
141 are empty banks. Note, the last bank does not count here, only the
142 first banks are important. Holes on non-bank boundaries can not exist
143 due to the way the detection algorithm works. */
144 if (priv.size < map->bank_size)
145 map->bank_size = priv.size;
146 priv.is_banked = 0;
147 for (I = 0; I != priv.size/map->bank_size - 1; I++)
148 {
149 if (priv.bank_fill[I] != map->bank_size)
150 priv.is_banked = 1;
151
152 /* This even could be eliminated, but new de-optimized read/write
153 functions have to be written */
154 if (priv.bank_fill[I] != priv.bank_fill[0])
155 {
156 printk("mtd: Failed. Cannot handle unsymetric banking\n");
157 return 0;
158 }
159 }
160 if (priv.is_banked == 1)
161 strcat(Part,", banked");
162
163 xprintf("Part: '%s'\n",Part);
164
165 memset(MTD,0,sizeof(*MTD));
166 strncpy(MTD->name,Part,sizeof(MTD->name));
167 MTD->name[sizeof(MTD->name)-1] = 0;
168 MTD->type = MTD_NORFLASH;
169 MTD->flags = MTD_CAP_NORFLASH;
170 MTD->erasesize = SectorSize*(map->bus_width/8);
171 MTD->size = priv.size;
172 //MTD->module = THIS_MODULE; // ? Maybe this should be the low level module?
173 MTD->erase = flash_erase;
174 if (priv.is_banked == 1)
175 MTD->read = jedec_read_banked;
176 else
177 MTD->read = jedec_read;
178 MTD->write = flash_write;
179 MTD->sync = jedec_sync;
180 MTD->priv = map;
181 map->fldrv_priv = &priv;
182
183 return MTD;
184 }
185
186 /* Helper for the JEDEC function, JEDEC numbers all have odd parity */
187 static int checkparity(u_char C)
188 {
189 u_char parity = 0;
190 while (C != 0)
191 {
192 parity ^= C & 1;
193 C >>= 1;
194 }
195
196 return parity == 1;
197 }
198
199
200 /* Take an array of JEDEC numbers that represent interleved flash chips
201 and process them. Check to make sure they are good JEDEC numbers, look
202 them up and then add them to the chip list */
203 int handle_jedecs(struct map_info *map,__u8 *Mfg,__u8 *Id,unsigned Count,
204 unsigned long base,struct jedec_private *priv)
205 {
206 unsigned I,J;
207 unsigned long Size;
208 unsigned long SectorSize;
209 const struct JEDECTable *JEDEC;
210
211 // Test #2 JEDEC numbers exhibit odd parity
212 for (I = 0; I != Count; I++)
213 {
214 if (checkparity(Mfg[I]) == 0 || checkparity(Id[I]) == 0)
215 return 0;
216 }
217
218 // Finally, just make sure all the chip sizes are the same
219 JEDEC = jedec_idtoinf(Mfg[0],Id[0]);
220
221 if (JEDEC == 0)
222 {
223 printk("mtd: Found JEDEC flash chip, but do not have a table entry for %x:%x\n",Mfg[0],Mfg[1]);
224 return 0;
225 }
226
227 Size = JEDEC->size;
228 SectorSize = JEDEC->sectorsize;
229 for (I = 0; I != Count; I++)
230 {
231 JEDEC = jedec_idtoinf(Mfg[0],Id[0]);
232 if (JEDEC == 0)
233 {
234 printk("mtd: Found JEDEC flash chip, but do not have a table entry for %x:%x\n",Mfg[0],Mfg[1]);
235 return 0;
236 }
237
238 if (Size != JEDEC->size || SectorSize != JEDEC->sectorsize)
239 {
240 printk("mtd: Failed. Interleved flash does not have matching characteristics\n");
241 return 0;
242 }
243 }
244
245 // Load the Chips
246 for (I = 0; I != MAX_JEDEC_CHIPS; I++)
247 {
248 if (priv->chips[I].jedec == 0)
249 break;
250 }
251
252 if (I + Count > MAX_JEDEC_CHIPS)
253 {
254 printk("mtd: Device has too many chips. Increase MAX_JEDEC_CHIPS\n");
255 return 0;
256 }
257
258 // Add them to the table
259 for (J = 0; J != Count; J++)
260 {
261 unsigned long Bank;
262
263 JEDEC = jedec_idtoinf(Mfg[J],Id[J]);
264 priv->chips[I].jedec = (Mfg[J] << 8) | Id[J];
265 priv->chips[I].size = JEDEC->size;
266 priv->chips[I].sectorsize = JEDEC->sectorsize;
267 priv->chips[I].base = base + J;
268 priv->chips[I].datashift = J*8;
269 priv->chips[I].capabilities = JEDEC->capabilities;
270 priv->chips[I].offset = priv->size + J;
271
272 // log2 n :|
273 priv->chips[I].addrshift = 0;
274 for (Bank = Count; Bank != 1; Bank >>= 1, priv->chips[I].addrshift++);
275
276 // Determine how filled this bank is.
277 Bank = base & (~(map->bank_size-1));
278 if (priv->bank_fill[Bank/map->bank_size] < base +
279 (JEDEC->size << priv->chips[I].addrshift) - Bank)
280 priv->bank_fill[Bank/map->bank_size] = base + (JEDEC->size << priv->chips[I].addrshift) - Bank;
281 I++;
282 }
283
284 priv->size += priv->chips[I-1].size*Count;
285
286 return priv->chips[I-1].size;
287 }
288
289 /* Lookup the chip information from the JEDEC ID table. */
290 const struct JEDECTable *jedec_idtoinf(__u8 mfr,__u8 id)
291 {
292 __u16 Id = (mfr << 8) | id;
293 unsigned long I = 0;
294 for (I = 0; JEDEC_table[I].jedec != 0; I++)
295 if (JEDEC_table[I].jedec == Id)
296 return JEDEC_table + I;
297 return 0;
298 }
299
300 // Look for flash using an 8 bit bus interface
301 int jedec_probe8(struct map_info *map,unsigned long base,
302 struct jedec_private *priv)
303 {
304 return 0;
305 }
306
307 // Look for flash using a 16 bit bus interface (ie 2 8-bit chips)
308 int jedec_probe16(struct map_info *map,unsigned long base,
309 struct jedec_private *priv)
310 {
311 return 0;
312 }
313
314 // Look for flash using a 32 bit bus interface (ie 4 8-bit chips)
315 int jedec_probe32(struct map_info *map,unsigned long base,
316 struct jedec_private *priv)
317 {
318 #define flread(x) map->read32(map,base+((x)<<2))
319 #define flwrite(v,x) map->write32(map,v,base+((x)<<2))
320
321 const unsigned long AutoSel1 = 0xAAAAAAAA;
322 const unsigned long AutoSel2 = 0x55555555;
323 const unsigned long AutoSel3 = 0x90909090;
324 const unsigned long Reset = 0x90909090;
325 __u32 OldVal;
326 __u8 Mfg[4];
327 __u8 Id[4];
328 unsigned I;
329 unsigned long Size;
330
331 // Wait for any write/erase operation to settle
332 OldVal = flread(base);
333 for (I = 0; OldVal != flread(base) && I < 10000; I++)
334 OldVal = flread(base);
335
336 // Reset the chip
337 flwrite(Reset,0x555);
338
339 // Send the sequence
340 flwrite(AutoSel1,0x555);
341 flwrite(AutoSel2,0x2AA);
342 flwrite(AutoSel3,0x555);
343
344 // Test #1, JEDEC numbers are readable from 0x??00/0x??01
345 if (flread(0) != flread(0x100) ||
346 flread(1) != flread(0x101))
347 {
348 flwrite(Reset,0x555);
349 return 0;
350 }
351
352 // Split up the JEDEC numbers
353 OldVal = flread(0);
354 for (I = 0; I != 4; I++)
355 Mfg[I] = (OldVal >> (I*8));
356 OldVal = flread(1);
357 for (I = 0; I != 4; I++)
358 Id[I] = (OldVal >> (I*8));
359
360 Size = handle_jedecs(map,Mfg,Id,4,base,priv);
361 if (Size == 0)
362 {
363 flwrite(Reset,0x555);
364 return 0;
365 }
366
367 /* Check if there is address wrap around within a single bank, if this
368 returns JEDEC numbers then we assume that it is wrap around. Notice
369 we call this routine with the JEDEC return still enabled, if two or
370 more flashes have a truncated address space the probe test will still
371 work */
372 if (base + Size+0x555 < map->size &&
373 base + Size+0x555 < (base & (~(map->bank_size-1))) + map->bank_size)
374 {
375 if (flread(base+Size) != flread(base+Size + 0x100) ||
376 flread(base+Size + 1) != flread(base+Size + 0x101))
377 {
378 jedec_probe32(map,base+Size,priv);
379 }
380 }
381
382 // Reset.
383 flwrite(0xF0F0F0F0,0x555);
384
385 return 1;
386
387 #undef flread
388 #undef flwrite
389 }
390
391 /* Linear read. */
392 static int jedec_read(struct mtd_info *mtd, loff_t from, size_t len,
393 size_t *retlen, u_char *buf)
394 {
395 struct map_info *map = (struct map_info *)mtd->priv;
396
397 map->copy_from(map, buf, from, len);
398 *retlen = len;
399 return 0;
400 }
401
402 /* Banked read. Take special care to jump past the holes in the bank
403 mapping. This version assumes symetry in the holes.. */
404 static int jedec_read_banked(struct mtd_info *mtd, loff_t from, size_t len,
405 size_t *retlen, u_char *buf)
406 {
407 struct map_info *map = (struct map_info *)mtd->priv;
408 struct jedec_private *priv = (struct jedec_private *)map->fldrv_priv;
409
410 *retlen = 0;
411 while (len > 0)
412 {
413 // Determine what bank and offset into that bank the first byte is
414 unsigned long bank = from & (~(priv->bank_fill[0]-1));
415 unsigned long offset = from & (priv->bank_fill[0]-1);
416 unsigned long get = len;
417 if (priv->bank_fill[0] - offset < len)
418 get = priv->bank_fill[0] - offset;
419
420 bank /= priv->bank_fill[0];
421 map->copy_from(map,buf + *retlen,bank*map->bank_size + offset,get);
422
423 len -= get;
424 *retlen += get;
425 from += get;
426 }
427 return 0;
428 }
429
430 /* Pass the flags value that the flash return before it re-entered read
431 mode. */
432 static void jedec_flash_failed(unsigned char code)
433 {
434 /* Bit 5 being high indicates that there was an internal device
435 failure, erasure time limits exceeded or something */
436 if ((code & (1 << 5)) != 0)
437 {
438 printk("mtd: Internal Flash failure\n");
439 return;
440 }
441 printk("mtd: Programming didn't take\n");
442 }
443
444 /* This uses the erasure function described in the AMD Flash Handbook,
445 it will work for flashes with a fixed sector size only. Flashes with
446 a selection of sector sizes (ie the AMD Am29F800B) will need a different
447 routine. This routine tries to parallize erasing multiple chips/sectors
448 where possible */
449 static int flash_erase(struct mtd_info *mtd, struct erase_info *instr)
450 {
451 // Does IO to the currently selected chip
452 #define flread(x) map->read8(map,chip->base+((x)<<chip->addrshift))
453 #define flwrite(v,x) map->write8(map,v,chip->base+((x)<<chip->addrshift))
454
455 unsigned long Time = 0;
456 unsigned long NoTime = 0;
457 unsigned long start = instr->addr, len = instr->len;
458 unsigned int I;
459 struct map_info *map = (struct map_info *)mtd->priv;
460 struct jedec_private *priv = (struct jedec_private *)map->fldrv_priv;
461
462 // Verify the arguments..
463 if (start + len > mtd->size ||
464 (start % mtd->erasesize) != 0 ||
465 (len % mtd->erasesize) != 0 ||
466 (len/mtd->erasesize) == 0)
467 return -EINVAL;
468
469 jedec_flash_chip_scan(priv,start,len);
470
471 // Start the erase sequence on each chip
472 for (I = 0; priv->chips[I].jedec != 0 && I < MAX_JEDEC_CHIPS; I++)
473 {
474 unsigned long off;
475 struct jedec_flash_chip *chip = priv->chips + I;
476
477 if (chip->length == 0)
478 continue;
479
480 // Send the erase setup code
481 xprintf("Erase: ");
482 puth(chip->start); putc(' ');
483 puth(chip->base); putc(' ');
484 puth(chip->length); putc(' ');
485 puth(chip->sectorsize); putc('\n');
486
487 if (chip->start + chip->length > chip->size)
488 {
489 xprintf("DIE\n");
490 return -EIO;
491 }
492
493 flwrite(0xF0,chip->start + 0x555);
494 flwrite(0xAA,chip->start + 0x555);
495 flwrite(0x55,chip->start + 0x2AA);
496 flwrite(0x80,chip->start + 0x555);
497 flwrite(0xAA,chip->start + 0x555);
498 flwrite(0x55,chip->start + 0x2AA);
499
500 // Use chip erase if possible
501 if (chip->start == 0 && chip->length == chip->size)
502 {
503 flwrite(0x10,0x555);
504 continue;
505 }
506
507 /* Once we start selecting the erase sectors the delay between each
508 command must not exceed 50us or it will immediately start erasing
509 and ignore the other sectors */
510 /* how do you portably turn off interrupts?
511 save_flags(flags);
512 cli();*/
513 for (off = 0; off < chip->length; off += chip->sectorsize)
514 {
515 // Check to make sure we didn't timeout
516 flwrite(0x30,chip->start + off);
517 if (off == 0)
518 continue;
519 if ((flread(chip->start + off) & (1 << 3)) != 0)
520 {
521 printk("mtd: Ack! We timed out the erase timer!\n");
522 return -EIO;
523 }
524 }
525 // restore_flags(flags);
526 }
527
528 /* We could split this into a timer routine and return early, performing
529 background erasure.. Maybe later if the need warrents */
530
531 /* Poll the flash for erasure completion, specs say this can take as long
532 as 480 seconds to do all the sectors (for a 2 meg flash).
533 Erasure time is dependant on chip age, temp and wear.. */
534
535 /* This being a generic routine assumes a 32 bit bus. It does read32s
536 and bundles interleved chips into the same grouping. This will work
537 for all bus widths */
538 Time = 0;
539 NoTime = 0;
540 for (I = 0; priv->chips[I].jedec != 0 && I < MAX_JEDEC_CHIPS; I++)
541 {
542 struct jedec_flash_chip *chip = priv->chips + I;
543 unsigned long off = 0;
544 unsigned todo[4] = {0,0,0,0};
545 unsigned todo_left = 0;
546 unsigned J;
547
548 if (chip->length == 0)
549 continue;
550
551 /* Find all chips in this data line, realistically this is all
552 or nothing up to the interleve count */
553 for (J = 0; priv->chips[J].jedec != 0 && J < MAX_JEDEC_CHIPS; J++)
554 {
555 if ((priv->chips[J].base & (~((1<<chip->addrshift)-1))) ==
556 (chip->base & (~((1<<chip->addrshift)-1))))
557 {
558 todo_left++;
559 todo[priv->chips[J].base & ((1<<chip->addrshift)-1)] = 1;
560 }
561 }
562
563 xprintf("todo: %x %x %x %x\n",(short)todo[0],(short)todo[1],
564 (short)todo[2],(short)todo[3]);
565
566 while (1)
567 {
568 __u32 Last[4];
569 unsigned long Count = 0;
570
571 /* During erase bit 7 is held low and bit 6 toggles, we watch this,
572 should it stop toggling or go high then the erase is completed,
573 or this is not really flash ;> */
574 Last[0] = map->read32(map,(chip->base >> chip->addrshift) + chip->start + off);
575 Last[1] = map->read32(map,(chip->base >> chip->addrshift) + chip->start + off);
576 Last[2] = map->read32(map,(chip->base >> chip->addrshift) + chip->start + off);
577 Count = 3;
578 while (todo_left != 0)
579 {
580 for (J = 0; J != 4; J++)
581 {
582 __u8 Byte1 = (Last[(Count-1)%4] >> (J*8)) & 0xFF;
583 __u8 Byte2 = (Last[(Count-2)%4] >> (J*8)) & 0xFF;
584 __u8 Byte3 = (Last[(Count-3)%4] >> (J*8)) & 0xFF;
585 if (todo[J] == 0)
586 continue;
587
588 if ((Byte1 & (1 << 7)) == 0 && Byte1 != Byte2)
589 {
590 // printk("Check %x %x %x\n",(short)J,(short)Byte1,(short)Byte2);
591 continue;
592 }
593
594 if (Byte1 == Byte2)
595 {
596 jedec_flash_failed(Byte3);
597 return -EIO;
598 }
599
600 todo[J] = 0;
601 todo_left--;
602 }
603
604 /* if (NoTime == 0)
605 Time += HZ/10 - schedule_timeout(HZ/10);*/
606 NoTime = 0;
607
608 Last[Count % 4] = map->read32(map,(chip->base >> chip->addrshift) + chip->start + off);
609 Count++;
610
611 putc('.');
612
613 /* // Count time, max of 15s per sector (according to AMD)
614 if (Time > 15*len/mtd->erasesize*HZ)
615 {
616 printk("mtd: Flash Erase Timed out\n");
617 return -EIO;
618 } */
619 }
620
621 puts("out\n");
622
623 // Skip to the next chip if we used chip erase
624 if (chip->length == chip->size)
625 off = chip->size;
626 else
627 off += chip->sectorsize;
628
629 if (off >= chip->length)
630 break;
631 NoTime = 1;
632 }
633
634 for (J = 0; priv->chips[J].jedec != 0 && J < MAX_JEDEC_CHIPS; J++)
635 {
636 if ((priv->chips[J].base & (~((1<<chip->addrshift)-1))) ==
637 (chip->base & (~((1<<chip->addrshift)-1))))
638 priv->chips[J].length = 0;
639 }
640 }
641
642 puts("done\n");
643 return 0;
644
645 #undef flread
646 #undef flwrite
647 }
648
649 /* This is the simple flash writing function. It writes to every byte, in
650 sequence. It takes care of how to properly address the flash if
651 the flash is interleved. It can only be used if all the chips in the
652 array are identical!*/
653 static int flash_write(struct mtd_info *mtd, loff_t start, size_t len,
654 size_t *retlen, const u_char *buf)
655 {
656 /* Does IO to the currently selected chip. It takes the bank addressing
657 base (which is divisable by the chip size) adds the necesary lower bits
658 of addrshift (interleve index) and then adds the control register index. */
659 #define flread(x) map->read8(map,base+(off&((1<<chip->addrshift)-1))+((x)<<chip->addrshift))
660 #define flwrite(v,x) map->write8(map,v,base+(off&((1<<chip->addrshift)-1))+((x)<<chip->addrshift))
661
662 struct map_info *map = (struct map_info *)mtd->priv;
663 struct jedec_private *priv = (struct jedec_private *)map->fldrv_priv;
664 unsigned long base;
665 unsigned long off;
666
667 if (start + len > mtd->size)
668 return -EIO;
669
670 puts("Here");
671
672 while (len != 0)
673 {
674 struct jedec_flash_chip *chip = priv->chips;
675 unsigned long bank;
676 unsigned long boffset;
677
678 // Compute the base of the flash.
679 off = start % (chip->size << chip->addrshift);
680 base = start - off;
681
682 // Perform banked addressing translation.
683 bank = base & (~(priv->bank_fill[0]-1));
684 boffset = base & (priv->bank_fill[0]-1);
685 bank = (bank/priv->bank_fill[0])*map->bank_size;
686 base = bank + boffset;
687
688 xprintf("Flasing %X %X %X\n",base,chip->size,len);
689
690 // Loop over this page
691 for (; off != (chip->size << chip->addrshift) && len != 0; start++, len--, off++,buf++)
692 {
693 unsigned char oldbyte = map->read8(map,base+off);
694 unsigned char Last[4];
695 unsigned long Count = 0;
696
697 // putc('.');
698
699 if (oldbyte == *buf)
700 continue;
701 if (((~oldbyte) & *buf) != 0)
702 printk("mtd: warn: Trying to set a 0 to a 1\n");
703
704 // Write
705 flwrite(0xAA,0x555);
706 flwrite(0x55,0x2AA);
707 flwrite(0xA0,0x555);
708 map->write8(map,*buf,base + off);
709 Last[0] = map->read8(map,base + off);
710 Last[1] = map->read8(map,base + off);
711 Last[2] = map->read8(map,base + off);
712
713 /* Wait for the flash to finish the operation. We store the last 4
714 status bytes that have been retrieved so we can determine why
715 it failed. The toggle bits keep toggling when there is a
716 failure */
717 for (Count = 3; Last[(Count - 1) % 4] != Last[(Count - 2) % 4] &&
718 Count < 10000; Count++)
719 Last[Count % 4] = map->read8(map,base + off);
720 if (Last[(Count - 1) % 4] != *buf)
721 {
722 jedec_flash_failed(Last[(Count - 3) % 4]);
723 return -EIO;
724 }
725 }
726 }
727 *retlen = len;
728 return 0;
729 }
730
731 /* This is used to enhance the speed of the erase routine,
732 when things are being done to multiple chips it is possible to
733 parallize the operations, particularly full memory erases of multi
734 chip memories benifit */
735 static void jedec_flash_chip_scan(struct jedec_private *priv,unsigned long start,
736 unsigned long len)
737 {
738 unsigned int I;
739
740 // Zero the records
741 for (I = 0; priv->chips[I].jedec != 0 && I < MAX_JEDEC_CHIPS; I++)
742 priv->chips[I].start = priv->chips[I].length = 0;
743
744 // Intersect the region with each chip
745 for (I = 0; priv->chips[I].jedec != 0 && I < MAX_JEDEC_CHIPS; I++)
746 {
747 struct jedec_flash_chip *chip = priv->chips + I;
748 unsigned long ByteStart;
749 unsigned long ChipEndByte = chip->offset + (chip->size << chip->addrshift);
750
751 // End is before this chip or the start is after it
752 if (start+len < chip->offset ||
753 ChipEndByte - (1 << chip->addrshift) < start)
754 continue;
755
756 if (start < chip->offset)
757 {
758 ByteStart = chip->offset;
759 chip->start = 0;
760 }
761 else
762 {
763 chip->start = (start - chip->offset + (1 << chip->addrshift)-1) >> chip->addrshift;
764 ByteStart = start;
765 }
766
767 if (start + len >= ChipEndByte)
768 chip->length = (ChipEndByte - ByteStart) >> chip->addrshift;
769 else
770 chip->length = (start + len - ByteStart + (1 << chip->addrshift)-1) >> chip->addrshift;
771 }
772 }
773 /*}}}*/
774
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.