summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/mtd/altera_qspi.c56
1 files changed, 46 insertions, 10 deletions
diff --git a/drivers/mtd/altera_qspi.c b/drivers/mtd/altera_qspi.c
index c7e37add018..a9148a7fe41 100644
--- a/drivers/mtd/altera_qspi.c
+++ b/drivers/mtd/altera_qspi.c
@@ -5,6 +5,7 @@
*/
#include <common.h>
+#include <console.h>
#include <dm.h>
#include <errno.h>
#include <fdt_support.h>
@@ -52,6 +53,7 @@ struct altera_qspi_platdata {
unsigned long size;
};
+static uint flash_verbose;
flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; /* FLASH chips info */
static void altera_qspi_get_locked_range(struct mtd_info *mtd, loff_t *ofs,
@@ -74,6 +76,11 @@ void flash_print_info(flash_info_t *info)
putc('\n');
}
+void flash_set_verbose(uint v)
+{
+ flash_verbose = v;
+}
+
int flash_erase(flash_info_t *info, int s_first, int s_last)
{
struct mtd_info *mtd = info->mtd;
@@ -84,10 +91,13 @@ int flash_erase(flash_info_t *info, int s_first, int s_last)
instr.mtd = mtd;
instr.addr = mtd->erasesize * s_first;
instr.len = mtd->erasesize * (s_last + 1 - s_first);
+ flash_set_verbose(1);
ret = mtd_erase(mtd, &instr);
+ flash_set_verbose(0);
if (ret)
return ERR_PROTECTED;
+ puts(" done\n");
return 0;
}
@@ -131,23 +141,49 @@ 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, &regs->mem_op);
- stat = readl(&regs->isr);
- if (stat & QUADSPI_ISR_ILLEGAL_ERASE) {
- /* erase failed, sector might be protected */
- debug("erase %08x fail %x\n", sect, stat);
- writel(stat, &regs->isr); /* clear isr */
+ if (ctrlc()) {
+ if (flash_verbose)
+ putc('\n');
+ instr->fail_addr = MTD_FAIL_ADDR_UNKNOWN;
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, &regs->mem_op);
+ stat = readl(&regs->isr);
+ if (stat & QUADSPI_ISR_ILLEGAL_ERASE) {
+ /* erase failed, sector might be protected */
+ debug("erase %08x fail %x\n", sect, stat);
+ writel(stat, &regs->isr); /* clear isr */
+ instr->fail_addr = addr;
+ instr->state = MTD_ERASE_FAILED;
+ mtd_erase_callback(instr);
+ return -EIO;
+ }
+ if (flash_verbose)
+ putc('.');
+ } else {
+ if (flash_verbose)
+ putc(',');
+ }
addr += mtd->erasesize;
}
instr->state = MTD_ERASE_DONE;