diff options
author | Tim Lin <tim2.lin@ite.corp-partner.google.com> | 2021-06-29 16:13:44 +0800 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2021-07-01 15:00:54 +0000 |
commit | 300daebbb748a7b5f51bf411adfb985b83c085a4 (patch) | |
tree | 2c83f946ecabd09f4057316c3092c740e5dd1e12 /zephyr/drivers | |
parent | 1e6aad6a6c55d9d04158625766f9ed419fedcfd9 (diff) | |
download | chrome-ec-300daebbb748a7b5f51bf411adfb985b83c085a4.tar.gz |
zephyr/drivers: npcx: reorganizes the flash driver(2)
Move NPCX specific code flash_dev_init(), crec_flash_physical_write()
and crec_flash_physical_erase() from shim/flash.c to
cros_flash/cros_flash_npcx.c.
BUG=b:187192628
BRANCH=none
TEST=none
Cq-Depend: chromium:2994429
Signed-off-by: Tim Lin <tim2.lin@ite.corp-partner.google.com>
Change-Id: I094e26c5b670402872a665ba4d24a6594f7ca77e
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2994430
Reviewed-by: Keith Short <keithshort@chromium.org>
Reviewed-by: Denis Brockus <dbrockus@chromium.org>
Commit-Queue: Keith Short <keithshort@chromium.org>
Diffstat (limited to 'zephyr/drivers')
-rw-r--r-- | zephyr/drivers/cros_flash/cros_flash_npcx.c | 329 |
1 files changed, 186 insertions, 143 deletions
diff --git a/zephyr/drivers/cros_flash/cros_flash_npcx.c b/zephyr/drivers/cros_flash/cros_flash_npcx.c index f23cc09293..bac7d61e0b 100644 --- a/zephyr/drivers/cros_flash/cros_flash_npcx.c +++ b/zephyr/drivers/cros_flash/cros_flash_npcx.c @@ -263,149 +263,6 @@ static int cros_flash_npcx_program_bytes(const struct device *dev, return ret; } -/* cros ec flash api functions */ -static int cros_flash_npcx_init(const struct device *dev) -{ - const struct cros_flash_npcx_config *const config = DRV_CONFIG(dev); - struct cros_flash_npcx_data *data = DRV_DATA(dev); - - /* initialize mutux for flash interface controller */ - k_sem_init(&data->lock_sem, 1, 1); - - /* Configure pin-mux for FIU device */ - npcx_pinctrl_mux_configure(config->alts_list, config->alts_size, 1); - - return 0; -} - -static int cros_flash_npcx_read(const struct device *dev, int offset, int size, - char *dst_data) -{ - int ret = 0; - - /* Unlock flash interface device during reading flash */ - cros_flash_npcx_mutex_lock(dev); - - /* Chip Select down */ - cros_flash_npcx_cs_level(dev, 0); - - /* Set read address */ - cros_flash_npcx_set_address(dev, offset); - /* Start with fast read command (skip one dummy byte) */ - cros_flash_npcx_exec_cmd(dev, SPI_NOR_CMD_FAST_READ, - UMA_CODE_CMD_ADR_WR_BYTE(1)); - /* Execute burst read */ - cros_flash_npcx_burst_read(dev, dst_data, size); - - /* Chip Select up */ - cros_flash_npcx_cs_level(dev, 1); - - /* Unlock flash interface device */ - cros_flash_npcx_mutex_unlock(dev); - - return ret; -} - -static int cros_flash_npcx_write(const struct device *dev, int offset, int size, - const char *src_data) -{ - struct cros_flash_npcx_data *const data = DRV_DATA(dev); - int ret = 0; - - /* Is write protection enabled? */ - if (data->write_protectied) { - return -EACCES; - } - - /* Invalid data pointer? */ - if (src_data == 0) { - return -EINVAL; - } - - /* Unlock flash interface device during writing flash */ - cros_flash_npcx_mutex_lock(dev); - - while (size > 0) { - /* First write multiples of 256, then (size % 256) last */ - int write_len = - ((size % CONFIG_FLASH_WRITE_IDEAL_SIZE) == size) ? - size : - CONFIG_FLASH_WRITE_IDEAL_SIZE; - - ret = cros_flash_npcx_program_bytes(dev, offset, write_len, - src_data); - if (ret != 0) - break; - - src_data += write_len; - offset += write_len; - size -= write_len; - } - - /* Unlock flash interface device */ - cros_flash_npcx_mutex_unlock(dev); - - return ret; -} - -static int cros_flash_npcx_erase(const struct device *dev, int offset, int size) -{ - const struct cros_flash_npcx_config *const config = DRV_CONFIG(dev); - struct cros_flash_npcx_data *const data = DRV_DATA(dev); - int ret = 0; - - /* Is write protection enabled? */ - if (data->write_protectied) { - return -EACCES; - } - /* affected region should be within device */ - if (offset < 0 || (offset + size) > config->size) { - LOG_ERR("Flash erase address or size exceeds expected values. " - "Addr: 0x%lx size %zu", - (long)offset, size); - return -EINVAL; - } - - /* address must be aligned to erase size */ - if ((offset % CONFIG_FLASH_ERASE_SIZE) != 0) { - return -EINVAL; - } - - /* Erase size must be a non-zero multiple of sectors */ - if ((size == 0) || (size % CONFIG_FLASH_ERASE_SIZE) != 0) { - return -EINVAL; - } - - /* Unlock flash interface device during erasing flash */ - cros_flash_npcx_mutex_lock(dev); - - /* Alignment has been checked in upper layer */ - for (; size > 0; size -= CONFIG_FLASH_ERASE_SIZE, - offset += CONFIG_FLASH_ERASE_SIZE) { - - /* Enable write */ - ret = cros_flash_npcx_set_write_enable(dev); - if (ret != 0) - break; - - /* Set erase address */ - cros_flash_npcx_set_address(dev, offset); - /* Start erasing */ - cros_flash_npcx_exec_cmd(dev, SPI_NOR_CMD_BE, UMA_CODE_CMD_ADR); - - /* Wait erase completed */ - ret = cros_flash_npcx_wait_ready(dev); - if (ret != 0) { - break; - } - } - - /* Unlock flash interface device */ - cros_flash_npcx_mutex_unlock(dev); - - return ret; -} - static int cros_flash_npcx_get_status_reg(const struct device *dev, char cmd_code, char *data) { @@ -661,6 +518,192 @@ static int flash_write_prot_reg(const struct device *dev, unsigned int offset, return flash_set_status_for_prot(dev, sr1, sr2); } +static int flash_check_prot_range(unsigned int offset, unsigned int bytes) +{ + /* Invalid value */ + if (offset + bytes > CONFIG_FLASH_SIZE_BYTES) + return EC_ERROR_INVAL; + + /* Check if ranges overlap */ + if (MAX(addr_prot_start, offset) < + MIN(addr_prot_start + addr_prot_length, offset + bytes)) + return EC_ERROR_ACCESS_DENIED; + + return EC_SUCCESS; +} + +/* cros ec flash api functions */ +static int cros_flash_npcx_init(const struct device *dev) +{ + const struct cros_flash_npcx_config *const config = DRV_CONFIG(dev); + struct cros_flash_npcx_data *data = DRV_DATA(dev); + + /* initialize mutux for flash interface controller */ + k_sem_init(&data->lock_sem, 1, 1); + + /* Configure pin-mux for FIU device */ + npcx_pinctrl_mux_configure(config->alts_list, config->alts_size, 1); + + /* + * Protect status registers of internal spi-flash if WP# is active + * during ec initialization. + */ +#ifdef CONFIG_WP_ACTIVE_HIGH + flash_protect_int_flash(dev, gpio_get_level(GPIO_WP)); +#else + flash_protect_int_flash(dev, !gpio_get_level(GPIO_WP_L)); +#endif /*CONFIG_WP_ACTIVE_HIGH */ + + /* Initialize UMA to unlocked */ + flash_uma_lock(dev, 0); + + return 0; +} + +static int cros_flash_npcx_read(const struct device *dev, int offset, int size, + char *dst_data) +{ + int ret = 0; + + /* Unlock flash interface device during reading flash */ + cros_flash_npcx_mutex_lock(dev); + + /* Chip Select down */ + cros_flash_npcx_cs_level(dev, 0); + + /* Set read address */ + cros_flash_npcx_set_address(dev, offset); + /* Start with fast read command (skip one dummy byte) */ + cros_flash_npcx_exec_cmd(dev, SPI_NOR_CMD_FAST_READ, + UMA_CODE_CMD_ADR_WR_BYTE(1)); + /* Execute burst read */ + cros_flash_npcx_burst_read(dev, dst_data, size); + + /* Chip Select up */ + cros_flash_npcx_cs_level(dev, 1); + + /* Unlock flash interface device */ + cros_flash_npcx_mutex_unlock(dev); + + return ret; +} + +static int cros_flash_npcx_write(const struct device *dev, int offset, int size, + const char *src_data) +{ + struct cros_flash_npcx_data *const data = DRV_DATA(dev); + int ret = 0; + + /* check protection */ + if (all_protected) + return EC_ERROR_ACCESS_DENIED; + + /* check protection */ + if (flash_check_prot_range(offset, size)) + return EC_ERROR_ACCESS_DENIED; + + /* Is write protection enabled? */ + if (data->write_protectied) { + return -EACCES; + } + + /* Invalid data pointer? */ + if (src_data == 0) { + return -EINVAL; + } + + /* Unlock flash interface device during writing flash */ + cros_flash_npcx_mutex_lock(dev); + + while (size > 0) { + /* First write multiples of 256, then (size % 256) last */ + int write_len = + ((size % CONFIG_FLASH_WRITE_IDEAL_SIZE) == size) ? + size : + CONFIG_FLASH_WRITE_IDEAL_SIZE; + + ret = cros_flash_npcx_program_bytes(dev, offset, write_len, + src_data); + if (ret != 0) + break; + + src_data += write_len; + offset += write_len; + size -= write_len; + } + + /* Unlock flash interface device */ + cros_flash_npcx_mutex_unlock(dev); + + return ret; +} + +static int cros_flash_npcx_erase(const struct device *dev, int offset, int size) +{ + const struct cros_flash_npcx_config *const config = DRV_CONFIG(dev); + struct cros_flash_npcx_data *const data = DRV_DATA(dev); + int ret = 0; + + /* check protection */ + if (all_protected) + return EC_ERROR_ACCESS_DENIED; + + /* check protection */ + if (flash_check_prot_range(offset, size)) + return EC_ERROR_ACCESS_DENIED; + + /* Is write protection enabled? */ + if (data->write_protectied) { + return -EACCES; + } + /* affected region should be within device */ + if (offset < 0 || (offset + size) > config->size) { + LOG_ERR("Flash erase address or size exceeds expected values. " + "Addr: 0x%lx size %zu", + (long)offset, size); + return -EINVAL; + } + + /* address must be aligned to erase size */ + if ((offset % CONFIG_FLASH_ERASE_SIZE) != 0) { + return -EINVAL; + } + + /* Erase size must be a non-zero multiple of sectors */ + if ((size == 0) || (size % CONFIG_FLASH_ERASE_SIZE) != 0) { + return -EINVAL; + } + + /* Unlock flash interface device during erasing flash */ + cros_flash_npcx_mutex_lock(dev); + + /* Alignment has been checked in upper layer */ + for (; size > 0; size -= CONFIG_FLASH_ERASE_SIZE, + offset += CONFIG_FLASH_ERASE_SIZE) { + + /* Enable write */ + ret = cros_flash_npcx_set_write_enable(dev); + if (ret != 0) + break; + + /* Set erase address */ + cros_flash_npcx_set_address(dev, offset); + /* Start erasing */ + cros_flash_npcx_exec_cmd(dev, SPI_NOR_CMD_BE, UMA_CODE_CMD_ADR); + + /* Wait erase completed */ + ret = cros_flash_npcx_wait_ready(dev); + if (ret != 0) { + break; + } + } + + /* Unlock flash interface device */ + cros_flash_npcx_mutex_unlock(dev); + + return ret; +} + /* cros ec flash driver registration */ static const struct cros_flash_driver_api cros_flash_npcx_driver_api = { .init = cros_flash_npcx_init, |