[PATCH 12/15] mtd: spi-nor-core: Parse xSPI Profile 1.0 table
Pratyush Yadav
p.yadav at ti.com
Wed Feb 26 13:56:02 CET 2020
This table is indication that the flash is xSPI compliant and hence
supports octal DTR mode. Extract information like the fast read opcode,
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.
The default dummy cycles for a fast octal DTR read are set to 20. Since
there is no simple way of determining the dummy cycles needed for the
fast read command, flashes that use a different value should update it
in their flash-specific hooks.
Signed-off-by: Pratyush Yadav <p.yadav at ti.com>
---
drivers/mtd/spi/spi-nor-core.c | 81 ++++++++++++++++++++++++++++++++++
include/linux/mtd/spi-nor.h | 7 +++
2 files changed, 88 insertions(+)
diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c
index 47c72fd260..0d3ab44a41 100644
--- a/drivers/mtd/spi/spi-nor-core.c
+++ b/drivers/mtd/spi/spi-nor-core.c
@@ -17,6 +17,7 @@
#include <linux/log2.h>
#include <linux/math64.h>
#include <linux/sizes.h>
+#include <linux/bitfield.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/spi-nor.h>
@@ -55,6 +56,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_PROFILE1_ID 0xff05 /* xSPI Profile 1.0 Table */
#define SFDP_SIGNATURE 0x50444653U
#define SFDP_JESD216_MAJOR 1
@@ -151,6 +153,11 @@ struct sfdp_header {
#define BFPT_DWORD18_CMD_EXT_RES (0x2UL << 29) /* Reserved */
#define BFPT_DWORD18_CMD_EXT_16B (0x3UL << 29) /* 16-bit opcode */
+/* xSPI Profile 1.0 table (from JESD216D.01). */
+#define PROFILE1_DWORD1_RD_FAST_CMD GENMASK(15, 8)
+#define PROFILE1_DWORD1_RDSR_DUMMY BIT(28)
+#define PROFILE1_DWORD1_RDSR_ADDR_BYTES BIT(29)
+
struct sfdp_bfpt {
u32 dwords[BFPT_DWORD_MAX];
};
@@ -2020,6 +2027,74 @@ static int spi_nor_parse_bfpt(struct spi_nor *nor,
return spi_nor_post_bfpt_fixups(nor, bfpt_header, &bfpt, params);
}
+/**
+ * spi_nor_parse_profile1() - parse the xSPI Profile 1.0 table
+ * @nor: pointer to a 'struct spi_nor'
+ * @param_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 *table, opcode, addr;
+ size_t len;
+ int ret, i;
+
+ len = profile1_header->length * sizeof(*table);
+ table = kmalloc(len, GFP_KERNEL);
+ if (!table)
+ return -ENOMEM;
+
+ addr = SFDP_PARAM_HEADER_PTP(profile1_header);
+ ret = spi_nor_read_sfdp(nor, addr, len, table);
+ if (ret)
+ goto out;
+
+ /* Fix endianness of the table DWORDs. */
+ for (i = 0; i < profile1_header->length; i++)
+ table[i] = le32_to_cpu(table[i]);
+
+ /* Get 8D-8D-8D fast read opcode and dummy cycles. */
+ opcode = FIELD_GET(PROFILE1_DWORD1_RD_FAST_CMD, table[0]);
+
+ /*
+ * Update the fast read settings. We set the default dummy cycles to 20
+ * here. Flashes can change this value if they need to when enabling
+ * octal mode.
+ */
+ params->hwcaps.mask |= SNOR_HWCAPS_READ_8_8_8_DTR;
+ spi_nor_set_read_settings(¶ms->reads[SNOR_CMD_READ_8_8_8_DTR],
+ 0, 20, opcode,
+ SNOR_PROTO_8_8_8_DTR);
+
+ /*
+ * Since the flash supports xSPI DTR reads, it should also support DTR
+ * Page Program opcodes.
+ */
+ params->hwcaps.mask |= SNOR_HWCAPS_PP_8_8_8_DTR;
+
+ /*
+ * Set the Read Status Register dummy cycles and dummy address bytes.
+ */
+ if (table[0] & PROFILE1_DWORD1_RDSR_DUMMY)
+ params->rdsr_dummy = 8;
+ else
+ params->rdsr_dummy = 4;
+
+ if (table[0] & PROFILE1_DWORD1_RDSR_ADDR_BYTES)
+ params->rdsr_addr_nbytes = 4;
+ else
+ params->rdsr_addr_nbytes = 0;
+
+out:
+ kfree(table);
+ return ret;
+}
+
/**
* spi_nor_parse_microchip_sfdp() - parse the Microchip manufacturer specific
* SFDP table.
@@ -2148,6 +2223,10 @@ static int spi_nor_parse_sfdp(struct spi_nor *nor,
err = spi_nor_parse_microchip_sfdp(nor, param_header);
break;
+ case SFDP_PROFILE1_ID:
+ err = spi_nor_parse_profile1(nor, param_header, params);
+ break;
+
default:
break;
}
@@ -2720,6 +2799,8 @@ int spi_nor_scan(struct spi_nor *nor)
if (ret)
return ret;
+ nor->rdsr_dummy = params.rdsr_dummy;
+ nor->rdsr_addr_nbytes = params.rdsr_addr_nbytes;
nor->name = mtd->name;
nor->size = mtd->size;
nor->erase_size = mtd->erasesize;
diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h
index 9a41e5b25b..1c076fc7f2 100644
--- a/include/linux/mtd/spi-nor.h
+++ b/include/linux/mtd/spi-nor.h
@@ -374,6 +374,8 @@ enum spi_nor_pp_command_index {
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];
@@ -410,6 +412,9 @@ struct flash_info;
* @read_opcode: the read opcode
* @read_dummy: the dummy needed by the read operation
* @program_opcode: the program opcode
+ * @rdsr_dummy dummy cycles needed for Read Status Register command.
+ * @rdsr_addr_nbytes: dummy address bytes needed for Read Status Register
+ * command.
* @bank_read_cmd: Bank read cmd
* @bank_write_cmd: Bank write cmd
* @bank_curr: Current flash bank
@@ -450,6 +455,8 @@ struct spi_nor {
u8 read_opcode;
u8 read_dummy;
u8 program_opcode;
+ u8 rdsr_dummy;
+ u8 rdsr_addr_nbytes;
#ifdef CONFIG_SPI_FLASH_BAR
u8 bank_read_cmd;
u8 bank_write_cmd;
--
2.25.0
More information about the U-Boot
mailing list