From 87947eac809fee0a2d40936d83cc8b216e7134bf Mon Sep 17 00:00:00 2001 From: JaimeLiao Date: Mon, 4 Jul 2022 14:12:41 +0800 Subject: [PATCH] mtd: spi-nor: Parse SFDP SCCR Map Parse SCCR 22nd dword and check DTR Octal Mode Enable Volatile bit for Octal DTR enable Signed-off-by: JaimeLiao Reviewed-by: Jagan Teki --- drivers/mtd/spi/spi-nor-core.c | 52 ++++++++++++++++++++++++++++++++++ include/linux/mtd/spi-nor.h | 1 + 2 files changed, 53 insertions(+) diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c index 50460feaf8..1ff34cc317 100644 --- a/drivers/mtd/spi/spi-nor-core.c +++ b/drivers/mtd/spi/spi-nor-core.c @@ -65,6 +65,10 @@ struct sfdp_parameter_header { #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_SCCR_MAP_ID 0xff87 /* + * Status, Control and Configuration + * Register Map. + */ #define SFDP_SIGNATURE 0x50444653U #define SFDP_JESD216_MAJOR 1 @@ -174,6 +178,9 @@ struct sfdp_header { #define PROFILE1_DWORD5_DUMMY_100MHZ GENMASK(11, 7) #define PROFILE1_DUMMY_DEFAULT 20 +/* Status, Control and Configuration Register Map(SCCR) */ +#define SCCR_DWORD22_OCTAL_DTR_EN_VOLATILE BIT(31) + struct sfdp_bfpt { u32 dwords[BFPT_DWORD_MAX]; }; @@ -2456,6 +2463,44 @@ out: return ret; } +/** + * spi_nor_parse_sccr() - Parse the Status, Control and Configuration Register + * Map. + * @nor: pointer to a 'struct spi_nor' + * @sccr_header: pointer to the 'struct sfdp_parameter_header' describing + * the SCCR Map table length and version. + * + * Return: 0 on success, -errno otherwise. + */ +static int spi_nor_parse_sccr(struct spi_nor *nor, + const struct sfdp_parameter_header *sccr_header) +{ + u32 *table, addr; + size_t len; + int ret, i; + + len = sccr_header->length * sizeof(*table); + table = kmalloc(len, GFP_KERNEL); + if (!table) + return -ENOMEM; + + addr = SFDP_PARAM_HEADER_PTP(sccr_header); + ret = spi_nor_read_sfdp(nor, addr, len, table); + if (ret) + goto out; + + /* Fix endianness of the table DWORDs. */ + for (i = 0; i < sccr_header->length; i++) + table[i] = le32_to_cpu(table[i]); + + if (FIELD_GET(SCCR_DWORD22_OCTAL_DTR_EN_VOLATILE, table[22])) + nor->flags |= SNOR_F_IO_MODE_EN_VOLATILE; + +out: + kfree(table); + return ret; +} + /** * spi_nor_parse_sfdp() - parse the Serial Flash Discoverable Parameters. * @nor: pointer to a 'struct spi_nor' @@ -2562,6 +2607,10 @@ static int spi_nor_parse_sfdp(struct spi_nor *nor, err = spi_nor_parse_profile1(nor, param_header, params); break; + case SFDP_SCCR_MAP_ID: + err = spi_nor_parse_sccr(nor, param_header); + break; + default: break; } @@ -3620,6 +3669,9 @@ static int spi_nor_octal_dtr_enable(struct spi_nor *nor) nor->write_proto == SNOR_PROTO_8_8_8_DTR)) return 0; + if (!(nor->flags & SNOR_F_IO_MODE_EN_VOLATILE)) + return 0; + ret = nor->octal_dtr_enable(nor); if (ret) return ret; diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h index c76235d701..ba98ad467f 100644 --- a/include/linux/mtd/spi-nor.h +++ b/include/linux/mtd/spi-nor.h @@ -290,6 +290,7 @@ enum spi_nor_option_flags { SNOR_F_USE_CLSR = BIT(5), SNOR_F_BROKEN_RESET = BIT(6), SNOR_F_SOFT_RESET = BIT(7), + SNOR_F_IO_MODE_EN_VOLATILE = BIT(8), }; struct spi_nor; -- 2.39.5