// SPDX-License-Identifier: GPL-2.0 /* * Copyright (C) 2005, Intec Automation Inc. * Copyright (C) 2014, Freescale Semiconductor, Inc. */ #include <linux/bitfield.h> #include <linux/mtd/spi-nor.h> #include <linux/slab.h> #include <linux/sort.h> #include "core.h" #define SFDP_PARAM_HEADER_ID(p) … #define SFDP_PARAM_HEADER_PTP(p) … #define SFDP_PARAM_HEADER_PARAM_LEN(p) … #define SFDP_BFPT_ID … #define SFDP_SECTOR_MAP_ID … #define SFDP_4BAIT_ID … #define SFDP_PROFILE1_ID … #define SFDP_SCCR_MAP_ID … #define SFDP_SCCR_MAP_MC_ID … #define SFDP_SIGNATURE … struct sfdp_header { … }; /* Fast Read settings. */ struct sfdp_bfpt_read { … }; struct sfdp_bfpt_erase { … }; #define SMPT_CMD_ADDRESS_LEN_MASK … #define SMPT_CMD_ADDRESS_LEN_0 … #define SMPT_CMD_ADDRESS_LEN_3 … #define SMPT_CMD_ADDRESS_LEN_4 … #define SMPT_CMD_ADDRESS_LEN_USE_CURRENT … #define SMPT_CMD_READ_DUMMY_MASK … #define SMPT_CMD_READ_DUMMY_SHIFT … #define SMPT_CMD_READ_DUMMY(_cmd) … #define SMPT_CMD_READ_DUMMY_IS_VARIABLE … #define SMPT_CMD_READ_DATA_MASK … #define SMPT_CMD_READ_DATA_SHIFT … #define SMPT_CMD_READ_DATA(_cmd) … #define SMPT_CMD_OPCODE_MASK … #define SMPT_CMD_OPCODE_SHIFT … #define SMPT_CMD_OPCODE(_cmd) … #define SMPT_MAP_REGION_COUNT_MASK … #define SMPT_MAP_REGION_COUNT_SHIFT … #define SMPT_MAP_REGION_COUNT(_header) … #define SMPT_MAP_ID_MASK … #define SMPT_MAP_ID_SHIFT … #define SMPT_MAP_ID(_header) … #define SMPT_MAP_REGION_SIZE_MASK … #define SMPT_MAP_REGION_SIZE_SHIFT … #define SMPT_MAP_REGION_SIZE(_region) … #define SMPT_MAP_REGION_ERASE_TYPE_MASK … #define SMPT_MAP_REGION_ERASE_TYPE(_region) … #define SMPT_DESC_TYPE_MAP … #define SMPT_DESC_END … #define SFDP_4BAIT_DWORD_MAX … struct sfdp_4bait { … }; /** * spi_nor_read_raw() - raw read of serial flash memory. read_opcode, * addr_nbytes and read_dummy members of the struct spi_nor * should be previously set. * @nor: pointer to a 'struct spi_nor' * @addr: offset in the serial flash memory * @len: number of bytes to read * @buf: buffer where the data is copied into (dma-safe memory) * * Return: 0 on success, -errno otherwise. */ static int spi_nor_read_raw(struct spi_nor *nor, u32 addr, size_t len, u8 *buf) { … } /** * spi_nor_read_sfdp() - read Serial Flash Discoverable Parameters. * @nor: pointer to a 'struct spi_nor' * @addr: offset in the SFDP area to start reading data from * @len: number of bytes to read * @buf: buffer where the SFDP data are copied into (dma-safe memory) * * Whatever the actual numbers of bytes for address and dummy cycles are * for (Fast) Read commands, the Read SFDP (5Ah) instruction is always * followed by a 3-byte address and 8 dummy clock cycles. * * Return: 0 on success, -errno otherwise. */ static int spi_nor_read_sfdp(struct spi_nor *nor, u32 addr, size_t len, void *buf) { … } /** * spi_nor_read_sfdp_dma_unsafe() - read Serial Flash Discoverable Parameters. * @nor: pointer to a 'struct spi_nor' * @addr: offset in the SFDP area to start reading data from * @len: number of bytes to read * @buf: buffer where the SFDP data are copied into * * Wrap spi_nor_read_sfdp() using a kmalloc'ed bounce buffer as @buf is now not * guaranteed to be dma-safe. * * Return: -ENOMEM if kmalloc() fails, the return code of spi_nor_read_sfdp() * otherwise. */ static int spi_nor_read_sfdp_dma_unsafe(struct spi_nor *nor, u32 addr, size_t len, void *buf) { … } static void spi_nor_set_read_settings_from_bfpt(struct spi_nor_read_command *read, u16 half, enum spi_nor_protocol proto) { … } static const struct sfdp_bfpt_read sfdp_bfpt_reads[] = …; static const struct sfdp_bfpt_erase sfdp_bfpt_erases[] = …; /** * spi_nor_set_erase_settings_from_bfpt() - set erase type settings from BFPT * @erase: pointer to a structure that describes a SPI NOR erase type * @size: the size of the sector/block erased by the erase type * @opcode: the SPI command op code to erase the sector/block * @i: erase type index as sorted in the Basic Flash Parameter Table * * The supported Erase Types will be sorted at init in ascending order, with * the smallest Erase Type size being the first member in the erase_type array * of the spi_nor_erase_map structure. Save the Erase Type index as sorted in * the Basic Flash Parameter Table since it will be used later on to * synchronize with the supported Erase Types defined in SFDP optional tables. */ static void spi_nor_set_erase_settings_from_bfpt(struct spi_nor_erase_type *erase, u32 size, u8 opcode, u8 i) { … } /** * spi_nor_map_cmp_erase_type() - compare the map's erase types by size * @l: member in the left half of the map's erase_type array * @r: member in the right half of the map's erase_type array * * Comparison function used in the sort() call to sort in ascending order the * map's erase types, the smallest erase type size being the first member in the * sorted erase_type array. * * Return: the result of @l->size - @r->size */ static int spi_nor_map_cmp_erase_type(const void *l, const void *r) { … } /** * spi_nor_sort_erase_mask() - sort erase mask * @map: the erase map of the SPI NOR * @erase_mask: the erase type mask to be sorted * * Replicate the sort done for the map's erase types in BFPT: sort the erase * mask in ascending order with the smallest erase type size starting from * BIT(0) in the sorted erase mask. * * Return: sorted erase mask. */ static u8 spi_nor_sort_erase_mask(struct spi_nor_erase_map *map, u8 erase_mask) { … } /** * spi_nor_regions_sort_erase_types() - sort erase types in each region * @map: the erase map of the SPI NOR * * Function assumes that the erase types defined in the erase map are already * sorted in ascending order, with the smallest erase type size being the first * member in the erase_type array. It replicates the sort done for the map's * erase types. Each region's erase bitmask will indicate which erase types are * supported from the sorted erase types defined in the erase map. * Sort the all region's erase type at init in order to speed up the process of * finding the best erase command at runtime. */ static void spi_nor_regions_sort_erase_types(struct spi_nor_erase_map *map) { … } /** * spi_nor_parse_bfpt() - read and parse the Basic Flash Parameter Table. * @nor: pointer to a 'struct spi_nor' * @bfpt_header: pointer to the 'struct sfdp_parameter_header' describing * the Basic Flash Parameter Table length and version * * The Basic Flash Parameter Table is the main and only mandatory table as * defined by the SFDP (JESD216) specification. * It provides us with the total size (memory density) of the data array and * the number of address bytes for Fast Read, Page Program and Sector Erase * commands. * For Fast READ commands, it also gives the number of mode clock cycles and * wait states (regrouped in the number of dummy clock cycles) for each * supported instruction op code. * For Page Program, the page size is now available since JESD216 rev A, however * the supported instruction op codes are still not provided. * For Sector Erase commands, this table stores the supported instruction op * codes and the associated sector sizes. * Finally, the Quad Enable Requirements (QER) are also available since JESD216 * rev A. The QER bits encode the manufacturer dependent procedure to be * executed to set the Quad Enable (QE) bit in some internal register of the * Quad SPI memory. Indeed the QE bit, when it exists, must be set before * sending any Quad SPI command to the memory. Actually, setting the QE bit * tells the memory to reassign its WP# and HOLD#/RESET# pins to functions IO2 * and IO3 hence enabling 4 (Quad) I/O lines. * * Return: 0 on success, -errno otherwise. */ static int spi_nor_parse_bfpt(struct spi_nor *nor, const struct sfdp_parameter_header *bfpt_header) { … } /** * spi_nor_smpt_addr_nbytes() - return the number of address bytes used in the * configuration detection command. * @nor: pointer to a 'struct spi_nor' * @settings: configuration detection command descriptor, dword1 */ static u8 spi_nor_smpt_addr_nbytes(const struct spi_nor *nor, const u32 settings) { … } /** * spi_nor_smpt_read_dummy() - return the configuration detection command read * latency, in clock cycles. * @nor: pointer to a 'struct spi_nor' * @settings: configuration detection command descriptor, dword1 * * Return: the number of dummy cycles for an SMPT read */ static u8 spi_nor_smpt_read_dummy(const struct spi_nor *nor, const u32 settings) { … } /** * spi_nor_get_map_in_use() - get the configuration map in use * @nor: pointer to a 'struct spi_nor' * @smpt: pointer to the sector map parameter table * @smpt_len: sector map parameter table length * * Return: pointer to the map in use, ERR_PTR(-errno) otherwise. */ static const u32 *spi_nor_get_map_in_use(struct spi_nor *nor, const u32 *smpt, u8 smpt_len) { … } /** * spi_nor_region_check_overlay() - set overlay bit when the region is overlaid * @region: pointer to a structure that describes a SPI NOR erase region * @erase: pointer to a structure that describes a SPI NOR erase type * @erase_type: erase type bitmask */ static void spi_nor_region_check_overlay(struct spi_nor_erase_region *region, const struct spi_nor_erase_type *erase, const u8 erase_type) { … } /** * spi_nor_init_non_uniform_erase_map() - initialize the non-uniform erase map * @nor: pointer to a 'struct spi_nor' * @smpt: pointer to the sector map parameter table * * Return: 0 on success, -errno otherwise. */ static int spi_nor_init_non_uniform_erase_map(struct spi_nor *nor, const u32 *smpt) { … } /** * spi_nor_parse_smpt() - parse Sector Map Parameter Table * @nor: pointer to a 'struct spi_nor' * @smpt_header: sector map parameter table header * * This table is optional, but when available, we parse it to identify the * location and size of sectors within the main data array of the flash memory * device and to identify which Erase Types are supported by each sector. * * Return: 0 on success, -errno otherwise. */ static int spi_nor_parse_smpt(struct spi_nor *nor, const struct sfdp_parameter_header *smpt_header) { … } /** * spi_nor_parse_4bait() - parse the 4-Byte Address Instruction 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. * * Return: 0 on success, -errno otherwise. */ static int spi_nor_parse_4bait(struct spi_nor *nor, const struct sfdp_parameter_header *param_header) { … } #define PROFILE1_DWORD1_RDSR_ADDR_BYTES … #define PROFILE1_DWORD1_RDSR_DUMMY … #define PROFILE1_DWORD1_RD_FAST_CMD … #define PROFILE1_DWORD4_DUMMY_200MHZ … #define PROFILE1_DWORD5_DUMMY_166MHZ … #define PROFILE1_DWORD5_DUMMY_133MHZ … #define PROFILE1_DWORD5_DUMMY_100MHZ … /** * 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 Profile 1.0 Table length and version. * * Return: 0 on success, -errno otherwise. */ static int spi_nor_parse_profile1(struct spi_nor *nor, const struct sfdp_parameter_header *profile1_header) { … } #define SCCR_DWORD22_OCTAL_DTR_EN_VOLATILE … /** * 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) { … } /** * 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) { … } /** * 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. * @nor: pointer to a 'struct spi_nor' * * Used to tweak various flash parameters when information provided by the SFDP * tables are wrong. */ static int spi_nor_post_sfdp_fixups(struct spi_nor *nor) { … } /** * spi_nor_check_sfdp_signature() - check for a valid SFDP signature * @nor: pointer to a 'struct spi_nor' * * Used to detect if the flash supports the RDSFDP command as well as the * presence of a valid SFDP table. * * Return: 0 on success, -errno otherwise. */ int spi_nor_check_sfdp_signature(struct spi_nor *nor) { … } /** * spi_nor_parse_sfdp() - parse the Serial Flash Discoverable Parameters. * @nor: pointer to a 'struct spi_nor' * * The Serial Flash Discoverable Parameters are described by the JEDEC JESD216 * specification. This is a standard which tends to supported by almost all * (Q)SPI memory manufacturers. Those hard-coded tables allow us to learn at * runtime the main parameters needed to perform basic SPI flash operations such * as Fast Read, Page Program or Sector Erase commands. * * Return: 0 on success, -errno otherwise. */ int spi_nor_parse_sfdp(struct spi_nor *nor) { … }