From f9c4d632005b30b5f89221654a383c332377be9e Mon Sep 17 00:00:00 2001 From: Vicente Date: Fri, 12 Jul 2013 17:06:32 +0200 Subject: [PATCH] Add support for newer flash chips in latest RT-N66U hardware revision https://github.com/RMerl/asuswrt-merlin/commit/3504e69e3e037368c3f65f47ca5aa30e8783f382 --- .../linux-2.6/drivers/mtd/chips/cfi_cmdset_0002.c | 88 ++++++++++------------ 1 file changed, 41 insertions(+), 47 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 f04e9e9a66..d81a69022d 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 @@ -165,7 +165,12 @@ static void fixup_use_write_buffers(struct mtd_info *mtd, void *param) 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"); } + } } /* Atmel chips don't use the same PRI format as AMD chips */ @@ -294,7 +299,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'))) { @@ -1244,22 +1249,18 @@ static int cfi_amdstd_write_words(struct mtd_info *mtd, loff_t to, size_t len, return 0; } - -/* - * 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; @@ -1279,6 +1280,20 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip, XIP_INVAL_CACHED_RANGE(map, adr, len); 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); @@ -1295,9 +1310,20 @@ 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)) { + 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); + map_write(map, datum, adr + z); z += map_bankwidth(map); buf += map_bankwidth(map); @@ -1345,8 +1371,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__ ); @@ -1378,37 +1406,13 @@ 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); if (ret) @@ -1427,16 +1431,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; } -- 2.11.4.GIT