diff options
| author | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
|---|---|---|
| committer | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
| commit | 8dea78da5cee153b8af9c07a2745f6c55057fe12 (patch) | |
| tree | a8f4d49d63b1ecc92f2fddceba0655b2472c5bd9 /drivers/mtd/chips | |
| parent | 406089d01562f1e2bf9f089fd7637009ebaad589 (diff) | |
Patched in Tegra support.
Diffstat (limited to 'drivers/mtd/chips')
| -rw-r--r-- | drivers/mtd/chips/Kconfig | 11 | ||||
| -rw-r--r-- | drivers/mtd/chips/cfi_cmdset_0001.c | 103 | ||||
| -rw-r--r-- | drivers/mtd/chips/cfi_cmdset_0002.c | 507 | ||||
| -rw-r--r-- | drivers/mtd/chips/cfi_cmdset_0020.c | 46 | ||||
| -rw-r--r-- | drivers/mtd/chips/cfi_util.c | 6 | ||||
| -rw-r--r-- | drivers/mtd/chips/chipreg.c | 5 | ||||
| -rw-r--r-- | drivers/mtd/chips/fwh_lock.h | 7 | ||||
| -rw-r--r-- | drivers/mtd/chips/jedec_probe.c | 34 | ||||
| -rw-r--r-- | drivers/mtd/chips/map_absent.c | 10 | ||||
| -rw-r--r-- | drivers/mtd/chips/map_ram.c | 14 | ||||
| -rw-r--r-- | drivers/mtd/chips/map_rom.c | 13 |
11 files changed, 245 insertions, 511 deletions
diff --git a/drivers/mtd/chips/Kconfig b/drivers/mtd/chips/Kconfig index e469b01d40d..b1e3c26edd6 100644 --- a/drivers/mtd/chips/Kconfig +++ b/drivers/mtd/chips/Kconfig | |||
| @@ -43,6 +43,9 @@ choice | |||
| 43 | prompt "Flash cmd/query data swapping" | 43 | prompt "Flash cmd/query data swapping" |
| 44 | depends on MTD_CFI_ADV_OPTIONS | 44 | depends on MTD_CFI_ADV_OPTIONS |
| 45 | default MTD_CFI_NOSWAP | 45 | default MTD_CFI_NOSWAP |
| 46 | |||
| 47 | config MTD_CFI_NOSWAP | ||
| 48 | bool "NO" | ||
| 46 | ---help--- | 49 | ---help--- |
| 47 | This option defines the way in which the CPU attempts to arrange | 50 | This option defines the way in which the CPU attempts to arrange |
| 48 | data bits when writing the 'magic' commands to the chips. Saying | 51 | data bits when writing the 'magic' commands to the chips. Saying |
| @@ -52,8 +55,12 @@ choice | |||
| 52 | Specific arrangements are possible with the BIG_ENDIAN_BYTE and | 55 | Specific arrangements are possible with the BIG_ENDIAN_BYTE and |
| 53 | LITTLE_ENDIAN_BYTE, if the bytes are reversed. | 56 | LITTLE_ENDIAN_BYTE, if the bytes are reversed. |
| 54 | 57 | ||
| 55 | config MTD_CFI_NOSWAP | 58 | If you have a LART, on which the data (and address) lines were |
| 56 | bool "NO" | 59 | connected in a fashion which ensured that the nets were as short |
| 60 | as possible, resulting in a bit-shuffling which seems utterly | ||
| 61 | random to the untrained eye, you need the LART_ENDIAN_BYTE option. | ||
| 62 | |||
| 63 | Yes, there really exists something sicker than PDP-endian :) | ||
| 57 | 64 | ||
| 58 | config MTD_CFI_BE_BYTE_SWAP | 65 | config MTD_CFI_BE_BYTE_SWAP |
| 59 | bool "BIG_ENDIAN_BYTE" | 66 | bool "BIG_ENDIAN_BYTE" |
diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c index 77514430f1f..e1e122f2f92 100644 --- a/drivers/mtd/chips/cfi_cmdset_0001.c +++ b/drivers/mtd/chips/cfi_cmdset_0001.c | |||
| @@ -87,7 +87,7 @@ static int cfi_intelext_partition_fixup(struct mtd_info *, struct cfi_private ** | |||
| 87 | 87 | ||
| 88 | static int cfi_intelext_point (struct mtd_info *mtd, loff_t from, size_t len, | 88 | static int cfi_intelext_point (struct mtd_info *mtd, loff_t from, size_t len, |
| 89 | size_t *retlen, void **virt, resource_size_t *phys); | 89 | size_t *retlen, void **virt, resource_size_t *phys); |
| 90 | static int cfi_intelext_unpoint(struct mtd_info *mtd, loff_t from, size_t len); | 90 | static void cfi_intelext_unpoint(struct mtd_info *mtd, loff_t from, size_t len); |
| 91 | 91 | ||
| 92 | static int chip_ready (struct map_info *map, struct flchip *chip, unsigned long adr, int mode); | 92 | static int chip_ready (struct map_info *map, struct flchip *chip, unsigned long adr, int mode); |
| 93 | static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr, int mode); | 93 | static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr, int mode); |
| @@ -262,9 +262,9 @@ static void fixup_st_m28w320cb(struct mtd_info *mtd) | |||
| 262 | static void fixup_use_point(struct mtd_info *mtd) | 262 | static void fixup_use_point(struct mtd_info *mtd) |
| 263 | { | 263 | { |
| 264 | struct map_info *map = mtd->priv; | 264 | struct map_info *map = mtd->priv; |
| 265 | if (!mtd->_point && map_is_linear(map)) { | 265 | if (!mtd->point && map_is_linear(map)) { |
| 266 | mtd->_point = cfi_intelext_point; | 266 | mtd->point = cfi_intelext_point; |
| 267 | mtd->_unpoint = cfi_intelext_unpoint; | 267 | mtd->unpoint = cfi_intelext_unpoint; |
| 268 | } | 268 | } |
| 269 | } | 269 | } |
| 270 | 270 | ||
| @@ -274,8 +274,8 @@ static void fixup_use_write_buffers(struct mtd_info *mtd) | |||
| 274 | struct cfi_private *cfi = map->fldrv_priv; | 274 | struct cfi_private *cfi = map->fldrv_priv; |
| 275 | if (cfi->cfiq->BufWriteTimeoutTyp) { | 275 | if (cfi->cfiq->BufWriteTimeoutTyp) { |
| 276 | printk(KERN_INFO "Using buffer write method\n" ); | 276 | printk(KERN_INFO "Using buffer write method\n" ); |
| 277 | mtd->_write = cfi_intelext_write_buffers; | 277 | mtd->write = cfi_intelext_write_buffers; |
| 278 | mtd->_writev = cfi_intelext_writev; | 278 | mtd->writev = cfi_intelext_writev; |
| 279 | } | 279 | } |
| 280 | } | 280 | } |
| 281 | 281 | ||
| @@ -443,15 +443,15 @@ struct mtd_info *cfi_cmdset_0001(struct map_info *map, int primary) | |||
| 443 | mtd->type = MTD_NORFLASH; | 443 | mtd->type = MTD_NORFLASH; |
| 444 | 444 | ||
| 445 | /* Fill in the default mtd operations */ | 445 | /* Fill in the default mtd operations */ |
| 446 | mtd->_erase = cfi_intelext_erase_varsize; | 446 | mtd->erase = cfi_intelext_erase_varsize; |
| 447 | mtd->_read = cfi_intelext_read; | 447 | mtd->read = cfi_intelext_read; |
| 448 | mtd->_write = cfi_intelext_write_words; | 448 | mtd->write = cfi_intelext_write_words; |
| 449 | mtd->_sync = cfi_intelext_sync; | 449 | mtd->sync = cfi_intelext_sync; |
| 450 | mtd->_lock = cfi_intelext_lock; | 450 | mtd->lock = cfi_intelext_lock; |
| 451 | mtd->_unlock = cfi_intelext_unlock; | 451 | mtd->unlock = cfi_intelext_unlock; |
| 452 | mtd->_is_locked = cfi_intelext_is_locked; | 452 | mtd->is_locked = cfi_intelext_is_locked; |
| 453 | mtd->_suspend = cfi_intelext_suspend; | 453 | mtd->suspend = cfi_intelext_suspend; |
| 454 | mtd->_resume = cfi_intelext_resume; | 454 | mtd->resume = cfi_intelext_resume; |
| 455 | mtd->flags = MTD_CAP_NORFLASH; | 455 | mtd->flags = MTD_CAP_NORFLASH; |
| 456 | mtd->name = map->name; | 456 | mtd->name = map->name; |
| 457 | mtd->writesize = 1; | 457 | mtd->writesize = 1; |
| @@ -600,12 +600,12 @@ static struct mtd_info *cfi_intelext_setup(struct mtd_info *mtd) | |||
| 600 | } | 600 | } |
| 601 | 601 | ||
| 602 | #ifdef CONFIG_MTD_OTP | 602 | #ifdef CONFIG_MTD_OTP |
| 603 | mtd->_read_fact_prot_reg = cfi_intelext_read_fact_prot_reg; | 603 | mtd->read_fact_prot_reg = cfi_intelext_read_fact_prot_reg; |
| 604 | mtd->_read_user_prot_reg = cfi_intelext_read_user_prot_reg; | 604 | mtd->read_user_prot_reg = cfi_intelext_read_user_prot_reg; |
| 605 | mtd->_write_user_prot_reg = cfi_intelext_write_user_prot_reg; | 605 | mtd->write_user_prot_reg = cfi_intelext_write_user_prot_reg; |
| 606 | mtd->_lock_user_prot_reg = cfi_intelext_lock_user_prot_reg; | 606 | mtd->lock_user_prot_reg = cfi_intelext_lock_user_prot_reg; |
| 607 | mtd->_get_fact_prot_info = cfi_intelext_get_fact_prot_info; | 607 | mtd->get_fact_prot_info = cfi_intelext_get_fact_prot_info; |
| 608 | mtd->_get_user_prot_info = cfi_intelext_get_user_prot_info; | 608 | mtd->get_user_prot_info = cfi_intelext_get_user_prot_info; |
| 609 | #endif | 609 | #endif |
| 610 | 610 | ||
| 611 | /* This function has the potential to distort the reality | 611 | /* This function has the potential to distort the reality |
| @@ -1017,6 +1017,8 @@ static void put_chip(struct map_info *map, struct flchip *chip, unsigned long ad | |||
| 1017 | case FL_READY: | 1017 | case FL_READY: |
| 1018 | case FL_STATUS: | 1018 | case FL_STATUS: |
| 1019 | case FL_JEDEC_QUERY: | 1019 | case FL_JEDEC_QUERY: |
| 1020 | /* We should really make set_vpp() count, rather than doing this */ | ||
| 1021 | DISABLE_VPP(map); | ||
| 1020 | break; | 1022 | break; |
| 1021 | default: | 1023 | default: |
| 1022 | printk(KERN_ERR "%s: put_chip() called with oldstate %d!!\n", map->name, chip->oldstate); | 1024 | printk(KERN_ERR "%s: put_chip() called with oldstate %d!!\n", map->name, chip->oldstate); |
| @@ -1322,7 +1324,7 @@ static int cfi_intelext_point(struct mtd_info *mtd, loff_t from, size_t len, | |||
| 1322 | int chipnum; | 1324 | int chipnum; |
| 1323 | int ret = 0; | 1325 | int ret = 0; |
| 1324 | 1326 | ||
| 1325 | if (!map->virt) | 1327 | if (!map->virt || (from + len > mtd->size)) |
| 1326 | return -EINVAL; | 1328 | return -EINVAL; |
| 1327 | 1329 | ||
| 1328 | /* Now lock the chip(s) to POINT state */ | 1330 | /* Now lock the chip(s) to POINT state */ |
| @@ -1332,6 +1334,7 @@ static int cfi_intelext_point(struct mtd_info *mtd, loff_t from, size_t len, | |||
| 1332 | ofs = from - (chipnum << cfi->chipshift); | 1334 | ofs = from - (chipnum << cfi->chipshift); |
| 1333 | 1335 | ||
| 1334 | *virt = map->virt + cfi->chips[chipnum].start + ofs; | 1336 | *virt = map->virt + cfi->chips[chipnum].start + ofs; |
| 1337 | *retlen = 0; | ||
| 1335 | if (phys) | 1338 | if (phys) |
| 1336 | *phys = map->phys + cfi->chips[chipnum].start + ofs; | 1339 | *phys = map->phys + cfi->chips[chipnum].start + ofs; |
| 1337 | 1340 | ||
| @@ -1366,12 +1369,12 @@ static int cfi_intelext_point(struct mtd_info *mtd, loff_t from, size_t len, | |||
| 1366 | return 0; | 1369 | return 0; |
| 1367 | } | 1370 | } |
| 1368 | 1371 | ||
| 1369 | static int cfi_intelext_unpoint(struct mtd_info *mtd, loff_t from, size_t len) | 1372 | static void cfi_intelext_unpoint(struct mtd_info *mtd, loff_t from, size_t len) |
| 1370 | { | 1373 | { |
| 1371 | struct map_info *map = mtd->priv; | 1374 | struct map_info *map = mtd->priv; |
| 1372 | struct cfi_private *cfi = map->fldrv_priv; | 1375 | struct cfi_private *cfi = map->fldrv_priv; |
| 1373 | unsigned long ofs; | 1376 | unsigned long ofs; |
| 1374 | int chipnum, err = 0; | 1377 | int chipnum; |
| 1375 | 1378 | ||
| 1376 | /* Now unlock the chip(s) POINT state */ | 1379 | /* Now unlock the chip(s) POINT state */ |
| 1377 | 1380 | ||
| @@ -1379,7 +1382,7 @@ static int cfi_intelext_unpoint(struct mtd_info *mtd, loff_t from, size_t len) | |||
| 1379 | chipnum = (from >> cfi->chipshift); | 1382 | chipnum = (from >> cfi->chipshift); |
| 1380 | ofs = from - (chipnum << cfi->chipshift); | 1383 | ofs = from - (chipnum << cfi->chipshift); |
| 1381 | 1384 | ||
| 1382 | while (len && !err) { | 1385 | while (len) { |
| 1383 | unsigned long thislen; | 1386 | unsigned long thislen; |
| 1384 | struct flchip *chip; | 1387 | struct flchip *chip; |
| 1385 | 1388 | ||
| @@ -1397,10 +1400,8 @@ static int cfi_intelext_unpoint(struct mtd_info *mtd, loff_t from, size_t len) | |||
| 1397 | chip->ref_point_counter--; | 1400 | chip->ref_point_counter--; |
| 1398 | if(chip->ref_point_counter == 0) | 1401 | if(chip->ref_point_counter == 0) |
| 1399 | chip->state = FL_READY; | 1402 | chip->state = FL_READY; |
| 1400 | } else { | 1403 | } else |
| 1401 | printk(KERN_ERR "%s: Error: unpoint called on non pointed region\n", map->name); | 1404 | printk(KERN_ERR "%s: Warning: unpoint called on non pointed region\n", map->name); /* Should this give an error? */ |
| 1402 | err = -EINVAL; | ||
| 1403 | } | ||
| 1404 | 1405 | ||
| 1405 | put_chip(map, chip, chip->start); | 1406 | put_chip(map, chip, chip->start); |
| 1406 | mutex_unlock(&chip->mutex); | 1407 | mutex_unlock(&chip->mutex); |
| @@ -1409,8 +1410,6 @@ static int cfi_intelext_unpoint(struct mtd_info *mtd, loff_t from, size_t len) | |||
| 1409 | ofs = 0; | 1410 | ofs = 0; |
| 1410 | chipnum++; | 1411 | chipnum++; |
| 1411 | } | 1412 | } |
| 1412 | |||
| 1413 | return err; | ||
| 1414 | } | 1413 | } |
| 1415 | 1414 | ||
| 1416 | static inline int do_read_onechip(struct map_info *map, struct flchip *chip, loff_t adr, size_t len, u_char *buf) | 1415 | static inline int do_read_onechip(struct map_info *map, struct flchip *chip, loff_t adr, size_t len, u_char *buf) |
| @@ -1457,6 +1456,8 @@ static int cfi_intelext_read (struct mtd_info *mtd, loff_t from, size_t len, siz | |||
| 1457 | chipnum = (from >> cfi->chipshift); | 1456 | chipnum = (from >> cfi->chipshift); |
| 1458 | ofs = from - (chipnum << cfi->chipshift); | 1457 | ofs = from - (chipnum << cfi->chipshift); |
| 1459 | 1458 | ||
| 1459 | *retlen = 0; | ||
| 1460 | |||
| 1460 | while (len) { | 1461 | while (len) { |
| 1461 | unsigned long thislen; | 1462 | unsigned long thislen; |
| 1462 | 1463 | ||
| @@ -1550,8 +1551,7 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip, | |||
| 1550 | } | 1551 | } |
| 1551 | 1552 | ||
| 1552 | xip_enable(map, chip, adr); | 1553 | xip_enable(map, chip, adr); |
| 1553 | out: DISABLE_VPP(map); | 1554 | out: put_chip(map, chip, adr); |
| 1554 | put_chip(map, chip, adr); | ||
| 1555 | mutex_unlock(&chip->mutex); | 1555 | mutex_unlock(&chip->mutex); |
| 1556 | return ret; | 1556 | return ret; |
| 1557 | } | 1557 | } |
| @@ -1565,6 +1565,10 @@ static int cfi_intelext_write_words (struct mtd_info *mtd, loff_t to , size_t le | |||
| 1565 | int chipnum; | 1565 | int chipnum; |
| 1566 | unsigned long ofs; | 1566 | unsigned long ofs; |
| 1567 | 1567 | ||
| 1568 | *retlen = 0; | ||
| 1569 | if (!len) | ||
| 1570 | return 0; | ||
| 1571 | |||
| 1568 | chipnum = to >> cfi->chipshift; | 1572 | chipnum = to >> cfi->chipshift; |
| 1569 | ofs = to - (chipnum << cfi->chipshift); | 1573 | ofs = to - (chipnum << cfi->chipshift); |
| 1570 | 1574 | ||
| @@ -1790,8 +1794,7 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip, | |||
| 1790 | } | 1794 | } |
| 1791 | 1795 | ||
| 1792 | xip_enable(map, chip, cmd_adr); | 1796 | xip_enable(map, chip, cmd_adr); |
| 1793 | out: DISABLE_VPP(map); | 1797 | out: put_chip(map, chip, cmd_adr); |
| 1794 | put_chip(map, chip, cmd_adr); | ||
| 1795 | mutex_unlock(&chip->mutex); | 1798 | mutex_unlock(&chip->mutex); |
| 1796 | return ret; | 1799 | return ret; |
| 1797 | } | 1800 | } |
| @@ -1810,6 +1813,7 @@ static int cfi_intelext_writev (struct mtd_info *mtd, const struct kvec *vecs, | |||
| 1810 | for (i = 0; i < count; i++) | 1813 | for (i = 0; i < count; i++) |
| 1811 | len += vecs[i].iov_len; | 1814 | len += vecs[i].iov_len; |
| 1812 | 1815 | ||
| 1816 | *retlen = 0; | ||
| 1813 | if (!len) | 1817 | if (!len) |
| 1814 | return 0; | 1818 | return 0; |
| 1815 | 1819 | ||
| @@ -1928,7 +1932,6 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip, | |||
| 1928 | ret = -EIO; | 1932 | ret = -EIO; |
| 1929 | } else if (chipstatus & 0x20 && retries--) { | 1933 | } else if (chipstatus & 0x20 && retries--) { |
| 1930 | printk(KERN_DEBUG "block erase failed at 0x%08lx: status 0x%lx. Retrying...\n", adr, chipstatus); | 1934 | printk(KERN_DEBUG "block erase failed at 0x%08lx: status 0x%lx. Retrying...\n", adr, chipstatus); |
| 1931 | DISABLE_VPP(map); | ||
| 1932 | put_chip(map, chip, adr); | 1935 | put_chip(map, chip, adr); |
| 1933 | mutex_unlock(&chip->mutex); | 1936 | mutex_unlock(&chip->mutex); |
| 1934 | goto retry; | 1937 | goto retry; |
| @@ -1941,8 +1944,7 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip, | |||
| 1941 | } | 1944 | } |
| 1942 | 1945 | ||
| 1943 | xip_enable(map, chip, adr); | 1946 | xip_enable(map, chip, adr); |
| 1944 | out: DISABLE_VPP(map); | 1947 | out: put_chip(map, chip, adr); |
| 1945 | put_chip(map, chip, adr); | ||
| 1946 | mutex_unlock(&chip->mutex); | 1948 | mutex_unlock(&chip->mutex); |
| 1947 | return ret; | 1949 | return ret; |
| 1948 | } | 1950 | } |
| @@ -2043,7 +2045,7 @@ static int __xipram do_xxlock_oneblock(struct map_info *map, struct flchip *chip | |||
| 2043 | { | 2045 | { |
| 2044 | struct cfi_private *cfi = map->fldrv_priv; | 2046 | struct cfi_private *cfi = map->fldrv_priv; |
| 2045 | struct cfi_pri_intelext *extp = cfi->cmdset_priv; | 2047 | struct cfi_pri_intelext *extp = cfi->cmdset_priv; |
| 2046 | int mdelay; | 2048 | int udelay; |
| 2047 | int ret; | 2049 | int ret; |
| 2048 | 2050 | ||
| 2049 | adr += chip->start; | 2051 | adr += chip->start; |
| @@ -2072,17 +2074,9 @@ static int __xipram do_xxlock_oneblock(struct map_info *map, struct flchip *chip | |||
| 2072 | * If Instant Individual Block Locking supported then no need | 2074 | * If Instant Individual Block Locking supported then no need |
| 2073 | * to delay. | 2075 | * to delay. |
| 2074 | */ | 2076 | */ |
| 2075 | /* | 2077 | udelay = (!extp || !(extp->FeatureSupport & (1 << 5))) ? 1000000/HZ : 0; |
| 2076 | * Unlocking may take up to 1.4 seconds on some Intel flashes. So | ||
| 2077 | * lets use a max of 1.5 seconds (1500ms) as timeout. | ||
| 2078 | * | ||
| 2079 | * See "Clear Block Lock-Bits Time" on page 40 in | ||
| 2080 | * "3 Volt Intel StrataFlash Memory" 28F128J3,28F640J3,28F320J3 manual | ||
| 2081 | * from February 2003 | ||
| 2082 | */ | ||
| 2083 | mdelay = (!extp || !(extp->FeatureSupport & (1 << 5))) ? 1500 : 0; | ||
| 2084 | 2078 | ||
| 2085 | ret = WAIT_TIMEOUT(map, chip, adr, mdelay, mdelay * 1000); | 2079 | ret = WAIT_TIMEOUT(map, chip, adr, udelay, udelay * 100); |
| 2086 | if (ret) { | 2080 | if (ret) { |
| 2087 | map_write(map, CMD(0x70), adr); | 2081 | map_write(map, CMD(0x70), adr); |
| 2088 | chip->state = FL_STATUS; | 2082 | chip->state = FL_STATUS; |
| @@ -2092,8 +2086,7 @@ static int __xipram do_xxlock_oneblock(struct map_info *map, struct flchip *chip | |||
| 2092 | } | 2086 | } |
| 2093 | 2087 | ||
| 2094 | xip_enable(map, chip, adr); | 2088 | xip_enable(map, chip, adr); |
| 2095 | out: DISABLE_VPP(map); | 2089 | out: put_chip(map, chip, adr); |
| 2096 | put_chip(map, chip, adr); | ||
| 2097 | mutex_unlock(&chip->mutex); | 2090 | mutex_unlock(&chip->mutex); |
| 2098 | return ret; | 2091 | return ret; |
| 2099 | } | 2092 | } |
| @@ -2490,7 +2483,7 @@ static int cfi_intelext_suspend(struct mtd_info *mtd) | |||
| 2490 | allowed to. Or should we return -EAGAIN, because the upper layers | 2483 | allowed to. Or should we return -EAGAIN, because the upper layers |
| 2491 | ought to have already shut down anything which was using the device | 2484 | ought to have already shut down anything which was using the device |
| 2492 | anyway? The latter for now. */ | 2485 | anyway? The latter for now. */ |
| 2493 | printk(KERN_NOTICE "Flash device refused suspend due to active operation (state %d)\n", chip->state); | 2486 | printk(KERN_NOTICE "Flash device refused suspend due to active operation (state %d)\n", chip->oldstate); |
| 2494 | ret = -EAGAIN; | 2487 | ret = -EAGAIN; |
| 2495 | case FL_PM_SUSPENDED: | 2488 | case FL_PM_SUSPENDED: |
| 2496 | break; | 2489 | break; |
| @@ -2533,10 +2526,12 @@ static void cfi_intelext_restore_locks(struct mtd_info *mtd) | |||
| 2533 | if (!region->lockmap) | 2526 | if (!region->lockmap) |
| 2534 | continue; | 2527 | continue; |
| 2535 | 2528 | ||
| 2536 | for_each_clear_bit(block, region->lockmap, region->numblocks) { | 2529 | for (block = 0; block < region->numblocks; block++) { |
| 2537 | len = region->erasesize; | 2530 | len = region->erasesize; |
| 2538 | adr = region->offset + block * len; | 2531 | adr = region->offset + block * len; |
| 2539 | cfi_intelext_unlock(mtd, adr, len); | 2532 | |
| 2533 | if (!test_bit(block, region->lockmap)) | ||
| 2534 | cfi_intelext_unlock(mtd, adr, len); | ||
| 2540 | } | 2535 | } |
| 2541 | } | 2536 | } |
| 2542 | } | 2537 | } |
diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c index b86197286f2..51d79223bc7 100644 --- a/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/drivers/mtd/chips/cfi_cmdset_0002.c | |||
| @@ -59,9 +59,6 @@ static void cfi_amdstd_resume (struct mtd_info *); | |||
| 59 | static int cfi_amdstd_reboot(struct notifier_block *, unsigned long, void *); | 59 | static int cfi_amdstd_reboot(struct notifier_block *, unsigned long, void *); |
| 60 | static int cfi_amdstd_secsi_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *); | 60 | static int cfi_amdstd_secsi_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *); |
| 61 | 61 | ||
| 62 | static int cfi_amdstd_panic_write(struct mtd_info *mtd, loff_t to, size_t len, | ||
| 63 | size_t *retlen, const u_char *buf); | ||
| 64 | |||
| 65 | static void cfi_amdstd_destroy(struct mtd_info *); | 62 | static void cfi_amdstd_destroy(struct mtd_info *); |
| 66 | 63 | ||
| 67 | struct mtd_info *cfi_cmdset_0002(struct map_info *, int); | 64 | struct mtd_info *cfi_cmdset_0002(struct map_info *, int); |
| @@ -148,7 +145,8 @@ static void fixup_amd_bootblock(struct mtd_info *mtd) | |||
| 148 | if (((major << 8) | minor) < 0x3131) { | 145 | if (((major << 8) | minor) < 0x3131) { |
| 149 | /* CFI version 1.0 => don't trust bootloc */ | 146 | /* CFI version 1.0 => don't trust bootloc */ |
| 150 | 147 | ||
| 151 | pr_debug("%s: JEDEC Vendor ID is 0x%02X Device ID is 0x%02X\n", | 148 | DEBUG(MTD_DEBUG_LEVEL1, |
| 149 | "%s: JEDEC Vendor ID is 0x%02X Device ID is 0x%02X\n", | ||
| 152 | map->name, cfi->mfr, cfi->id); | 150 | map->name, cfi->mfr, cfi->id); |
| 153 | 151 | ||
| 154 | /* AFAICS all 29LV400 with a bottom boot block have a device ID | 152 | /* AFAICS all 29LV400 with a bottom boot block have a device ID |
| @@ -168,7 +166,8 @@ static void fixup_amd_bootblock(struct mtd_info *mtd) | |||
| 168 | * the 8-bit device ID. | 166 | * the 8-bit device ID. |
| 169 | */ | 167 | */ |
| 170 | (cfi->mfr == CFI_MFR_MACRONIX)) { | 168 | (cfi->mfr == CFI_MFR_MACRONIX)) { |
| 171 | pr_debug("%s: Macronix MX29LV400C with bottom boot block" | 169 | DEBUG(MTD_DEBUG_LEVEL1, |
| 170 | "%s: Macronix MX29LV400C with bottom boot block" | ||
| 172 | " detected\n", map->name); | 171 | " detected\n", map->name); |
| 173 | extp->TopBottom = 2; /* bottom boot */ | 172 | extp->TopBottom = 2; /* bottom boot */ |
| 174 | } else | 173 | } else |
| @@ -179,7 +178,8 @@ static void fixup_amd_bootblock(struct mtd_info *mtd) | |||
| 179 | extp->TopBottom = 2; /* bottom boot */ | 178 | extp->TopBottom = 2; /* bottom boot */ |
| 180 | } | 179 | } |
| 181 | 180 | ||
| 182 | pr_debug("%s: AMD CFI PRI V%c.%c has no boot block field;" | 181 | DEBUG(MTD_DEBUG_LEVEL1, |
| 182 | "%s: AMD CFI PRI V%c.%c has no boot block field;" | ||
| 183 | " deduced %s from Device ID\n", map->name, major, minor, | 183 | " deduced %s from Device ID\n", map->name, major, minor, |
| 184 | extp->TopBottom == 2 ? "bottom" : "top"); | 184 | extp->TopBottom == 2 ? "bottom" : "top"); |
| 185 | } | 185 | } |
| @@ -190,9 +190,17 @@ static void fixup_use_write_buffers(struct mtd_info *mtd) | |||
| 190 | { | 190 | { |
| 191 | struct map_info *map = mtd->priv; | 191 | struct map_info *map = mtd->priv; |
| 192 | struct cfi_private *cfi = map->fldrv_priv; | 192 | struct cfi_private *cfi = map->fldrv_priv; |
| 193 | struct cfi_pri_amdstd *extp = cfi->cmdset_priv; | ||
| 194 | |||
| 193 | if (cfi->cfiq->BufWriteTimeoutTyp) { | 195 | if (cfi->cfiq->BufWriteTimeoutTyp) { |
| 194 | pr_debug("Using buffer write method\n" ); | 196 | DEBUG(MTD_DEBUG_LEVEL1, "Using buffer write method\n" ); |
| 195 | mtd->_write = cfi_amdstd_write_buffers; | 197 | mtd->write = cfi_amdstd_write_buffers; |
| 198 | |||
| 199 | if (extp->SiliconRevision >= 0x1C) { | ||
| 200 | mtd->writesize = 512; | ||
| 201 | mtd->flags &= ~MTD_BIT_WRITEABLE; | ||
| 202 | printk(KERN_INFO "Enabling Spansion 65nm mode, writesize = 512 bytes\n"); | ||
| 203 | } | ||
| 196 | } | 204 | } |
| 197 | } | 205 | } |
| 198 | 206 | ||
| @@ -231,8 +239,8 @@ static void fixup_convert_atmel_pri(struct mtd_info *mtd) | |||
| 231 | static void fixup_use_secsi(struct mtd_info *mtd) | 239 | static void fixup_use_secsi(struct mtd_info *mtd) |
| 232 | { | 240 | { |
| 233 | /* Setup for chips with a secsi area */ | 241 | /* Setup for chips with a secsi area */ |
| 234 | mtd->_read_user_prot_reg = cfi_amdstd_secsi_read; | 242 | mtd->read_user_prot_reg = cfi_amdstd_secsi_read; |
| 235 | mtd->_read_fact_prot_reg = cfi_amdstd_secsi_read; | 243 | mtd->read_fact_prot_reg = cfi_amdstd_secsi_read; |
| 236 | } | 244 | } |
| 237 | 245 | ||
| 238 | static void fixup_use_erase_chip(struct mtd_info *mtd) | 246 | static void fixup_use_erase_chip(struct mtd_info *mtd) |
| @@ -241,7 +249,7 @@ static void fixup_use_erase_chip(struct mtd_info *mtd) | |||
| 241 | struct cfi_private *cfi = map->fldrv_priv; | 249 | struct cfi_private *cfi = map->fldrv_priv; |
| 242 | if ((cfi->cfiq->NumEraseRegions == 1) && | 250 | if ((cfi->cfiq->NumEraseRegions == 1) && |
| 243 | ((cfi->cfiq->EraseRegionInfo[0] & 0xffff) == 0)) { | 251 | ((cfi->cfiq->EraseRegionInfo[0] & 0xffff) == 0)) { |
| 244 | mtd->_erase = cfi_amdstd_erase_chip; | 252 | mtd->erase = cfi_amdstd_erase_chip; |
| 245 | } | 253 | } |
| 246 | 254 | ||
| 247 | } | 255 | } |
| @@ -252,8 +260,8 @@ static void fixup_use_erase_chip(struct mtd_info *mtd) | |||
| 252 | */ | 260 | */ |
| 253 | static void fixup_use_atmel_lock(struct mtd_info *mtd) | 261 | static void fixup_use_atmel_lock(struct mtd_info *mtd) |
| 254 | { | 262 | { |
| 255 | mtd->_lock = cfi_atmel_lock; | 263 | mtd->lock = cfi_atmel_lock; |
| 256 | mtd->_unlock = cfi_atmel_unlock; | 264 | mtd->unlock = cfi_atmel_unlock; |
| 257 | mtd->flags |= MTD_POWERUP_LOCK; | 265 | mtd->flags |= MTD_POWERUP_LOCK; |
| 258 | } | 266 | } |
| 259 | 267 | ||
| @@ -317,7 +325,7 @@ static void fixup_s29gl064n_sectors(struct mtd_info *mtd) | |||
| 317 | 325 | ||
| 318 | if ((cfi->cfiq->EraseRegionInfo[0] & 0xffff) == 0x003f) { | 326 | if ((cfi->cfiq->EraseRegionInfo[0] & 0xffff) == 0x003f) { |
| 319 | cfi->cfiq->EraseRegionInfo[0] |= 0x0040; | 327 | cfi->cfiq->EraseRegionInfo[0] |= 0x0040; |
| 320 | pr_warning("%s: Bad S29GL064N CFI data; adjust from 64 to 128 sectors\n", mtd->name); | 328 | pr_warning("%s: Bad S29GL064N CFI data, adjust from 64 to 128 sectors\n", mtd->name); |
| 321 | } | 329 | } |
| 322 | } | 330 | } |
| 323 | 331 | ||
| @@ -328,23 +336,10 @@ static void fixup_s29gl032n_sectors(struct mtd_info *mtd) | |||
| 328 | 336 | ||
| 329 | if ((cfi->cfiq->EraseRegionInfo[1] & 0xffff) == 0x007e) { | 337 | if ((cfi->cfiq->EraseRegionInfo[1] & 0xffff) == 0x007e) { |
| 330 | cfi->cfiq->EraseRegionInfo[1] &= ~0x0040; | 338 | cfi->cfiq->EraseRegionInfo[1] &= ~0x0040; |
| 331 | pr_warning("%s: Bad S29GL032N CFI data; adjust from 127 to 63 sectors\n", mtd->name); | 339 | pr_warning("%s: Bad S29GL032N CFI data, adjust from 127 to 63 sectors\n", mtd->name); |
| 332 | } | 340 | } |
| 333 | } | 341 | } |
| 334 | 342 | ||
| 335 | static void fixup_s29ns512p_sectors(struct mtd_info *mtd) | ||
| 336 | { | ||
| 337 | struct map_info *map = mtd->priv; | ||
| 338 | struct cfi_private *cfi = map->fldrv_priv; | ||
| 339 | |||
| 340 | /* | ||
| 341 | * S29NS512P flash uses more than 8bits to report number of sectors, | ||
| 342 | * which is not permitted by CFI. | ||
| 343 | */ | ||
| 344 | cfi->cfiq->EraseRegionInfo[0] = 0x020001ff; | ||
| 345 | pr_warning("%s: Bad S29NS512P CFI data; adjust to 512 sectors\n", mtd->name); | ||
| 346 | } | ||
| 347 | |||
| 348 | /* Used to fix CFI-Tables of chips without Extended Query Tables */ | 343 | /* Used to fix CFI-Tables of chips without Extended Query Tables */ |
| 349 | static struct cfi_fixup cfi_nopri_fixup_table[] = { | 344 | static struct cfi_fixup cfi_nopri_fixup_table[] = { |
| 350 | { CFI_MFR_SST, 0x234a, fixup_sst39vf }, /* SST39VF1602 */ | 345 | { CFI_MFR_SST, 0x234a, fixup_sst39vf }, /* SST39VF1602 */ |
| @@ -375,7 +370,6 @@ static struct cfi_fixup cfi_fixup_table[] = { | |||
| 375 | { CFI_MFR_AMD, 0x1301, fixup_s29gl064n_sectors }, | 370 | { CFI_MFR_AMD, 0x1301, fixup_s29gl064n_sectors }, |
| 376 | { CFI_MFR_AMD, 0x1a00, fixup_s29gl032n_sectors }, | 371 | { CFI_MFR_AMD, 0x1a00, fixup_s29gl032n_sectors }, |
| 377 | { CFI_MFR_AMD, 0x1a01, fixup_s29gl032n_sectors }, | 372 | { CFI_MFR_AMD, 0x1a01, fixup_s29gl032n_sectors }, |
| 378 | { CFI_MFR_AMD, 0x3f00, fixup_s29ns512p_sectors }, | ||
| 379 | { CFI_MFR_SST, 0x536a, fixup_sst38vf640x_sectorsize }, /* SST38VF6402 */ | 373 | { CFI_MFR_SST, 0x536a, fixup_sst38vf640x_sectorsize }, /* SST38VF6402 */ |
| 380 | { CFI_MFR_SST, 0x536b, fixup_sst38vf640x_sectorsize }, /* SST38VF6401 */ | 374 | { CFI_MFR_SST, 0x536b, fixup_sst38vf640x_sectorsize }, /* SST38VF6401 */ |
| 381 | { CFI_MFR_SST, 0x536c, fixup_sst38vf640x_sectorsize }, /* SST38VF6404 */ | 375 | { CFI_MFR_SST, 0x536c, fixup_sst38vf640x_sectorsize }, /* SST38VF6404 */ |
| @@ -431,68 +425,6 @@ static void cfi_fixup_major_minor(struct cfi_private *cfi, | |||
| 431 | } | 425 | } |
| 432 | } | 426 | } |
| 433 | 427 | ||
| 434 | static int is_m29ew(struct cfi_private *cfi) | ||
| 435 | { | ||
| 436 | if (cfi->mfr == CFI_MFR_INTEL && | ||
| 437 | ((cfi->device_type == CFI_DEVICETYPE_X8 && (cfi->id & 0xff) == 0x7e) || | ||
| 438 | (cfi->device_type == CFI_DEVICETYPE_X16 && cfi->id == 0x227e))) | ||
| 439 | return 1; | ||
| 440 | return 0; | ||
| 441 | } | ||
| 442 | |||
| 443 | /* | ||
| 444 | * From TN-13-07: Patching the Linux Kernel and U-Boot for M29 Flash, page 20: | ||
| 445 | * Some revisions of the M29EW suffer from erase suspend hang ups. In | ||
| 446 | * particular, it can occur when the sequence | ||
| 447 | * Erase Confirm -> Suspend -> Program -> Resume | ||
| 448 | * causes a lockup due to internal timing issues. The consequence is that the | ||
| 449 | * erase cannot be resumed without inserting a dummy command after programming | ||
| 450 | * and prior to resuming. [...] The work-around is to issue a dummy write cycle | ||
| 451 | * that writes an F0 command code before the RESUME command. | ||
| 452 | */ | ||
| 453 | static void cfi_fixup_m29ew_erase_suspend(struct map_info *map, | ||
| 454 | unsigned long adr) | ||
| 455 | { | ||
| 456 | struct cfi_private *cfi = map->fldrv_priv; | ||
| 457 | /* before resume, insert a dummy 0xF0 cycle for Micron M29EW devices */ | ||
| 458 | if (is_m29ew(cfi)) | ||
| 459 | map_write(map, CMD(0xF0), adr); | ||
| 460 | } | ||
| 461 | |||
| 462 | /* | ||
| 463 | * From TN-13-07: Patching the Linux Kernel and U-Boot for M29 Flash, page 22: | ||
| 464 | * | ||
| 465 | * Some revisions of the M29EW (for example, A1 and A2 step revisions) | ||
| 466 | * are affected by a problem that could cause a hang up when an ERASE SUSPEND | ||
| 467 | * command is issued after an ERASE RESUME operation without waiting for a | ||
| 468 | * minimum delay. The result is that once the ERASE seems to be completed | ||
| 469 | * (no bits are toggling), the contents of the Flash memory block on which | ||
| 470 | * the erase was ongoing could be inconsistent with the expected values | ||
| 471 | * (typically, the array value is stuck to the 0xC0, 0xC4, 0x80, or 0x84 | ||
| 472 | * values), causing a consequent failure of the ERASE operation. | ||
| 473 | * The occurrence of this issue could be high, especially when file system | ||
| 474 | * operations on the Flash are intensive. As a result, it is recommended | ||
| 475 | * that a patch be applied. Intensive file system operations can cause many | ||
| 476 | * calls to the garbage routine to free Flash space (also by erasing physical | ||
| 477 | * Flash blocks) and as a result, many consecutive SUSPEND and RESUME | ||
| 478 | * commands can occur. The problem disappears when a delay is inserted after | ||
| 479 | * the RESUME command by using the udelay() function available in Linux. | ||
| 480 | * The DELAY value must be tuned based on the customer's platform. | ||
| 481 | * The maximum value that fixes the problem in all cases is 500us. | ||
| 482 | * But, in our experience, a delay of 30 µs to 50 µs is sufficient | ||
| 483 | * in most cases. | ||
| 484 | * We have chosen 500µs because this latency is acceptable. | ||
| 485 | */ | ||
| 486 | static void cfi_fixup_m29ew_delay_after_resume(struct cfi_private *cfi) | ||
| 487 | { | ||
| 488 | /* | ||
| 489 | * Resolving the Delay After Resume Issue see Micron TN-13-07 | ||
| 490 | * Worst case delay must be 500µs but 30-50µs should be ok as well | ||
| 491 | */ | ||
| 492 | if (is_m29ew(cfi)) | ||
| 493 | cfi_udelay(500); | ||
| 494 | } | ||
| 495 | |||
| 496 | struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary) | 428 | struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary) |
| 497 | { | 429 | { |
| 498 | struct cfi_private *cfi = map->fldrv_priv; | 430 | struct cfi_private *cfi = map->fldrv_priv; |
| @@ -508,21 +440,20 @@ struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary) | |||
| 508 | mtd->type = MTD_NORFLASH; | 440 | mtd->type = MTD_NORFLASH; |
| 509 | 441 | ||
| 510 | /* Fill in the default mtd operations */ | 442 | /* Fill in the default mtd operations */ |
| 511 | mtd->_erase = cfi_amdstd_erase_varsize; | 443 | mtd->erase = cfi_amdstd_erase_varsize; |
| 512 | mtd->_write = cfi_amdstd_write_words; | 444 | mtd->write = cfi_amdstd_write_words; |
| 513 | mtd->_read = cfi_amdstd_read; | 445 | mtd->read = cfi_amdstd_read; |
| 514 | mtd->_sync = cfi_amdstd_sync; | 446 | mtd->sync = cfi_amdstd_sync; |
| 515 | mtd->_suspend = cfi_amdstd_suspend; | 447 | mtd->suspend = cfi_amdstd_suspend; |
| 516 | mtd->_resume = cfi_amdstd_resume; | 448 | mtd->resume = cfi_amdstd_resume; |
| 517 | mtd->flags = MTD_CAP_NORFLASH; | 449 | mtd->flags = MTD_CAP_NORFLASH; |
| 518 | mtd->name = map->name; | 450 | mtd->name = map->name; |
| 519 | mtd->writesize = 1; | 451 | mtd->writesize = 1; |
| 520 | mtd->writebufsize = cfi_interleave(cfi) << cfi->cfiq->MaxBufWriteSize; | 452 | mtd->writebufsize = cfi_interleave(cfi) << cfi->cfiq->MaxBufWriteSize; |
| 521 | 453 | ||
| 522 | pr_debug("MTD %s(): write buffer size %d\n", __func__, | 454 | DEBUG(MTD_DEBUG_LEVEL3, "MTD %s(): write buffer size %d\n", |
| 523 | mtd->writebufsize); | 455 | __func__, mtd->writebufsize); |
| 524 | 456 | ||
| 525 | mtd->_panic_write = cfi_amdstd_panic_write; | ||
| 526 | mtd->reboot_notifier.notifier_call = cfi_amdstd_reboot; | 457 | mtd->reboot_notifier.notifier_call = cfi_amdstd_reboot; |
| 527 | 458 | ||
| 528 | if (cfi->cfi_mode==CFI_MODE_CFI){ | 459 | if (cfi->cfi_mode==CFI_MODE_CFI){ |
| @@ -838,10 +769,7 @@ static void put_chip(struct map_info *map, struct flchip *chip, unsigned long ad | |||
| 838 | 769 | ||
| 839 | switch(chip->oldstate) { | 770 | switch(chip->oldstate) { |
| 840 | case FL_ERASING: | 771 | case FL_ERASING: |
| 841 | cfi_fixup_m29ew_erase_suspend(map, | ||
| 842 | chip->in_progress_block_addr); | ||
| 843 | map_write(map, cfi->sector_erase_cmd, chip->in_progress_block_addr); | 772 | map_write(map, cfi->sector_erase_cmd, chip->in_progress_block_addr); |
| 844 | cfi_fixup_m29ew_delay_after_resume(cfi); | ||
| 845 | chip->oldstate = FL_READY; | 773 | chip->oldstate = FL_READY; |
| 846 | chip->state = FL_ERASING; | 774 | chip->state = FL_ERASING; |
| 847 | break; | 775 | break; |
| @@ -853,6 +781,8 @@ static void put_chip(struct map_info *map, struct flchip *chip, unsigned long ad | |||
| 853 | 781 | ||
| 854 | case FL_READY: | 782 | case FL_READY: |
| 855 | case FL_STATUS: | 783 | case FL_STATUS: |
| 784 | /* We should really make set_vpp() count, rather than doing this */ | ||
| 785 | DISABLE_VPP(map); | ||
| 856 | break; | 786 | break; |
| 857 | default: | 787 | default: |
| 858 | printk(KERN_ERR "MTD: put_chip() called with oldstate %d!!\n", chip->oldstate); | 788 | printk(KERN_ERR "MTD: put_chip() called with oldstate %d!!\n", chip->oldstate); |
| @@ -981,8 +911,6 @@ static void __xipram xip_udelay(struct map_info *map, struct flchip *chip, | |||
| 981 | /* Disallow XIP again */ | 911 | /* Disallow XIP again */ |
| 982 | local_irq_disable(); | 912 | local_irq_disable(); |
| 983 | 913 | ||
| 984 | /* Correct Erase Suspend Hangups for M29EW */ | ||
| 985 | cfi_fixup_m29ew_erase_suspend(map, adr); | ||
| 986 | /* Resume the write or erase operation */ | 914 | /* Resume the write or erase operation */ |
| 987 | map_write(map, cfi->sector_erase_cmd, adr); | 915 | map_write(map, cfi->sector_erase_cmd, adr); |
| 988 | chip->state = oldstate; | 916 | chip->state = oldstate; |
| @@ -1096,9 +1024,13 @@ static int cfi_amdstd_read (struct mtd_info *mtd, loff_t from, size_t len, size_ | |||
| 1096 | int ret = 0; | 1024 | int ret = 0; |
| 1097 | 1025 | ||
| 1098 | /* ofs: offset within the first chip that the first read should start */ | 1026 | /* ofs: offset within the first chip that the first read should start */ |
| 1027 | |||
| 1099 | chipnum = (from >> cfi->chipshift); | 1028 | chipnum = (from >> cfi->chipshift); |
| 1100 | ofs = from - (chipnum << cfi->chipshift); | 1029 | ofs = from - (chipnum << cfi->chipshift); |
| 1101 | 1030 | ||
| 1031 | |||
| 1032 | *retlen = 0; | ||
| 1033 | |||
| 1102 | while (len) { | 1034 | while (len) { |
| 1103 | unsigned long thislen; | 1035 | unsigned long thislen; |
| 1104 | 1036 | ||
| @@ -1176,11 +1108,16 @@ static int cfi_amdstd_secsi_read (struct mtd_info *mtd, loff_t from, size_t len, | |||
| 1176 | int chipnum; | 1108 | int chipnum; |
| 1177 | int ret = 0; | 1109 | int ret = 0; |
| 1178 | 1110 | ||
| 1111 | |||
| 1179 | /* ofs: offset within the first chip that the first read should start */ | 1112 | /* ofs: offset within the first chip that the first read should start */ |
| 1113 | |||
| 1180 | /* 8 secsi bytes per chip */ | 1114 | /* 8 secsi bytes per chip */ |
| 1181 | chipnum=from>>3; | 1115 | chipnum=from>>3; |
| 1182 | ofs=from & 7; | 1116 | ofs=from & 7; |
| 1183 | 1117 | ||
| 1118 | |||
| 1119 | *retlen = 0; | ||
| 1120 | |||
| 1184 | while (len) { | 1121 | while (len) { |
| 1185 | unsigned long thislen; | 1122 | unsigned long thislen; |
| 1186 | 1123 | ||
| @@ -1234,7 +1171,7 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip, | |||
| 1234 | return ret; | 1171 | return ret; |
| 1235 | } | 1172 | } |
| 1236 | 1173 | ||
| 1237 | pr_debug("MTD %s(): WRITE 0x%.8lx(0x%.8lx)\n", | 1174 | DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): WRITE 0x%.8lx(0x%.8lx)\n", |
| 1238 | __func__, adr, datum.x[0] ); | 1175 | __func__, adr, datum.x[0] ); |
| 1239 | 1176 | ||
| 1240 | /* | 1177 | /* |
| @@ -1245,7 +1182,7 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip, | |||
| 1245 | */ | 1182 | */ |
| 1246 | oldd = map_read(map, adr); | 1183 | oldd = map_read(map, adr); |
| 1247 | if (map_word_equal(map, oldd, datum)) { | 1184 | if (map_word_equal(map, oldd, datum)) { |
| 1248 | pr_debug("MTD %s(): NOP\n", | 1185 | DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): NOP\n", |
| 1249 | __func__); | 1186 | __func__); |
| 1250 | goto op_done; | 1187 | goto op_done; |
| 1251 | } | 1188 | } |
| @@ -1308,7 +1245,6 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip, | |||
| 1308 | xip_enable(map, chip, adr); | 1245 | xip_enable(map, chip, adr); |
| 1309 | op_done: | 1246 | op_done: |
| 1310 | chip->state = FL_READY; | 1247 | chip->state = FL_READY; |
| 1311 | DISABLE_VPP(map); | ||
| 1312 | put_chip(map, chip, adr); | 1248 | put_chip(map, chip, adr); |
| 1313 | mutex_unlock(&chip->mutex); | 1249 | mutex_unlock(&chip->mutex); |
| 1314 | 1250 | ||
| @@ -1326,6 +1262,10 @@ static int cfi_amdstd_write_words(struct mtd_info *mtd, loff_t to, size_t len, | |||
| 1326 | unsigned long ofs, chipstart; | 1262 | unsigned long ofs, chipstart; |
| 1327 | DECLARE_WAITQUEUE(wait, current); | 1263 | DECLARE_WAITQUEUE(wait, current); |
| 1328 | 1264 | ||
| 1265 | *retlen = 0; | ||
| 1266 | if (!len) | ||
| 1267 | return 0; | ||
| 1268 | |||
| 1329 | chipnum = to >> cfi->chipshift; | 1269 | chipnum = to >> cfi->chipshift; |
| 1330 | ofs = to - (chipnum << cfi->chipshift); | 1270 | ofs = to - (chipnum << cfi->chipshift); |
| 1331 | chipstart = cfi->chips[chipnum].start; | 1271 | chipstart = cfi->chips[chipnum].start; |
| @@ -1440,21 +1380,18 @@ static int cfi_amdstd_write_words(struct mtd_info *mtd, loff_t to, size_t len, | |||
| 1440 | } | 1380 | } |
| 1441 | 1381 | ||
| 1442 | 1382 | ||
| 1443 | /* | ||
| 1444 | * FIXME: interleaved mode not tested, and probably not supported! | ||
| 1445 | */ | ||
| 1446 | static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip, | 1383 | static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip, |
| 1447 | unsigned long adr, const u_char *buf, | 1384 | unsigned long adr, const u_char *buf, |
| 1448 | int len) | 1385 | int len) |
| 1449 | { | 1386 | { |
| 1450 | struct cfi_private *cfi = map->fldrv_priv; | 1387 | struct cfi_private *cfi = map->fldrv_priv; |
| 1451 | unsigned long timeo = jiffies + HZ; | 1388 | unsigned long timeo = jiffies + HZ; |
| 1452 | /* see comments in do_write_oneword() regarding uWriteTimeo. */ | 1389 | /* see comments in do_write_oneword() regarding uWriteTimeout, 20ms */ |
| 1453 | unsigned long uWriteTimeout = ( HZ / 1000 ) + 1; | 1390 | unsigned long uWriteTimeout = (HZ / 50) + 1; |
| 1454 | int ret = -EIO; | 1391 | int ret = -EIO; |
| 1455 | unsigned long cmd_adr; | 1392 | unsigned long cmd_adr; |
| 1456 | int z, words; | 1393 | int z, words, prolog, epilog, buflen = len; |
| 1457 | map_word datum; | 1394 | map_word datum, pdat, edat; |
| 1458 | 1395 | ||
| 1459 | adr += chip->start; | 1396 | adr += chip->start; |
| 1460 | cmd_adr = adr; | 1397 | cmd_adr = adr; |
| @@ -1468,13 +1405,28 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip, | |||
| 1468 | 1405 | ||
| 1469 | datum = map_word_load(map, buf); | 1406 | datum = map_word_load(map, buf); |
| 1470 | 1407 | ||
| 1471 | pr_debug("MTD %s(): WRITE 0x%.8lx(0x%.8lx)\n", | 1408 | DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): WRITE 0x%.8lx(0x%.8lx)\n", |
| 1472 | __func__, adr, datum.x[0] ); | 1409 | __func__, adr, datum.x[0] ); |
| 1473 | 1410 | ||
| 1474 | XIP_INVAL_CACHED_RANGE(map, adr, len); | 1411 | XIP_INVAL_CACHED_RANGE(map, adr, len); |
| 1475 | ENABLE_VPP(map); | 1412 | ENABLE_VPP(map); |
| 1476 | xip_disable(map, chip, cmd_adr); | 1413 | xip_disable(map, chip, cmd_adr); |
| 1477 | 1414 | ||
| 1415 | /* If start is not bus-aligned, prepend old contents of flash */ | ||
| 1416 | prolog = (adr & (map_bankwidth(map)-1)); | ||
| 1417 | if (prolog) { | ||
| 1418 | adr -= prolog; | ||
| 1419 | cmd_adr -= prolog; | ||
| 1420 | len += prolog; | ||
| 1421 | pdat = map_read(map, adr); | ||
| 1422 | } | ||
| 1423 | /* If end is not bus-aligned, append old contents of flash */ | ||
| 1424 | epilog = ((adr + len) & (map_bankwidth(map)-1)); | ||
| 1425 | if (epilog) { | ||
| 1426 | len += map_bankwidth(map)-epilog; | ||
| 1427 | edat = map_read(map, adr + len - map_bankwidth(map)); | ||
| 1428 | } | ||
| 1429 | |||
| 1478 | cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); | 1430 | cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); |
| 1479 | cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL); | 1431 | cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL); |
| 1480 | 1432 | ||
| @@ -1488,8 +1440,21 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip, | |||
| 1488 | map_write(map, CMD(words - 1), cmd_adr); | 1440 | map_write(map, CMD(words - 1), cmd_adr); |
| 1489 | /* Write data */ | 1441 | /* Write data */ |
| 1490 | z = 0; | 1442 | z = 0; |
| 1443 | if (prolog) { | ||
| 1444 | datum = map_word_load_partial(map, pdat, buf, prolog, | ||
| 1445 | min_t(int, buflen, | ||
| 1446 | map_bankwidth(map) - prolog)); | ||
| 1447 | map_write(map, datum, adr); | ||
| 1448 | |||
| 1449 | z += map_bankwidth(map); | ||
| 1450 | buf += map_bankwidth(map) - prolog; | ||
| 1451 | } | ||
| 1491 | while(z < words * map_bankwidth(map)) { | 1452 | while(z < words * map_bankwidth(map)) { |
| 1492 | datum = map_word_load(map, buf); | 1453 | if (epilog && z >= (words-1) * map_bankwidth(map)) |
| 1454 | datum = map_word_load_partial(map, edat, | ||
| 1455 | buf, 0, epilog); | ||
| 1456 | else | ||
| 1457 | datum = map_word_load(map, buf); | ||
| 1493 | map_write(map, datum, adr + z); | 1458 | map_write(map, datum, adr + z); |
| 1494 | 1459 | ||
| 1495 | z += map_bankwidth(map); | 1460 | z += map_bankwidth(map); |
| @@ -1536,22 +1501,15 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip, | |||
| 1536 | UDELAY(map, chip, adr, 1); | 1501 | UDELAY(map, chip, adr, 1); |
| 1537 | } | 1502 | } |
| 1538 | 1503 | ||
| 1539 | /* | 1504 | /* reset on all failures. */ |
| 1540 | * Recovery from write-buffer programming failures requires | 1505 | map_write( map, CMD(0xF0), chip->start ); |
| 1541 | * the write-to-buffer-reset sequence. Since the last part | 1506 | cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, |
| 1542 | * of the sequence also works as a normal reset, we can run | 1507 | cfi, cfi->device_type, NULL); |
| 1543 | * the same commands regardless of why we are here. | 1508 | cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, |
| 1544 | * See e.g. | 1509 | cfi, cfi->device_type, NULL); |
| 1545 | * http://www.spansion.com/Support/Application%20Notes/MirrorBit_Write_Buffer_Prog_Page_Buffer_Read_AN.pdf | 1510 | cfi_send_gen_cmd(0xF0, cfi->addr_unlock1, chip->start, map, |
| 1546 | */ | 1511 | cfi, cfi->device_type, NULL); |
| 1547 | cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, | ||
| 1548 | cfi->device_type, NULL); | ||
| 1549 | cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, | ||
| 1550 | cfi->device_type, NULL); | ||
| 1551 | cfi_send_gen_cmd(0xF0, cfi->addr_unlock1, chip->start, map, cfi, | ||
| 1552 | cfi->device_type, NULL); | ||
| 1553 | xip_enable(map, chip, adr); | 1512 | xip_enable(map, chip, adr); |
| 1554 | /* FIXME - should have reset delay before continuing */ | ||
| 1555 | 1513 | ||
| 1556 | printk(KERN_WARNING "MTD %s(): software timeout\n", | 1514 | printk(KERN_WARNING "MTD %s(): software timeout\n", |
| 1557 | __func__ ); | 1515 | __func__ ); |
| @@ -1559,7 +1517,6 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip, | |||
| 1559 | ret = -EIO; | 1517 | ret = -EIO; |
| 1560 | op_done: | 1518 | op_done: |
| 1561 | chip->state = FL_READY; | 1519 | chip->state = FL_READY; |
| 1562 | DISABLE_VPP(map); | ||
| 1563 | put_chip(map, chip, adr); | 1520 | put_chip(map, chip, adr); |
| 1564 | mutex_unlock(&chip->mutex); | 1521 | mutex_unlock(&chip->mutex); |
| 1565 | 1522 | ||
| @@ -1577,39 +1534,19 @@ static int cfi_amdstd_write_buffers(struct mtd_info *mtd, loff_t to, size_t len, | |||
| 1577 | int chipnum; | 1534 | int chipnum; |
| 1578 | unsigned long ofs; | 1535 | unsigned long ofs; |
| 1579 | 1536 | ||
| 1537 | *retlen = 0; | ||
| 1538 | if (!len) | ||
| 1539 | return 0; | ||
| 1540 | |||
| 1580 | chipnum = to >> cfi->chipshift; | 1541 | chipnum = to >> cfi->chipshift; |
| 1581 | ofs = to - (chipnum << cfi->chipshift); | 1542 | ofs = to - (chipnum << cfi->chipshift); |
| 1582 | 1543 | ||
| 1583 | /* If it's not bus-aligned, do the first word write */ | 1544 | while (len) { |
| 1584 | if (ofs & (map_bankwidth(map)-1)) { | ||
| 1585 | size_t local_len = (-ofs)&(map_bankwidth(map)-1); | ||
| 1586 | if (local_len > len) | ||
| 1587 | local_len = len; | ||
| 1588 | ret = cfi_amdstd_write_words(mtd, ofs + (chipnum<<cfi->chipshift), | ||
| 1589 | local_len, retlen, buf); | ||
| 1590 | if (ret) | ||
| 1591 | return ret; | ||
| 1592 | ofs += local_len; | ||
| 1593 | buf += local_len; | ||
| 1594 | len -= local_len; | ||
| 1595 | |||
| 1596 | if (ofs >> cfi->chipshift) { | ||
| 1597 | chipnum ++; | ||
| 1598 | ofs = 0; | ||
| 1599 | if (chipnum == cfi->numchips) | ||
| 1600 | return 0; | ||
| 1601 | } | ||
| 1602 | } | ||
| 1603 | |||
| 1604 | /* Write buffer is worth it only if more than one word to write... */ | ||
| 1605 | while (len >= map_bankwidth(map) * 2) { | ||
| 1606 | /* We must not cross write block boundaries */ | 1545 | /* We must not cross write block boundaries */ |
| 1607 | int size = wbufsize - (ofs & (wbufsize-1)); | 1546 | int size = wbufsize - (ofs & (wbufsize-1)); |
| 1608 | 1547 | ||
| 1609 | if (size > len) | 1548 | if (size > len) |
| 1610 | size = len; | 1549 | size = len; |
| 1611 | if (size % map_bankwidth(map)) | ||
| 1612 | size -= size % map_bankwidth(map); | ||
| 1613 | 1550 | ||
| 1614 | ret = do_write_buffer(map, &cfi->chips[chipnum], | 1551 | ret = do_write_buffer(map, &cfi->chips[chipnum], |
| 1615 | ofs, buf, size); | 1552 | ofs, buf, size); |
| @@ -1629,248 +1566,6 @@ static int cfi_amdstd_write_buffers(struct mtd_info *mtd, loff_t to, size_t len, | |||
| 1629 | } | 1566 | } |
| 1630 | } | 1567 | } |
| 1631 | 1568 | ||
| 1632 | if (len) { | ||
| 1633 | size_t retlen_dregs = 0; | ||
| 1634 | |||
| 1635 | ret = cfi_amdstd_write_words(mtd, ofs + (chipnum<<cfi->chipshift), | ||
| 1636 | len, &retlen_dregs, buf); | ||
| 1637 | |||
| 1638 | *retlen += retlen_dregs; | ||
| 1639 | return ret; | ||
| 1640 | } | ||
| 1641 | |||
| 1642 | return 0; | ||
| 1643 | } | ||
| 1644 | |||
| 1645 | /* | ||
| 1646 | * Wait for the flash chip to become ready to write data | ||
| 1647 | * | ||
| 1648 | * This is only called during the panic_write() path. When panic_write() | ||
| 1649 | * is called, the kernel is in the process of a panic, and will soon be | ||
| 1650 | * dead. Therefore we don't take any locks, and attempt to get access | ||
| 1651 | * to the chip as soon as possible. | ||
| 1652 | */ | ||
| 1653 | static int cfi_amdstd_panic_wait(struct map_info *map, struct flchip *chip, | ||
| 1654 | unsigned long adr) | ||
| 1655 | { | ||
| 1656 | struct cfi_private *cfi = map->fldrv_priv; | ||
| 1657 | int retries = 10; | ||
| 1658 | int i; | ||
| 1659 | |||
| 1660 | /* | ||
| 1661 | * If the driver thinks the chip is idle, and no toggle bits | ||
| 1662 | * are changing, then the chip is actually idle for sure. | ||
| 1663 | */ | ||
| 1664 | if (chip->state == FL_READY && chip_ready(map, adr)) | ||
| 1665 | return 0; | ||
| 1666 | |||
| 1667 | /* | ||
| 1668 | * Try several times to reset the chip and then wait for it | ||
| 1669 | * to become idle. The upper limit of a few milliseconds of | ||
| 1670 | * delay isn't a big problem: the kernel is dying anyway. It | ||
| 1671 | * is more important to save the messages. | ||
| 1672 | */ | ||
| 1673 | while (retries > 0) { | ||
| 1674 | const unsigned long timeo = (HZ / 1000) + 1; | ||
| 1675 | |||
| 1676 | /* send the reset command */ | ||
| 1677 | map_write(map, CMD(0xF0), chip->start); | ||
| 1678 | |||
| 1679 | /* wait for the chip to become ready */ | ||
| 1680 | for (i = 0; i < jiffies_to_usecs(timeo); i++) { | ||
| 1681 | if (chip_ready(map, adr)) | ||
| 1682 | return 0; | ||
| 1683 | |||
| 1684 | udelay(1); | ||
| 1685 | } | ||
| 1686 | } | ||
| 1687 | |||
| 1688 | /* the chip never became ready */ | ||
| 1689 | return -EBUSY; | ||
| 1690 | } | ||
| 1691 | |||
| 1692 | /* | ||
| 1693 | * Write out one word of data to a single flash chip during a kernel panic | ||
| 1694 | * | ||
| 1695 | * This is only called during the panic_write() path. When panic_write() | ||
| 1696 | * is called, the kernel is in the process of a panic, and will soon be | ||
| 1697 | * dead. Therefore we don't take any locks, and attempt to get access | ||
| 1698 | * to the chip as soon as possible. | ||
| 1699 | * | ||
| 1700 | * The implementation of this routine is intentionally similar to | ||
| 1701 | * do_write_oneword(), in order to ease code maintenance. | ||
| 1702 | */ | ||
| 1703 | static int do_panic_write_oneword(struct map_info *map, struct flchip *chip, | ||
| 1704 | unsigned long adr, map_word datum) | ||
| 1705 | { | ||
| 1706 | const unsigned long uWriteTimeout = (HZ / 1000) + 1; | ||
| 1707 | struct cfi_private *cfi = map->fldrv_priv; | ||
| 1708 | int retry_cnt = 0; | ||
| 1709 | map_word oldd; | ||
| 1710 | int ret = 0; | ||
| 1711 | int i; | ||
| 1712 | |||
| 1713 | adr += chip->start; | ||
| 1714 | |||
| 1715 | ret = cfi_amdstd_panic_wait(map, chip, adr); | ||
| 1716 | if (ret) | ||
| 1717 | return ret; | ||
| 1718 | |||
| 1719 | pr_debug("MTD %s(): PANIC WRITE 0x%.8lx(0x%.8lx)\n", | ||
| 1720 | __func__, adr, datum.x[0]); | ||
| 1721 | |||
| 1722 | /* | ||
| 1723 | * Check for a NOP for the case when the datum to write is already | ||
| 1724 | * present - it saves time and works around buggy chips that corrupt | ||
| 1725 | * data at other locations when 0xff is written to a location that | ||
| 1726 | * already contains 0xff. | ||
| 1727 | */ | ||
| 1728 | oldd = map_read(map, adr); | ||
| 1729 | if (map_word_equal(map, oldd, datum)) { | ||
| 1730 | pr_debug("MTD %s(): NOP\n", __func__); | ||
| 1731 | goto op_done; | ||
| 1732 | } | ||
| 1733 | |||
| 1734 | ENABLE_VPP(map); | ||
| 1735 | |||
| 1736 | retry: | ||
| 1737 | cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); | ||
| 1738 | cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL); | ||
| 1739 | cfi_send_gen_cmd(0xA0, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); | ||
| 1740 | map_write(map, datum, adr); | ||
| 1741 | |||
| 1742 | for (i = 0; i < jiffies_to_usecs(uWriteTimeout); i++) { | ||
| 1743 | if (chip_ready(map, adr)) | ||
| 1744 | break; | ||
| 1745 | |||
| 1746 | udelay(1); | ||
| 1747 | } | ||
| 1748 | |||
| 1749 | if (!chip_good(map, adr, datum)) { | ||
| 1750 | /* reset on all failures. */ | ||
| 1751 | map_write(map, CMD(0xF0), chip->start); | ||
| 1752 | /* FIXME - should have reset delay before continuing */ | ||
| 1753 | |||
| 1754 | if (++retry_cnt <= MAX_WORD_RETRIES) | ||
| 1755 | goto retry; | ||
| 1756 | |||
| 1757 | ret = -EIO; | ||
| 1758 | } | ||
| 1759 | |||
| 1760 | op_done: | ||
| 1761 | DISABLE_VPP(map); | ||
| 1762 | return ret; | ||
| 1763 | } | ||
| 1764 | |||
| 1765 | /* | ||
| 1766 | * Write out some data during a kernel panic | ||
| 1767 | * | ||
| 1768 | * This is used by the mtdoops driver to save the dying messages from a | ||
| 1769 | * kernel which has panic'd. | ||
| 1770 | * | ||
| 1771 | * This routine ignores all of the locking used throughout the rest of the | ||
| 1772 | * driver, in order to ensure that the data gets written out no matter what | ||
| 1773 | * state this driver (and the flash chip itself) was in when the kernel crashed. | ||
| 1774 | * | ||
| 1775 | * The implementation of this routine is intentionally similar to | ||
| 1776 | * cfi_amdstd_write_words(), in order to ease code maintenance. | ||
| 1777 | */ | ||
| 1778 | static int cfi_amdstd_panic_write(struct mtd_info *mtd, loff_t to, size_t len, | ||
| 1779 | size_t *retlen, const u_char *buf) | ||
| 1780 | { | ||
| 1781 | struct map_info *map = mtd->priv; | ||
| 1782 | struct cfi_private *cfi = map->fldrv_priv; | ||
| 1783 | unsigned long ofs, chipstart; | ||
| 1784 | int ret = 0; | ||
| 1785 | int chipnum; | ||
| 1786 | |||
| 1787 | chipnum = to >> cfi->chipshift; | ||
| 1788 | ofs = to - (chipnum << cfi->chipshift); | ||
| 1789 | chipstart = cfi->chips[chipnum].start; | ||
| 1790 | |||
| 1791 | /* If it's not bus aligned, do the first byte write */ | ||
| 1792 | if (ofs & (map_bankwidth(map) - 1)) { | ||
| 1793 | unsigned long bus_ofs = ofs & ~(map_bankwidth(map) - 1); | ||
| 1794 | int i = ofs - bus_ofs; | ||
| 1795 | int n = 0; | ||
| 1796 | map_word tmp_buf; | ||
| 1797 | |||
| 1798 | ret = cfi_amdstd_panic_wait(map, &cfi->chips[chipnum], bus_ofs); | ||
| 1799 | if (ret) | ||
| 1800 | return ret; | ||
| 1801 | |||
| 1802 | /* Load 'tmp_buf' with old contents of flash */ | ||
| 1803 | tmp_buf = map_read(map, bus_ofs + chipstart); | ||
| 1804 | |||
| 1805 | /* Number of bytes to copy from buffer */ | ||
| 1806 | n = min_t(int, len, map_bankwidth(map) - i); | ||
| 1807 | |||
| 1808 | tmp_buf = map_word_load_partial(map, tmp_buf, buf, i, n); | ||
| 1809 | |||
| 1810 | ret = do_panic_write_oneword(map, &cfi->chips[chipnum], | ||
| 1811 | bus_ofs, tmp_buf); | ||
| 1812 | if (ret) | ||
| 1813 | return ret; | ||
| 1814 | |||
| 1815 | ofs += n; | ||
| 1816 | buf += n; | ||
| 1817 | (*retlen) += n; | ||
| 1818 | len -= n; | ||
| 1819 | |||
| 1820 | if (ofs >> cfi->chipshift) { | ||
| 1821 | chipnum++; | ||
| 1822 | ofs = 0; | ||
| 1823 | if (chipnum == cfi->numchips) | ||
| 1824 | return 0; | ||
| 1825 | } | ||
| 1826 | } | ||
| 1827 | |||
| 1828 | /* We are now aligned, write as much as possible */ | ||
| 1829 | while (len >= map_bankwidth(map)) { | ||
| 1830 | map_word datum; | ||
| 1831 | |||
| 1832 | datum = map_word_load(map, buf); | ||
| 1833 | |||
| 1834 | ret = do_panic_write_oneword(map, &cfi->chips[chipnum], | ||
| 1835 | ofs, datum); | ||
| 1836 | if (ret) | ||
| 1837 | return ret; | ||
| 1838 | |||
| 1839 | ofs += map_bankwidth(map); | ||
| 1840 | buf += map_bankwidth(map); | ||
| 1841 | (*retlen) += map_bankwidth(map); | ||
| 1842 | len -= map_bankwidth(map); | ||
| 1843 | |||
| 1844 | if (ofs >> cfi->chipshift) { | ||
| 1845 | chipnum++; | ||
| 1846 | ofs = 0; | ||
| 1847 | if (chipnum == cfi->numchips) | ||
| 1848 | return 0; | ||
| 1849 | |||
| 1850 | chipstart = cfi->chips[chipnum].start; | ||
| 1851 | } | ||
| 1852 | } | ||
| 1853 | |||
| 1854 | /* Write the trailing bytes if any */ | ||
| 1855 | if (len & (map_bankwidth(map) - 1)) { | ||
| 1856 | map_word tmp_buf; | ||
| 1857 | |||
| 1858 | ret = cfi_amdstd_panic_wait(map, &cfi->chips[chipnum], ofs); | ||
| 1859 | if (ret) | ||
| 1860 | return ret; | ||
| 1861 | |||
| 1862 | tmp_buf = map_read(map, ofs + chipstart); | ||
| 1863 | |||
| 1864 | tmp_buf = map_word_load_partial(map, tmp_buf, buf, 0, len); | ||
| 1865 | |||
| 1866 | ret = do_panic_write_oneword(map, &cfi->chips[chipnum], | ||
| 1867 | ofs, tmp_buf); | ||
| 1868 | if (ret) | ||
| 1869 | return ret; | ||
| 1870 | |||
| 1871 | (*retlen) += len; | ||
| 1872 | } | ||
| 1873 | |||
| 1874 | return 0; | 1569 | return 0; |
| 1875 | } | 1570 | } |
| 1876 | 1571 | ||
| @@ -1896,7 +1591,7 @@ static int __xipram do_erase_chip(struct map_info *map, struct flchip *chip) | |||
| 1896 | return ret; | 1591 | return ret; |
| 1897 | } | 1592 | } |
| 1898 | 1593 | ||
| 1899 | pr_debug("MTD %s(): ERASE 0x%.8lx\n", | 1594 | DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): ERASE 0x%.8lx\n", |
| 1900 | __func__, chip->start ); | 1595 | __func__, chip->start ); |
| 1901 | 1596 | ||
| 1902 | XIP_INVAL_CACHED_RANGE(map, adr, map->size); | 1597 | XIP_INVAL_CACHED_RANGE(map, adr, map->size); |
| @@ -1961,7 +1656,6 @@ static int __xipram do_erase_chip(struct map_info *map, struct flchip *chip) | |||
| 1961 | 1656 | ||
| 1962 | chip->state = FL_READY; | 1657 | chip->state = FL_READY; |
| 1963 | xip_enable(map, chip, adr); | 1658 | xip_enable(map, chip, adr); |
| 1964 | DISABLE_VPP(map); | ||
| 1965 | put_chip(map, chip, adr); | 1659 | put_chip(map, chip, adr); |
| 1966 | mutex_unlock(&chip->mutex); | 1660 | mutex_unlock(&chip->mutex); |
| 1967 | 1661 | ||
| @@ -1985,7 +1679,7 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip, | |||
| 1985 | return ret; | 1679 | return ret; |
| 1986 | } | 1680 | } |
| 1987 | 1681 | ||
| 1988 | pr_debug("MTD %s(): ERASE 0x%.8lx\n", | 1682 | DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): ERASE 0x%.8lx\n", |
| 1989 | __func__, adr ); | 1683 | __func__, adr ); |
| 1990 | 1684 | ||
| 1991 | XIP_INVAL_CACHED_RANGE(map, adr, len); | 1685 | XIP_INVAL_CACHED_RANGE(map, adr, len); |
| @@ -2052,7 +1746,6 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip, | |||
| 2052 | } | 1746 | } |
| 2053 | 1747 | ||
| 2054 | chip->state = FL_READY; | 1748 | chip->state = FL_READY; |
| 2055 | DISABLE_VPP(map); | ||
| 2056 | put_chip(map, chip, adr); | 1749 | put_chip(map, chip, adr); |
| 2057 | mutex_unlock(&chip->mutex); | 1750 | mutex_unlock(&chip->mutex); |
| 2058 | return ret; | 1751 | return ret; |
| @@ -2112,7 +1805,8 @@ static int do_atmel_lock(struct map_info *map, struct flchip *chip, | |||
| 2112 | goto out_unlock; | 1805 | goto out_unlock; |
| 2113 | chip->state = FL_LOCKING; | 1806 | chip->state = FL_LOCKING; |
| 2114 | 1807 | ||
| 2115 | pr_debug("MTD %s(): LOCK 0x%08lx len %d\n", __func__, adr, len); | 1808 | DEBUG(MTD_DEBUG_LEVEL3, "MTD %s(): LOCK 0x%08lx len %d\n", |
| 1809 | __func__, adr, len); | ||
| 2116 | 1810 | ||
| 2117 | cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, | 1811 | cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, |
| 2118 | cfi->device_type, NULL); | 1812 | cfi->device_type, NULL); |
| @@ -2147,7 +1841,8 @@ static int do_atmel_unlock(struct map_info *map, struct flchip *chip, | |||
| 2147 | goto out_unlock; | 1841 | goto out_unlock; |
| 2148 | chip->state = FL_UNLOCKING; | 1842 | chip->state = FL_UNLOCKING; |
| 2149 | 1843 | ||
| 2150 | pr_debug("MTD %s(): LOCK 0x%08lx len %d\n", __func__, adr, len); | 1844 | DEBUG(MTD_DEBUG_LEVEL3, "MTD %s(): LOCK 0x%08lx len %d\n", |
| 1845 | __func__, adr, len); | ||
| 2151 | 1846 | ||
| 2152 | cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, | 1847 | cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, |
| 2153 | cfi->device_type, NULL); | 1848 | cfi->device_type, NULL); |
diff --git a/drivers/mtd/chips/cfi_cmdset_0020.c b/drivers/mtd/chips/cfi_cmdset_0020.c index 096993f9711..179814a95f3 100644 --- a/drivers/mtd/chips/cfi_cmdset_0020.c +++ b/drivers/mtd/chips/cfi_cmdset_0020.c | |||
| @@ -139,9 +139,8 @@ struct mtd_info *cfi_cmdset_0020(struct map_info *map, int primary) | |||
| 139 | } | 139 | } |
| 140 | 140 | ||
| 141 | /* Do some byteswapping if necessary */ | 141 | /* Do some byteswapping if necessary */ |
| 142 | extp->FeatureSupport = cfi32_to_cpu(map, extp->FeatureSupport); | 142 | extp->FeatureSupport = cfi32_to_cpu(extp->FeatureSupport); |
| 143 | extp->BlkStatusRegMask = cfi32_to_cpu(map, | 143 | extp->BlkStatusRegMask = cfi32_to_cpu(extp->BlkStatusRegMask); |
| 144 | extp->BlkStatusRegMask); | ||
| 145 | 144 | ||
| 146 | #ifdef DEBUG_CFI_FEATURES | 145 | #ifdef DEBUG_CFI_FEATURES |
| 147 | /* Tell the user about it in lots of lovely detail */ | 146 | /* Tell the user about it in lots of lovely detail */ |
| @@ -228,15 +227,15 @@ static struct mtd_info *cfi_staa_setup(struct map_info *map) | |||
| 228 | } | 227 | } |
| 229 | 228 | ||
| 230 | /* Also select the correct geometry setup too */ | 229 | /* Also select the correct geometry setup too */ |
| 231 | mtd->_erase = cfi_staa_erase_varsize; | 230 | mtd->erase = cfi_staa_erase_varsize; |
| 232 | mtd->_read = cfi_staa_read; | 231 | mtd->read = cfi_staa_read; |
| 233 | mtd->_write = cfi_staa_write_buffers; | 232 | mtd->write = cfi_staa_write_buffers; |
| 234 | mtd->_writev = cfi_staa_writev; | 233 | mtd->writev = cfi_staa_writev; |
| 235 | mtd->_sync = cfi_staa_sync; | 234 | mtd->sync = cfi_staa_sync; |
| 236 | mtd->_lock = cfi_staa_lock; | 235 | mtd->lock = cfi_staa_lock; |
| 237 | mtd->_unlock = cfi_staa_unlock; | 236 | mtd->unlock = cfi_staa_unlock; |
| 238 | mtd->_suspend = cfi_staa_suspend; | 237 | mtd->suspend = cfi_staa_suspend; |
| 239 | mtd->_resume = cfi_staa_resume; | 238 | mtd->resume = cfi_staa_resume; |
| 240 | mtd->flags = MTD_CAP_NORFLASH & ~MTD_BIT_WRITEABLE; | 239 | mtd->flags = MTD_CAP_NORFLASH & ~MTD_BIT_WRITEABLE; |
| 241 | mtd->writesize = 8; /* FIXME: Should be 0 for STMicro flashes w/out ECC */ | 240 | mtd->writesize = 8; /* FIXME: Should be 0 for STMicro flashes w/out ECC */ |
| 242 | mtd->writebufsize = cfi_interleave(cfi) << cfi->cfiq->MaxBufWriteSize; | 241 | mtd->writebufsize = cfi_interleave(cfi) << cfi->cfiq->MaxBufWriteSize; |
| @@ -394,6 +393,8 @@ static int cfi_staa_read (struct mtd_info *mtd, loff_t from, size_t len, size_t | |||
| 394 | chipnum = (from >> cfi->chipshift); | 393 | chipnum = (from >> cfi->chipshift); |
| 395 | ofs = from - (chipnum << cfi->chipshift); | 394 | ofs = from - (chipnum << cfi->chipshift); |
| 396 | 395 | ||
| 396 | *retlen = 0; | ||
| 397 | |||
| 397 | while (len) { | 398 | while (len) { |
| 398 | unsigned long thislen; | 399 | unsigned long thislen; |
| 399 | 400 | ||
| @@ -615,6 +616,10 @@ static int cfi_staa_write_buffers (struct mtd_info *mtd, loff_t to, | |||
| 615 | int chipnum; | 616 | int chipnum; |
| 616 | unsigned long ofs; | 617 | unsigned long ofs; |
| 617 | 618 | ||
| 619 | *retlen = 0; | ||
| 620 | if (!len) | ||
| 621 | return 0; | ||
| 622 | |||
| 618 | chipnum = to >> cfi->chipshift; | 623 | chipnum = to >> cfi->chipshift; |
| 619 | ofs = to - (chipnum << cfi->chipshift); | 624 | ofs = to - (chipnum << cfi->chipshift); |
| 620 | 625 | ||
| @@ -693,8 +698,7 @@ cfi_staa_writev(struct mtd_info *mtd, const struct kvec *vecs, | |||
| 693 | continue; | 698 | continue; |
| 694 | } | 699 | } |
| 695 | memcpy(buffer+buflen, elem_base, ECCBUF_SIZE-buflen); | 700 | memcpy(buffer+buflen, elem_base, ECCBUF_SIZE-buflen); |
| 696 | ret = mtd_write(mtd, to, ECCBUF_SIZE, &thislen, | 701 | ret = mtd->write(mtd, to, ECCBUF_SIZE, &thislen, buffer); |
| 697 | buffer); | ||
| 698 | totlen += thislen; | 702 | totlen += thislen; |
| 699 | if (ret || thislen != ECCBUF_SIZE) | 703 | if (ret || thislen != ECCBUF_SIZE) |
| 700 | goto write_error; | 704 | goto write_error; |
| @@ -703,8 +707,7 @@ cfi_staa_writev(struct mtd_info *mtd, const struct kvec *vecs, | |||
| 703 | to += ECCBUF_SIZE; | 707 | to += ECCBUF_SIZE; |
| 704 | } | 708 | } |
| 705 | if (ECCBUF_DIV(elem_len)) { /* write clean aligned data */ | 709 | if (ECCBUF_DIV(elem_len)) { /* write clean aligned data */ |
| 706 | ret = mtd_write(mtd, to, ECCBUF_DIV(elem_len), | 710 | ret = mtd->write(mtd, to, ECCBUF_DIV(elem_len), &thislen, elem_base); |
| 707 | &thislen, elem_base); | ||
| 708 | totlen += thislen; | 711 | totlen += thislen; |
| 709 | if (ret || thislen != ECCBUF_DIV(elem_len)) | 712 | if (ret || thislen != ECCBUF_DIV(elem_len)) |
| 710 | goto write_error; | 713 | goto write_error; |
| @@ -718,7 +721,7 @@ cfi_staa_writev(struct mtd_info *mtd, const struct kvec *vecs, | |||
| 718 | } | 721 | } |
| 719 | if (buflen) { /* flush last page, even if not full */ | 722 | if (buflen) { /* flush last page, even if not full */ |
| 720 | /* This is sometimes intended behaviour, really */ | 723 | /* This is sometimes intended behaviour, really */ |
| 721 | ret = mtd_write(mtd, to, buflen, &thislen, buffer); | 724 | ret = mtd->write(mtd, to, buflen, &thislen, buffer); |
| 722 | totlen += thislen; | 725 | totlen += thislen; |
| 723 | if (ret || thislen != ECCBUF_SIZE) | 726 | if (ret || thislen != ECCBUF_SIZE) |
| 724 | goto write_error; | 727 | goto write_error; |
| @@ -898,6 +901,12 @@ static int cfi_staa_erase_varsize(struct mtd_info *mtd, | |||
| 898 | int i, first; | 901 | int i, first; |
| 899 | struct mtd_erase_region_info *regions = mtd->eraseregions; | 902 | struct mtd_erase_region_info *regions = mtd->eraseregions; |
| 900 | 903 | ||
| 904 | if (instr->addr > mtd->size) | ||
| 905 | return -EINVAL; | ||
| 906 | |||
| 907 | if ((instr->len + instr->addr) > mtd->size) | ||
| 908 | return -EINVAL; | ||
| 909 | |||
| 901 | /* Check that both start and end of the requested erase are | 910 | /* Check that both start and end of the requested erase are |
| 902 | * aligned with the erasesize at the appropriate addresses. | 911 | * aligned with the erasesize at the appropriate addresses. |
| 903 | */ | 912 | */ |
| @@ -1143,6 +1152,9 @@ static int cfi_staa_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len) | |||
| 1143 | if (len & (mtd->erasesize -1)) | 1152 | if (len & (mtd->erasesize -1)) |
| 1144 | return -EINVAL; | 1153 | return -EINVAL; |
| 1145 | 1154 | ||
| 1155 | if ((len + ofs) > mtd->size) | ||
| 1156 | return -EINVAL; | ||
| 1157 | |||
| 1146 | chipnum = ofs >> cfi->chipshift; | 1158 | chipnum = ofs >> cfi->chipshift; |
| 1147 | adr = ofs - (chipnum << cfi->chipshift); | 1159 | adr = ofs - (chipnum << cfi->chipshift); |
| 1148 | 1160 | ||
diff --git a/drivers/mtd/chips/cfi_util.c b/drivers/mtd/chips/cfi_util.c index f992418f40a..8e464054a63 100644 --- a/drivers/mtd/chips/cfi_util.c +++ b/drivers/mtd/chips/cfi_util.c | |||
| @@ -173,6 +173,12 @@ int cfi_varsize_frob(struct mtd_info *mtd, varsize_frob_t frob, | |||
| 173 | int i, first; | 173 | int i, first; |
| 174 | struct mtd_erase_region_info *regions = mtd->eraseregions; | 174 | struct mtd_erase_region_info *regions = mtd->eraseregions; |
| 175 | 175 | ||
| 176 | if (ofs > mtd->size) | ||
| 177 | return -EINVAL; | ||
| 178 | |||
| 179 | if ((len + ofs) > mtd->size) | ||
| 180 | return -EINVAL; | ||
| 181 | |||
| 176 | /* Check that both start and end of the requested erase are | 182 | /* Check that both start and end of the requested erase are |
| 177 | * aligned with the erasesize at the appropriate addresses. | 183 | * aligned with the erasesize at the appropriate addresses. |
| 178 | */ | 184 | */ |
diff --git a/drivers/mtd/chips/chipreg.c b/drivers/mtd/chips/chipreg.c index 0bbc61ba952..da1f96f385c 100644 --- a/drivers/mtd/chips/chipreg.c +++ b/drivers/mtd/chips/chipreg.c | |||
| @@ -76,7 +76,10 @@ struct mtd_info *do_map_probe(const char *name, struct map_info *map) | |||
| 76 | */ | 76 | */ |
| 77 | module_put(drv->module); | 77 | module_put(drv->module); |
| 78 | 78 | ||
| 79 | return ret; | 79 | if (ret) |
| 80 | return ret; | ||
| 81 | |||
| 82 | return NULL; | ||
| 80 | } | 83 | } |
| 81 | /* | 84 | /* |
| 82 | * Destroy an MTD device which was created for a map device. | 85 | * Destroy an MTD device which was created for a map device. |
diff --git a/drivers/mtd/chips/fwh_lock.h b/drivers/mtd/chips/fwh_lock.h index 800b0e853e8..5e3cc80128a 100644 --- a/drivers/mtd/chips/fwh_lock.h +++ b/drivers/mtd/chips/fwh_lock.h | |||
| @@ -34,7 +34,8 @@ static int fwh_xxlock_oneblock(struct map_info *map, struct flchip *chip, | |||
| 34 | 34 | ||
| 35 | /* Refuse the operation if the we cannot look behind the chip */ | 35 | /* Refuse the operation if the we cannot look behind the chip */ |
| 36 | if (chip->start < 0x400000) { | 36 | if (chip->start < 0x400000) { |
| 37 | pr_debug( "MTD %s(): chip->start: %lx wanted >= 0x400000\n", | 37 | DEBUG( MTD_DEBUG_LEVEL3, |
| 38 | "MTD %s(): chip->start: %lx wanted >= 0x400000\n", | ||
| 38 | __func__, chip->start ); | 39 | __func__, chip->start ); |
| 39 | return -EIO; | 40 | return -EIO; |
| 40 | } | 41 | } |
| @@ -101,7 +102,7 @@ static void fixup_use_fwh_lock(struct mtd_info *mtd) | |||
| 101 | { | 102 | { |
| 102 | printk(KERN_NOTICE "using fwh lock/unlock method\n"); | 103 | printk(KERN_NOTICE "using fwh lock/unlock method\n"); |
| 103 | /* Setup for the chips with the fwh lock method */ | 104 | /* Setup for the chips with the fwh lock method */ |
| 104 | mtd->_lock = fwh_lock_varsize; | 105 | mtd->lock = fwh_lock_varsize; |
| 105 | mtd->_unlock = fwh_unlock_varsize; | 106 | mtd->unlock = fwh_unlock_varsize; |
| 106 | } | 107 | } |
| 107 | #endif /* FWH_LOCK_H */ | 108 | #endif /* FWH_LOCK_H */ |
diff --git a/drivers/mtd/chips/jedec_probe.c b/drivers/mtd/chips/jedec_probe.c index c443f527a53..ea832ea0e4a 100644 --- a/drivers/mtd/chips/jedec_probe.c +++ b/drivers/mtd/chips/jedec_probe.c | |||
| @@ -1914,10 +1914,11 @@ static void jedec_reset(u32 base, struct map_info *map, struct cfi_private *cfi) | |||
| 1914 | * (oh and incidentaly the jedec spec - 3.5.3.3) the reset | 1914 | * (oh and incidentaly the jedec spec - 3.5.3.3) the reset |
| 1915 | * sequence is *supposed* to be 0xaa at 0x5555, 0x55 at | 1915 | * sequence is *supposed* to be 0xaa at 0x5555, 0x55 at |
| 1916 | * 0x2aaa, 0xF0 at 0x5555 this will not affect the AMD chips | 1916 | * 0x2aaa, 0xF0 at 0x5555 this will not affect the AMD chips |
| 1917 | * as they will ignore the writes and don't care what address | 1917 | * as they will ignore the writes and dont care what address |
| 1918 | * the F0 is written to */ | 1918 | * the F0 is written to */ |
| 1919 | if (cfi->addr_unlock1) { | 1919 | if (cfi->addr_unlock1) { |
| 1920 | pr_debug( "reset unlock called %x %x \n", | 1920 | DEBUG( MTD_DEBUG_LEVEL3, |
| 1921 | "reset unlock called %x %x \n", | ||
| 1921 | cfi->addr_unlock1,cfi->addr_unlock2); | 1922 | cfi->addr_unlock1,cfi->addr_unlock2); |
| 1922 | cfi_send_gen_cmd(0xaa, cfi->addr_unlock1, base, map, cfi, cfi->device_type, NULL); | 1923 | cfi_send_gen_cmd(0xaa, cfi->addr_unlock1, base, map, cfi, cfi->device_type, NULL); |
| 1923 | cfi_send_gen_cmd(0x55, cfi->addr_unlock2, base, map, cfi, cfi->device_type, NULL); | 1924 | cfi_send_gen_cmd(0x55, cfi->addr_unlock2, base, map, cfi, cfi->device_type, NULL); |
| @@ -1940,7 +1941,7 @@ static int cfi_jedec_setup(struct map_info *map, struct cfi_private *cfi, int in | |||
| 1940 | uint8_t uaddr; | 1941 | uint8_t uaddr; |
| 1941 | 1942 | ||
| 1942 | if (!(jedec_table[index].devtypes & cfi->device_type)) { | 1943 | if (!(jedec_table[index].devtypes & cfi->device_type)) { |
| 1943 | pr_debug("Rejecting potential %s with incompatible %d-bit device type\n", | 1944 | DEBUG(MTD_DEBUG_LEVEL1, "Rejecting potential %s with incompatible %d-bit device type\n", |
| 1944 | jedec_table[index].name, 4 * (1<<cfi->device_type)); | 1945 | jedec_table[index].name, 4 * (1<<cfi->device_type)); |
| 1945 | return 0; | 1946 | return 0; |
| 1946 | } | 1947 | } |
| @@ -2020,7 +2021,7 @@ static inline int jedec_match( uint32_t base, | |||
| 2020 | * there aren't. | 2021 | * there aren't. |
| 2021 | */ | 2022 | */ |
| 2022 | if (finfo->dev_id > 0xff) { | 2023 | if (finfo->dev_id > 0xff) { |
| 2023 | pr_debug("%s(): ID is not 8bit\n", | 2024 | DEBUG( MTD_DEBUG_LEVEL3, "%s(): ID is not 8bit\n", |
| 2024 | __func__); | 2025 | __func__); |
| 2025 | goto match_done; | 2026 | goto match_done; |
| 2026 | } | 2027 | } |
| @@ -2044,10 +2045,12 @@ static inline int jedec_match( uint32_t base, | |||
| 2044 | } | 2045 | } |
| 2045 | 2046 | ||
| 2046 | /* the part size must fit in the memory window */ | 2047 | /* the part size must fit in the memory window */ |
| 2047 | pr_debug("MTD %s(): Check fit 0x%.8x + 0x%.8x = 0x%.8x\n", | 2048 | DEBUG( MTD_DEBUG_LEVEL3, |
| 2049 | "MTD %s(): Check fit 0x%.8x + 0x%.8x = 0x%.8x\n", | ||
| 2048 | __func__, base, 1 << finfo->dev_size, base + (1 << finfo->dev_size) ); | 2050 | __func__, base, 1 << finfo->dev_size, base + (1 << finfo->dev_size) ); |
| 2049 | if ( base + cfi_interleave(cfi) * ( 1 << finfo->dev_size ) > map->size ) { | 2051 | if ( base + cfi_interleave(cfi) * ( 1 << finfo->dev_size ) > map->size ) { |
| 2050 | pr_debug("MTD %s(): 0x%.4x 0x%.4x %dKiB doesn't fit\n", | 2052 | DEBUG( MTD_DEBUG_LEVEL3, |
| 2053 | "MTD %s(): 0x%.4x 0x%.4x %dKiB doesn't fit\n", | ||
| 2051 | __func__, finfo->mfr_id, finfo->dev_id, | 2054 | __func__, finfo->mfr_id, finfo->dev_id, |
| 2052 | 1 << finfo->dev_size ); | 2055 | 1 << finfo->dev_size ); |
| 2053 | goto match_done; | 2056 | goto match_done; |
| @@ -2058,12 +2061,13 @@ static inline int jedec_match( uint32_t base, | |||
| 2058 | 2061 | ||
| 2059 | uaddr = finfo->uaddr; | 2062 | uaddr = finfo->uaddr; |
| 2060 | 2063 | ||
| 2061 | pr_debug("MTD %s(): check unlock addrs 0x%.4x 0x%.4x\n", | 2064 | DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): check unlock addrs 0x%.4x 0x%.4x\n", |
| 2062 | __func__, cfi->addr_unlock1, cfi->addr_unlock2 ); | 2065 | __func__, cfi->addr_unlock1, cfi->addr_unlock2 ); |
| 2063 | if ( MTD_UADDR_UNNECESSARY != uaddr && MTD_UADDR_DONT_CARE != uaddr | 2066 | if ( MTD_UADDR_UNNECESSARY != uaddr && MTD_UADDR_DONT_CARE != uaddr |
| 2064 | && ( unlock_addrs[uaddr].addr1 / cfi->device_type != cfi->addr_unlock1 || | 2067 | && ( unlock_addrs[uaddr].addr1 / cfi->device_type != cfi->addr_unlock1 || |
| 2065 | unlock_addrs[uaddr].addr2 / cfi->device_type != cfi->addr_unlock2 ) ) { | 2068 | unlock_addrs[uaddr].addr2 / cfi->device_type != cfi->addr_unlock2 ) ) { |
| 2066 | pr_debug("MTD %s(): 0x%.4x 0x%.4x did not match\n", | 2069 | DEBUG( MTD_DEBUG_LEVEL3, |
| 2070 | "MTD %s(): 0x%.4x 0x%.4x did not match\n", | ||
| 2067 | __func__, | 2071 | __func__, |
| 2068 | unlock_addrs[uaddr].addr1, | 2072 | unlock_addrs[uaddr].addr1, |
| 2069 | unlock_addrs[uaddr].addr2); | 2073 | unlock_addrs[uaddr].addr2); |
| @@ -2079,13 +2083,15 @@ static inline int jedec_match( uint32_t base, | |||
| 2079 | * FIXME - write a driver that takes all of the chip info as | 2083 | * FIXME - write a driver that takes all of the chip info as |
| 2080 | * module parameters, doesn't probe but forces a load. | 2084 | * module parameters, doesn't probe but forces a load. |
| 2081 | */ | 2085 | */ |
| 2082 | pr_debug("MTD %s(): check ID's disappear when not in ID mode\n", | 2086 | DEBUG( MTD_DEBUG_LEVEL3, |
| 2087 | "MTD %s(): check ID's disappear when not in ID mode\n", | ||
| 2083 | __func__ ); | 2088 | __func__ ); |
| 2084 | jedec_reset( base, map, cfi ); | 2089 | jedec_reset( base, map, cfi ); |
| 2085 | mfr = jedec_read_mfr( map, base, cfi ); | 2090 | mfr = jedec_read_mfr( map, base, cfi ); |
| 2086 | id = jedec_read_id( map, base, cfi ); | 2091 | id = jedec_read_id( map, base, cfi ); |
| 2087 | if ( mfr == cfi->mfr && id == cfi->id ) { | 2092 | if ( mfr == cfi->mfr && id == cfi->id ) { |
| 2088 | pr_debug("MTD %s(): ID 0x%.2x:0x%.2x did not change after reset:\n" | 2093 | DEBUG( MTD_DEBUG_LEVEL3, |
| 2094 | "MTD %s(): ID 0x%.2x:0x%.2x did not change after reset:\n" | ||
| 2089 | "You might need to manually specify JEDEC parameters.\n", | 2095 | "You might need to manually specify JEDEC parameters.\n", |
| 2090 | __func__, cfi->mfr, cfi->id ); | 2096 | __func__, cfi->mfr, cfi->id ); |
| 2091 | goto match_done; | 2097 | goto match_done; |
| @@ -2098,7 +2104,7 @@ static inline int jedec_match( uint32_t base, | |||
| 2098 | * Put the device back in ID mode - only need to do this if we | 2104 | * Put the device back in ID mode - only need to do this if we |
| 2099 | * were truly frobbing a real device. | 2105 | * were truly frobbing a real device. |
| 2100 | */ | 2106 | */ |
| 2101 | pr_debug("MTD %s(): return to ID mode\n", __func__ ); | 2107 | DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): return to ID mode\n", __func__ ); |
| 2102 | if (cfi->addr_unlock1) { | 2108 | if (cfi->addr_unlock1) { |
| 2103 | cfi_send_gen_cmd(0xaa, cfi->addr_unlock1, base, map, cfi, cfi->device_type, NULL); | 2109 | cfi_send_gen_cmd(0xaa, cfi->addr_unlock1, base, map, cfi, cfi->device_type, NULL); |
| 2104 | cfi_send_gen_cmd(0x55, cfi->addr_unlock2, base, map, cfi, cfi->device_type, NULL); | 2110 | cfi_send_gen_cmd(0x55, cfi->addr_unlock2, base, map, cfi, cfi->device_type, NULL); |
| @@ -2161,11 +2167,13 @@ static int jedec_probe_chip(struct map_info *map, __u32 base, | |||
| 2161 | 2167 | ||
| 2162 | cfi->mfr = jedec_read_mfr(map, base, cfi); | 2168 | cfi->mfr = jedec_read_mfr(map, base, cfi); |
| 2163 | cfi->id = jedec_read_id(map, base, cfi); | 2169 | cfi->id = jedec_read_id(map, base, cfi); |
| 2164 | pr_debug("Search for id:(%02x %02x) interleave(%d) type(%d)\n", | 2170 | DEBUG(MTD_DEBUG_LEVEL3, |
| 2171 | "Search for id:(%02x %02x) interleave(%d) type(%d)\n", | ||
| 2165 | cfi->mfr, cfi->id, cfi_interleave(cfi), cfi->device_type); | 2172 | cfi->mfr, cfi->id, cfi_interleave(cfi), cfi->device_type); |
| 2166 | for (i = 0; i < ARRAY_SIZE(jedec_table); i++) { | 2173 | for (i = 0; i < ARRAY_SIZE(jedec_table); i++) { |
| 2167 | if ( jedec_match( base, map, cfi, &jedec_table[i] ) ) { | 2174 | if ( jedec_match( base, map, cfi, &jedec_table[i] ) ) { |
| 2168 | pr_debug("MTD %s(): matched device 0x%x,0x%x unlock_addrs: 0x%.4x 0x%.4x\n", | 2175 | DEBUG( MTD_DEBUG_LEVEL3, |
| 2176 | "MTD %s(): matched device 0x%x,0x%x unlock_addrs: 0x%.4x 0x%.4x\n", | ||
| 2169 | __func__, cfi->mfr, cfi->id, | 2177 | __func__, cfi->mfr, cfi->id, |
| 2170 | cfi->addr_unlock1, cfi->addr_unlock2 ); | 2178 | cfi->addr_unlock1, cfi->addr_unlock2 ); |
| 2171 | if (!cfi_jedec_setup(map, cfi, i)) | 2179 | if (!cfi_jedec_setup(map, cfi, i)) |
diff --git a/drivers/mtd/chips/map_absent.c b/drivers/mtd/chips/map_absent.c index f7a5bca92ae..f2b87294687 100644 --- a/drivers/mtd/chips/map_absent.c +++ b/drivers/mtd/chips/map_absent.c | |||
| @@ -55,10 +55,10 @@ static struct mtd_info *map_absent_probe(struct map_info *map) | |||
| 55 | mtd->name = map->name; | 55 | mtd->name = map->name; |
| 56 | mtd->type = MTD_ABSENT; | 56 | mtd->type = MTD_ABSENT; |
| 57 | mtd->size = map->size; | 57 | mtd->size = map->size; |
| 58 | mtd->_erase = map_absent_erase; | 58 | mtd->erase = map_absent_erase; |
| 59 | mtd->_read = map_absent_read; | 59 | mtd->read = map_absent_read; |
| 60 | mtd->_write = map_absent_write; | 60 | mtd->write = map_absent_write; |
| 61 | mtd->_sync = map_absent_sync; | 61 | mtd->sync = map_absent_sync; |
| 62 | mtd->flags = 0; | 62 | mtd->flags = 0; |
| 63 | mtd->erasesize = PAGE_SIZE; | 63 | mtd->erasesize = PAGE_SIZE; |
| 64 | mtd->writesize = 1; | 64 | mtd->writesize = 1; |
| @@ -70,11 +70,13 @@ static struct mtd_info *map_absent_probe(struct map_info *map) | |||
| 70 | 70 | ||
| 71 | static int map_absent_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) | 71 | static int map_absent_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) |
| 72 | { | 72 | { |
| 73 | *retlen = 0; | ||
| 73 | return -ENODEV; | 74 | return -ENODEV; |
| 74 | } | 75 | } |
| 75 | 76 | ||
| 76 | static int map_absent_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf) | 77 | static int map_absent_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf) |
| 77 | { | 78 | { |
| 79 | *retlen = 0; | ||
| 78 | return -ENODEV; | 80 | return -ENODEV; |
| 79 | } | 81 | } |
| 80 | 82 | ||
diff --git a/drivers/mtd/chips/map_ram.c b/drivers/mtd/chips/map_ram.c index 991c2a1c05d..67640ccb2d4 100644 --- a/drivers/mtd/chips/map_ram.c +++ b/drivers/mtd/chips/map_ram.c | |||
| @@ -64,11 +64,11 @@ static struct mtd_info *map_ram_probe(struct map_info *map) | |||
| 64 | mtd->name = map->name; | 64 | mtd->name = map->name; |
| 65 | mtd->type = MTD_RAM; | 65 | mtd->type = MTD_RAM; |
| 66 | mtd->size = map->size; | 66 | mtd->size = map->size; |
| 67 | mtd->_erase = mapram_erase; | 67 | mtd->erase = mapram_erase; |
| 68 | mtd->_get_unmapped_area = mapram_unmapped_area; | 68 | mtd->get_unmapped_area = mapram_unmapped_area; |
| 69 | mtd->_read = mapram_read; | 69 | mtd->read = mapram_read; |
| 70 | mtd->_write = mapram_write; | 70 | mtd->write = mapram_write; |
| 71 | mtd->_sync = mapram_nop; | 71 | mtd->sync = mapram_nop; |
| 72 | mtd->flags = MTD_CAP_RAM; | 72 | mtd->flags = MTD_CAP_RAM; |
| 73 | mtd->writesize = 1; | 73 | mtd->writesize = 1; |
| 74 | 74 | ||
| @@ -122,10 +122,14 @@ static int mapram_erase (struct mtd_info *mtd, struct erase_info *instr) | |||
| 122 | unsigned long i; | 122 | unsigned long i; |
| 123 | 123 | ||
| 124 | allff = map_word_ff(map); | 124 | allff = map_word_ff(map); |
| 125 | |||
| 125 | for (i=0; i<instr->len; i += map_bankwidth(map)) | 126 | for (i=0; i<instr->len; i += map_bankwidth(map)) |
| 126 | map_write(map, allff, instr->addr + i); | 127 | map_write(map, allff, instr->addr + i); |
| 128 | |||
| 127 | instr->state = MTD_ERASE_DONE; | 129 | instr->state = MTD_ERASE_DONE; |
| 130 | |||
| 128 | mtd_erase_callback(instr); | 131 | mtd_erase_callback(instr); |
| 132 | |||
| 129 | return 0; | 133 | return 0; |
| 130 | } | 134 | } |
| 131 | 135 | ||
diff --git a/drivers/mtd/chips/map_rom.c b/drivers/mtd/chips/map_rom.c index 47a43cf7e5c..593f73d480d 100644 --- a/drivers/mtd/chips/map_rom.c +++ b/drivers/mtd/chips/map_rom.c | |||
| @@ -41,11 +41,11 @@ static struct mtd_info *map_rom_probe(struct map_info *map) | |||
| 41 | mtd->name = map->name; | 41 | mtd->name = map->name; |
| 42 | mtd->type = MTD_ROM; | 42 | mtd->type = MTD_ROM; |
| 43 | mtd->size = map->size; | 43 | mtd->size = map->size; |
| 44 | mtd->_get_unmapped_area = maprom_unmapped_area; | 44 | mtd->get_unmapped_area = maprom_unmapped_area; |
| 45 | mtd->_read = maprom_read; | 45 | mtd->read = maprom_read; |
| 46 | mtd->_write = maprom_write; | 46 | mtd->write = maprom_write; |
| 47 | mtd->_sync = maprom_nop; | 47 | mtd->sync = maprom_nop; |
| 48 | mtd->_erase = maprom_erase; | 48 | mtd->erase = maprom_erase; |
| 49 | mtd->flags = MTD_CAP_ROM; | 49 | mtd->flags = MTD_CAP_ROM; |
| 50 | mtd->erasesize = map->size; | 50 | mtd->erasesize = map->size; |
| 51 | mtd->writesize = 1; | 51 | mtd->writesize = 1; |
| @@ -85,7 +85,8 @@ static void maprom_nop(struct mtd_info *mtd) | |||
| 85 | 85 | ||
| 86 | static int maprom_write (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf) | 86 | static int maprom_write (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf) |
| 87 | { | 87 | { |
| 88 | return -EROFS; | 88 | printk(KERN_NOTICE "maprom_write called\n"); |
| 89 | return -EIO; | ||
| 89 | } | 90 | } |
| 90 | 91 | ||
| 91 | static int maprom_erase (struct mtd_info *mtd, struct erase_info *info) | 92 | static int maprom_erase (struct mtd_info *mtd, struct erase_info *info) |
