From 69ff24ce97e392fcc9b5bc6e6a4145f4de769f57 Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Mon, 21 Mar 2022 15:09:20 -0500 Subject: [PATCH] drivers: memc: memc_mcux_flexspi: move device data into RAM flexspi driver should not interact with flash whenever possible, and should never use flash while in a critical write or erase section. Move device data to RAM to prevent this read-while-write hazard. Fixes #44043 Signed-off-by: Daniel DeGrasse --- drivers/memc/memc_mcux_flexspi.c | 58 ++++++++++++++------------------ 1 file changed, 26 insertions(+), 32 deletions(-) diff --git a/drivers/memc/memc_mcux_flexspi.c b/drivers/memc/memc_mcux_flexspi.c index 815ab9906d..c416d1d177 100644 --- a/drivers/memc/memc_mcux_flexspi.c +++ b/drivers/memc/memc_mcux_flexspi.c @@ -25,7 +25,8 @@ LOG_MODULE_REGISTER(memc_flexspi, CONFIG_MEMC_LOG_LEVEL); -struct memc_flexspi_config { +/* flexspi device data should be stored in RAM to avoid read-while-write hazards */ +struct memc_flexspi_data { FLEXSPI_Type *base; uint8_t *ahb_base; bool xip; @@ -36,33 +37,30 @@ struct memc_flexspi_config { bool combination_mode; bool sck_differential_clock; flexspi_read_sample_clock_t rx_sample_clock; -}; - -struct memc_flexspi_data { size_t size[kFLEXSPI_PortCount]; }; void memc_flexspi_wait_bus_idle(const struct device *dev) { - const struct memc_flexspi_config *config = dev->config; + struct memc_flexspi_data *data = dev->data; - while (false == FLEXSPI_GetBusIdleStatus(config->base)) { + while (false == FLEXSPI_GetBusIdleStatus(data->base)) { } } bool memc_flexspi_is_running_xip(const struct device *dev) { - const struct memc_flexspi_config *config = dev->config; + struct memc_flexspi_data *data = dev->data; - return config->xip; + return data->xip; } int memc_flexspi_update_lut(const struct device *dev, uint32_t index, const uint32_t *cmd, uint32_t count) { - const struct memc_flexspi_config *config = dev->config; + struct memc_flexspi_data *data = dev->data; - FLEXSPI_UpdateLUT(config->base, index, cmd, count); + FLEXSPI_UpdateLUT(data->base, index, cmd, count); return 0; } @@ -71,7 +69,6 @@ int memc_flexspi_set_device_config(const struct device *dev, const flexspi_device_config_t *device_config, flexspi_port_t port) { - const struct memc_flexspi_config *config = dev->config; struct memc_flexspi_data *data = dev->data; if (port >= kFLEXSPI_PortCount) { @@ -81,7 +78,7 @@ int memc_flexspi_set_device_config(const struct device *dev, data->size[port] = device_config->flashSize * KB(1); - FLEXSPI_SetFlashConfig(config->base, + FLEXSPI_SetFlashConfig(data->base, (flexspi_device_config_t *) device_config, port); @@ -90,9 +87,9 @@ int memc_flexspi_set_device_config(const struct device *dev, int memc_flexspi_reset(const struct device *dev) { - const struct memc_flexspi_config *config = dev->config; + struct memc_flexspi_data *data = dev->data; - FLEXSPI_SoftwareReset(config->base); + FLEXSPI_SoftwareReset(data->base); return 0; } @@ -100,8 +97,8 @@ int memc_flexspi_reset(const struct device *dev) int memc_flexspi_transfer(const struct device *dev, flexspi_transfer_t *transfer) { - const struct memc_flexspi_config *config = dev->config; - status_t status = FLEXSPI_TransferBlocking(config->base, transfer); + struct memc_flexspi_data *data = dev->data; + status_t status = FLEXSPI_TransferBlocking(data->base, transfer); if (status != kStatus_Success) { LOG_ERR("Transfer error: %d", status); @@ -114,7 +111,6 @@ int memc_flexspi_transfer(const struct device *dev, void *memc_flexspi_get_ahb_address(const struct device *dev, flexspi_port_t port, off_t offset) { - const struct memc_flexspi_config *config = dev->config; struct memc_flexspi_data *data = dev->data; int i; @@ -127,12 +123,12 @@ void *memc_flexspi_get_ahb_address(const struct device *dev, offset += data->size[port]; } - return config->ahb_base + offset; + return data->ahb_base + offset; } static int memc_flexspi_init(const struct device *dev) { - const struct memc_flexspi_config *config = dev->config; + struct memc_flexspi_data *data = dev->data; flexspi_config_t flexspi_config; /* we should not configure the device we are running on */ @@ -143,18 +139,18 @@ static int memc_flexspi_init(const struct device *dev) FLEXSPI_GetDefaultConfig(&flexspi_config); - flexspi_config.ahbConfig.enableAHBBufferable = config->ahb_bufferable; - flexspi_config.ahbConfig.enableAHBCachable = config->ahb_cacheable; - flexspi_config.ahbConfig.enableAHBPrefetch = config->ahb_prefetch; - flexspi_config.ahbConfig.enableReadAddressOpt = config->ahb_read_addr_opt; + flexspi_config.ahbConfig.enableAHBBufferable = data->ahb_bufferable; + flexspi_config.ahbConfig.enableAHBCachable = data->ahb_cacheable; + flexspi_config.ahbConfig.enableAHBPrefetch = data->ahb_prefetch; + flexspi_config.ahbConfig.enableReadAddressOpt = data->ahb_read_addr_opt; #if !(defined(FSL_FEATURE_FLEXSPI_HAS_NO_MCR0_COMBINATIONEN) && \ FSL_FEATURE_FLEXSPI_HAS_NO_MCR0_COMBINATIONEN) - flexspi_config.enableCombination = config->combination_mode; + flexspi_config.enableCombination = data->combination_mode; #endif - flexspi_config.enableSckBDiffOpt = config->sck_differential_clock; - flexspi_config.rxSampleClock = config->rx_sample_clock; + flexspi_config.enableSckBDiffOpt = data->sck_differential_clock; + flexspi_config.rxSampleClock = data->rx_sample_clock; - FLEXSPI_Init(config->base, &flexspi_config); + FLEXSPI_Init(data->base, &flexspi_config); return 0; } @@ -170,8 +166,8 @@ static int memc_flexspi_init(const struct device *dev) #endif #define MEMC_FLEXSPI(n) \ - static const struct memc_flexspi_config \ - memc_flexspi_config_##n = { \ + static struct memc_flexspi_data \ + memc_flexspi_data_##n = { \ .base = (FLEXSPI_Type *) DT_INST_REG_ADDR(n), \ .xip = MEMC_FLEXSPI_CFG_XIP(DT_DRV_INST(n)), \ .ahb_base = (uint8_t *) DT_INST_REG_ADDR_BY_IDX(n, 1), \ @@ -184,13 +180,11 @@ static int memc_flexspi_init(const struct device *dev) .rx_sample_clock = DT_INST_PROP(n, rx_clock_source), \ }; \ \ - static struct memc_flexspi_data memc_flexspi_data_##n; \ - \ DEVICE_DT_INST_DEFINE(n, \ memc_flexspi_init, \ NULL, \ &memc_flexspi_data_##n, \ - &memc_flexspi_config_##n, \ + NULL, \ POST_KERNEL, \ CONFIG_KERNEL_INIT_PRIORITY_DEVICE, \ NULL);