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 <michallenc@seznam.cz>
This commit is contained in:
Michal Lenc
2026-03-19 16:02:54 +01:00
committed by Matteo Golin
parent ff29b04e66
commit 014f22b1c2

View File

@@ -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);