ssize_t up_progmem_ispageerased(size_t page) { size_t addr; size_t count; size_t bwritten = 0; if (page >= (EFM32_FLASH_NPAGES+EFM32_USERDATA_NPAGES)) { return -EFAULT; } /* Verify */ for (addr = up_progmem_getaddress(page), count = up_progmem_pagesize(page); count; count--, addr++) { if (getreg8(addr) != 0xff) { bwritten++; } } return bwritten; }
ssize_t up_progmem_erasepage(size_t page) { size_t addr; irqstate_t irqs; if (page >= up_progmem_npages()) { return -EFAULT; } addr = up_progmem_getaddress(page); /* Disable IRQs while erasing sector */ irqs = irqsave(); s5j_sflash_disable_wp(); /* Set sector address and then send erase command */ putreg32(addr - S5J_FLASH_PADDR, S5J_SFLASH_ERASE_ADDRESS); putreg8(0xff, S5J_SFLASH_SE); /* Wait for the completion */ while (s5j_sflash_read_status() & 0x1) ; s5j_sflash_enable_wp(); /* Invalidate cache */ arch_invalidate_dcache(addr, addr + up_progmem_blocksize()); /* Restore IRQs */ irqrestore(irqs); return up_progmem_blocksize(); }
ssize_t up_progmem_ispageerased(size_t page) { size_t addr; size_t count; size_t bwritten; if (page >= up_progmem_npages()) { return -EFAULT; } bwritten = 0; addr = up_progmem_getaddress(page); for (count = up_progmem_pagesize(page); count; count--) { if (getreg32(addr) != 0xffffff) { bwritten++; } addr += sizeof(int); } return bwritten * sizeof(int); }
ssize_t up_progmem_ispageerased(size_t page) { size_t addr; size_t count; size_t bwritten = 0; if (page >= STM32_FLASH_NPAGES) { return -EFAULT; } /* Verify */ for (addr = up_progmem_getaddress(page), count = up_progmem_pagesize(page); count; count--, addr++) { if (getreg8(addr) != FLASH_ERASEDVALUE) { bwritten++; } } return bwritten; }
ssize_t up_progmem_eraseblock(size_t block) { uintptr_t base; size_t page_address; if (block >= STM32_FLASH_NPAGES) { return -EFAULT; } #if defined(STM32_FLASH_DUAL_BANK) /* Handle paged FLASH */ if (block >= STM32_FLASH_BANK0_NPAGES) { base = STM32_FLASH_BANK1_BASE; } else #endif { base = STM32_FLASH_BANK0_BASE; } sem_lock(); if ((getreg32(base + STM32_RCC_CR_OFFSET) & RCC_CR_HSION) == 0) { sem_unlock(); return -EPERM; } /* Get flash ready and begin erasing single page */ flash_unlock(base); modifyreg32(base + STM32_FLASH_CR_OFFSET, 0, FLASH_CR_PER); /* Must be valid - page index checked above */ page_address = up_progmem_getaddress(block); putreg32(page_address, base + STM32_FLASH_AR_OFFSET); modifyreg32(base + STM32_FLASH_CR_OFFSET, 0, FLASH_CR_STRT); while ((getreg32(base + STM32_FLASH_SR_OFFSET) & FLASH_SR_BSY) != 0) { up_waste(); } modifyreg32(base + STM32_FLASH_CR_OFFSET, FLASH_CR_PER, 0); sem_unlock(); /* Verify */ if (up_progmem_ispageerased(block) == 0) { return up_progmem_erasesize(block); /* success */ } else { return -EIO; /* failure */ } }
ssize_t __ramfunc__ up_progmem_erasepage(size_t page) { int ret = 0; int timeout; uint32_t regval; irqstate_t flags; if (page >= (EFM32_FLASH_NPAGES+EFM32_USERDATA_NPAGES)) { return -EFAULT; } efm32_flash_unlock(); flags = enter_critical_section(); /* enable writing to the flash */ bitband_set_peripheral(EFM32_MSC_WRITECTRL, _MSC_WRITECTRL_WREN_SHIFT, 1); /* Load address */ putreg32((uint32_t)up_progmem_getaddress(page), EFM32_MSC_ADDRB); putreg32(MSC_WRITECMD_LADDRIM, EFM32_MSC_WRITECMD); regval = getreg32(EFM32_MSC_STATUS); /* Check for invalid address */ if (regval & MSC_STATUS_INVADDR) { ret = -EINVAL; } /* Check for write protected page */ if ((ret == 0) && (regval & MSC_STATUS_LOCKED)) { ret = -EPERM; } /* Send erase page command */ if (ret == 0) { putreg32(MSC_WRITECMD_ERASEPAGE, EFM32_MSC_WRITECMD); /* Wait for the erase to complete */ timeout = MSC_PROGRAM_TIMEOUT; while ((getreg32(EFM32_MSC_STATUS) & MSC_STATUS_BUSY) && (timeout != 0)) { timeout--; } if (timeout == 0) { ret = -ETIMEDOUT; } } /* Disable writing to the MSC */ bitband_set_peripheral(EFM32_MSC_WRITECTRL, _MSC_WRITECTRL_WREN_SHIFT, 0); if (ret == 0) { /* Verify */ if (up_progmem_ispageerased(page) != 0) { ret = -EIO; } } leave_critical_section(flags); if (ret != 0) { return ret; } /* Success */ return up_progmem_pagesize(page); }