From a11c081da3dfbef309cd21ab54b7b2582d0c9f35 Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Wed, 13 Nov 2019 15:42:52 +0000 Subject: [PATCH] mtd: spi: spi-nor-core: Add SST vendor specific SFDP parser 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 Reviewed-by: Vignesh Raghavendra --- 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 5a8c084255..ee77151f20 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 @@ -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: diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h index f9964a7664..1d91177291 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.39.5