[U-Boot] [PATCH v2 1/4] mtd: spi: spi-nor-core: Add SST vendor specific SFDP parser

Tudor.Ambarus at microchip.com Tudor.Ambarus at microchip.com
Wed Nov 13 15:42:52 UTC 2019


From: Tudor Ambarus <tudor.ambarus at microchip.com>

JESD216 allow vendors to define their own SFDP tables.

Add SST SFDP parser. The vendor table is allocated using resource-managed
kmalloc - the table will be freed on driver detach. It will be accessible
by getting the UCLASS_SPI_FLASH's private data.

The SST's SFDP table is particularly of interest because contains
pre-programmed globally unique EUI-48 and EUI-64 identifiers.

Signed-off-by: Tudor Ambarus <tudor.ambarus at microchip.com>
---
 drivers/mtd/spi/spi-nor-core.c | 46 ++++++++++++++++++++++++++++++++++++++++--
 include/linux/mtd/spi-nor.h    |  2 ++
 2 files changed, 46 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c
index 5a8c08425566..ee77151f20de 100644
--- a/drivers/mtd/spi/spi-nor-core.c
+++ b/drivers/mtd/spi/spi-nor-core.c
@@ -1588,6 +1588,7 @@ struct sfdp_parameter_header {
 
 #define SFDP_BFPT_ID		0xff00	/* Basic Flash Parameter Table */
 #define SFDP_SECTOR_MAP_ID	0xff81	/* Sector Map Table */
+#define SFDP_SST_ID		0x01bf	/* Manufacturer specific Table */
 
 #define SFDP_SIGNATURE		0x50444653U
 #define SFDP_JESD216_MAJOR	1
@@ -1968,6 +1969,34 @@ static int spi_nor_parse_bfpt(struct spi_nor *nor,
 }
 
 /**
+ * spi_nor_parse_microchip_sfdp() - parse the Microchip manufacturer specific
+ * SFDP table.
+ * @nor:		pointer to a 'struct spi_nor'.
+ * @param_header:	pointer to the SFDP parameter header.
+ *
+ * Return: 0 on success, -errno otherwise.
+ */
+static int
+spi_nor_parse_microchip_sfdp(struct spi_nor *nor,
+			     const struct sfdp_parameter_header *param_header)
+{
+	size_t size;
+	u32 addr;
+	int ret;
+
+	size = param_header->length * sizeof(u32);
+	addr = SFDP_PARAM_HEADER_PTP(param_header);
+
+	nor->manufacturer_sfdp = devm_kmalloc(nor->dev, size, GFP_KERNEL);
+	if (!nor->manufacturer_sfdp)
+		return -ENOMEM;
+
+	ret = spi_nor_read_sfdp(nor, addr, size, nor->manufacturer_sfdp);
+
+	return ret;
+}
+
+/**
  * spi_nor_parse_sfdp() - parse the Serial Flash Discoverable Parameters.
  * @nor:		pointer to a 'struct spi_nor'
  * @params:		pointer to the 'struct spi_nor_flash_parameter' to be
@@ -2063,12 +2092,25 @@ static int spi_nor_parse_sfdp(struct spi_nor *nor,
 			dev_info(dev, "non-uniform erase sector maps are not supported yet.\n");
 			break;
 
+		case SFDP_SST_ID:
+			err = spi_nor_parse_microchip_sfdp(nor, param_header);
+			break;
+
 		default:
 			break;
 		}
 
-		if (err)
-			goto exit;
+		if (err) {
+			dev_warn(dev, "Failed to parse optional parameter table: %04x\n",
+				 SFDP_PARAM_HEADER_ID(param_header));
+			/*
+			 * Let's not drop all information we extracted so far
+			 * if optional table parsers fail. In case of failing,
+			 * each optional parser is responsible to roll back to
+			 * the previously known spi_nor data.
+			 */
+			err = 0;
+		}
 	}
 
 exit:
diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h
index f9964a766456..1d911772917d 100644
--- a/include/linux/mtd/spi-nor.h
+++ b/include/linux/mtd/spi-nor.h
@@ -261,6 +261,7 @@ struct flash_info;
  * @lock:		the lock for the read/write/erase/lock/unlock operations
  * @dev:		point to a spi device, or a spi nor controller device.
  * @info:		spi-nor part JDEC MFR id and other info
+ * @manufacturer_sfdp:	manufacturer specific SFDP table
  * @page_size:		the page size of the SPI NOR
  * @addr_width:		number of address bytes
  * @erase_opcode:	the opcode for erasing a sector
@@ -299,6 +300,7 @@ struct spi_nor {
 	struct udevice		*dev;
 	struct spi_slave	*spi;
 	const struct flash_info	*info;
+	u8			*manufacturer_sfdp;
 	u32			page_size;
 	u8			addr_width;
 	u8			erase_opcode;
-- 
2.9.5



More information about the U-Boot mailing list