From f4e767b4c9b2d5139387175f0c57afd81f0b62de Mon Sep 17 00:00:00 2001 From: Tokunori Ikegami Date: Sat, 19 Feb 2022 19:39:32 +0900 Subject: [PATCH v3] mtd: cfi_cmdset_0002: Change chip_good() to check DQ true data 0xFF on S29GL064N The regression issue has been caused on S29GL064N and reported it. The change mentioned for regression is to use chip_good() for buffered write. Also it seems that the 0xFF value is read on the error case. It is possible to be caused by DQ true data described by S29GL064N datasheet. So change chip_good() to check DQ true data 0xFF additionally for the error. Fixes: dfeae1073583("mtd: cfi_cmdset_0002: Change write buffer to check correct value") Signed-off-by: Tokunori Ikegami Cc: Miquel Raynal Cc: Richard Weinberger Cc: Vignesh Raghavendra Cc: linux-mtd@lists.infradead.org Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/b687c259-6413-26c9-d4c9-b3afa69ea124@pengutronix.de/ --- drivers/mtd/chips/cfi_cmdset_0002.c | 36 ++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c index a761134fd3be..99c1c6741b69 100644 --- a/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/drivers/mtd/chips/cfi_cmdset_0002.c @@ -48,6 +48,7 @@ #define SST49LF040B 0x0050 #define SST49LF008A 0x005a #define AT49BV6416 0x00d6 +#define S29GL064N_MN12 0x0c01 /* * Status Register bit description. Used by flash devices that don't @@ -462,7 +463,7 @@ static struct cfi_fixup cfi_fixup_table[] = { { CFI_MFR_AMD, 0x0056, fixup_use_secsi }, { CFI_MFR_AMD, 0x005C, fixup_use_secsi }, { CFI_MFR_AMD, 0x005F, fixup_use_secsi }, - { CFI_MFR_AMD, 0x0c01, fixup_s29gl064n_sectors }, + { CFI_MFR_AMD, S29GL064N_MN12, fixup_s29gl064n_sectors }, { CFI_MFR_AMD, 0x1301, fixup_s29gl064n_sectors }, { CFI_MFR_AMD, 0x1a00, fixup_s29gl032n_sectors }, { CFI_MFR_AMD, 0x1a01, fixup_s29gl032n_sectors }, @@ -837,6 +838,11 @@ static int __xipram chip_ready(struct map_info *map, struct flchip *chip, return map_word_equal(map, d, t); } +static bool __xipram cfi_use_dq_true_data(struct cfi_private *cfi) +{ + return cfi->mfr == CFI_MFR_AMD && cfi->id == S29GL064N_MN12; +} + /* * Return true if the chip is ready and has the correct value. * @@ -853,7 +859,7 @@ static int __xipram chip_ready(struct map_info *map, struct flchip *chip, * */ static int __xipram chip_good(struct map_info *map, struct flchip *chip, - unsigned long addr, map_word expected) + unsigned long addr, map_word *expected) { struct cfi_private *cfi = map->fldrv_priv; map_word oldd, curd; @@ -875,8 +881,16 @@ static int __xipram chip_good(struct map_info *map, struct flchip *chip, oldd = map_read(map, addr); curd = map_read(map, addr); - return map_word_equal(map, oldd, curd) && - map_word_equal(map, curd, expected); + if (!map_word_equal(map, oldd, curd)) + return 0; + + if (expected && map_word_equal(map, curd, *expected)) + return 1; + + if (cfi_use_dq_true_data(cfi)) + return map_word_equal(map, oldd, map_word_ff(map)); + + return 0; } static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr, int mode) @@ -1699,7 +1713,7 @@ static int __xipram do_write_oneword_once(struct map_info *map, * "chip_good" to avoid the failure due to scheduling. */ if (time_after(jiffies, timeo) && - !chip_good(map, chip, adr, datum)) { + !chip_good(map, chip, adr, &datum)) { xip_enable(map, chip, adr); printk(KERN_WARNING "MTD %s(): software timeout\n", __func__); xip_disable(map, chip, adr); @@ -1707,7 +1721,7 @@ static int __xipram do_write_oneword_once(struct map_info *map, break; } - if (chip_good(map, chip, adr, datum)) { + if (chip_good(map, chip, adr, &datum)) { if (cfi_check_err_status(map, chip, adr)) ret = -EIO; break; @@ -1979,14 +1993,14 @@ static int __xipram do_write_buffer_wait(struct map_info *map, * "chip_good" to avoid the failure due to scheduling. */ if (time_after(jiffies, timeo) && - !chip_good(map, chip, adr, datum)) { + !chip_good(map, chip, adr, &datum)) { pr_err("MTD %s(): software timeout, address:0x%.8lx.\n", __func__, adr); ret = -EIO; break; } - if (chip_good(map, chip, adr, datum)) { + if (chip_good(map, chip, adr, &datum)) { if (cfi_check_err_status(map, chip, adr)) ret = -EIO; break; @@ -2282,7 +2296,7 @@ static int do_panic_write_oneword(struct map_info *map, struct flchip *chip, udelay(1); } - if (!chip_good(map, chip, adr, datum) || + if (!chip_good(map, chip, adr, &datum) || cfi_check_err_status(map, chip, adr)) { /* reset on all failures. */ map_write(map, CMD(0xF0), chip->start); @@ -2478,7 +2492,7 @@ static int __xipram do_erase_chip(struct map_info *map, struct flchip *chip) chip->erase_suspended = 0; } - if (chip_good(map, chip, adr, map_word_ff(map))) { + if (chip_good(map, chip, adr, NULL)) { if (cfi_check_err_status(map, chip, adr)) ret = -EIO; break; @@ -2577,7 +2591,7 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip, chip->erase_suspended = 0; } - if (chip_good(map, chip, adr, map_word_ff(map))) { + if (chip_good(map, chip, adr, NULL)) { if (cfi_check_err_status(map, chip, adr)) ret = -EIO; break; -- 2.32.0