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 <tudor.ambarus@microchip.com>
Reviewed-by: Vignesh Raghavendra <vigneshr@ti.com>
This commit is contained in:
Tudor Ambarus 2019-11-13 15:42:52 +00:00 committed by Eugen Hristev
parent ef7c2af659
commit a11c081da3
2 changed files with 46 additions and 2 deletions

View 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:

View 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;