Unverified Commit 7ab8b810 authored by Takahiro Kuwano's avatar Takahiro Kuwano Committed by Tudor Ambarus
Browse files

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: default avatarTakahiro Kuwano <Takahiro.Kuwano@infineon.com>
Link: https://lore.kernel.org/r/89c892d52f8cbddbd14373f6a02db496885ae4f1.1680849425.git.Takahiro.Kuwano@infineon.com


Signed-off-by: default avatarTudor Ambarus <tudor.ambarus@linaro.org>
parent 706fd00d
Loading
Loading
Loading
Loading
+66 −0
Original line number Diff line number Diff line
@@ -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

@@ -1264,6 +1269,63 @@ static int spi_nor_parse_sccr(struct spi_nor *nor,
	return ret;
}

/**
 * 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
@@ -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;
		}