mtd: spi: spi-nor-core: Add SST vendor specific SFDP parser
authorTudor Ambarus <tudor.ambarus@microchip.com>
Wed, 13 Nov 2019 15:42:52 +0000 (15:42 +0000)
committerEugen Hristev <eugen.hristev@microchip.com>
Tue, 17 Dec 2019 07:49:05 +0000 (09:49 +0200)
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@microchip.com>
Reviewed-by: Vignesh Raghavendra <vigneshr@ti.com>
drivers/mtd/spi/spi-nor-core.c
include/linux/mtd/spi-nor.h

index 5a8c084255662669930584bb2dbb0606be671d74..ee77151f20de885e807ad5d78a7907b517e27b16 100644 (file)
@@ -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
@@ -1967,6 +1968,34 @@ static int spi_nor_parse_bfpt(struct spi_nor *nor,
        return 0;
 }
 
+/**
+ * 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'
@@ -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:
index f9964a7664568615831b839d2f9e850c44b84ff8..1d911772917d919cb13cb196438efc2afafa71f4 100644 (file)
@@ -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;