From 7ab8b810757a32b083c75a61b5638bca82e17a4c Mon Sep 17 00:00:00 2001 From: Takahiro Kuwano Date: Fri, 7 Apr 2023 15:41:00 +0900 Subject: [PATCH] mtd: spi-nor: sfdp: Add support for SCCR map for multi-chip device SCCR map for multi-chip devices contains the number of additional dice in the device and register offset values for each additional dice. spi_nor_parse_sccr_mc() is added to determine the number of dice and volatile register offset for each die. The volatile register offset table may already be allocated and contains offset value for die-0 via SCCR map parse. So, we should use devm_krealloc() to expand the table with preserving die-0 offset. Signed-off-by: Takahiro Kuwano Link: https://lore.kernel.org/r/89c892d52f8cbddbd14373f6a02db496885ae4f1.1680849425.git.Takahiro.Kuwano@infineon.com Signed-off-by: Tudor Ambarus --- drivers/mtd/spi-nor/sfdp.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/drivers/mtd/spi-nor/sfdp.c b/drivers/mtd/spi-nor/sfdp.c index 9d43e18..b3b11df 100644 --- a/drivers/mtd/spi-nor/sfdp.c +++ b/drivers/mtd/spi-nor/sfdp.c @@ -26,6 +26,11 @@ * Status, Control and Configuration * Register Map. */ +#define SFDP_SCCR_MAP_MC_ID 0xff88 /* + * Status, Control and Configuration + * Register Map Offsets for Multi-Chip + * SPI Memory Devices. + */ #define SFDP_SIGNATURE 0x50444653U @@ -1265,6 +1270,63 @@ out: } /** + * spi_nor_parse_sccr_mc() - Parse the Status, Control and Configuration + * Register Map Offsets for Multi-Chip SPI Memory + * Devices. + * @nor: pointer to a 'struct spi_nor' + * @sccr_mc_header: pointer to the 'struct sfdp_parameter_header' describing + * the SCCR Map offsets table length and version. + * + * Return: 0 on success, -errno otherwise. + */ +static int spi_nor_parse_sccr_mc(struct spi_nor *nor, + const struct sfdp_parameter_header *sccr_mc_header) +{ + struct spi_nor_flash_parameter *params = nor->params; + u32 *dwords, addr; + u8 i, n_dice; + size_t len; + int ret; + + len = sccr_mc_header->length * sizeof(*dwords); + dwords = kmalloc(len, GFP_KERNEL); + if (!dwords) + return -ENOMEM; + + addr = SFDP_PARAM_HEADER_PTP(sccr_mc_header); + ret = spi_nor_read_sfdp(nor, addr, len, dwords); + if (ret) + goto out; + + le32_to_cpu_array(dwords, sccr_mc_header->length); + + /* + * Pair of DOWRDs (volatile and non-volatile register offsets) per + * additional die. Hence, length = 2 * (number of additional dice). + */ + n_dice = 1 + sccr_mc_header->length / 2; + + /* Address offset for volatile registers of additional dice */ + params->vreg_offset = + devm_krealloc(nor->dev, params->vreg_offset, + n_dice * sizeof(*dwords), + GFP_KERNEL); + if (!params->vreg_offset) { + ret = -ENOMEM; + goto out; + } + + for (i = 1; i < n_dice; i++) + params->vreg_offset[i] = dwords[SFDP_DWORD(i) * 2]; + + params->n_dice = n_dice; + +out: + kfree(dwords); + return ret; +} + +/** * spi_nor_post_sfdp_fixups() - Updates the flash's parameters and settings * after SFDP has been parsed. Called only for flashes that define JESD216 SFDP * tables. @@ -1480,6 +1542,10 @@ int spi_nor_parse_sfdp(struct spi_nor *nor) err = spi_nor_parse_sccr(nor, param_header); break; + case SFDP_SCCR_MAP_MC_ID: + err = spi_nor_parse_sccr_mc(nor, param_header); + break; + default: break; } -- 2.7.4