drivers: flash: flash_mcux_flexspi_*: copy LUT to ram when updating

Copy the LUT to SRAM before updating it. This avoids the application
reading LUT entries from FlexSPI while trying to write them to FlexSPI
configuration registers, which could result in invalid LUT entries being
added.

This update is applied to all in tree flash FlexSPI drivers, although
the failure has only been observed with the flash_mcux_flexspi_nor
driver.

Signed-off-by: Daniel DeGrasse <daniel.degrasse@nxp.com>
This commit is contained in:
Daniel DeGrasse 2023-05-19 22:14:03 +00:00 committed by Mahesh Mahadevan
commit 095d453d7a
3 changed files with 42 additions and 8 deletions

View file

@ -1,5 +1,6 @@
/*
* Copyright (c) 2021 Volvo Construction Equipment
* Copyright 2023 NXP
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -595,6 +596,7 @@ static int flash_flexspi_hyperflash_init(const struct device *dev)
{
const struct flash_flexspi_hyperflash_config *config = dev->config;
struct flash_flexspi_hyperflash_data *data = dev->data;
uint32_t temp_lut[sizeof(flash_flexspi_hyperflash_lut) / sizeof(uint32_t)];
/* Since the controller variable may be used in critical sections,
* copy the device pointer into a variable stored in RAM
@ -615,9 +617,19 @@ static int flash_flexspi_hyperflash_init(const struct device *dev)
return -EINVAL;
}
/*
* Using the LUT stored in the FlexSPI directly when updating
* the FlexSPI can result in an invalid LUT entry being stored,
* as the LUT itself describes how the FlexSPI should access the flash.
* To resolve this, copy the LUT to a array placed in RAM before
* updating the FlexSPI.
*/
memcpy(temp_lut, flash_flexspi_hyperflash_lut,
sizeof(flash_flexspi_hyperflash_lut));
if (memc_flexspi_update_lut(&data->controller, 0,
(const uint32_t *) flash_flexspi_hyperflash_lut,
sizeof(flash_flexspi_hyperflash_lut)/4)) {
(const uint32_t *) temp_lut,
sizeof(temp_lut) / sizeof(uint32_t))) {
LOG_ERR("Could not update lut");
return -EINVAL;
}

View file

@ -1,5 +1,5 @@
/*
* Copyright 2021 NXP
* Copyright 2021,2023 NXP
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -504,6 +504,7 @@ static int flash_flexspi_nor_init(const struct device *dev)
{
struct flash_flexspi_nor_data *data = dev->data;
uint8_t vendor_id;
uint32_t temp_lut[sizeof(flash_flexspi_nor_lut) / sizeof(uint32_t)];
if (!device_is_ready(data->controller)) {
LOG_ERR("Controller device not ready");
@ -517,9 +518,19 @@ static int flash_flexspi_nor_init(const struct device *dev)
return -EINVAL;
}
/*
* Using the LUT stored in the FlexSPI directly when updating
* the FlexSPI can result in an invalid LUT entry being stored,
* as the LUT itself describes how the FlexSPI should access the flash.
* To resolve this, copy the LUT to a array placed in RAM before
* updating the FlexSPI.
*/
memcpy(temp_lut, flash_flexspi_nor_lut,
sizeof(flash_flexspi_nor_lut));
if (memc_flexspi_update_lut(data->controller, 0,
(const uint32_t *) flash_flexspi_nor_lut,
sizeof(flash_flexspi_nor_lut) / 4)) {
(const uint32_t *) temp_lut,
sizeof(temp_lut) / sizeof(uint32_t))) {
LOG_ERR("Could not update lut");
return -EINVAL;
}

View file

@ -1,5 +1,5 @@
/*
* Copyright 2020 NXP
* Copyright 2020,2023 NXP
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -506,6 +506,7 @@ static int flash_flexspi_nor_init(const struct device *dev)
{
struct flash_flexspi_nor_data *data = dev->data;
uint8_t vendor_id;
uint32_t temp_lut[sizeof(flash_flexspi_nor_lut) / sizeof(uint32_t)];
if (!device_is_ready(data->controller)) {
LOG_ERR("Controller device is not ready");
@ -519,9 +520,19 @@ static int flash_flexspi_nor_init(const struct device *dev)
return -EINVAL;
}
/*
* Using the LUT stored in the FlexSPI directly when updating
* the FlexSPI can result in an invalid LUT entry being stored,
* as the LUT itself describes how the FlexSPI should access the flash.
* To resolve this, copy the LUT to a array placed in RAM before
* updating the FlexSPI.
*/
memcpy(temp_lut, flash_flexspi_nor_lut,
sizeof(flash_flexspi_nor_lut));
if (memc_flexspi_update_lut(data->controller, 0,
(const uint32_t *) flash_flexspi_nor_lut,
sizeof(flash_flexspi_nor_lut) / 4)) {
(const uint32_t *) temp_lut,
sizeof(temp_lut) / sizeof(uint32_t))) {
LOG_ERR("Could not update lut");
return -EINVAL;
}