Commit 083084df authored by Tokunori Ikegami's avatar Tokunori Ikegami Committed by Miquel Raynal

mtd: cfi_cmdset_0002: Move and rename chip_check/chip_ready/chip_good_for_write

This is a preparation patch for the S29GL064N buffer writes fix. There
is no functional change.

Link: https://lore.kernel.org/r/b687c259-6413-26c9-d4c9-b3afa69ea124@pengutronix.de/
Fixes: dfeae107("mtd: cfi_cmdset_0002: Change write buffer to check correct value")
Signed-off-by: default avatarTokunori Ikegami <ikegami.t@gmail.com>
Cc: stable@vger.kernel.org
Acked-by: default avatarVignesh Raghavendra <vigneshr@ti.com>
Signed-off-by: default avatarMiquel Raynal <miquel.raynal@bootlin.com>
Link: https://lore.kernel.org/linux-mtd/20220323170458.5608-2-ikegami.t@gmail.com
parent aa641a22
...@@ -802,21 +802,25 @@ static struct mtd_info *cfi_amdstd_setup(struct mtd_info *mtd) ...@@ -802,21 +802,25 @@ static struct mtd_info *cfi_amdstd_setup(struct mtd_info *mtd)
} }
/* /*
* Return true if the chip is ready. * Return true if the chip is ready and has the correct value.
* *
* Ready is one of: read mode, query mode, erase-suspend-read mode (in any * Ready is one of: read mode, query mode, erase-suspend-read mode (in any
* non-suspended sector) and is indicated by no toggle bits toggling. * non-suspended sector) and is indicated by no toggle bits toggling.
* *
* Error are indicated by toggling bits or bits held with the wrong value,
* or with bits toggling.
*
* Note that anything more complicated than checking if no bits are toggling * Note that anything more complicated than checking if no bits are toggling
* (including checking DQ5 for an error status) is tricky to get working * (including checking DQ5 for an error status) is tricky to get working
* correctly and is therefore not done (particularly with interleaved chips * correctly and is therefore not done (particularly with interleaved chips
* as each chip must be checked independently of the others). * as each chip must be checked independently of the others).
*/ */
static int __xipram chip_ready(struct map_info *map, struct flchip *chip, static int __xipram chip_ready(struct map_info *map, struct flchip *chip,
unsigned long addr) unsigned long addr, map_word *expected)
{ {
struct cfi_private *cfi = map->fldrv_priv; struct cfi_private *cfi = map->fldrv_priv;
map_word d, t; map_word d, t;
int ret;
if (cfi_use_status_reg(cfi)) { if (cfi_use_status_reg(cfi)) {
map_word ready = CMD(CFI_SR_DRB); map_word ready = CMD(CFI_SR_DRB);
...@@ -826,57 +830,20 @@ static int __xipram chip_ready(struct map_info *map, struct flchip *chip, ...@@ -826,57 +830,20 @@ static int __xipram chip_ready(struct map_info *map, struct flchip *chip,
*/ */
cfi_send_gen_cmd(0x70, cfi->addr_unlock1, chip->start, map, cfi, cfi_send_gen_cmd(0x70, cfi->addr_unlock1, chip->start, map, cfi,
cfi->device_type, NULL); cfi->device_type, NULL);
d = map_read(map, addr); t = map_read(map, addr);
return map_word_andequal(map, d, ready, ready); return map_word_andequal(map, t, ready, ready);
} }
d = map_read(map, addr); d = map_read(map, addr);
t = map_read(map, addr); t = map_read(map, addr);
return map_word_equal(map, d, t); ret = map_word_equal(map, d, t);
}
/*
* Return true if the chip is ready and has the correct value.
*
* Ready is one of: read mode, query mode, erase-suspend-read mode (in any
* non-suspended sector) and it is indicated by no bits toggling.
*
* Error are indicated by toggling bits or bits held with the wrong value,
* or with bits toggling.
*
* Note that anything more complicated than checking if no bits are toggling
* (including checking DQ5 for an error status) is tricky to get working
* correctly and is therefore not done (particularly with interleaved chips
* as each chip must be checked independently of the others).
*
*/
static int __xipram chip_good(struct map_info *map, struct flchip *chip,
unsigned long addr, map_word expected)
{
struct cfi_private *cfi = map->fldrv_priv;
map_word oldd, curd;
if (cfi_use_status_reg(cfi)) {
map_word ready = CMD(CFI_SR_DRB);
/*
* For chips that support status register, check device
* ready bit
*/
cfi_send_gen_cmd(0x70, cfi->addr_unlock1, chip->start, map, cfi,
cfi->device_type, NULL);
curd = map_read(map, addr);
return map_word_andequal(map, curd, ready, ready);
}
oldd = map_read(map, addr); if (!ret || !expected)
curd = map_read(map, addr); return ret;
return map_word_equal(map, oldd, curd) && return map_word_equal(map, t, *expected);
map_word_equal(map, curd, expected);
} }
static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr, int mode) static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr, int mode)
...@@ -893,7 +860,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr ...@@ -893,7 +860,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr
case FL_STATUS: case FL_STATUS:
for (;;) { for (;;) {
if (chip_ready(map, chip, adr)) if (chip_ready(map, chip, adr, NULL))
break; break;
if (time_after(jiffies, timeo)) { if (time_after(jiffies, timeo)) {
...@@ -932,7 +899,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr ...@@ -932,7 +899,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr
chip->state = FL_ERASE_SUSPENDING; chip->state = FL_ERASE_SUSPENDING;
chip->erase_suspended = 1; chip->erase_suspended = 1;
for (;;) { for (;;) {
if (chip_ready(map, chip, adr)) if (chip_ready(map, chip, adr, NULL))
break; break;
if (time_after(jiffies, timeo)) { if (time_after(jiffies, timeo)) {
...@@ -1463,7 +1430,7 @@ static int do_otp_lock(struct map_info *map, struct flchip *chip, loff_t adr, ...@@ -1463,7 +1430,7 @@ static int do_otp_lock(struct map_info *map, struct flchip *chip, loff_t adr,
/* wait for chip to become ready */ /* wait for chip to become ready */
timeo = jiffies + msecs_to_jiffies(2); timeo = jiffies + msecs_to_jiffies(2);
for (;;) { for (;;) {
if (chip_ready(map, chip, adr)) if (chip_ready(map, chip, adr, NULL))
break; break;
if (time_after(jiffies, timeo)) { if (time_after(jiffies, timeo)) {
...@@ -1695,11 +1662,11 @@ static int __xipram do_write_oneword_once(struct map_info *map, ...@@ -1695,11 +1662,11 @@ static int __xipram do_write_oneword_once(struct map_info *map,
} }
/* /*
* We check "time_after" and "!chip_good" before checking * We check "time_after" and "!chip_ready" before checking
* "chip_good" to avoid the failure due to scheduling. * "chip_ready" to avoid the failure due to scheduling.
*/ */
if (time_after(jiffies, timeo) && if (time_after(jiffies, timeo) &&
!chip_good(map, chip, adr, datum)) { !chip_ready(map, chip, adr, &datum)) {
xip_enable(map, chip, adr); xip_enable(map, chip, adr);
printk(KERN_WARNING "MTD %s(): software timeout\n", __func__); printk(KERN_WARNING "MTD %s(): software timeout\n", __func__);
xip_disable(map, chip, adr); xip_disable(map, chip, adr);
...@@ -1707,7 +1674,7 @@ static int __xipram do_write_oneword_once(struct map_info *map, ...@@ -1707,7 +1674,7 @@ static int __xipram do_write_oneword_once(struct map_info *map,
break; break;
} }
if (chip_good(map, chip, adr, datum)) { if (chip_ready(map, chip, adr, &datum)) {
if (cfi_check_err_status(map, chip, adr)) if (cfi_check_err_status(map, chip, adr))
ret = -EIO; ret = -EIO;
break; break;
...@@ -1975,18 +1942,18 @@ static int __xipram do_write_buffer_wait(struct map_info *map, ...@@ -1975,18 +1942,18 @@ static int __xipram do_write_buffer_wait(struct map_info *map,
} }
/* /*
* We check "time_after" and "!chip_good" before checking * We check "time_after" and "!chip_ready" before checking
* "chip_good" to avoid the failure due to scheduling. * "chip_ready" to avoid the failure due to scheduling.
*/ */
if (time_after(jiffies, timeo) && if (time_after(jiffies, timeo) &&
!chip_good(map, chip, adr, datum)) { !chip_ready(map, chip, adr, &datum)) {
pr_err("MTD %s(): software timeout, address:0x%.8lx.\n", pr_err("MTD %s(): software timeout, address:0x%.8lx.\n",
__func__, adr); __func__, adr);
ret = -EIO; ret = -EIO;
break; break;
} }
if (chip_good(map, chip, adr, datum)) { if (chip_ready(map, chip, adr, &datum)) {
if (cfi_check_err_status(map, chip, adr)) if (cfi_check_err_status(map, chip, adr))
ret = -EIO; ret = -EIO;
break; break;
...@@ -2195,7 +2162,7 @@ static int cfi_amdstd_panic_wait(struct map_info *map, struct flchip *chip, ...@@ -2195,7 +2162,7 @@ static int cfi_amdstd_panic_wait(struct map_info *map, struct flchip *chip,
* If the driver thinks the chip is idle, and no toggle bits * If the driver thinks the chip is idle, and no toggle bits
* are changing, then the chip is actually idle for sure. * are changing, then the chip is actually idle for sure.
*/ */
if (chip->state == FL_READY && chip_ready(map, chip, adr)) if (chip->state == FL_READY && chip_ready(map, chip, adr, NULL))
return 0; return 0;
/* /*
...@@ -2212,7 +2179,7 @@ static int cfi_amdstd_panic_wait(struct map_info *map, struct flchip *chip, ...@@ -2212,7 +2179,7 @@ static int cfi_amdstd_panic_wait(struct map_info *map, struct flchip *chip,
/* wait for the chip to become ready */ /* wait for the chip to become ready */
for (i = 0; i < jiffies_to_usecs(timeo); i++) { for (i = 0; i < jiffies_to_usecs(timeo); i++) {
if (chip_ready(map, chip, adr)) if (chip_ready(map, chip, adr, NULL))
return 0; return 0;
udelay(1); udelay(1);
...@@ -2276,13 +2243,13 @@ static int do_panic_write_oneword(struct map_info *map, struct flchip *chip, ...@@ -2276,13 +2243,13 @@ static int do_panic_write_oneword(struct map_info *map, struct flchip *chip,
map_write(map, datum, adr); map_write(map, datum, adr);
for (i = 0; i < jiffies_to_usecs(uWriteTimeout); i++) { for (i = 0; i < jiffies_to_usecs(uWriteTimeout); i++) {
if (chip_ready(map, chip, adr)) if (chip_ready(map, chip, adr, NULL))
break; break;
udelay(1); udelay(1);
} }
if (!chip_good(map, chip, adr, datum) || if (!chip_ready(map, chip, adr, &datum) ||
cfi_check_err_status(map, chip, adr)) { cfi_check_err_status(map, chip, adr)) {
/* reset on all failures. */ /* reset on all failures. */
map_write(map, CMD(0xF0), chip->start); map_write(map, CMD(0xF0), chip->start);
...@@ -2424,6 +2391,7 @@ static int __xipram do_erase_chip(struct map_info *map, struct flchip *chip) ...@@ -2424,6 +2391,7 @@ static int __xipram do_erase_chip(struct map_info *map, struct flchip *chip)
DECLARE_WAITQUEUE(wait, current); DECLARE_WAITQUEUE(wait, current);
int ret; int ret;
int retry_cnt = 0; int retry_cnt = 0;
map_word datum = map_word_ff(map);
adr = cfi->addr_unlock1; adr = cfi->addr_unlock1;
...@@ -2478,7 +2446,7 @@ static int __xipram do_erase_chip(struct map_info *map, struct flchip *chip) ...@@ -2478,7 +2446,7 @@ static int __xipram do_erase_chip(struct map_info *map, struct flchip *chip)
chip->erase_suspended = 0; chip->erase_suspended = 0;
} }
if (chip_good(map, chip, adr, map_word_ff(map))) { if (chip_ready(map, chip, adr, &datum)) {
if (cfi_check_err_status(map, chip, adr)) if (cfi_check_err_status(map, chip, adr))
ret = -EIO; ret = -EIO;
break; break;
...@@ -2523,6 +2491,7 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip, ...@@ -2523,6 +2491,7 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip,
DECLARE_WAITQUEUE(wait, current); DECLARE_WAITQUEUE(wait, current);
int ret; int ret;
int retry_cnt = 0; int retry_cnt = 0;
map_word datum = map_word_ff(map);
adr += chip->start; adr += chip->start;
...@@ -2577,7 +2546,7 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip, ...@@ -2577,7 +2546,7 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip,
chip->erase_suspended = 0; chip->erase_suspended = 0;
} }
if (chip_good(map, chip, adr, map_word_ff(map))) { if (chip_ready(map, chip, adr, &datum)) {
if (cfi_check_err_status(map, chip, adr)) if (cfi_check_err_status(map, chip, adr))
ret = -EIO; ret = -EIO;
break; break;
...@@ -2771,7 +2740,7 @@ static int __maybe_unused do_ppb_xxlock(struct map_info *map, ...@@ -2771,7 +2740,7 @@ static int __maybe_unused do_ppb_xxlock(struct map_info *map,
*/ */
timeo = jiffies + msecs_to_jiffies(2000); /* 2s max (un)locking */ timeo = jiffies + msecs_to_jiffies(2000); /* 2s max (un)locking */
for (;;) { for (;;) {
if (chip_ready(map, chip, adr)) if (chip_ready(map, chip, adr, NULL))
break; break;
if (time_after(jiffies, timeo)) { if (time_after(jiffies, timeo)) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment