Merge "Add device support for reading OTP."
diff --git a/drivers/mtd/nand/comcerto_nand.c b/drivers/mtd/nand/comcerto_nand.c
index d5ca078..7a1c161 100644
--- a/drivers/mtd/nand/comcerto_nand.c
+++ b/drivers/mtd/nand/comcerto_nand.c
@@ -262,9 +262,8 @@
static int comcerto_correct_ecc(struct mtd_info *mtd, uint8_t *dat,
uint8_t *read_ecc, uint8_t *calc_ecc)
{
-#if !defined (CONFIG_NAND_COMCERTO_ECC_8_HW_BCH) && !defined (CONFIG_NAND_COMCERTO_ECC_24_HW_BCH)
struct nand_chip *nand_device = mtd->priv;
-#else
+#if defined (CONFIG_NAND_COMCERTO_ECC_8_HW_BCH) || defined (CONFIG_NAND_COMCERTO_ECC_24_HW_BCH)
uint8_t err_count = 0;
uint32_t err_corr_data_prev;
#endif
@@ -274,11 +273,13 @@
unsigned long timeo = jiffies + 2;
/* Wait for syndrome calculation to complete */
- do {
- if ((readl_relaxed(ecc_base_addr + ECC_IDLE_STAT)) & ECC_IDLE)
- break;
+ while (!(readl_relaxed(ecc_base_addr + ECC_IDLE_STAT) & ECC_IDLE)) {
touch_softlockup_watchdog();
- } while (time_before(jiffies, timeo));
+ if (time_after_eq(jiffies, timeo)) {
+ pr_warn_ratelimited("Timeout waiting for parity module to become idle");
+ return -EIO;
+ }
+ }
/* If no correction is required */
if (likely(!((readl_relaxed(ecc_base_addr + ECC_POLY_STAT)) & ECC_CORR_REQ))) {
@@ -292,15 +293,20 @@
udelay(25);
+ timeo = jiffies + 2;
err_corr_data_prev = 0;
/* Read Correction data status register till header is 0x7FD */
- do {
+ while(1) {
err_corr_data_prev = readl_relaxed(ecc_base_addr + ECC_CORR_DATA_STAT);
if ((err_corr_data_prev >> ECC_BCH_INDEX_SHIFT) == 0x87FD)
break;
touch_softlockup_watchdog();
- } while (time_before(jiffies, timeo));
+ if (time_after_eq(jiffies, timeo)) {
+ pr_warn_ratelimited("Timeout waiting for ECC correction data");
+ return -EIO;
+ }
+ }
udelay(25);
err_corr_data = 0x0;
@@ -314,6 +320,12 @@
err_corr_data_prev = err_corr_data;
index = (err_corr_data >> 16) & 0x7FF;
mask = err_corr_data & 0xFFFF;
+ if (index * 2 >= nand_device->ecc.size) {
+ pr_warn_ratelimited("ECC correction index out of "
+ "bounds. ECC_CORR_DATA_STAT %08x",
+ err_corr_data);
+ continue;
+ }
*((uint16_t *)(dat + (index * 2))) ^= mask;
while (mask) {
if (mask & 1)