diff --git a/drivers/flash/Kconfig.npcx_fiu b/drivers/flash/Kconfig.npcx_fiu index 3ddf9a2b7e5..1137b1ad1ab 100644 --- a/drivers/flash/Kconfig.npcx_fiu +++ b/drivers/flash/Kconfig.npcx_fiu @@ -65,4 +65,12 @@ config FLASH_NPCX_FIU_SUPP_DRA_2_DEV Selected if NPCX series supports two external SPI devices in Direct Read Access (DRA) on QSPI bus. +DT_NPCX_FIU_LOW_DEV_SWAP := $(dt_nodelabel_bool_prop,qspi_fiu1,flash-dev-inv) +config FLASH_NPCX_FIU_SUPP_LOW_DEV_SWAP + bool "Inverse the access of the two external flashes" + default y if SOC_SERIES_NPCX4 && FLASH_NPCX_FIU_SUPP_DRA_2_DEV && \ + "$(DT_NPCX_FIU_LOW_DEV_SWAP)" + help + Select if it needs to swap the access of the two external flashes. + endif #FLASH_NPCX_FIU_QSPI diff --git a/drivers/flash/flash_npcx_fiu_nor.c b/drivers/flash/flash_npcx_fiu_nor.c index ae3a31945fd..c368f646ad0 100644 --- a/drivers/flash/flash_npcx_fiu_nor.c +++ b/drivers/flash/flash_npcx_fiu_nor.c @@ -587,9 +587,23 @@ static int flash_npcx_nor_init(const struct device *dev) } } + if (config->qspi_cfg.is_logical_low_dev && IS_ENABLED(CONFIG_FLASH_NPCX_FIU_DRA_V2)) { + qspi_npcx_fiu_set_spi_size(config->qspi_bus, &config->qspi_cfg); + } + return 0; } +#define NPCX_FLASH_IS_LOGICAL_LOW_DEV(n) \ + (DT_PROP(DT_PARENT(DT_DRV_INST(n)), en_direct_access_2dev) && \ + (DT_PROP(DT_PARENT(DT_DRV_INST(n)), flash_dev_inv) == \ + ((DT_INST_PROP(n, qspi_flags) & NPCX_QSPI_SEC_FLASH_SL) == \ + NPCX_QSPI_SEC_FLASH_SL))) + +#define NPCX_FLASH_SPI_ALLOCATE_SIZE(n) \ + COND_CODE_1(DT_INST_NODE_HAS_PROP(n, spi_dev_size), \ + (DT_INST_STRING_TOKEN(n, spi_dev_size)), (0xFF)) + #define NPCX_FLASH_NOR_INIT(n) \ BUILD_ASSERT(DT_INST_QUAD_EN_PROP_OR(n) == JESD216_DW15_QER_NONE || \ DT_INST_STRING_TOKEN(n, rd_mode) == NPCX_RD_MODE_FAST_DUAL, \ @@ -606,6 +620,8 @@ static const struct flash_npcx_nor_config flash_npcx_nor_config_##n = { \ .enter_4ba = DT_INST_PROP_OR(n, enter_4byte_addr, 0), \ .qer_type = DT_INST_QUAD_EN_PROP_OR(n), \ .rd_mode = DT_INST_STRING_TOKEN(n, rd_mode), \ + .is_logical_low_dev = NPCX_FLASH_IS_LOGICAL_LOW_DEV(n), \ + .spi_dev_sz = NPCX_FLASH_SPI_ALLOCATE_SIZE(n), \ }, \ IF_ENABLED(CONFIG_FLASH_PAGE_LAYOUT, ( \ .layout = { \ diff --git a/drivers/flash/flash_npcx_fiu_qspi.c b/drivers/flash/flash_npcx_fiu_qspi.c index 4084a84fb21..5d78eed2f3c 100644 --- a/drivers/flash/flash_npcx_fiu_qspi.c +++ b/drivers/flash/flash_npcx_fiu_qspi.c @@ -30,6 +30,7 @@ struct npcx_qspi_fiu_config { struct npcx_clk_cfg clk_cfg; /* Enable 2 external SPI devices for direct read on QSPI bus */ bool en_direct_access_2dev; + bool base_flash_inv; }; /* Device data */ @@ -244,6 +245,25 @@ void qspi_npcx_fiu_mutex_unlock(const struct device *dev) k_sem_give(&data->lock_sem); } +#if defined(CONFIG_FLASH_NPCX_FIU_DRA_V2) +void qspi_npcx_fiu_set_spi_size(const struct device *dev, const struct npcx_qspi_cfg *cfg) +{ + struct fiu_reg *const inst = HAL_INSTANCE(dev); + uint8_t flags = cfg->flags; + + if (cfg->spi_dev_sz <= NPCX_SPI_DEV_SIZE_128M) { + if ((flags & NPCX_QSPI_SEC_FLASH_SL) == 0) { + SET_FIELD(inst->BURST_CFG, NPCX_BURST_CFG_SPI_DEV_SEL, NPCX_SPI_F_CS0); + } else { + SET_FIELD(inst->BURST_CFG, NPCX_BURST_CFG_SPI_DEV_SEL, NPCX_SPI_F_CS1); + } + inst->SPI_DEV_SIZE = BIT(cfg->spi_dev_sz); + } else { + LOG_ERR("Invalid setting of low device size"); + } +} +#endif + static int qspi_npcx_fiu_init(const struct device *dev) { const struct npcx_qspi_fiu_config *const config = dev->config; @@ -273,6 +293,11 @@ static int qspi_npcx_fiu_init(const struct device *dev) struct fiu_reg *const inst = HAL_INSTANCE(dev); inst->FIU_EXT_CFG |= BIT(NPCX_FIU_EXT_CFG_SPI1_2DEV); +#if defined(CONFIG_FLASH_NPCX_FIU_SUPP_LOW_DEV_SWAP) + if (config->base_flash_inv) { + inst->FIU_EXT_CFG |= BIT(NPCX_FIU_EXT_CFG_LOW_DEV_NUM); + } +#endif #endif } @@ -284,6 +309,7 @@ static const struct npcx_qspi_fiu_config npcx_qspi_fiu_config_##n = { \ .base = DT_INST_REG_ADDR(n), \ .clk_cfg = NPCX_DT_CLK_CFG_ITEM(n), \ .en_direct_access_2dev = DT_INST_PROP(n, en_direct_access_2dev), \ + .base_flash_inv = DT_INST_PROP(n, flash_dev_inv), \ }; \ static struct npcx_qspi_fiu_data npcx_qspi_fiu_data_##n; \ DEVICE_DT_INST_DEFINE(n, qspi_npcx_fiu_init, NULL, \ diff --git a/drivers/flash/flash_npcx_fiu_qspi.h b/drivers/flash/flash_npcx_fiu_qspi.h index 1136684d453..b9ac87b3b20 100644 --- a/drivers/flash/flash_npcx_fiu_qspi.h +++ b/drivers/flash/flash_npcx_fiu_qspi.h @@ -25,6 +25,20 @@ extern "C" { #define NPCX_DEV_NUM_ADDR_3BYTE 3 #define NPCX_DEV_NUM_ADDR_4BYTE 4 +#define NPCX_SPI_F_CS0 0 +#define NPCX_SPI_F_CS1 1 + +enum NPCX_SPI_DEV_SIZE { + NPCX_SPI_DEV_SIZE_1M, + NPCX_SPI_DEV_SIZE_2M, + NPCX_SPI_DEV_SIZE_4M, + NPCX_SPI_DEV_SIZE_8M, + NPCX_SPI_DEV_SIZE_16M, + NPCX_SPI_DEV_SIZE_32M, + NPCX_SPI_DEV_SIZE_64M, + NPCX_SPI_DEV_SIZE_128M, +}; + /* UMA operation configuration for a SPI device */ struct npcx_uma_cfg { uint8_t opcode; @@ -48,6 +62,8 @@ struct npcx_qspi_cfg { uint8_t enter_4ba; /* SPI read access type of Direct Read Access mode */ uint8_t rd_mode; + bool is_logical_low_dev; + uint8_t spi_dev_sz; /* Configurations for the Quad-SPI peripherals */ int flags; }; @@ -81,6 +97,16 @@ void qspi_npcx_fiu_mutex_lock_configure(const struct device *dev, */ void qspi_npcx_fiu_mutex_unlock(const struct device *dev); +#if defined(CONFIG_FLASH_NPCX_FIU_DRA_V2) +/** + * @brief Set the size of the address space allocated for SPI device. + * + * @param dev Pointer to the device structure for qspi bus controller instance. + * @param cfg Pointer to the configuration for the device on qspi bus. + */ +void qspi_npcx_fiu_set_spi_size(const struct device *dev, const struct npcx_qspi_cfg *cfg); +#endif + #ifdef __cplusplus } #endif diff --git a/soc/nuvoton/npcx/npcx4/soc.h b/soc/nuvoton/npcx/npcx4/soc.h index 4ada738102c..d3f387edd27 100644 --- a/soc/nuvoton/npcx/npcx4/soc.h +++ b/soc/nuvoton/npcx/npcx4/soc.h @@ -38,6 +38,7 @@ /* NPCX4 FIU register fields */ #define NPCX_FIU_EXT_CFG_SPI1_2DEV 6 +#define NPCX_FIU_EXT_CFG_LOW_DEV_NUM 7 /* NPCX4 supported group mask of DEVALT_LK */ #define NPCX_DEVALT_LK_GROUP_MASK \