📄 1009.mtd.patch
字号:
diff -Naur --exclude=CVS --exclude='*.o' --exclude='*.a' --exclude='*.so' --exclude='*.elf' --exclude=System.map --exclude=Makefile.d --exclude='*log' --exclude='*log2' --exclude='*~' --exclude='.*~' --exclude='.#*' --exclude='*.bak' --exclude='*.orig' --exclude='*.rej' --exclude='core.[0-9]*' --exclude=.depend --exclude='.*.o.flags' --exclude='*.gz' --exclude=.depend --exclude='.*.o.flags' --exclude='*.gz' --exclude=vmlinux --exclude=vmlinux.bin --exclude=yamon-02.06-SIGMADESIGNS-01_el.bin linuxmips-2.4.30.ref/drivers/mtd/chips/cfi_cmdset_0002.c linuxmips-2.4.30/drivers/mtd/chips/cfi_cmdset_0002.c--- linuxmips-2.4.30.ref/drivers/mtd/chips/cfi_cmdset_0002.c 2004-11-18 16:28:39.000000000 -0800+++ linuxmips-2.4.30/drivers/mtd/chips/cfi_cmdset_0002.c 2006-08-22 15:10:17.000000000 -0700@@ -18,6 +18,7 @@ #include <linux/sched.h> #include <asm/io.h> #include <asm/byteorder.h>+#include <asm/unaligned.h> #include <linux/errno.h> #include <linux/slab.h>@@ -29,7 +30,8 @@ #define AMD_BOOTLOC_BUG static int cfi_amdstd_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *);-static int cfi_amdstd_write(struct mtd_info *, loff_t, size_t, size_t *, const u_char *);+static int cfi_amdstd_write_words(struct mtd_info *, loff_t, size_t, size_t *, const u_char *);+static int cfi_amdstd_write_buffers(struct mtd_info *, loff_t, size_t, size_t *, const u_char *); static int cfi_amdstd_erase_chip(struct mtd_info *, struct erase_info *); static int cfi_amdstd_erase_onesize(struct mtd_info *, struct erase_info *); static int cfi_amdstd_erase_varsize(struct mtd_info *, struct erase_info *);@@ -223,7 +225,19 @@ else mtd->erase = cfi_amdstd_erase_onesize; mtd->read = cfi_amdstd_read;- mtd->write = cfi_amdstd_write;+#if 1+ if( cfi->cfiq->BufWriteTimeoutTyp ) + {+ printk( "Using buffer write method\n" );+ mtd->write = cfi_amdstd_write_buffers;+ } else {+#endif+ printk( "Using word write method\n" );+ mtd->write = cfi_amdstd_write_words;+#if 1+ }+#endif+ break; default:@@ -232,7 +246,7 @@ break; } if (cfi->fast_prog) {- /* In cfi_amdstd_write() we frob the protection stuff+ /* In cfi_amdstd_write_words() we frob the protection stuff without paying any attention to the state machine. This upsets in-progress erases. So we turn this flag off for now till the code gets fixed. */@@ -461,6 +475,11 @@ unsigned int dq6, dq5; struct cfi_private *cfi = map->fldrv_priv; DECLARE_WAITQUEUE(wait, current);+ int ret = 0;+#ifdef CONFIG_TANGO2+ unsigned int newv, oldv;+ unsigned int mask = ((cfi_buswidth_is_2()) ? 0xffff : 0xff);+#endif retry: cfi_spin_lock(chip->mutex);@@ -487,6 +506,12 @@ } chip->state = FL_WRITING;+#ifdef CONFIG_TANGO2+ if (adr == 0)+ oldv = datum;+ else+ oldv = *(volatile unsigned int *)map->map_priv_1;+#endif adr += chip->start; ENABLE_VPP(map);@@ -510,15 +535,28 @@ or tells us why it failed. */ dq6 = CMD(1<<6); dq5 = CMD(1<<5);- timeo = jiffies + (HZ/1000); /* setting timeout to 1ms for now */ - oldstatus = cfi_read(map, adr);- status = cfi_read(map, adr);-- while( (status & dq6) != (oldstatus & dq6) && - (status & dq5) != dq5 &&- !time_after(jiffies, timeo) ) {+ timeo = jiffies + ((((chip->word_write_time << cfi->cfiq->WordWriteTimeoutMax) * HZ) / 1000000) == 0 ? + (HZ/10) /* setting timeout to 100ms */ :+ (((chip->word_write_time << cfi->cfiq->WordWriteTimeoutMax) * HZ) / 1000000) + 1); ++ /*+ * some toshiba flash acts weird with the toggle bits, so+ * we check the datum as well+ */+ do {+ oldstatus = cfi_read( map, adr );+ status = cfi_read( map, adr );+#ifdef CONFIG_TANGO2+ newv = *(volatile unsigned int *)map->map_priv_1;+ if ((oldv & mask) == (newv & mask)) {+#endif+ if (!((status != datum || ((status & dq6) != (oldstatus & dq6) && (status & dq5) != dq5))))+ break; +#ifdef CONFIG_TANGO2+ }+#endif if (need_resched()) { cfi_spin_unlock(chip->mutex); yield();@@ -526,9 +564,7 @@ } else udelay(1); - oldstatus = cfi_read( map, adr );- status = cfi_read( map, adr );- }+ } while( !time_after(jiffies, timeo) ); if( (status & dq6) != (oldstatus & dq6) ) { /* The erasing didn't stop?? */@@ -553,7 +589,7 @@ wake_up(&chip->wq); cfi_spin_unlock(chip->mutex); DISABLE_VPP(map);- return -EIO;+ ret = -EIO; } } @@ -562,10 +598,145 @@ wake_up(&chip->wq); cfi_spin_unlock(chip->mutex); - return 0;+ return ret;+}++static inline int do_write_buffer(struct map_info *map, struct flchip *chip, + unsigned long adr, const u_char *buf, int len)+{+ unsigned long timeo = jiffies + HZ;+ unsigned int status;+ unsigned int dq7, dq5, dq1; + struct cfi_private *cfi = map->fldrv_priv;+ DECLARE_WAITQUEUE(wait, current);+ int ret = 0;+ int z;+ __u32 datum = 0;+#ifdef CONFIG_TANGO2+ unsigned int newv, oldv;+ unsigned int mask = ((cfi_buswidth_is_2()) ? 0xffff : 0xff);+#endif+ + if( (!cfi_buswidth_is_2() && !cfi_buswidth_is_4()) ||+ !len || (len % CFIDEV_BUSWIDTH) )+ return -EINVAL;+ + retry:+ cfi_spin_lock(chip->mutex);++ if (chip->state != FL_READY) {+ set_current_state(TASK_UNINTERRUPTIBLE);+ add_wait_queue(&chip->wq, &wait);+ + cfi_spin_unlock(chip->mutex);++ schedule();+ remove_wait_queue(&chip->wq, &wait);+ timeo = jiffies + HZ;++ goto retry;+ } ++ chip->state = FL_WRITING_TO_BUFFER;+#ifdef CONFIG_TANGO2+ if (adr == 0)+ oldv = get_unaligned((__u32*)buf);+ else+ oldv = *(volatile unsigned int *)map->map_priv_1;+#endif++ adr += chip->start;+ ENABLE_VPP(map);++ /* write buffers algorithm taken from Am29LV641MH/L manual */+ cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL);+ cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL);+ cfi_write(map, CMD(0x25), adr);+ cfi_write(map, CMD(len/CFIDEV_BUSWIDTH-1), adr); /* word count */++ /* Write data */+ for (z = 0; z < len; z += CFIDEV_BUSWIDTH) {+ if (cfi_buswidth_is_2())+ map->write16 (map, datum = *((__u16*)buf)++, adr+z);+ else if (cfi_buswidth_is_4())+ map->write32 (map, datum = *((__u32*)buf)++, adr+z);+ }++ /* start program */+ cfi_write(map, CMD(0x29), adr);++ cfi_spin_unlock(chip->mutex);+ cfi_udelay(chip->buffer_write_time);+ cfi_spin_lock(chip->mutex);++ /* use data polling algorithm */+ dq1 = CMD(1<<1);+ dq5 = CMD(1<<5);+ dq7 = CMD(1<<7);++ timeo = jiffies + ((((chip->buffer_write_time << cfi->cfiq->BufWriteTimeoutMax) * HZ) / 1000000) == 0 ? + (HZ/10) /* setting timeout to 100ms */ :+ (((chip->buffer_write_time << cfi->cfiq->BufWriteTimeoutMax) * HZ) / 1000000) + 1); ++ z -= CFIDEV_BUSWIDTH; /* go to last written address */+ do {+ status = cfi_read(map, adr+z);++#ifdef CONFIG_TANGO2+ newv = *(volatile unsigned int *)map->map_priv_1;+ if ((oldv & mask) == (newv & mask)) {+#endif+ if( (dq7 & status) == (dq7 & datum) )+ break;+ if( ((dq5 & status) == dq5) ||+ ((dq1 & status) == dq1) ) {+ status = cfi_read( map, adr+z );+ if( (dq7 & status) != (dq7 & datum) )+ {+ ret = -EIO;+ break;+ } else break;+ }+#ifdef CONFIG_TANGO2+ }+#endif++ if (need_resched()) {+ cfi_spin_unlock(chip->mutex);+ yield();+ cfi_spin_lock(chip->mutex);+ } else + udelay(1);++ } while( !time_after(jiffies, timeo) );++ if( !ret && time_after( jiffies, timeo ) )+ {+ printk(KERN_WARNING "Waiting for write to complete timed out in do_write_buffer."); + ret = -EIO;+ }++ if( ret == -EIO ) {+ if( (dq1 & status) == dq1 ) {+ printk( "Flash write to Buffer aborted @ 0x%lx = 0x%x\n", adr, status );+ cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL);+ cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL);+ cfi_send_gen_cmd(0xF0, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL);+ } else {+ printk( "Flash write to buffer failed @ 0x%lx = 0x%x\n", adr, status );+ cfi_write(map, CMD(0xF0), chip->start);+ }+ }++ DISABLE_VPP(map);+ chip->state = FL_READY;+ wake_up(&chip->wq);+ cfi_spin_unlock(chip->mutex);++ return ret; } -static int cfi_amdstd_write (struct mtd_info *mtd, loff_t to , size_t len, size_t *retlen, const u_char *buf)+static int cfi_amdstd_write_words (struct mtd_info *mtd, loff_t to , size_t len, size_t *retlen, const u_char *buf) { struct map_info *map = mtd->priv; struct cfi_private *cfi = map->fldrv_priv;@@ -632,9 +803,9 @@ if (cfi_buswidth_is_1()) { datum = *(__u8*)buf; } else if (cfi_buswidth_is_2()) {- datum = *(__u16*)buf;+ datum = get_unaligned((__u16*)buf); } else if (cfi_buswidth_is_4()) {- datum = *(__u32*)buf;+ datum = get_unaligned((__u32*)buf); } else { return -EINVAL; }@@ -710,6 +881,82 @@ return 0; } +static int cfi_amdstd_write_buffers (struct mtd_info *mtd, loff_t to , size_t len, size_t *retlen, const u_char *buf)+{+ struct map_info *map = mtd->priv;+ struct cfi_private *cfi = map->fldrv_priv;+ int wbufsize = CFIDEV_INTERLEAVE << cfi->cfiq->MaxBufWriteSize;+ int ret = 0;+ int chipnum;+ unsigned long ofs;+ + /* code derived from cfi_cmdset_0001.c:cfi_intelext_write_words */+ *retlen = 0;+ if (!len)+ return 0;++ chipnum = to >> cfi->chipshift;+ ofs = to - (chipnum << cfi->chipshift);++ /* If it's not bus-aligned, do the first word write */+ if (ofs & (CFIDEV_BUSWIDTH-1)) {+ size_t local_len = (-ofs)&(CFIDEV_BUSWIDTH-1);+ if (local_len > len)+ local_len = len;+ ret = cfi_amdstd_write_words(mtd, to, local_len,+ retlen, buf);+ if (ret)+ return ret;+ ofs += local_len;+ buf += local_len;+ len -= local_len;++ if (ofs >> cfi->chipshift) {+ chipnum ++;+ ofs = 0;+ if (chipnum == cfi->numchips)+ return 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -