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

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

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

  1 /*
  2  * Common Flash Interface support:
  3  *   AMD & Fujitsu Extended Vendor Command Set (ID 0x0002)
  4  *
  5  * Copyright (C) 2000 Crossnet Co. <info@crossnet.co.jp>
  6  *
  7  * This code is GPL
  8  *
  9  * $Id: cfi_cmdset_0002.c,v 1.1 2000/07/11 12:32:09 dwmw2 Exp $
 10  *
 11  */
 12 
 13 #include <linux/module.h>
 14 #include <linux/types.h>
 15 #include <linux/kernel.h>
 16 #include <linux/sched.h>
 17 #include <asm/io.h>
 18 #include <asm/byteorder.h>
 19 
 20 #include <linux/errno.h>
 21 #include <linux/malloc.h>
 22 #include <linux/delay.h>
 23 #include <linux/mtd/map.h>
 24 #include <linux/mtd/cfi.h>
 25 
 26 #if LINUX_VERSION_CODE < 0x20300
 27 #define set_current_state(x) current->state = (x);
 28 #endif
 29 
 30 static int cfi_amdext_read_2_by_16 (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
 31 static int cfi_amdext_write_2_by_16(struct mtd_info *, loff_t, size_t, size_t *, const u_char *);
 32 static int cfi_amdext_erase_2_by_16 (struct mtd_info *, struct erase_info *);
 33 static void cfi_amdext_sync (struct mtd_info *);
 34 static int cfi_amdext_suspend (struct mtd_info *);
 35 static void cfi_amdext_resume (struct mtd_info *);
 36 
 37 static void cfi_amdext_destroy(struct mtd_info *);
 38 
 39 static void cfi_cmdset_0002(struct map_info *, int, unsigned long);
 40 
 41 static struct mtd_info *cfi_amdext_setup (struct map_info *);
 42 
 43 static const char im_name[] = "cfi_cmdset_0002";
 44 
 45 static void cfi_cmdset_0002(struct map_info *map, int primary, unsigned long base)
 46 {
 47         struct cfi_private *cfi = map->fldrv_priv;
 48         int i;
 49 //      struct cfi_pri_intelext *extp;
 50 
 51         __u16 adr = primary?cfi->cfiq.P_ADR:cfi->cfiq.A_ADR;
 52 
 53         printk(" Amd/Fujitsu Extended Query Table at 0x%4.4X\n", adr);
 54 
 55 
 56         /* If there was an old setup function, decrease its use count */
 57         if (cfi->cmdset_setup)
 58                 inter_module_put(cfi->im_name);
 59         if (cfi->cmdset_priv)
 60                 kfree(cfi->cmdset_priv);
 61 
 62         for (i=0; i< cfi->numchips; i++) {
 63                 cfi->chips[i].word_write_time = 128;
 64                 cfi->chips[i].buffer_write_time = 128;
 65                 cfi->chips[i].erase_time = 1024;
 66         }               
 67                 
 68 
 69         cfi->cmdset_setup = cfi_amdext_setup;
 70         cfi->im_name = im_name;
 71 //      cfi->cmdset_priv = extp;
 72         
 73         return;
 74 }
 75 
 76 static struct mtd_info *cfi_amdext_setup(struct map_info *map)
 77 {
 78         struct cfi_private *cfi = map->fldrv_priv;
 79         struct mtd_info *mtd;
 80 
 81         mtd = kmalloc(sizeof(*mtd), GFP_KERNEL);
 82         printk("number of CFI chips: %d\n", cfi->numchips);
 83 
 84         if (!mtd) {
 85           printk("Failed to allocate memory for MTD device\n");
 86           kfree(cfi->cmdset_priv);
 87           return NULL;
 88         }
 89 
 90         memset(mtd, 0, sizeof(*mtd));
 91         mtd->priv = map;
 92         mtd->type = MTD_NORFLASH;
 93         mtd->erasesize = 0x20000; /* FIXME */
 94         /* Also select the correct geometry setup too */ 
 95         mtd->size = (1 << cfi->cfiq.DevSize) * cfi->numchips * cfi->interleave;
 96         mtd->erase = cfi_amdext_erase_2_by_16;
 97         mtd->read = cfi_amdext_read_2_by_16;
 98         mtd->write = cfi_amdext_write_2_by_16;
 99         mtd->sync = cfi_amdext_sync;
100         mtd->suspend = cfi_amdext_suspend;
101         mtd->resume = cfi_amdext_resume;
102         mtd->flags = MTD_CAP_NORFLASH;
103         map->fldrv_destroy = cfi_amdext_destroy;
104         mtd->name = map->name;
105         return mtd;
106 }
107 
108 static inline int do_read_2_by_16_onechip(struct map_info *map, struct flchip *chip, loff_t adr, size_t len, u_char *buf)
109 {
110         DECLARE_WAITQUEUE(wait, current);
111         unsigned long timeo = jiffies + HZ;
112 
113  retry:
114         spin_lock_bh(chip->mutex);
115 
116         if (chip->state != FL_READY){
117 printk("Waiting for chip to read, status = %d\n", chip->state);
118                 set_current_state(TASK_INTERRUPTIBLE);
119                 add_wait_queue(&chip->wq, &wait);
120                 
121                 spin_unlock_bh(chip->mutex);
122 
123                 schedule();
124                 remove_wait_queue(&chip->wq, &wait);
125 
126                 if(signal_pending(current))
127                         return -EINTR;
128 
129                 timeo = jiffies + HZ;
130 
131                 goto retry;
132         }       
133 
134         adr += chip->start;
135 
136 //      map->write32(map, cpu_to_le32(0x00F000F0), adr);
137 
138         chip->state = FL_READY;
139 
140         map->copy_from(map, buf, adr, len);
141 
142         wake_up(&chip->wq);
143         spin_unlock_bh(chip->mutex);
144 
145         return 0;
146 }
147 
148 static int cfi_amdext_read_2_by_16 (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf)
149 {
150         struct map_info *map = mtd->priv;
151         struct cfi_private *cfi = map->fldrv_priv;
152         unsigned long ofs;
153         int chipnum;
154         int ret = 0;
155 
156         /* ofs: offset within the first chip that the first read should start */
157 
158         chipnum = (from >> cfi->chipshift);
159         chipnum /= (cfi->interleave);
160         ofs = from - (chipnum <<  cfi->chipshift) * (cfi->interleave);
161 
162         *retlen = 0;
163 
164         while (len) {
165                 unsigned long thislen;
166 
167                 if (chipnum >= cfi->numchips)
168                         break;
169 
170                 if (((len + ofs -1) >> cfi->chipshift) / (cfi->interleave))
171                         thislen = (1<<cfi->chipshift) * (cfi->interleave) - ofs;
172                 else
173                         thislen = len;
174 
175                 ret = do_read_2_by_16_onechip(map, &cfi->chips[chipnum], ofs, thislen, buf);
176                 if (ret)
177                         break;
178 
179                 *retlen += thislen;
180                 len -= thislen;
181                 buf += thislen;
182 
183                 ofs = 0;
184                 chipnum++;
185         }
186         return ret;
187 }
188 
189 static inline int do_write_2_by_16_oneword(struct map_info *map, struct flchip *chip, unsigned long adr, __u32 datum)
190 {
191         unsigned long timeo = jiffies + HZ;
192         unsigned int Last[4];
193         unsigned long Count = 0;
194         DECLARE_WAITQUEUE(wait, current);
195         int ret = 0;
196 
197  retry:
198         spin_lock_bh(chip->mutex);
199 
200         if (chip->state != FL_READY){
201 printk("Waiting for chip to write, status = %d\n", chip->state);
202                 set_current_state(TASK_INTERRUPTIBLE);
203                 add_wait_queue(&chip->wq, &wait);
204                 
205                 spin_unlock_bh(chip->mutex);
206 
207                 schedule();
208                 remove_wait_queue(&chip->wq, &wait);
209 printk("Wake up to write:\n");
210                 if(signal_pending(current))
211                         return -EINTR;
212 
213                 timeo = jiffies + HZ;
214 
215                 goto retry;
216         }       
217 
218         chip->state = FL_WRITING;
219 
220         adr += chip->start;
221 
222         map->write32(map, cpu_to_le32(0x00AA00AA), 0x555 *4);
223         map->write32(map, cpu_to_le32(0x00550055), 0x2AA *4);
224         map->write32(map, cpu_to_le32(0x00A000A0), 0x555 *4);
225         map->write32(map, cpu_to_le32(datum), adr);
226 
227         spin_unlock_bh(chip->mutex);
228         udelay(chip->word_write_time);
229         spin_lock_bh(chip->mutex);
230 
231         Last[0] = map->read32(map, adr);
232         Last[1] = map->read32(map, adr);
233         Last[2] = map->read32(map, adr);
234 
235         for (Count = 3; Last[(Count - 1) % 4] != Last[(Count - 2) % 4] && Count < 10000; Count++){
236                 udelay(10);
237 
238                 Last[Count % 4] = map->read32(map, adr);
239         }
240 
241         if (Last[(Count - 1) % 4] != datum){
242                 map->write32(map, cpu_to_le32(0x00F000F0), adr);
243                 ret = -EIO;
244         }       
245 
246         chip->state = FL_READY;
247         wake_up(&chip->wq);
248         spin_unlock_bh(chip->mutex);
249 
250         return ret;
251 }
252 
253 
254 static int cfi_amdext_write_2_by_16 (struct mtd_info *mtd, loff_t to , size_t len, size_t *retlen, const u_char *buf)
255 {
256         struct map_info *map = mtd->priv;
257         struct cfi_private *cfi = map->fldrv_priv;
258         int ret = 0;
259         int chipnum;
260         unsigned long ofs;
261 
262         *retlen = 0;
263 
264         chipnum = (to >> cfi->chipshift);
265         chipnum /= cfi->interleave;
266         ofs = to  - (chipnum << cfi->chipshift) * cfi->interleave;
267 
268         while(len > 3) {
269 
270                 ret = do_write_2_by_16_oneword(map, &cfi->chips[chipnum],
271                                                ofs, *(__u32 *)buf);
272                 if (ret)
273                         return ret;
274 
275                 ofs += 4;
276                 buf += 4;
277                 (*retlen) += 4;
278                 len -= 4;
279 
280                 if ((ofs >> cfi->chipshift) / cfi->interleave) {
281                         chipnum ++; 
282                         ofs = 0;
283                         if (chipnum == cfi->numchips)
284                                 return 0;
285                 }
286         }
287 
288         if (len) {
289                 unsigned int tmp;
290 
291                 /* Final byte to write */
292 #if defined(__LITTLE_ENDIAN)
293                 tmp = map->read32(map, ofs);
294 
295                 tmp = 0xffffffff >> (len*8);
296                 tmp = tmp << (len*8);
297 
298                 tmp |= *(__u32 *)(buf);
299 
300                 ret = do_write_2_by_16_oneword(map, &cfi->chips[chipnum],
301                                                ofs, tmp);
302 
303 #elif defined(__BIG_ENDIAN) 
304 #error not support big endian yet
305 #else
306 #error define a sensible endianness
307 #endif
308 
309                 if (ret) 
310                         return ret;
311                 
312                 (*retlen)+=len;
313         }
314 
315         return 0;
316 }
317 
318 
319 static inline int do_erase_2_by_16_oneblock(struct map_info *map, struct flchip *chip, unsigned long adr)
320 {
321         unsigned int status;
322         unsigned long timeo = jiffies + HZ;
323         DECLARE_WAITQUEUE(wait, current);
324 
325  retry:
326         spin_lock_bh(chip->mutex);
327 
328         if (chip->state != FL_READY){
329                 set_current_state(TASK_INTERRUPTIBLE);
330                 add_wait_queue(&chip->wq, &wait);
331                 
332                 spin_unlock_bh(chip->mutex);
333 
334                 schedule();
335                 remove_wait_queue(&chip->wq, &wait);
336 
337                 if(signal_pending(current))
338                         return -EINTR;
339 
340                 timeo = jiffies + HZ;
341 
342                 goto retry;
343         }       
344 
345         chip->state = FL_ERASING;
346 
347         adr += chip->start;
348 
349         map->write32(map, cpu_to_le32(0x00AA00AA), 0x555 *4);
350         map->write32(map, cpu_to_le32(0x00550055), 0x2AA *4);
351         map->write32(map, cpu_to_le32(0x00800080), 0x555 *4);
352         map->write32(map, cpu_to_le32(0x00AA00AA), 0x555 *4);
353         map->write32(map, cpu_to_le32(0x00550055), 0x2AA *4);
354         map->write32(map, cpu_to_le32(0x00300030), adr);
355 
356         
357         timeo = jiffies + (HZ*20);
358 
359         spin_unlock_bh(chip->mutex);
360         schedule_timeout(HZ);
361         spin_lock_bh(chip->mutex);
362 
363         /* FIXME. Use a timer to check this, and return immediately. */
364         /* Once the state machine's known to be working I'll do that */
365 
366         while ( ( (status = le32_to_cpu(map->read32(map, 0x00))) & 0x80808080 ) != 0x80808080 ) {
367                 static int z=0;
368 
369                 if (chip->state != FL_ERASING) {
370                         /* Someone's suspended the erase. Sleep */
371                         set_current_state(TASK_INTERRUPTIBLE);
372                         add_wait_queue(&chip->wq, &wait);
373                         
374                         spin_unlock_bh(chip->mutex);
375                         printk("erase suspended. Sleeping\n");
376                         
377                         schedule();
378                         remove_wait_queue(&chip->wq, &wait);
379                         
380                         if (signal_pending(current))
381                                 return -EINTR;
382                         
383                         timeo = jiffies + (HZ*2); /* FIXME */
384                         spin_lock_bh(chip->mutex);
385                         continue;
386                 }
387 
388                 /* OK Still waiting */
389                 if (time_after(jiffies, timeo)) {
390                         chip->state = FL_READY;
391                         spin_unlock_bh(chip->mutex);
392                         printk("waiting for erase to complete timed out.");
393                         return -EIO;
394                 }
395                 
396                 /* Latency issues. Drop the lock, wait a while and retry */
397                 spin_unlock_bh(chip->mutex);
398 
399                 z++;
400                 if ( 0 && !(z % 100 )) 
401                         printk("chip not ready yet after erase. looping\n");
402 
403                 udelay(1);
404                 
405                 spin_lock_bh(chip->mutex);
406                 continue;
407         }
408         
409         /* Done and happy. */
410         chip->state = FL_READY;
411         wake_up(&chip->wq);
412         spin_unlock_bh(chip->mutex);
413         printk("erase ret OK\n");
414         return 0;
415 }
416 
417 static int cfi_amdext_erase_2_by_16 (struct mtd_info *mtd, struct erase_info *instr)
418 {
419         struct map_info *map = mtd->priv;
420         struct cfi_private *cfi = map->fldrv_priv;
421         unsigned long adr, len;
422         int chipnum, ret = 0;
423 
424 //printk("erase : 0x%x 0x%x 0x%x\n", instr->addr, instr->len, mtd->size);
425 
426         if (instr->addr & (mtd->erasesize - 1))
427                 return -EINVAL;
428 
429         if (instr->len & (mtd->erasesize -1))
430                 return -EINVAL;
431 
432         if ((instr->len + instr->addr) > mtd->size)
433                 return -EINVAL;
434 
435         chipnum = instr->addr >> cfi->chipshift;
436         chipnum /= cfi->interleave;
437         adr = instr->addr - (chipnum << cfi->chipshift) * (cfi->interleave);
438         len = instr->len;
439 
440         printk("erase : 0x%lx 0x%lx 0x%x 0x%lx\n", adr, len, chipnum, mtd->size);
441 
442         while(len) {
443 //printk("erase : 0x%x 0x%x 0x%x 0x%x\n", chipnum, adr, len, cfi->chipshift);
444                 ret = do_erase_2_by_16_oneblock(map, &cfi->chips[chipnum], adr);
445 
446                 if (ret)
447                         return ret;
448 
449                 adr += mtd->erasesize;
450                 len -= mtd->erasesize;
451 
452                 if ((adr >> cfi->chipshift) / (cfi->interleave)) {
453                         adr = 0;
454                         chipnum++;
455                         
456                         if (chipnum >= cfi->numchips)
457                         break;
458                 }
459         }
460                 
461         if (instr->callback)
462                 instr->callback(instr);
463         
464         return 0;
465 }
466 
467 
468 
469 static void cfi_amdext_sync (struct mtd_info *mtd)
470 {
471         struct map_info *map = mtd->priv;
472         struct cfi_private *cfi = map->fldrv_priv;
473         int i;
474         struct flchip *chip;
475         int ret = 0;
476         DECLARE_WAITQUEUE(wait, current);
477 printk("sync\n");
478 
479         for (i=0; !ret && i<cfi->numchips; i++) {
480                 chip = &cfi->chips[i];
481 
482         retry:
483                 spin_lock_bh(chip->mutex);
484 
485                 switch(chip->state) {
486                 case FL_READY:
487                 case FL_STATUS:
488                 case FL_CFI_QUERY:
489                 case FL_JEDEC_QUERY:
490                         chip->oldstate = chip->state;
491                         chip->state = FL_SYNCING;
492                         /* No need to wake_up() on this state change - 
493                          * as the whole point is that nobody can do anything
494                          * with the chip now anyway.
495                          */
496                         spin_unlock_bh(chip->mutex);
497                         break;
498 
499                 default:
500                         /* Not an idle state */
501                         add_wait_queue(&chip->wq, &wait);
502                         
503                         spin_unlock_bh(chip->mutex);
504 
505                         schedule();
506                         
507                         remove_wait_queue(&chip->wq, &wait);
508 
509                         goto retry;
510                 }
511         }
512 
513         /* Unlock the chips again */
514 
515         for (i--; i >=0; i--) {
516                 chip = &cfi->chips[i];
517 
518                 spin_lock_bh(chip->mutex);
519                 
520                 if (chip->state == FL_SYNCING) {
521                         chip->state = chip->oldstate;
522                         wake_up(&chip->wq);
523                 }
524                 spin_unlock_bh(chip->mutex);
525         }
526 printk("sync end\n");
527 }
528 
529 
530 static int cfi_amdext_suspend(struct mtd_info *mtd)
531 {
532         struct map_info *map = mtd->priv;
533         struct cfi_private *cfi = map->fldrv_priv;
534         int i;
535         struct flchip *chip;
536         int ret = 0;
537 //printk("suspend\n");
538 
539         for (i=0; !ret && i<cfi->numchips; i++) {
540                 chip = &cfi->chips[i];
541 
542                 spin_lock_bh(chip->mutex);
543 
544                 switch(chip->state) {
545                 case FL_READY:
546                 case FL_STATUS:
547                 case FL_CFI_QUERY:
548                 case FL_JEDEC_QUERY:
549                         chip->oldstate = chip->state;
550                         chip->state = FL_PM_SUSPENDED;
551                         /* No need to wake_up() on this state change - 
552                          * as the whole point is that nobody can do anything
553                          * with the chip now anyway.
554                          */
555                         spin_unlock_bh(chip->mutex);
556                         break;
557 
558                 default:
559                         ret = -EAGAIN;
560                         break;
561                 }
562         }
563 
564         /* Unlock the chips again */
565 
566         for (i--; i >=0; i--) {
567                 chip = &cfi->chips[i];
568 
569                 spin_lock_bh(chip->mutex);
570                 
571                 if (chip->state == FL_PM_SUSPENDED) {
572                         chip->state = chip->oldstate;
573                         wake_up(&chip->wq);
574                 }
575                 spin_unlock_bh(chip->mutex);
576         }
577         
578         return ret;
579 }
580 
581 static void cfi_amdext_resume(struct mtd_info *mtd)
582 {
583         struct map_info *map = mtd->priv;
584         struct cfi_private *cfi = map->fldrv_priv;
585         int i;
586         struct flchip *chip;
587 //printk("resume\n");
588 
589         for (i=0; i<cfi->numchips; i++) {
590         
591                 chip = &cfi->chips[i];
592 
593                 spin_lock_bh(chip->mutex);
594                 
595                 if (chip->state == FL_PM_SUSPENDED) {
596                         chip->state = chip->oldstate;
597                         wake_up(&chip->wq);
598                 }
599                 else
600                         printk("Argh. Chip not in PM_SUSPENDED state upon resume()\n");
601 
602                 spin_unlock_bh(chip->mutex);
603         }
604 }
605 
606 static void cfi_amdext_destroy(struct mtd_info *mtd)
607 {
608         struct map_info *map = mtd->priv;
609         struct cfi_private *cfi = map->fldrv_priv;
610         kfree(cfi->cmdset_priv);
611         inter_module_put(cfi->im_name);
612         kfree(cfi);
613 }
614 
615 
616 static int __init cfi_amdext_init(void)
617 {
618         inter_module_register(im_name, THIS_MODULE, &cfi_cmdset_0002);
619         return 0;
620 }
621 
622 static void __exit cfi_amdext_exit(void)
623 {
624         inter_module_unregister(im_name);
625 }
626 
627 module_init(cfi_amdext_init);
628 module_exit(cfi_amdext_exit);
629 

~ [ 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.