From 3504e69e3e037368c3f65f47ca5aa30e8783f382 Mon Sep 17 00:00:00 2001 From: Eric Sauvageau Date: Thu, 11 Jul 2013 19:30:29 -0400 Subject: [PATCH] Add support for newer flash chips in latest RT-N66U hardware revision --- .../drivers/mtd/chips/cfi_cmdset_0002.c | 89 +++++++++---------- 1 file changed, 44 insertions(+), 45 deletions(-) diff --git a/release/src-rt/linux/linux-2.6/drivers/mtd/chips/cfi_cmdset_0002.c b/release/src-rt/linux/linux-2.6/drivers/mtd/chips/cfi_cmdset_0002.c index 07efb355611..3d36c058fe9 100644 --- a/release/src-rt/linux/linux-2.6/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/release/src-rt/linux/linux-2.6/drivers/mtd/chips/cfi_cmdset_0002.c @@ -162,9 +162,17 @@ static void fixup_use_write_buffers(struct mtd_info *mtd, void *param) { struct map_info *map = mtd->priv; struct cfi_private *cfi = map->fldrv_priv; + struct cfi_pri_amdstd *extp = cfi->cmdset_priv; + if (cfi->cfiq->BufWriteTimeoutTyp) { DEBUG(MTD_DEBUG_LEVEL1, "Using buffer write method\n" ); mtd->write = cfi_amdstd_write_buffers; + + if (extp->SiliconRevision >= 0x1C) { + mtd->writesize = 512; + mtd->flags &= ~MTD_BIT_WRITEABLE; + printk(KERN_INFO "Enabling Spansion 65nm mode, writesize = 512 bytes\n"); + } } } @@ -294,7 +302,7 @@ struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary) } if (extp->MajorVersion < '0' || extp->MajorVersion > '3' || - (extp->MinorVersion < '0' || extp->MinorVersion > '4')) { + (extp->MinorVersion < '0' || extp->MinorVersion > '5')) { if (cfi->mfr == MANUFACTURER_SAMSUNG && ((extp->MajorVersion == '3' && extp->MinorVersion == '3') || (extp->MajorVersion == '0'))) { @@ -1247,21 +1255,18 @@ static int cfi_amdstd_write_words(struct mtd_info *mtd, loff_t to, size_t len, } -/* - * FIXME: interleaved mode not tested, and probably not supported! - */ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip, unsigned long adr, const u_char *buf, int len) { struct cfi_private *cfi = map->fldrv_priv; unsigned long timeo = jiffies + HZ; - /* see comments in do_write_oneword() regarding uWriteTimeo. */ - unsigned long uWriteTimeout = ( HZ / 1000 ) + 1; + /* see comments in do_write_oneword() regarding uWriteTimeout, 20ms */ + unsigned long uWriteTimeout = ( HZ / 50 ) + 1; int ret = -EIO; unsigned long cmd_adr; - int z, words; - map_word datum; + int z, words, prolog, epilog, buflen = len; + map_word datum, pdat, edat; adr += chip->start; cmd_adr = adr; @@ -1282,6 +1287,21 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip, ENABLE_VPP(map); xip_disable(map, chip, cmd_adr); + /* If start is not bus-aligned, prepend old contents of flash */ + prolog = (adr & (map_bankwidth(map)-1)); + if (prolog) { + adr -= prolog; + cmd_adr -= prolog; + len += prolog; + pdat = map_read(map, adr); + } + /* If end is not bus-aligned, append old contents of flash */ + epilog = ((adr + len) & (map_bankwidth(map)-1)); + if (epilog) { + len += map_bankwidth(map)-epilog; + edat = map_read(map, adr + len - map_bankwidth(map)); + } + cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL); //cfi_send_gen_cmd(0xA0, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); @@ -1296,8 +1316,19 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip, map_write(map, CMD(words - 1), cmd_adr); /* Write data */ z = 0; + if (prolog) { + datum = map_word_load_partial(map, pdat, buf, prolog, + min_t(int, buflen, map_bankwidth(map) - prolog)); + map_write(map, datum, adr); + + z += map_bankwidth(map); + buf += map_bankwidth(map) - prolog; + } while(z < words * map_bankwidth(map)) { - datum = map_word_load(map, buf); + if (epilog && z >= (words-1) * map_bankwidth(map)) + datum = map_word_load_partial(map, edat, buf, 0, epilog); + else + datum = map_word_load(map, buf); map_write(map, datum, adr + z); z += map_bankwidth(map); @@ -1346,8 +1377,10 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip, /* reset on all failures. */ map_write( map, CMD(0xF0), chip->start ); + cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); + cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL); + cfi_send_gen_cmd(0xF0, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); xip_enable(map, chip, adr); - /* FIXME - should have reset delay before continuing */ printk(KERN_WARNING "MTD %s(): software timeout\n", __func__ ); @@ -1379,36 +1412,12 @@ static int cfi_amdstd_write_buffers(struct mtd_info *mtd, loff_t to, size_t len, chipnum = to >> cfi->chipshift; ofs = to - (chipnum << cfi->chipshift); - /* If it's not bus-aligned, do the first word write */ - if (ofs & (map_bankwidth(map)-1)) { - size_t local_len = (-ofs)&(map_bankwidth(map)-1); - if (local_len > len) - local_len = len; - ret = cfi_amdstd_write_words(mtd, ofs + (chipnum<chipshift), - 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; - } - } - - /* Write buffer is worth it only if more than one word to write... */ - while (len >= map_bankwidth(map) * 2) { + while (len) { /* We must not cross write block boundaries */ int size = wbufsize - (ofs & (wbufsize-1)); if (size > len) size = len; - if (size % map_bankwidth(map)) - size -= size % map_bankwidth(map); ret = do_write_buffer(map, &cfi->chips[chipnum], ofs, buf, size); @@ -1428,16 +1437,6 @@ static int cfi_amdstd_write_buffers(struct mtd_info *mtd, loff_t to, size_t len, } } - if (len) { - size_t retlen_dregs = 0; - - ret = cfi_amdstd_write_words(mtd, ofs + (chipnum<chipshift), - len, &retlen_dregs, buf); - - *retlen += retlen_dregs; - return ret; - } - return 0; }