diff options
author | Ladislav Michl <ladis@linux-mips.org> | 2016-07-12 18:28:19 (GMT) |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2016-07-22 18:46:11 (GMT) |
commit | d9098ee55f6cf6f51e2fbed0336957e2b7156225 (patch) | |
tree | 5a3752537692c3b2a25c7704768072258714c7b3 | |
parent | 9a9d3946399e91e0ff6de7e4678a3b242b66af74 (diff) | |
download | u-boot-fsl-qoriq-d9098ee55f6cf6f51e2fbed0336957e2b7156225.tar.xz |
mtd: OneNAND: add timeout to wait ready loops
Add timeout to onenand_wait ready loop as it hangs here indefinitely
when chip not present. Once there, do the same for onenand_bbt_wait
as well (note: recent Linux driver code does the same)
Signed-off-by: Ladislav Michl <ladis@linux-mips.org>
-rw-r--r-- | drivers/mtd/onenand/onenand_base.c | 30 |
1 files changed, 19 insertions, 11 deletions
diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c index 03deabc..d194d97 100644 --- a/drivers/mtd/onenand/onenand_base.c +++ b/drivers/mtd/onenand/onenand_base.c @@ -20,6 +20,7 @@ */ #include <common.h> +#include <watchdog.h> #include <linux/compat.h> #include <linux/mtd/mtd.h> #include "linux/mtd/flashchip.h" @@ -467,15 +468,18 @@ static int onenand_read_ecc(struct onenand_chip *this) static int onenand_wait(struct mtd_info *mtd, int state) { struct onenand_chip *this = mtd->priv; - unsigned int flags = ONENAND_INT_MASTER; unsigned int interrupt = 0; unsigned int ctrl; - while (1) { + /* Wait at most 20ms ... */ + u32 timeo = (CONFIG_SYS_HZ * 20) / 1000; + u32 time_start = get_timer(0); + do { + WATCHDOG_RESET(); + if (get_timer(time_start) > timeo) + return -EIO; interrupt = this->read_word(this->base + ONENAND_REG_INTERRUPT); - if (interrupt & flags) - break; - } + } while ((interrupt & ONENAND_INT_MASTER) == 0); ctrl = this->read_word(this->base + ONENAND_REG_CTRL_STATUS); @@ -1154,15 +1158,18 @@ int onenand_read_oob(struct mtd_info *mtd, loff_t from, static int onenand_bbt_wait(struct mtd_info *mtd, int state) { struct onenand_chip *this = mtd->priv; - unsigned int flags = ONENAND_INT_MASTER; unsigned int interrupt; unsigned int ctrl; - while (1) { + /* Wait at most 20ms ... */ + u32 timeo = (CONFIG_SYS_HZ * 20) / 1000; + u32 time_start = get_timer(0); + do { + WATCHDOG_RESET(); + if (get_timer(time_start) > timeo) + return ONENAND_BBT_READ_FATAL_ERROR; interrupt = this->read_word(this->base + ONENAND_REG_INTERRUPT); - if (interrupt & flags) - break; - } + } while ((interrupt & ONENAND_INT_MASTER) == 0); /* To get correct interrupt status in timeout case */ interrupt = this->read_word(this->base + ONENAND_REG_INTERRUPT); @@ -2536,7 +2543,8 @@ static int onenand_chip_probe(struct mtd_info *mtd) this->write_word(ONENAND_CMD_RESET, this->base + ONENAND_BOOTRAM); /* Wait reset */ - this->wait(mtd, FL_RESETING); + if (this->wait(mtd, FL_RESETING)) + return -ENXIO; /* Restore system configuration 1 */ this->write_word(syscfg, this->base + ONENAND_REG_SYS_CFG1); |