diff --git a/doc/releases/migration-guide-4.0.rst b/doc/releases/migration-guide-4.0.rst index 4dad028399d..2fcfabdcaac 100644 --- a/doc/releases/migration-guide-4.0.rst +++ b/doc/releases/migration-guide-4.0.rst @@ -196,6 +196,11 @@ Other Subsystems Flash map ========= + * ``CONFIG_SPI_NOR_IDLE_IN_DPD`` has been removed from the :kconfig:option:`CONFIG_SPI_NOR` + driver. An enhanced version of this functionality can be obtained by enabling + :ref:`pm-device-runtime` on the device (Tunable with + :kconfig:option:`CONFIG_SPI_NOR_ACTIVE_DWELL_MS`). + hawkBit ======= diff --git a/drivers/flash/Kconfig.nor b/drivers/flash/Kconfig.nor index 4a0275b2407..46ea130efbf 100644 --- a/drivers/flash/Kconfig.nor +++ b/drivers/flash/Kconfig.nor @@ -78,4 +78,15 @@ config SPI_NOR_FLASH_LAYOUT_PAGE_SIZE (32768), the sector size (4096), or any non-zero multiple of the sector size. +config SPI_NOR_ACTIVE_DWELL_MS + int "Dwell period (ms) after last use to stay in active mode" + depends on PM_DEVICE_RUNTIME + default 10 + help + Flash accesses commonly occur in bursts, where entering and exiting DPD + mode between each access adds significantly to the total operation time. + This option controls how long to remain in active mode after each API + call, eliminating the active->idle->active transition sequence if another + transaction occurs before the dwell period expires. + endif # SPI_NOR diff --git a/drivers/flash/spi_nor.c b/drivers/flash/spi_nor.c index aa0d71bec85..4f423f00112 100644 --- a/drivers/flash/spi_nor.c +++ b/drivers/flash/spi_nor.c @@ -19,6 +19,7 @@ #include #include #include +#include #include "spi_nor.h" #include "jesd216.h" @@ -65,6 +66,12 @@ LOG_MODULE_REGISTER(spi_nor, CONFIG_FLASH_LOG_LEVEL); #define ANY_INST_HAS_WP_GPIOS ANY_INST_HAS_PROP(wp_gpios) #define ANY_INST_HAS_HOLD_GPIOS ANY_INST_HAS_PROP(hold_gpios) +#ifdef CONFIG_SPI_NOR_ACTIVE_DWELL_MS +#define ACTIVE_DWELL_MS CONFIG_SPI_NOR_ACTIVE_DWELL_MS +#else +#define ACTIVE_DWELL_MS 0 +#endif + #define DEV_CFG(_dev_) ((const struct spi_nor_config * const) (_dev_)->config) /* MXICY Related defines*/ @@ -762,11 +769,19 @@ static int spi_nor_read(const struct device *dev, off_t addr, void *dest, return -EINVAL; } + /* Ensure flash is powered before read */ + if (pm_device_runtime_get(dev) < 0) { + return -EIO; + } + acquire_device(dev); ret = spi_nor_cmd_addr_read(dev, SPI_NOR_CMD_READ, addr, dest, size); release_device(dev); + + /* Release flash power requirement */ + (void)pm_device_runtime_put_async(dev, K_MSEC(ACTIVE_DWELL_MS)); return ret; } @@ -779,6 +794,10 @@ static int flash_spi_nor_ex_op(const struct device *dev, uint16_t code, ARG_UNUSED(in); ARG_UNUSED(out); + if (pm_device_runtime_get(dev) < 0) { + return -EIO; + } + acquire_device(dev); switch (code) { @@ -794,6 +813,7 @@ static int flash_spi_nor_ex_op(const struct device *dev, uint16_t code, } release_device(dev); + (void)pm_device_runtime_put_async(dev, K_MSEC(ACTIVE_DWELL_MS)); return ret; } #endif @@ -811,6 +831,11 @@ static int spi_nor_write(const struct device *dev, off_t addr, return -EINVAL; } + /* Ensure flash is powered before write */ + if (pm_device_runtime_get(dev) < 0) { + return -EIO; + } + acquire_device(dev); ret = spi_nor_write_protection_set(dev, false); if (ret == 0) { @@ -858,6 +883,9 @@ static int spi_nor_write(const struct device *dev, off_t addr, } release_device(dev); + + /* Release flash power requirement */ + (void)pm_device_runtime_put_async(dev, K_MSEC(ACTIVE_DWELL_MS)); return ret; } @@ -881,6 +909,11 @@ static int spi_nor_erase(const struct device *dev, off_t addr, size_t size) return -EINVAL; } + /* Ensure flash is powered before erase */ + if (pm_device_runtime_get(dev) < 0) { + return -EIO; + } + acquire_device(dev); ret = spi_nor_write_protection_set(dev, false); @@ -936,6 +969,8 @@ static int spi_nor_erase(const struct device *dev, off_t addr, size_t size) release_device(dev); + /* Release flash power requirement */ + (void)pm_device_runtime_put_async(dev, K_MSEC(ACTIVE_DWELL_MS)); return ret; } @@ -977,12 +1012,18 @@ static int spi_nor_write_protection_set(const struct device *dev, static int spi_nor_sfdp_read(const struct device *dev, off_t addr, void *dest, size_t size) { + if (pm_device_runtime_get(dev) < 0) { + return -EIO; + } + acquire_device(dev); int ret = read_sfdp(dev, addr, dest, size); release_device(dev); + (void)pm_device_runtime_put_async(dev, K_MSEC(ACTIVE_DWELL_MS)); + return ret; } @@ -995,12 +1036,18 @@ static int spi_nor_read_jedec_id(const struct device *dev, return -EINVAL; } + if (pm_device_runtime_get(dev) < 0) { + return -EIO; + } + acquire_device(dev); int ret = spi_nor_cmd_read(dev, SPI_NOR_CMD_RDID, id, SPI_NOR_MAX_ID_LEN); release_device(dev); + (void)pm_device_runtime_put_async(dev, K_MSEC(ACTIVE_DWELL_MS)); + return ret; }