~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/drivers/mtd/jedec.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.