diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2023-04-25 17:23:42 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2023-04-25 17:23:42 -0700 |
commit | eb8322d714ea98fdc620d682fb517b50ea282aa5 (patch) | |
tree | fe42ba5cc042d5285e99d43a786c553f53b9aad7 /drivers/mtd/spi-nor/sfdp.c | |
parent | 2c96606a0f8b7900387dbeb6532b59527999834d (diff) | |
parent | 7227aacb62aeb59b007a6d3489b11f78fa332696 (diff) | |
download | linux-stable-eb8322d714ea98fdc620d682fb517b50ea282aa5.tar.gz linux-stable-eb8322d714ea98fdc620d682fb517b50ea282aa5.tar.bz2 linux-stable-eb8322d714ea98fdc620d682fb517b50ea282aa5.zip |
Merge tag 'mtd/for-6.4' of git://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux
Pull mtd updates from Miquel Raynal:
"Core MTD changes:
- dt-bindings: Drop unneeded quotes
- mtdblock: Tolerate corrected bit-flips
- Use of_property_read_bool() for boolean properties
- Avoid magic values
- Avoid printing error messages on probe deferrals
- Prepare mtd_otp_nvmem_add() to handle -EPROBE_DEFER
- Fix error path for nvmem provider
- Fix nvmem error reporting
- Provide unique name for nvmem device
MTD device changes:
- lpddr_cmds: Remove unused words variable
- bcm63xxpart: Remove MODULE_LICENSE in non-modules
SPI NOR core changes:
- Introduce Read While Write support for flashes featuring several
banks
- Set the 4-Byte Address Mode method based on SFDP data
- Allow post_sfdp hook to return errors
- Parse SCCR MC table and introduce support for multi-chip devices
SPI NOR manufacturer drivers changes:
- macronix: Add support for mx25uw51245g with RWW
- spansion:
- Determine current address mode at runtime as it can be changed
in a non-volatile way and differ from factory defaults or from
what SFDP advertises.
- Enable JFFS2 write buffer mode for few ECC'd NOR flashes:
S25FS256T, s25hx and s28hx
- Add support for s25hl02gt and s25hs02gt
Raw NAND core changes:
- Convert to platform remove callback returning void
- Fix spelling mistake waifunc() -> waitfunc()
Raw NAND controller driver changes:
- imx: Remove unused is_imx51_nfc and imx53_nfc functions
- omap2: Drop obsolete dependency on COMPILE_TEST
- orion: Use devm_platform_ioremap_resource()
- qcom:
- Use of_property_present() for testing DT property presence
- Use devm_platform_get_and_ioremap_resource()
- stm32_fmc2: Depends on ARCH_STM32 instead of MACH_STM32MP157
- tmio: Remove reference to config MTD_NAND_TMIO in the parsers
Raw NAND manufacturer driver changes:
- hynix: Fix up bit 0 of sdr_timing_mode
SPI-NAND changes:
- Add support for ESMT F50x1G41LB"
* tag 'mtd/for-6.4' of git://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux: (55 commits)
mtd: nand: Convert to platform remove callback returning void
mtd: onenand: omap2: Drop obsolete dependency on COMPILE_TEST
mtd: spi-nor: spansion: Add support for s25hl02gt and s25hs02gt
mtd: spi-nor: spansion: Add a new ->ready() hook for multi-chip device
mtd: spi-nor: spansion: Rework cypress_nor_quad_enable_volatile() for multi-chip device support
mtd: spi-nor: spansion: Rework cypress_nor_get_page_size() for multi-chip device support
mtd: spi-nor: sfdp: Add support for SCCR map for multi-chip device
mtd: spi-nor: Extract volatile register offset from SCCR map
mtd: spi-nor: Allow post_sfdp hook to return errors
mtd: spi-nor: spansion: Rename method to cypress_nor_get_page_size
mtd: spi-nor: spansion: Enable JFFS2 write buffer for S25FS256T
mtd: spi-nor: spansion: Enable JFFS2 write buffer for Infineon s25hx SEMPER flash
mtd: spi-nor: spansion: Enable JFFS2 write buffer for Infineon s28hx SEMPER flash
mtd: spi-nor: spansion: Determine current address mode
mtd: spi-nor: core: Introduce spi_nor_set_4byte_addr_mode()
mtd: spi-nor: core: Update flash's current address mode when changing address mode
mtd: spi-nor: Stop exporting spi_nor_restore()
mtd: spi-nor: Set the 4-Byte Address Mode method based on SFDP data
mtd: spi-nor: core: Make spi_nor_set_4byte_addr_mode_brwr public
mtd: spi-nor: core: Update name and description of spi_nor_set_4byte_addr_mode
...
Diffstat (limited to 'drivers/mtd/spi-nor/sfdp.c')
-rw-r--r-- | drivers/mtd/spi-nor/sfdp.c | 107 |
1 files changed, 102 insertions, 5 deletions
diff --git a/drivers/mtd/spi-nor/sfdp.c b/drivers/mtd/spi-nor/sfdp.c index 298ab5e53a8c..b3b11dfed789 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 @@ -438,6 +443,7 @@ static int spi_nor_parse_bfpt(struct spi_nor *nor, size_t len; int i, cmd, err; u32 addr, val; + u32 dword; u16 half; u8 erase_mask; @@ -607,6 +613,16 @@ static int spi_nor_parse_bfpt(struct spi_nor *nor, break; } + dword = bfpt.dwords[SFDP_DWORD(16)] & BFPT_DWORD16_4B_ADDR_MODE_MASK; + if (SFDP_MASK_CHECK(dword, BFPT_DWORD16_4B_ADDR_MODE_BRWR)) + params->set_4byte_addr_mode = spi_nor_set_4byte_addr_mode_brwr; + else if (SFDP_MASK_CHECK(dword, BFPT_DWORD16_4B_ADDR_MODE_WREN_EN4B_EX4B)) + params->set_4byte_addr_mode = spi_nor_set_4byte_addr_mode_wren_en4b_ex4b; + else if (SFDP_MASK_CHECK(dword, BFPT_DWORD16_4B_ADDR_MODE_EN4B_EX4B)) + params->set_4byte_addr_mode = spi_nor_set_4byte_addr_mode_en4b_ex4b; + else + dev_dbg(nor->dev, "BFPT: 4-Byte Address Mode method is not recognized or not implemented\n"); + /* Soft Reset support. */ if (bfpt.dwords[SFDP_DWORD(16)] & BFPT_DWORD16_SWRST_EN_RST) nor->flags |= SNOR_F_SOFT_RESET; @@ -1215,6 +1231,7 @@ out: static int spi_nor_parse_sccr(struct spi_nor *nor, const struct sfdp_parameter_header *sccr_header) { + struct spi_nor_flash_parameter *params = nor->params; u32 *dwords, addr; size_t len; int ret; @@ -1231,6 +1248,18 @@ static int spi_nor_parse_sccr(struct spi_nor *nor, le32_to_cpu_array(dwords, sccr_header->length); + /* Address offset for volatile registers (die 0) */ + if (!params->vreg_offset) { + params->vreg_offset = devm_kmalloc(nor->dev, sizeof(*dwords), + GFP_KERNEL); + if (!params->vreg_offset) { + ret = -ENOMEM; + goto out; + } + } + params->vreg_offset[0] = dwords[SFDP_DWORD(1)]; + params->n_dice = 1; + if (FIELD_GET(SCCR_DWORD22_OCTAL_DTR_EN_VOLATILE, dwords[SFDP_DWORD(22)])) nor->flags |= SNOR_F_IO_MODE_EN_VOLATILE; @@ -1241,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. @@ -1249,14 +1335,21 @@ out: * Used to tweak various flash parameters when information provided by the SFDP * tables are wrong. */ -static void spi_nor_post_sfdp_fixups(struct spi_nor *nor) +static int spi_nor_post_sfdp_fixups(struct spi_nor *nor) { + int ret; + if (nor->manufacturer && nor->manufacturer->fixups && - nor->manufacturer->fixups->post_sfdp) - nor->manufacturer->fixups->post_sfdp(nor); + nor->manufacturer->fixups->post_sfdp) { + ret = nor->manufacturer->fixups->post_sfdp(nor); + if (ret) + return ret; + } if (nor->info->fixups && nor->info->fixups->post_sfdp) - nor->info->fixups->post_sfdp(nor); + return nor->info->fixups->post_sfdp(nor); + + return 0; } /** @@ -1449,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; } @@ -1466,7 +1563,7 @@ int spi_nor_parse_sfdp(struct spi_nor *nor) } } - spi_nor_post_sfdp_fixups(nor); + err = spi_nor_post_sfdp_fixups(nor); exit: kfree(param_headers); return err; |