static int omap2_onenand_wait(struct mtd_info *mtd, int state) { struct omap2_onenand *c = container_of(mtd, struct omap2_onenand, mtd); struct onenand_chip *this = mtd->priv; unsigned int intr = 0; unsigned int ctrl, ctrl_mask; unsigned long timeout; u32 syscfg; if (state == FL_RESETING || state == FL_PREPARING_ERASE || state == FL_VERIFYING_ERASE) { int i = 21; unsigned int intr_flags = ONENAND_INT_MASTER; switch (state) { case FL_RESETING: intr_flags |= ONENAND_INT_RESET; break; case FL_PREPARING_ERASE: intr_flags |= ONENAND_INT_ERASE; break; case FL_VERIFYING_ERASE: i = 101; break; } while (--i) { udelay(1); intr = read_reg(c, ONENAND_REG_INTERRUPT); if (intr & ONENAND_INT_MASTER) break; } ctrl = read_reg(c, ONENAND_REG_CTRL_STATUS); if (ctrl & ONENAND_CTRL_ERROR) { wait_err("controller error", state, ctrl, intr); return -EIO; } if ((intr & intr_flags) == intr_flags) return 0; /* Continue in wait for interrupt branch */ } if (state != FL_READING) { int result; /* Turn interrupts on */ syscfg = read_reg(c, ONENAND_REG_SYS_CFG1); if (!(syscfg & ONENAND_SYS_CFG1_IOBE)) { syscfg |= ONENAND_SYS_CFG1_IOBE; write_reg(c, syscfg, ONENAND_REG_SYS_CFG1); if (c->flags & ONENAND_IN_OMAP34XX) /* Add a delay to let GPIO settle */ syscfg = read_reg(c, ONENAND_REG_SYS_CFG1); } INIT_COMPLETION(c->irq_done); if (c->gpio_irq) { result = gpio_get_value(c->gpio_irq); if (result == -1) { ctrl = read_reg(c, ONENAND_REG_CTRL_STATUS); intr = read_reg(c, ONENAND_REG_INTERRUPT); wait_err("gpio error", state, ctrl, intr); return -EIO; } } else result = 0; if (result == 0) { int retry_cnt = 0; retry: result = wait_for_completion_timeout(&c->irq_done, msecs_to_jiffies(20)); if (result == 0) { /* Timeout after 20ms */ ctrl = read_reg(c, ONENAND_REG_CTRL_STATUS); if (ctrl & ONENAND_CTRL_ONGO && !this->ongoing) { /* * The operation seems to be still going * so give it some more time. */ retry_cnt += 1; if (retry_cnt < 3) goto retry; intr = read_reg(c, ONENAND_REG_INTERRUPT); wait_err("timeout", state, ctrl, intr); return -EIO; } intr = read_reg(c, ONENAND_REG_INTERRUPT); if ((intr & ONENAND_INT_MASTER) == 0) wait_warn("timeout", state, ctrl, intr); } } } else { int retry_cnt = 0; /* Turn interrupts off */ syscfg = read_reg(c, ONENAND_REG_SYS_CFG1); syscfg &= ~ONENAND_SYS_CFG1_IOBE; write_reg(c, syscfg, ONENAND_REG_SYS_CFG1); timeout = jiffies + msecs_to_jiffies(20); while (1) { if (time_before(jiffies, timeout)) { intr = read_reg(c, ONENAND_REG_INTERRUPT); if (intr & ONENAND_INT_MASTER) break; } else { /* Timeout after 20ms */ ctrl = read_reg(c, ONENAND_REG_CTRL_STATUS); if (ctrl & ONENAND_CTRL_ONGO) { /* * The operation seems to be still going * so give it some more time. */ retry_cnt += 1; if (retry_cnt < 3) { timeout = jiffies + msecs_to_jiffies(20); continue; } } break; } } } intr = read_reg(c, ONENAND_REG_INTERRUPT); ctrl = read_reg(c, ONENAND_REG_CTRL_STATUS); if (intr & ONENAND_INT_READ) { int ecc = read_reg(c, ONENAND_REG_ECC_STATUS); if (ecc) { unsigned int addr1, addr8; addr1 = read_reg(c, ONENAND_REG_START_ADDRESS1); addr8 = read_reg(c, ONENAND_REG_START_ADDRESS8); if (ecc & ONENAND_ECC_2BIT_ALL) { printk(KERN_ERR "onenand_wait: ECC error = " "0x%04x, addr1 %#x, addr8 %#x\n", ecc, addr1, addr8); mtd->ecc_stats.failed++; return -EBADMSG; } else if (ecc & ONENAND_ECC_1BIT_ALL) { printk(KERN_NOTICE "onenand_wait: correctable " "ECC error = 0x%04x, addr1 %#x, " "addr8 %#x\n", ecc, addr1, addr8); mtd->ecc_stats.corrected++; } } } else if (state == FL_READING) { wait_err("timeout", state, ctrl, intr); return -EIO; } if (ctrl & ONENAND_CTRL_ERROR) { wait_err("controller error", state, ctrl, intr); if (ctrl & ONENAND_CTRL_LOCK) printk(KERN_ERR "onenand_wait: " "Device is write protected!!!\n"); return -EIO; } ctrl_mask = 0xFE9F; if (this->ongoing) ctrl_mask &= ~0x8000; if (ctrl & ctrl_mask) wait_warn("unexpected controller status", state, ctrl, intr); return 0; }
static int omap2_onenand_wait(struct mtd_info *mtd, int state) { struct omap2_onenand *c = container_of(mtd, struct omap2_onenand, mtd); unsigned int intr = 0; unsigned int ctrl; unsigned long timeout; u32 syscfg; if (state == FL_RESETING) { int i; for (i = 0; i < 20; i++) { udelay(1); intr = read_reg(c, ONENAND_REG_INTERRUPT); if (intr & ONENAND_INT_MASTER) break; } ctrl = read_reg(c, ONENAND_REG_CTRL_STATUS); if (ctrl & ONENAND_CTRL_ERROR) { wait_err("controller error", state, ctrl, intr); return -EIO; } if (!(intr & ONENAND_INT_RESET)) { wait_err("timeout", state, ctrl, intr); return -EIO; } return 0; } if (state != FL_READING) { int result; syscfg = read_reg(c, ONENAND_REG_SYS_CFG1); if (!(syscfg & ONENAND_SYS_CFG1_IOBE)) { syscfg |= ONENAND_SYS_CFG1_IOBE; write_reg(c, syscfg, ONENAND_REG_SYS_CFG1); if (cpu_is_omap34xx()) syscfg = read_reg(c, ONENAND_REG_SYS_CFG1); } INIT_COMPLETION(c->irq_done); if (c->gpio_irq) { result = gpio_get_value(c->gpio_irq); if (result == -1) { ctrl = read_reg(c, ONENAND_REG_CTRL_STATUS); intr = read_reg(c, ONENAND_REG_INTERRUPT); wait_err("gpio error", state, ctrl, intr); return -EIO; } } else result = 0; if (result == 0) { int retry_cnt = 0; retry: result = wait_for_completion_timeout(&c->irq_done, msecs_to_jiffies(20)); if (result == 0) { ctrl = read_reg(c, ONENAND_REG_CTRL_STATUS); if (ctrl & ONENAND_CTRL_ONGO) { retry_cnt += 1; if (retry_cnt < 3) goto retry; intr = read_reg(c, ONENAND_REG_INTERRUPT); wait_err("timeout", state, ctrl, intr); return -EIO; } intr = read_reg(c, ONENAND_REG_INTERRUPT); if ((intr & ONENAND_INT_MASTER) == 0) wait_warn("timeout", state, ctrl, intr); } } } else { int retry_cnt = 0; syscfg = read_reg(c, ONENAND_REG_SYS_CFG1); syscfg &= ~ONENAND_SYS_CFG1_IOBE; write_reg(c, syscfg, ONENAND_REG_SYS_CFG1); timeout = jiffies + msecs_to_jiffies(20); while (1) { if (time_before(jiffies, timeout)) { intr = read_reg(c, ONENAND_REG_INTERRUPT); if (intr & ONENAND_INT_MASTER) break; } else { ctrl = read_reg(c, ONENAND_REG_CTRL_STATUS); if (ctrl & ONENAND_CTRL_ONGO) { retry_cnt += 1; if (retry_cnt < 3) { timeout = jiffies + msecs_to_jiffies(20); continue; } } break; } } } intr = read_reg(c, ONENAND_REG_INTERRUPT); ctrl = read_reg(c, ONENAND_REG_CTRL_STATUS); if (intr & ONENAND_INT_READ) { int ecc = read_reg(c, ONENAND_REG_ECC_STATUS); if (ecc) { unsigned int addr1, addr8; addr1 = read_reg(c, ONENAND_REG_START_ADDRESS1); addr8 = read_reg(c, ONENAND_REG_START_ADDRESS8); if (ecc & ONENAND_ECC_2BIT_ALL) { printk(KERN_ERR "onenand_wait: ECC error = " "0x%04x, addr1 %#x, addr8 %#x\n", ecc, addr1, addr8); mtd->ecc_stats.failed++; return -EBADMSG; } else if (ecc & ONENAND_ECC_1BIT_ALL) { printk(KERN_NOTICE "onenand_wait: correctable " "ECC error = 0x%04x, addr1 %#x, " "addr8 %#x\n", ecc, addr1, addr8); mtd->ecc_stats.corrected++; } } } else if (state == FL_READING) { wait_err("timeout", state, ctrl, intr); return -EIO; } if (ctrl & ONENAND_CTRL_ERROR) { wait_err("controller error", state, ctrl, intr); if (ctrl & ONENAND_CTRL_LOCK) printk(KERN_ERR "onenand_wait: " "Device is write protected!!!\n"); return -EIO; } if (ctrl & 0xFE9F) wait_warn("unexpected controller status", state, ctrl, intr); return 0; }