Commit d9098ee55f6cf6f51e2fbed0336957e2b7156225
Committed by
Tom Rini
1 parent
9a9d394639
Exists in
v2017.01-smarct4x
and in
25 other branches
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>
Showing 1 changed file with 19 additions and 11 deletions Side-by-side Diff
drivers/mtd/onenand/onenand_base.c
... | ... | @@ -20,6 +20,7 @@ |
20 | 20 | */ |
21 | 21 | |
22 | 22 | #include <common.h> |
23 | +#include <watchdog.h> | |
23 | 24 | #include <linux/compat.h> |
24 | 25 | #include <linux/mtd/mtd.h> |
25 | 26 | #include "linux/mtd/flashchip.h" |
26 | 27 | |
27 | 28 | |
... | ... | @@ -467,15 +468,18 @@ |
467 | 468 | static int onenand_wait(struct mtd_info *mtd, int state) |
468 | 469 | { |
469 | 470 | struct onenand_chip *this = mtd->priv; |
470 | - unsigned int flags = ONENAND_INT_MASTER; | |
471 | 471 | unsigned int interrupt = 0; |
472 | 472 | unsigned int ctrl; |
473 | 473 | |
474 | - while (1) { | |
474 | + /* Wait at most 20ms ... */ | |
475 | + u32 timeo = (CONFIG_SYS_HZ * 20) / 1000; | |
476 | + u32 time_start = get_timer(0); | |
477 | + do { | |
478 | + WATCHDOG_RESET(); | |
479 | + if (get_timer(time_start) > timeo) | |
480 | + return -EIO; | |
475 | 481 | interrupt = this->read_word(this->base + ONENAND_REG_INTERRUPT); |
476 | - if (interrupt & flags) | |
477 | - break; | |
478 | - } | |
482 | + } while ((interrupt & ONENAND_INT_MASTER) == 0); | |
479 | 483 | |
480 | 484 | ctrl = this->read_word(this->base + ONENAND_REG_CTRL_STATUS); |
481 | 485 | |
482 | 486 | |
483 | 487 | |
... | ... | @@ -1154,15 +1158,18 @@ |
1154 | 1158 | static int onenand_bbt_wait(struct mtd_info *mtd, int state) |
1155 | 1159 | { |
1156 | 1160 | struct onenand_chip *this = mtd->priv; |
1157 | - unsigned int flags = ONENAND_INT_MASTER; | |
1158 | 1161 | unsigned int interrupt; |
1159 | 1162 | unsigned int ctrl; |
1160 | 1163 | |
1161 | - while (1) { | |
1164 | + /* Wait at most 20ms ... */ | |
1165 | + u32 timeo = (CONFIG_SYS_HZ * 20) / 1000; | |
1166 | + u32 time_start = get_timer(0); | |
1167 | + do { | |
1168 | + WATCHDOG_RESET(); | |
1169 | + if (get_timer(time_start) > timeo) | |
1170 | + return ONENAND_BBT_READ_FATAL_ERROR; | |
1162 | 1171 | interrupt = this->read_word(this->base + ONENAND_REG_INTERRUPT); |
1163 | - if (interrupt & flags) | |
1164 | - break; | |
1165 | - } | |
1172 | + } while ((interrupt & ONENAND_INT_MASTER) == 0); | |
1166 | 1173 | |
1167 | 1174 | /* To get correct interrupt status in timeout case */ |
1168 | 1175 | interrupt = this->read_word(this->base + ONENAND_REG_INTERRUPT); |
... | ... | @@ -2536,7 +2543,8 @@ |
2536 | 2543 | this->write_word(ONENAND_CMD_RESET, this->base + ONENAND_BOOTRAM); |
2537 | 2544 | |
2538 | 2545 | /* Wait reset */ |
2539 | - this->wait(mtd, FL_RESETING); | |
2546 | + if (this->wait(mtd, FL_RESETING)) | |
2547 | + return -ENXIO; | |
2540 | 2548 | |
2541 | 2549 | /* Restore system configuration 1 */ |
2542 | 2550 | this->write_word(syscfg, this->base + ONENAND_REG_SYS_CFG1); |