The Linux Kernel Mailing List
 help / color / mirror / Atom feed
diff for duplicates of <20200916124418.833-7-p.yadav@ti.com>

diff --git a/a/1.txt b/N1/1.txt
index 15188f5..2dc967d 100644
--- a/a/1.txt
+++ b/N1/1.txt
@@ -1 +1,195 @@
-<<< No Message Collected >>>
+This table is indication that the flash is xSPI compliant and hence
+supports octal DTR mode. Extract information like the fast read opcode,
+dummy cycles, the number of dummy cycles needed for a Read Status
+Register command, and the number of address bytes needed for a Read
+Status Register command.
+
+We don't know what speed the controller is running at. Find the fast
+read dummy cycles for the fastest frequency the flash can run at to be
+sure we are never short of dummy cycles. If nothing is available,
+default to 20. Flashes that use a different value should update it in
+their fixup hooks.
+
+Since we want to set read settings, expose spi_nor_set_read_settings()
+in core.h.
+
+Signed-off-by: Pratyush Yadav <p.yadav@ti.com>
+---
+ drivers/mtd/spi-nor/core.c |  2 +-
+ drivers/mtd/spi-nor/core.h | 10 +++++
+ drivers/mtd/spi-nor/sfdp.c | 91 ++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 102 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
+index 7445d7122304..cbb1aab27d03 100644
+--- a/drivers/mtd/spi-nor/core.c
++++ b/drivers/mtd/spi-nor/core.c
+@@ -2333,7 +2333,7 @@ static int spi_nor_check(struct spi_nor *nor)
+ 	return 0;
+ }
+ 
+-static void
++void
+ spi_nor_set_read_settings(struct spi_nor_read_command *read,
+ 			  u8 num_mode_clocks,
+ 			  u8 num_wait_states,
+diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
+index 125d27b0a72f..42ec7692d8e7 100644
+--- a/drivers/mtd/spi-nor/core.h
++++ b/drivers/mtd/spi-nor/core.h
+@@ -192,6 +192,9 @@ struct spi_nor_locking_ops {
+  *
+  * @size:		the flash memory density in bytes.
+  * @page_size:		the page size of the SPI NOR flash memory.
++ * @rdsr_dummy:		dummy cycles needed for Read Status Register command.
++ * @rdsr_addr_nbytes:	dummy address bytes needed for Read Status Register
++ *			command.
+  * @hwcaps:		describes the read and page program hardware
+  *			capabilities.
+  * @reads:		read capabilities ordered by priority: the higher index
+@@ -214,6 +217,8 @@ struct spi_nor_locking_ops {
+ struct spi_nor_flash_parameter {
+ 	u64				size;
+ 	u32				page_size;
++	u8				rdsr_dummy;
++	u8				rdsr_addr_nbytes;
+ 
+ 	struct spi_nor_hwcaps		hwcaps;
+ 	struct spi_nor_read_command	reads[SNOR_CMD_READ_MAX];
+@@ -425,6 +430,11 @@ ssize_t spi_nor_write_data(struct spi_nor *nor, loff_t to, size_t len,
+ 
+ int spi_nor_hwcaps_read2cmd(u32 hwcaps);
+ u8 spi_nor_convert_3to4_read(u8 opcode);
++void spi_nor_set_read_settings(struct spi_nor_read_command *read,
++			       u8 num_mode_clocks,
++			       u8 num_wait_states,
++			       u8 opcode,
++			       enum spi_nor_protocol proto);
+ void spi_nor_set_pp_settings(struct spi_nor_pp_command *pp, u8 opcode,
+ 			     enum spi_nor_protocol proto);
+ 
+diff --git a/drivers/mtd/spi-nor/sfdp.c b/drivers/mtd/spi-nor/sfdp.c
+index c77655968f80..cadb1ed27ffe 100644
+--- a/drivers/mtd/spi-nor/sfdp.c
++++ b/drivers/mtd/spi-nor/sfdp.c
+@@ -4,6 +4,7 @@
+  * Copyright (C) 2014, Freescale Semiconductor, Inc.
+  */
+ 
++#include <linux/bitfield.h>
+ #include <linux/slab.h>
+ #include <linux/sort.h>
+ #include <linux/mtd/spi-nor.h>
+@@ -19,6 +20,7 @@
+ #define SFDP_BFPT_ID		0xff00	/* Basic Flash Parameter Table */
+ #define SFDP_SECTOR_MAP_ID	0xff81	/* Sector Map Table */
+ #define SFDP_4BAIT_ID		0xff84  /* 4-byte Address Instruction Table */
++#define SFDP_PROFILE1_ID	0xff05	/* xSPI Profile 1.0 table. */
+ 
+ #define SFDP_SIGNATURE		0x50444653U
+ 
+@@ -1108,6 +1110,91 @@ static int spi_nor_parse_4bait(struct spi_nor *nor,
+ 	return ret;
+ }
+ 
++#define PROFILE1_DWORD1_RDSR_ADDR_BYTES		BIT(29)
++#define PROFILE1_DWORD1_RDSR_DUMMY		BIT(28)
++#define PROFILE1_DWORD1_RD_FAST_CMD		GENMASK(15, 8)
++#define PROFILE1_DWORD4_DUMMY_200MHZ		GENMASK(11, 7)
++#define PROFILE1_DWORD5_DUMMY_166MHZ		GENMASK(31, 27)
++#define PROFILE1_DWORD5_DUMMY_133MHZ		GENMASK(21, 17)
++#define PROFILE1_DWORD5_DUMMY_100MHZ		GENMASK(11, 7)
++#define PROFILE1_DUMMY_DEFAULT			20
++
++/**
++ * spi_nor_parse_profile1() - parse the xSPI Profile 1.0 table
++ * @nor:		pointer to a 'struct spi_nor'
++ * @profile1_header:	pointer to the 'struct sfdp_parameter_header' describing
++ *			the 4-Byte Address Instruction Table length and version.
++ * @params:		pointer to the 'struct spi_nor_flash_parameter' to be.
++ *
++ * Return: 0 on success, -errno otherwise.
++ */
++static int spi_nor_parse_profile1(struct spi_nor *nor,
++				  const struct sfdp_parameter_header *profile1_header,
++				  struct spi_nor_flash_parameter *params)
++{
++	u32 *dwords, addr;
++	size_t len;
++	int ret;
++	u8 dummy, opcode;
++
++	len = profile1_header->length * sizeof(*dwords);
++	dwords = kmalloc(len, GFP_KERNEL);
++	if (!dwords)
++		return -ENOMEM;
++
++	addr = SFDP_PARAM_HEADER_PTP(profile1_header);
++	ret = spi_nor_read_sfdp(nor, addr, len, dwords);
++	if (ret)
++		goto out;
++
++	le32_to_cpu_array(dwords, profile1_header->length);
++
++	/* Get 8D-8D-8D fast read opcode and dummy cycles. */
++	opcode = FIELD_GET(PROFILE1_DWORD1_RD_FAST_CMD, dwords[0]);
++
++	 /* Set the Read Status Register dummy cycles and dummy address bytes. */
++	if (dwords[0] & PROFILE1_DWORD1_RDSR_DUMMY)
++		params->rdsr_dummy = 8;
++	else
++		params->rdsr_dummy = 4;
++
++	if (dwords[0] & PROFILE1_DWORD1_RDSR_ADDR_BYTES)
++		params->rdsr_addr_nbytes = 4;
++	else
++		params->rdsr_addr_nbytes = 0;
++
++	/*
++	 * We don't know what speed the controller is running at. Find the
++	 * dummy cycles for the fastest frequency the flash can run at to be
++	 * sure we are never short of dummy cycles. A value of 0 means the
++	 * frequency is not supported.
++	 *
++	 * Default to PROFILE1_DUMMY_DEFAULT if we don't find anything, and let
++	 * flashes set the correct value if needed in their fixup hooks.
++	 */
++	dummy = FIELD_GET(PROFILE1_DWORD4_DUMMY_200MHZ, dwords[3]);
++	if (!dummy)
++		dummy = FIELD_GET(PROFILE1_DWORD5_DUMMY_166MHZ, dwords[4]);
++	if (!dummy)
++		dummy = FIELD_GET(PROFILE1_DWORD5_DUMMY_133MHZ, dwords[4]);
++	if (!dummy)
++		dummy = FIELD_GET(PROFILE1_DWORD5_DUMMY_100MHZ, dwords[4]);
++	if (!dummy)
++		dummy = PROFILE1_DUMMY_DEFAULT;
++
++	/* Round up to an even value to avoid tripping controllers up. */
++	dummy = round_up(dummy, 2);
++
++	/* Update the fast read settings. */
++	spi_nor_set_read_settings(&params->reads[SNOR_CMD_READ_8_8_8_DTR],
++				  0, dummy, opcode,
++				  SNOR_PROTO_8_8_8_DTR);
++
++out:
++	kfree(dwords);
++	return ret;
++}
++
+ /**
+  * spi_nor_parse_sfdp() - parse the Serial Flash Discoverable Parameters.
+  * @nor:		pointer to a 'struct spi_nor'
+@@ -1209,6 +1296,10 @@ int spi_nor_parse_sfdp(struct spi_nor *nor,
+ 			err = spi_nor_parse_4bait(nor, param_header, params);
+ 			break;
+ 
++		case SFDP_PROFILE1_ID:
++			err = spi_nor_parse_profile1(nor, param_header, params);
++			break;
++
+ 		default:
+ 			break;
+ 		}
+-- 
+2.28.0
diff --git a/a/content_digest b/N1/content_digest
index 7a940ee..9b22028 100644
--- a/a/content_digest
+++ b/N1/content_digest
@@ -13,6 +13,200 @@
  " Boris Brezillon <boris.brezillon@collabora.com>\0"
  "\00:1\0"
  "b\0"
- <<< No Message Collected >>>
+ "This table is indication that the flash is xSPI compliant and hence\n"
+ "supports octal DTR mode. Extract information like the fast read opcode,\n"
+ "dummy cycles, the number of dummy cycles needed for a Read Status\n"
+ "Register command, and the number of address bytes needed for a Read\n"
+ "Status Register command.\n"
+ "\n"
+ "We don't know what speed the controller is running at. Find the fast\n"
+ "read dummy cycles for the fastest frequency the flash can run at to be\n"
+ "sure we are never short of dummy cycles. If nothing is available,\n"
+ "default to 20. Flashes that use a different value should update it in\n"
+ "their fixup hooks.\n"
+ "\n"
+ "Since we want to set read settings, expose spi_nor_set_read_settings()\n"
+ "in core.h.\n"
+ "\n"
+ "Signed-off-by: Pratyush Yadav <p.yadav@ti.com>\n"
+ "---\n"
+ " drivers/mtd/spi-nor/core.c |  2 +-\n"
+ " drivers/mtd/spi-nor/core.h | 10 +++++\n"
+ " drivers/mtd/spi-nor/sfdp.c | 91 ++++++++++++++++++++++++++++++++++++++\n"
+ " 3 files changed, 102 insertions(+), 1 deletion(-)\n"
+ "\n"
+ "diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c\n"
+ "index 7445d7122304..cbb1aab27d03 100644\n"
+ "--- a/drivers/mtd/spi-nor/core.c\n"
+ "+++ b/drivers/mtd/spi-nor/core.c\n"
+ "@@ -2333,7 +2333,7 @@ static int spi_nor_check(struct spi_nor *nor)\n"
+ " \treturn 0;\n"
+ " }\n"
+ " \n"
+ "-static void\n"
+ "+void\n"
+ " spi_nor_set_read_settings(struct spi_nor_read_command *read,\n"
+ " \t\t\t  u8 num_mode_clocks,\n"
+ " \t\t\t  u8 num_wait_states,\n"
+ "diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h\n"
+ "index 125d27b0a72f..42ec7692d8e7 100644\n"
+ "--- a/drivers/mtd/spi-nor/core.h\n"
+ "+++ b/drivers/mtd/spi-nor/core.h\n"
+ "@@ -192,6 +192,9 @@ struct spi_nor_locking_ops {\n"
+ "  *\n"
+ "  * @size:\t\tthe flash memory density in bytes.\n"
+ "  * @page_size:\t\tthe page size of the SPI NOR flash memory.\n"
+ "+ * @rdsr_dummy:\t\tdummy cycles needed for Read Status Register command.\n"
+ "+ * @rdsr_addr_nbytes:\tdummy address bytes needed for Read Status Register\n"
+ "+ *\t\t\tcommand.\n"
+ "  * @hwcaps:\t\tdescribes the read and page program hardware\n"
+ "  *\t\t\tcapabilities.\n"
+ "  * @reads:\t\tread capabilities ordered by priority: the higher index\n"
+ "@@ -214,6 +217,8 @@ struct spi_nor_locking_ops {\n"
+ " struct spi_nor_flash_parameter {\n"
+ " \tu64\t\t\t\tsize;\n"
+ " \tu32\t\t\t\tpage_size;\n"
+ "+\tu8\t\t\t\trdsr_dummy;\n"
+ "+\tu8\t\t\t\trdsr_addr_nbytes;\n"
+ " \n"
+ " \tstruct spi_nor_hwcaps\t\thwcaps;\n"
+ " \tstruct spi_nor_read_command\treads[SNOR_CMD_READ_MAX];\n"
+ "@@ -425,6 +430,11 @@ ssize_t spi_nor_write_data(struct spi_nor *nor, loff_t to, size_t len,\n"
+ " \n"
+ " int spi_nor_hwcaps_read2cmd(u32 hwcaps);\n"
+ " u8 spi_nor_convert_3to4_read(u8 opcode);\n"
+ "+void spi_nor_set_read_settings(struct spi_nor_read_command *read,\n"
+ "+\t\t\t       u8 num_mode_clocks,\n"
+ "+\t\t\t       u8 num_wait_states,\n"
+ "+\t\t\t       u8 opcode,\n"
+ "+\t\t\t       enum spi_nor_protocol proto);\n"
+ " void spi_nor_set_pp_settings(struct spi_nor_pp_command *pp, u8 opcode,\n"
+ " \t\t\t     enum spi_nor_protocol proto);\n"
+ " \n"
+ "diff --git a/drivers/mtd/spi-nor/sfdp.c b/drivers/mtd/spi-nor/sfdp.c\n"
+ "index c77655968f80..cadb1ed27ffe 100644\n"
+ "--- a/drivers/mtd/spi-nor/sfdp.c\n"
+ "+++ b/drivers/mtd/spi-nor/sfdp.c\n"
+ "@@ -4,6 +4,7 @@\n"
+ "  * Copyright (C) 2014, Freescale Semiconductor, Inc.\n"
+ "  */\n"
+ " \n"
+ "+#include <linux/bitfield.h>\n"
+ " #include <linux/slab.h>\n"
+ " #include <linux/sort.h>\n"
+ " #include <linux/mtd/spi-nor.h>\n"
+ "@@ -19,6 +20,7 @@\n"
+ " #define SFDP_BFPT_ID\t\t0xff00\t/* Basic Flash Parameter Table */\n"
+ " #define SFDP_SECTOR_MAP_ID\t0xff81\t/* Sector Map Table */\n"
+ " #define SFDP_4BAIT_ID\t\t0xff84  /* 4-byte Address Instruction Table */\n"
+ "+#define SFDP_PROFILE1_ID\t0xff05\t/* xSPI Profile 1.0 table. */\n"
+ " \n"
+ " #define SFDP_SIGNATURE\t\t0x50444653U\n"
+ " \n"
+ "@@ -1108,6 +1110,91 @@ static int spi_nor_parse_4bait(struct spi_nor *nor,\n"
+ " \treturn ret;\n"
+ " }\n"
+ " \n"
+ "+#define PROFILE1_DWORD1_RDSR_ADDR_BYTES\t\tBIT(29)\n"
+ "+#define PROFILE1_DWORD1_RDSR_DUMMY\t\tBIT(28)\n"
+ "+#define PROFILE1_DWORD1_RD_FAST_CMD\t\tGENMASK(15, 8)\n"
+ "+#define PROFILE1_DWORD4_DUMMY_200MHZ\t\tGENMASK(11, 7)\n"
+ "+#define PROFILE1_DWORD5_DUMMY_166MHZ\t\tGENMASK(31, 27)\n"
+ "+#define PROFILE1_DWORD5_DUMMY_133MHZ\t\tGENMASK(21, 17)\n"
+ "+#define PROFILE1_DWORD5_DUMMY_100MHZ\t\tGENMASK(11, 7)\n"
+ "+#define PROFILE1_DUMMY_DEFAULT\t\t\t20\n"
+ "+\n"
+ "+/**\n"
+ "+ * spi_nor_parse_profile1() - parse the xSPI Profile 1.0 table\n"
+ "+ * @nor:\t\tpointer to a 'struct spi_nor'\n"
+ "+ * @profile1_header:\tpointer to the 'struct sfdp_parameter_header' describing\n"
+ "+ *\t\t\tthe 4-Byte Address Instruction Table length and version.\n"
+ "+ * @params:\t\tpointer to the 'struct spi_nor_flash_parameter' to be.\n"
+ "+ *\n"
+ "+ * Return: 0 on success, -errno otherwise.\n"
+ "+ */\n"
+ "+static int spi_nor_parse_profile1(struct spi_nor *nor,\n"
+ "+\t\t\t\t  const struct sfdp_parameter_header *profile1_header,\n"
+ "+\t\t\t\t  struct spi_nor_flash_parameter *params)\n"
+ "+{\n"
+ "+\tu32 *dwords, addr;\n"
+ "+\tsize_t len;\n"
+ "+\tint ret;\n"
+ "+\tu8 dummy, opcode;\n"
+ "+\n"
+ "+\tlen = profile1_header->length * sizeof(*dwords);\n"
+ "+\tdwords = kmalloc(len, GFP_KERNEL);\n"
+ "+\tif (!dwords)\n"
+ "+\t\treturn -ENOMEM;\n"
+ "+\n"
+ "+\taddr = SFDP_PARAM_HEADER_PTP(profile1_header);\n"
+ "+\tret = spi_nor_read_sfdp(nor, addr, len, dwords);\n"
+ "+\tif (ret)\n"
+ "+\t\tgoto out;\n"
+ "+\n"
+ "+\tle32_to_cpu_array(dwords, profile1_header->length);\n"
+ "+\n"
+ "+\t/* Get 8D-8D-8D fast read opcode and dummy cycles. */\n"
+ "+\topcode = FIELD_GET(PROFILE1_DWORD1_RD_FAST_CMD, dwords[0]);\n"
+ "+\n"
+ "+\t /* Set the Read Status Register dummy cycles and dummy address bytes. */\n"
+ "+\tif (dwords[0] & PROFILE1_DWORD1_RDSR_DUMMY)\n"
+ "+\t\tparams->rdsr_dummy = 8;\n"
+ "+\telse\n"
+ "+\t\tparams->rdsr_dummy = 4;\n"
+ "+\n"
+ "+\tif (dwords[0] & PROFILE1_DWORD1_RDSR_ADDR_BYTES)\n"
+ "+\t\tparams->rdsr_addr_nbytes = 4;\n"
+ "+\telse\n"
+ "+\t\tparams->rdsr_addr_nbytes = 0;\n"
+ "+\n"
+ "+\t/*\n"
+ "+\t * We don't know what speed the controller is running at. Find the\n"
+ "+\t * dummy cycles for the fastest frequency the flash can run at to be\n"
+ "+\t * sure we are never short of dummy cycles. A value of 0 means the\n"
+ "+\t * frequency is not supported.\n"
+ "+\t *\n"
+ "+\t * Default to PROFILE1_DUMMY_DEFAULT if we don't find anything, and let\n"
+ "+\t * flashes set the correct value if needed in their fixup hooks.\n"
+ "+\t */\n"
+ "+\tdummy = FIELD_GET(PROFILE1_DWORD4_DUMMY_200MHZ, dwords[3]);\n"
+ "+\tif (!dummy)\n"
+ "+\t\tdummy = FIELD_GET(PROFILE1_DWORD5_DUMMY_166MHZ, dwords[4]);\n"
+ "+\tif (!dummy)\n"
+ "+\t\tdummy = FIELD_GET(PROFILE1_DWORD5_DUMMY_133MHZ, dwords[4]);\n"
+ "+\tif (!dummy)\n"
+ "+\t\tdummy = FIELD_GET(PROFILE1_DWORD5_DUMMY_100MHZ, dwords[4]);\n"
+ "+\tif (!dummy)\n"
+ "+\t\tdummy = PROFILE1_DUMMY_DEFAULT;\n"
+ "+\n"
+ "+\t/* Round up to an even value to avoid tripping controllers up. */\n"
+ "+\tdummy = round_up(dummy, 2);\n"
+ "+\n"
+ "+\t/* Update the fast read settings. */\n"
+ "+\tspi_nor_set_read_settings(&params->reads[SNOR_CMD_READ_8_8_8_DTR],\n"
+ "+\t\t\t\t  0, dummy, opcode,\n"
+ "+\t\t\t\t  SNOR_PROTO_8_8_8_DTR);\n"
+ "+\n"
+ "+out:\n"
+ "+\tkfree(dwords);\n"
+ "+\treturn ret;\n"
+ "+}\n"
+ "+\n"
+ " /**\n"
+ "  * spi_nor_parse_sfdp() - parse the Serial Flash Discoverable Parameters.\n"
+ "  * @nor:\t\tpointer to a 'struct spi_nor'\n"
+ "@@ -1209,6 +1296,10 @@ int spi_nor_parse_sfdp(struct spi_nor *nor,\n"
+ " \t\t\terr = spi_nor_parse_4bait(nor, param_header, params);\n"
+ " \t\t\tbreak;\n"
+ " \n"
+ "+\t\tcase SFDP_PROFILE1_ID:\n"
+ "+\t\t\terr = spi_nor_parse_profile1(nor, param_header, params);\n"
+ "+\t\t\tbreak;\n"
+ "+\n"
+ " \t\tdefault:\n"
+ " \t\t\tbreak;\n"
+ " \t\t}\n"
+ "-- \n"
+ 2.28.0
 
-ee2a35b1b9178c2639170e92753d6dbc1f65ab1eb4b02ab41918f504f8892a13
+181e98aa827d8b535ac23057ead8f2267c29920b09cc4a53b50b9276529802e6

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox