From 014f22b1c24c02ebf7e53afffdac54b6c96fd8fc Mon Sep 17 00:00:00 2001 From: Michal Lenc Date: Thu, 19 Mar 2026 16:02:54 +0100 Subject: [PATCH] drivers/mtd/w25.c: ensure the device is not in power down mode If power down mode is set, trying to read ID ends in an infinite loop because w25_waitwritecomplete never returns as status register never signalizes write complete. Therefore ensure the device is not in a power down mode before trying to read from it. This can be an issue if the board is trying to check for more NOR memories on one SPI bus and one chip select. For example GD25 driver returns the memory to power down state after read id is finished, therefore board initialization is stuck in an infinite loop if it first checks for GD25 and then fallbacks to W25. The commit fixes the possible issue by ensuring W25 is brought back to normal operation mode before trying to obtain the manufacturer ID. Signed-off-by: Michal Lenc --- drivers/mtd/w25.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/drivers/mtd/w25.c b/drivers/mtd/w25.c index 0a025183c7d..831145baa71 100644 --- a/drivers/mtd/w25.c +++ b/drivers/mtd/w25.c @@ -255,6 +255,7 @@ struct w25_dev_s /* Helpers */ +static inline void w25_purdid(FAR struct w25_dev_s *priv); static void w25_lock(FAR struct spi_dev_s *spi); static inline void w25_unlock(FAR struct spi_dev_s *spi); static inline int w25_readid(FAR struct w25_dev_s *priv); @@ -326,6 +327,18 @@ static ssize_t w25_write(FAR struct mtd_dev_s *dev, * Private Functions ****************************************************************************/ +/**************************************************************************** + * Name: w25_purdid + ****************************************************************************/ + +static inline void w25_purdid(FAR struct w25_dev_s *priv) +{ + SPI_SELECT(priv->spi, SPIDEV_FLASH(0), true); + SPI_SEND(priv->spi, W25_PURDID); + SPI_SELECT(priv->spi, SPIDEV_FLASH(0), false); + nxsched_usleep(20); +} + /**************************************************************************** * Name: w25_lock ****************************************************************************/ @@ -386,6 +399,10 @@ static inline int w25_readid(struct w25_dev_s *priv) w25_lock(priv->spi); + /* Make sure the device is not in power down mode */ + + w25_purdid(priv); + /* Wait for any preceding write or erase operation to complete. */ w25_waitwritecomplete(priv);