diff options
-rw-r--r-- | drivers/mtd/altera_qspi.c | 39 |
1 files changed, 25 insertions, 14 deletions
diff --git a/drivers/mtd/altera_qspi.c b/drivers/mtd/altera_qspi.c index b0d4f2c..8a630a6 100644 --- a/drivers/mtd/altera_qspi.c +++ b/drivers/mtd/altera_qspi.c @@ -131,24 +131,35 @@ static int altera_qspi_erase(struct mtd_info *mtd, struct erase_info *instr) size_t end = addr + len; u32 sect; u32 stat; + u32 *flash, *last; instr->state = MTD_ERASING; addr &= ~(mtd->erasesize - 1); /* get lower aligned address */ while (addr < end) { - sect = addr / mtd->erasesize; - sect <<= 8; - sect |= QUADSPI_MEM_OP_SECTOR_ERASE; - debug("erase %08x\n", sect); - writel(sect, ®s->mem_op); - stat = readl(®s->isr); - if (stat & QUADSPI_ISR_ILLEGAL_ERASE) { - /* erase failed, sector might be protected */ - debug("erase %08x fail %x\n", sect, stat); - writel(stat, ®s->isr); /* clear isr */ - instr->fail_addr = addr; - instr->state = MTD_ERASE_FAILED; - mtd_erase_callback(instr); - return -EIO; + flash = pdata->base + addr; + last = pdata->base + addr + mtd->erasesize; + /* skip erase if sector is blank */ + while (flash < last) { + if (readl(flash) != 0xffffffff) + break; + flash++; + } + if (flash < last) { + sect = addr / mtd->erasesize; + sect <<= 8; + sect |= QUADSPI_MEM_OP_SECTOR_ERASE; + debug("erase %08x\n", sect); + writel(sect, ®s->mem_op); + stat = readl(®s->isr); + if (stat & QUADSPI_ISR_ILLEGAL_ERASE) { + /* erase failed, sector might be protected */ + debug("erase %08x fail %x\n", sect, stat); + writel(stat, ®s->isr); /* clear isr */ + instr->fail_addr = addr; + instr->state = MTD_ERASE_FAILED; + mtd_erase_callback(instr); + return -EIO; + } } addr += mtd->erasesize; } |