[PATCH 1/1] mtd: spi-nor: add a presence check for non-JEDEC spi nor

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This patch fixes the following kernel error message:

"flash operation timed out"

that occurs when a non-JEDEC spi-nor, declared in a Device Tree, but not
physically present on the board, is involved in a write operation, as:

cat datafile > /dev/mtd0

In some cases, with enough quantity of data, the writing hangs for minutes.

This situation can happen, for example, in some embedded systems, when
a non-JEDEC spi-nor is mounted using a removable add-on board. So is
important to find a method to check a non-JEDEC device presence before
using it.

The presence of a JEDEC compliant device is implicitly verified during the
JEDEC auto-detect procedure.
But for a non-JEDEC device, the presence must be explicitly checked,
reading one or more known registers, according to the chip features.

Without any check, if the spi-nor is declared in a Device Tree but not
physically present on the board, the driver (i.e. m25p80) is loaded anyway
and the correspondent mtd device is also created.
In this way any read operation on this device returns 0xff (or 0x00,
depending on the driver and the hardware used) and any write operation
hangs until the flash operation timeout occurs, with the "flash operation
timed out" error message.

This patch adds the non-JEDEC spi-nor presence check before initializing
the device.

Note: currently this presence check supports only the Everspin mr25h40,
      reading its status register.

      The support for other non-JEDEC devices has to be added.

Signed-off-by: Flavio Suligoi <f.suligoi@xxxxxxx>
---
 drivers/mtd/spi-nor/spi-nor.c | 43 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 43 insertions(+)

diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
index fae1474..d2cb710 100644
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -3981,6 +3981,42 @@ static const struct flash_info *spi_nor_match_id(const char *name)
 	return NULL;
 }
 
+/**
+ * check_nojedec_nor_presence() - check the real presence of a non-JEDEC nor
+ * @nor: pointer to a 'struct spi_nor'
+ *
+ * The presence of a JEDEC compliant device is implicity verified during the
+ * JEDEC auto-detect procedure.
+ * For a non-JEDEC device, the presence have to explicity checked, reading
+ * one or more known registers, according to the chip features.
+ *
+ * Return: 0 on success, -errno otherwise.
+ */
+int check_nojedec_nor_presence(struct spi_nor *nor)
+{
+	struct device *dev = nor->dev;
+	const struct flash_info *info = nor->info;
+	int ret = 0;
+	u8 val;
+
+	/* Check presence for Everspin mr25h40 MRAM */
+	if (!strcmp(info->name, "mr25h40")) {
+		/* Read the status register */
+		ret = nor->read_reg(nor, SPINOR_OP_RDSR, &val, 1);
+		if (ret)
+			return ret;
+
+		dev_dbg(dev, "%s - status register = 0x%2.2x\n",
+			info->name, val);
+
+		/* The factory preset of the status register is 0x00 */
+		if (val == 0xff)
+			return -ENODEV;
+	}
+
+	return 0;
+}
+
 int spi_nor_scan(struct spi_nor *nor, const char *name,
 		 const struct spi_nor_hwcaps *hwcaps)
 {
@@ -4158,6 +4194,13 @@ int spi_nor_scan(struct spi_nor *nor, const char *name,
 			return ret;
 	}
 
+	/* Check non-JEDEC nor presence */
+	if (!info->id_len) {
+		ret = check_nojedec_nor_presence(nor);
+		if (ret)
+			return ret;
+	}
+
 	/* Send all the required SPI flash commands to initialize device */
 	ret = spi_nor_init(nor);
 	if (ret)
-- 
2.7.4


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/



[Index of Archives]     [LARTC]     [Bugtraq]     [Yosemite Forum]     [Photo]

  Powered by Linux