int flash_physical_write(int offset, int size, const char *data) { int dest_addr = offset; const int sz_page = CONFIG_FLASH_WRITE_IDEAL_SIZE; /* Fail if offset, size, and data aren't at least word-aligned */ if ((offset | size | (uint32_t)(uintptr_t)data) & (CONFIG_FLASH_WRITE_SIZE - 1)) return EC_ERROR_INVAL; /* check protection */ if (all_protected) return EC_ERROR_ACCESS_DENIED; /* Disable tri-state */ TRISTATE_FLASH(0); /* Write the data per CONFIG_FLASH_WRITE_IDEAL_SIZE bytes */ for (; size >= sz_page; size -= sz_page) { /* check protection */ if (flash_check_prot_range(dest_addr, sz_page)) return EC_ERROR_ACCESS_DENIED; /* Enable write */ flash_write_enable(); /* Burst UMA transaction */ flash_burst_write(dest_addr, sz_page, data); /* Wait write completed */ flash_wait_ready(); data += sz_page; dest_addr += sz_page; } /* Handle final partial page, if any */ if (size != 0) { /* check protection */ if (flash_check_prot_range(dest_addr, size)) return EC_ERROR_ACCESS_DENIED; /* Enable write */ flash_write_enable(); /* Burst UMA transaction */ flash_burst_write(dest_addr, size, data); /* Wait write completed */ flash_wait_ready(); } /* Enable tri-state */ TRISTATE_FLASH(1); return EC_SUCCESS; }
static int flash_program_bytes(uint32_t offset, uint32_t bytes, const uint8_t const *data) { int write_size; int rv; while (bytes > 0) { /* Write length can not go beyond the end of the flash page */ write_size = MIN(bytes, CONFIG_FLASH_WRITE_IDEAL_SIZE - (offset & (CONFIG_FLASH_WRITE_IDEAL_SIZE - 1))); /* Enable write */ rv = flash_write_enable(); if (rv) return rv; /* Burst UMA transaction */ flash_burst_write(offset, write_size, data); /* Wait write completed */ rv = flash_wait_ready(FLASH_ABORT_TIMEOUT); if (rv) return rv; data += write_size; offset += write_size; bytes -= write_size; } return rv; }
int flash_physical_erase(int offset, int size) { int rv = EC_SUCCESS; /* check protection */ if (all_protected) return EC_ERROR_ACCESS_DENIED; /* Lock physical flash operations */ flash_lock_mapped_storage(1); /* Disable tri-state */ TRISTATE_FLASH(0); /* Alignment has been checked in upper layer */ for (; size > 0; size -= CONFIG_FLASH_ERASE_SIZE, offset += CONFIG_FLASH_ERASE_SIZE) { /* check protection */ if (flash_check_prot_range(offset, CONFIG_FLASH_ERASE_SIZE)) { rv = EC_ERROR_ACCESS_DENIED; break; } /* * Reload the watchdog timer, so that erasing many flash pages * doesn't cause a watchdog reset. May not need this now that * we're using msleep() below. */ watchdog_reload(); /* Enable write */ rv = flash_write_enable(); if (rv) break; /* Set erase address */ flash_set_address(offset); /* Start erase */ flash_execute_cmd(CMD_SECTOR_ERASE, MASK_CMD_ADR); /* Wait erase completed */ rv = flash_wait_ready(FLASH_ABORT_TIMEOUT); if (rv) break; } /* Enable tri-state */ TRISTATE_FLASH(1); /* Unlock physical flash operations */ flash_lock_mapped_storage(0); return rv; }
int flash_write_enable(void) { uint8_t mask = SPI_FLASH_SR1_WEL; /* Write enable command */ flash_execute_cmd(CMD_WRITE_EN, MASK_CMD_ONLY); /* Wait for flash is not busy */ flash_wait_ready(); if (NPCX_UMA_DB0 & mask) return 1; else return 0; }
static int flash_write_enable(void) { uint8_t mask = SPI_FLASH_SR1_WEL; int rv; /* Wait for previous operation to complete */ rv = flash_wait_ready(FLASH_ABORT_TIMEOUT); if (rv) return rv; /* Write enable command */ flash_execute_cmd(CMD_WRITE_EN, MASK_CMD_ONLY); /* Wait for flash is not busy */ rv = flash_wait_ready(FLASH_ABORT_TIMEOUT); if (rv) return rv; if (NPCX_UMA_DB0 & mask) return EC_SUCCESS; else return EC_ERROR_BUSY; }
int flash_physical_erase(int offset, int size) { /* check protection */ if (all_protected) return EC_ERROR_ACCESS_DENIED; /* Disable tri-state */ TRISTATE_FLASH(0); /* Alignment has been checked in upper layer */ for (; size > 0; size -= CONFIG_FLASH_ERASE_SIZE, offset += CONFIG_FLASH_ERASE_SIZE) { /* Do nothing if already erased */ if (flash_is_erased(offset, CONFIG_FLASH_ERASE_SIZE)) continue; /* check protection */ if (flash_check_prot_range(offset, CONFIG_FLASH_ERASE_SIZE)) return EC_ERROR_ACCESS_DENIED; /* * Reload the watchdog timer, so that erasing many flash pages * doesn't cause a watchdog reset. May not need this now that * we're using msleep() below. */ watchdog_reload(); /* Enable write */ flash_write_enable(); /* Set erase address */ flash_set_address(offset); /* Start erase */ flash_execute_cmd(CMD_SECTOR_ERASE, MASK_CMD_ADR); /* Wait erase completed */ flash_wait_ready(); } /* Enable tri-state */ TRISTATE_FLASH(1); return EC_SUCCESS; }