diff options
author | Tim Lin <tim2.lin@ite.corp-partner.google.com> | 2021-06-29 15:41:04 +0800 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2021-07-01 15:00:53 +0000 |
commit | 1e6aad6a6c55d9d04158625766f9ed419fedcfd9 (patch) | |
tree | c799e1e7448d56ee25b43e1cd1c76ca9a5d73769 | |
parent | f3e7625cc3f41f69a1fa79c3cf45bfc8a79e83d4 (diff) | |
download | chrome-ec-1e6aad6a6c55d9d04158625766f9ed419fedcfd9.tar.gz |
zephyr/drivers: npcx: reorganizes the flash driver(1)
Move the flash protection routines flash_get_status1() through
flash_write_prot_reg() from shim/flash.c to
cros_flash/cros_flash_npcx.c.
BUG=b:187192628
BRANCH=none
TEST=none
Cq-Depend: chromium:2891674
Signed-off-by: Tim Lin <tim2.lin@ite.corp-partner.google.com>
Change-Id: Iaca3a32cfb35a77df10b87745bdabc1ed1cd3c40
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2994429
Reviewed-by: Keith Short <keithshort@chromium.org>
Reviewed-by: Denis Brockus <dbrockus@chromium.org>
Commit-Queue: Keith Short <keithshort@chromium.org>
Tested-by: Keith Short <keithshort@chromium.org>
-rw-r--r-- | zephyr/drivers/cros_flash/cros_flash_npcx.c | 191 | ||||
-rw-r--r-- | zephyr/include/drivers/cros_flash.h | 136 | ||||
-rw-r--r-- | zephyr/shim/src/flash.c | 194 |
3 files changed, 186 insertions, 335 deletions
diff --git a/zephyr/drivers/cros_flash/cros_flash_npcx.c b/zephyr/drivers/cros_flash/cros_flash_npcx.c index 5c81353ef8..f23cc09293 100644 --- a/zephyr/drivers/cros_flash/cros_flash_npcx.c +++ b/zephyr/drivers/cros_flash/cros_flash_npcx.c @@ -15,12 +15,24 @@ #include <soc/nuvoton_npcx/reg_def_cros.h> #include <sys/__assert.h> #include "ec_tasks.h" +#include "flash.h" +#include "gpio.h" #include "soc_miwu.h" +#include "spi_flash_reg.h" #include "task.h" #include "../drivers/flash/spi_nor.h" LOG_MODULE_REGISTER(cros_flash, LOG_LEVEL_ERR); +static int all_protected; /* Has all-flash protection been requested? */ +static int addr_prot_start; +static int addr_prot_length; +static uint8_t saved_sr1; +static uint8_t saved_sr2; + +#define CMD_READ_STATUS_REG 0x05 +#define CMD_READ_STATUS_REG2 0x35 + /* Device config */ struct cros_flash_npcx_config { /* flash interface unit base address */ @@ -475,17 +487,186 @@ static int cros_flash_npcx_uma_lock(const struct device *dev, bool enable) return 0; } +static int flash_get_status1(const struct device *dev) +{ + uint8_t reg; + + if (all_protected) + return saved_sr1; + + /* Lock physical flash operations */ + crec_flash_lock_mapped_storage(1); + + cros_flash_npcx_get_status_reg(dev, CMD_READ_STATUS_REG, ®); + + /* Unlock physical flash operations */ + crec_flash_lock_mapped_storage(0); + + return reg; +} + +static int flash_get_status2(const struct device *dev) +{ + uint8_t reg; + + if (all_protected) + return saved_sr1; + + /* Lock physical flash operations */ + crec_flash_lock_mapped_storage(1); + + cros_flash_npcx_get_status_reg(dev, CMD_READ_STATUS_REG2, ®); + + /* Unlock physical flash operations */ + crec_flash_lock_mapped_storage(0); + + return reg; +} + +static int flash_write_status_reg(const struct device *dev, uint8_t *data) +{ + return cros_flash_npcx_set_status_reg(dev, data); +} + +static int is_int_flash_protected(const struct device *dev) +{ + return cros_flash_npcx_write_protection_is_set(dev); +} + +static void flash_protect_int_flash(const struct device *dev, int enable) +{ + /* + * Please notice the type of WP_IF bit is R/W1S. Once it's set, + * only rebooting EC can clear it. + */ + if (enable) + cros_flash_npcx_write_protection_set(dev, enable); +} + +static void flash_uma_lock(const struct device *dev, int enable) +{ + if (enable && !all_protected) { + /* + * Store SR1 / SR2 for later use since we're about to lock + * out all access (including read access) to these regs. + */ + saved_sr1 = flash_get_status1(dev); + saved_sr2 = flash_get_status2(dev); + } + + cros_flash_npcx_uma_lock(dev, enable); + all_protected = enable; +} + +static int flash_set_status_for_prot(const struct device *dev, int reg1, + int reg2) +{ + uint8_t regs[2]; + + /* + * Writing SR regs will fail if our UMA lock is enabled. If WP + * is deasserted then remove the lock and allow the write. + */ + if (all_protected) { + if (is_int_flash_protected(dev)) + return EC_ERROR_ACCESS_DENIED; + + if (crec_flash_get_protect() & EC_FLASH_PROTECT_GPIO_ASSERTED) + return EC_ERROR_ACCESS_DENIED; + flash_uma_lock(dev, 0); + } + + /* + * If WP# is active and ec doesn't protect the status registers of + * internal spi-flash, protect it now before setting them. + */ +#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_*/ + + /* Lock physical flash operations */ + crec_flash_lock_mapped_storage(1); + + regs[0] = reg1; + regs[1] = reg2; + flash_write_status_reg(dev, regs); + + /* Unlock physical flash operations */ + crec_flash_lock_mapped_storage(0); + + spi_flash_reg_to_protect(reg1, reg2, &addr_prot_start, + &addr_prot_length); + + return EC_SUCCESS; +} + +static int flash_check_prot_reg(const struct device *dev, unsigned int offset, + unsigned int bytes) +{ + unsigned int start; + unsigned int len; + uint8_t sr1, sr2; + int rv = EC_SUCCESS; + + /* + * If WP# is active and ec doesn't protect the status registers of + * internal spi-flash, protect it now. + */ +#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 */ + + sr1 = flash_get_status1(dev); + sr2 = flash_get_status2(dev); + + /* Invalid value */ + if (offset + bytes > CONFIG_FLASH_SIZE_BYTES) + return EC_ERROR_INVAL; + + /* Compute current protect range */ + rv = spi_flash_reg_to_protect(sr1, sr2, &start, &len); + if (rv) + return rv; + + /* Check if ranges overlap */ + if (MAX(start, offset) < MIN(start + len, offset + bytes)) + return EC_ERROR_ACCESS_DENIED; + + return EC_SUCCESS; +} + +static int flash_write_prot_reg(const struct device *dev, unsigned int offset, + unsigned int bytes, int hw_protect) +{ + int rv; + uint8_t sr1 = flash_get_status1(dev); + uint8_t sr2 = flash_get_status2(dev); + + /* Invalid values */ + if (offset + bytes > CONFIG_FLASH_SIZE_BYTES) + return EC_ERROR_INVAL; + + /* Compute desired protect range */ + rv = spi_flash_protect_to_reg(offset, bytes, &sr1, &sr2); + if (rv) + return rv; + + if (hw_protect) + sr1 |= SPI_FLASH_SR1_SRP0; + + return flash_set_status_for_prot(dev, sr1, sr2); +} + /* cros ec flash driver registration */ static const struct cros_flash_driver_api cros_flash_npcx_driver_api = { .init = cros_flash_npcx_init, .physical_read = cros_flash_npcx_read, .physical_write = cros_flash_npcx_write, .physical_erase = cros_flash_npcx_erase, - .write_protection = cros_flash_npcx_write_protection_set, - .write_protection_is_set = cros_flash_npcx_write_protection_is_set, - .get_status_reg = cros_flash_npcx_get_status_reg, - .set_status_reg = cros_flash_npcx_set_status_reg, - .uma_lock = cros_flash_npcx_uma_lock, }; static int flash_npcx_init(const struct device *dev) diff --git a/zephyr/include/drivers/cros_flash.h b/zephyr/include/drivers/cros_flash.h index fd2a0951e4..19c93210e1 100644 --- a/zephyr/include/drivers/cros_flash.h +++ b/zephyr/include/drivers/cros_flash.h @@ -45,25 +45,12 @@ typedef int (*cros_flash_api_physical_write)(const struct device *dev, typedef int (*cros_flash_api_physical_erase)(const struct device *dev, int offset, int size); -typedef int (*cros_flash_api_write_protection)(const struct device *dev, - bool enable); -typedef int (*cros_flash_api_write_protection_is_set)(const struct device *dev); -typedef int (*cros_flash_api_get_status_reg)(const struct device *dev, - char cmd_code, char *data); -typedef int (*cros_flash_api_set_status_reg)(const struct device *dev, - char *data); -typedef int (*cros_flash_api_uma_lock)(const struct device *dev, bool enable); __subsystem struct cros_flash_driver_api { cros_flash_api_init init; cros_flash_api_physical_read physical_read; cros_flash_api_physical_write physical_write; cros_flash_api_physical_erase physical_erase; - cros_flash_api_write_protection write_protection; - cros_flash_api_write_protection_is_set write_protection_is_set; - cros_flash_api_get_status_reg get_status_reg; - cros_flash_api_set_status_reg set_status_reg; - cros_flash_api_uma_lock uma_lock; }; /** @@ -179,129 +166,6 @@ static inline int z_impl_cros_flash_physical_erase(const struct device *dev, } /** - * @brief Enable or disable write protection for a flash memory - * - * Offset and size must be a multiple of CONFIG_FLASH_ERASE_SIZE. - * - * @param dev Pointer to the device structure for the flash driver instance. - * @param enable True to enable it, False to disable it. - * - * @return 0 If successful. - * @retval -ENOTSUP Not supported api function. - */ -__syscall int cros_flash_write_protection_set(const struct device *dev, - bool enable); - -static inline int -z_impl_cros_flash_write_protection_set(const struct device *dev, bool enable) -{ - const struct cros_flash_driver_api *api = - (const struct cros_flash_driver_api *)dev->api; - - if (!api->write_protection) { - return -ENOTSUP; - } - - return api->write_protection(dev, enable); -} - -/** - * @brief Get write protection status of the flash device - * - * @return 1 If write protection is set, 0 otherwise. - */ -__syscall bool cros_flash_write_protection_is_set(const struct device *dev); - -static inline bool -z_impl_cros_flash_write_protection_is_set(const struct device *dev) -{ - const struct cros_flash_driver_api *api = - (const struct cros_flash_driver_api *)dev->api; - - if (!api->write_protection_is_set) { - return -ENOTSUP; - } - - return api->write_protection_is_set(dev); -} - -/** - * @brief Read status registers of flash. - * - * cmd_code must be a valid code to read the status register. - * - * @param dev Pointer to the device structure for the flash driver instance. - * @param cmd_code instruction code to read status registers. - * @param data Buffer to store the value read back - * - * @return 0 If successful. - * @retval -ENOTSUP Not supported api function. - */ -__syscall int cros_flash_get_status_reg(const struct device *dev, char cmd_code, - char *data); - -static inline int z_impl_cros_flash_get_status_reg(const struct device *dev, - char cmd_code, char *data) -{ - const struct cros_flash_driver_api *api = - (const struct cros_flash_driver_api *)dev->api; - - if (!api->get_status_reg) { - return -ENOTSUP; - } - - return api->get_status_reg(dev, cmd_code, data); -} - -/** - * @brief Write status registers of flash. - * - * @param dev Pointer to the device structure for the flash driver instance. - * @param data Buffer to store the value to write - * - * @return 0 If successful. - * @retval -ENOTSUP Not supported api function. - */ -__syscall int cros_flash_set_status_reg(const struct device *dev, char *data); - -static inline int z_impl_cros_flash_set_status_reg(const struct device *dev, - char *data) -{ - const struct cros_flash_driver_api *api = - (const struct cros_flash_driver_api *)dev->api; - - if (!api->set_status_reg) { - return -ENOTSUP; - } - - return api->set_status_reg(dev, data); -} - -/** - * @brief Enable or disable UMA module to access the internal flash. - * - * @param dev Pointer to the device structure for the flash driver instance. - * @param enable True to lock it, False to unlock it. - * - * @return 0 If successful. - * @retval -ENOTSUP Not supported api function. - */ -__syscall int cros_flash_uma_lock(const struct device *dev, bool enable); - -static inline int -z_impl_cros_flash_uma_lock(const struct device *dev, bool enable) -{ - const struct cros_flash_driver_api *api = - (const struct cros_flash_driver_api *)dev->api; - - if (!api->uma_lock) { - return -ENOTSUP; - } - - return api->uma_lock(dev, enable); -} - -/** * @} */ #include <syscalls/cros_flash.h> diff --git a/zephyr/shim/src/flash.c b/zephyr/shim/src/flash.c index 3c8de4f4d4..4fe8e284b1 100644 --- a/zephyr/shim/src/flash.c +++ b/zephyr/shim/src/flash.c @@ -20,204 +20,10 @@ LOG_MODULE_REGISTER(shim_flash, LOG_LEVEL_ERR); #define CROS_FLASH_DEV DT_LABEL(DT_NODELABEL(fiu0)) static const struct device *cros_flash_dev; -static int all_protected; /* Has all-flash protection been requested? */ -static int addr_prot_start; -static int addr_prot_length; static uint8_t flag_prot_inconsistent; -static uint8_t saved_sr1; -static uint8_t saved_sr2; - -#define CMD_READ_STATUS_REG 0x05 -#define CMD_READ_STATUS_REG2 0x35 K_MUTEX_DEFINE(flash_lock); -static int flash_get_status1(void) -{ - uint8_t reg; - - if (all_protected) - return saved_sr1; - - /* Lock physical flash operations */ - crec_flash_lock_mapped_storage(1); - - cros_flash_get_status_reg(cros_flash_dev, CMD_READ_STATUS_REG, ®); - - /* Unlock physical flash operations */ - crec_flash_lock_mapped_storage(0); - - return reg; -} - -static int flash_get_status2(void) -{ - uint8_t reg; - - if (all_protected) - return saved_sr1; - - /* Lock physical flash operations */ - crec_flash_lock_mapped_storage(1); - - cros_flash_get_status_reg(cros_flash_dev, CMD_READ_STATUS_REG2, ®); - - /* Unlock physical flash operations */ - crec_flash_lock_mapped_storage(0); - - return reg; -} - -static int flash_write_status_reg(uint8_t *data) -{ - return cros_flash_set_status_reg(cros_flash_dev, data); -} - -static int is_int_flash_protected(void) -{ - return cros_flash_write_protection_is_set(cros_flash_dev); -} - -static void flash_protect_int_flash(int enable) -{ - /* - * Please notice the type of WP_IF bit is R/W1S. Once it's set, - * only rebooting EC can clear it. - */ - if (enable) - cros_flash_write_protection_set(cros_flash_dev, enable); -} - -static void flash_uma_lock(int enable) -{ - if (enable && !all_protected) { - /* - * Store SR1 / SR2 for later use since we're about to lock - * out all access (including read access) to these regs. - */ - saved_sr1 = flash_get_status1(); - saved_sr2 = flash_get_status2(); - } - - cros_flash_uma_lock(cros_flash_dev, enable); - all_protected = enable; -} - -static int flash_set_status_for_prot(int reg1, int reg2) -{ - uint8_t regs[2]; - - /* - * Writing SR regs will fail if our UMA lock is enabled. If WP - * is deasserted then remove the lock and allow the write. - */ - if (all_protected) { - if (is_int_flash_protected()) - return EC_ERROR_ACCESS_DENIED; - - if (crec_flash_get_protect() & EC_FLASH_PROTECT_GPIO_ASSERTED) - return EC_ERROR_ACCESS_DENIED; - flash_uma_lock(0); - } - - /* - * If WP# is active and ec doesn't protect the status registers of - * internal spi-flash, protect it now before setting them. - */ -#ifdef CONFIG_WP_ACTIVE_HIGH - flash_protect_int_flash(gpio_get_level(GPIO_WP)); -#else - flash_protect_int_flash(!gpio_get_level(GPIO_WP_L)); -#endif /*_CONFIG_WP_ACTIVE_HIGH_*/ - - /* Lock physical flash operations */ - crec_flash_lock_mapped_storage(1); - - regs[0] = reg1; - regs[1] = reg2; - flash_write_status_reg(regs); - - /* Unlock physical flash operations */ - crec_flash_lock_mapped_storage(0); - - spi_flash_reg_to_protect(reg1, reg2, &addr_prot_start, - &addr_prot_length); - - return EC_SUCCESS; -} - -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; -} - -static int flash_check_prot_reg(unsigned int offset, unsigned int bytes) -{ - unsigned int start; - unsigned int len; - uint8_t sr1, sr2; - int rv = EC_SUCCESS; - - /* - * If WP# is active and ec doesn't protect the status registers of - * internal spi-flash, protect it now. - */ -#ifdef CONFIG_WP_ACTIVE_HIGH - flash_protect_int_flash(gpio_get_level(GPIO_WP)); -#else - flash_protect_int_flash(!gpio_get_level(GPIO_WP_L)); -#endif /* CONFIG_WP_ACTIVE_HIGH */ - - sr1 = flash_get_status1(); - sr2 = flash_get_status2(); - - /* Invalid value */ - if (offset + bytes > CONFIG_FLASH_SIZE_BYTES) - return EC_ERROR_INVAL; - - /* Compute current protect range */ - rv = spi_flash_reg_to_protect(sr1, sr2, &start, &len); - if (rv) - return rv; - - /* Check if ranges overlap */ - if (MAX(start, offset) < MIN(start + len, offset + bytes)) - return EC_ERROR_ACCESS_DENIED; - - return EC_SUCCESS; -} - -static int flash_write_prot_reg(unsigned int offset, unsigned int bytes, - int hw_protect) -{ - int rv; - uint8_t sr1 = flash_get_status1(); - uint8_t sr2 = flash_get_status2(); - - /* Invalid values */ - if (offset + bytes > CONFIG_FLASH_SIZE_BYTES) - return EC_ERROR_INVAL; - - /* Compute desired protect range */ - rv = spi_flash_protect_to_reg(offset, bytes, &sr1, &sr2); - if (rv) - return rv; - - if (hw_protect) - sr1 |= SPI_FLASH_SR1_SRP0; - - return flash_set_status_for_prot(sr1, sr2); -} - /* TODO(b/174873770): Add calls to Zephyr code here */ #ifdef CONFIG_EXTERNAL_STORAGE void crec_flash_lock_mapped_storage(int lock) |