]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
mtd: OneNAND: add timeout to wait ready loops
authorLadislav Michl <ladis@linux-mips.org>
Tue, 12 Jul 2016 18:28:19 +0000 (20:28 +0200)
committerTom Rini <trini@konsulko.com>
Fri, 22 Jul 2016 18:46:11 +0000 (14:46 -0400)
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>
drivers/mtd/onenand/onenand_base.c

index 03deabce102341881a7b430f35164eea9c455ce6..d194d974661c567c12f8bd73ad1f75b6e2d67374 100644 (file)
@@ -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);