]> git.sur5r.net Git - u-boot/blobdiff - drivers/mtd/altera_qspi.c
mtd: cfi: Unlock current sector instead of sector 0 before buffered write
[u-boot] / drivers / mtd / altera_qspi.c
index 61a6a5ed9d4b06cbc143ceb7f95687dd711170b3..a9148a7fe41f0f0e4af4b66a0aa3ca94c3059f6d 100644 (file)
@@ -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;
@@ -81,12 +88,16 @@ int flash_erase(flash_info_t *info, int s_first, int s_last)
        int ret;
 
        memset(&instr, 0, sizeof(instr));
+       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_NOT_ERASED;
+               return ERR_PROTECTED;
 
+       puts(" done\n");
        return 0;
 }
 
@@ -102,7 +113,7 @@ int write_buff(flash_info_t *info, uchar *src, ulong addr, ulong cnt)
 
        ret = mtd_write(mtd, to, cnt, &retlen, src);
        if (ret)
-               return ERR_NOT_ERASED;
+               return ERR_PROTECTED;
 
        return 0;
 }
@@ -130,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;