diff options
Diffstat (limited to 'drivers/mtd/spi-nor/core.h')
| -rw-r--r-- | drivers/mtd/spi-nor/core.h | 242 |
1 files changed, 119 insertions, 123 deletions
diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h index f03b55cf7e6f..16b382d4f04f 100644 --- a/drivers/mtd/spi-nor/core.h +++ b/drivers/mtd/spi-nor/core.h @@ -10,6 +10,13 @@ #include "sfdp.h" #define SPI_NOR_MAX_ID_LEN 6 +/* + * 256 bytes is a sane default for most older flashes. Newer flashes will + * have the page size defined within their SFDP tables. + */ +#define SPI_NOR_DEFAULT_PAGE_SIZE 256 +#define SPI_NOR_DEFAULT_N_BANKS 1 +#define SPI_NOR_DEFAULT_SECTOR_SIZE SZ_64K /* Standard SPI NOR flash operations. */ #define SPI_NOR_READID_OP(naddr, ndummy, buf, len) \ @@ -78,9 +85,9 @@ SPI_MEM_OP_NO_DUMMY, \ SPI_MEM_OP_NO_DATA) -#define SPI_NOR_CHIP_ERASE_OP \ - SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_CHIP_ERASE, 0), \ - SPI_MEM_OP_NO_ADDR, \ +#define SPI_NOR_DIE_ERASE_OP(opcode, addr_nbytes, addr, dice) \ + SPI_MEM_OP(SPI_MEM_OP_CMD(opcode, 0), \ + SPI_MEM_OP_ADDR(dice ? addr_nbytes : 0, addr, 0), \ SPI_MEM_OP_NO_DUMMY, \ SPI_MEM_OP_NO_DATA) @@ -130,6 +137,10 @@ enum spi_nor_option_flags { SNOR_F_IO_MODE_EN_VOLATILE = BIT(11), SNOR_F_SOFT_RESET = BIT(12), SNOR_F_SWP_IS_VOLATILE = BIT(13), + SNOR_F_RWW = BIT(14), + SNOR_F_ECC = BIT(15), + SNOR_F_NO_WP = BIT(16), + SNOR_F_SWAP16 = BIT(17), }; struct spi_nor_read_command { @@ -230,27 +241,21 @@ struct spi_nor_erase_command { /** * struct spi_nor_erase_region - Structure to describe a SPI NOR erase region * @offset: the offset in the data array of erase region start. - * LSB bits are used as a bitmask encoding flags to - * determine if this region is overlaid, if this region is - * the last in the SPI NOR flash memory and to indicate - * all the supported erase commands inside this region. - * The erase types are sorted in ascending order with the - * smallest Erase Type size being at BIT(0). * @size: the size of the region in bytes. + * @erase_mask: bitmask to indicate all the supported erase commands + * inside this region. The erase types are sorted in + * ascending order with the smallest Erase Type size being + * at BIT(0). + * @overlaid: determine if this region is overlaid. */ struct spi_nor_erase_region { u64 offset; u64 size; + u8 erase_mask; + bool overlaid; }; #define SNOR_ERASE_TYPE_MAX 4 -#define SNOR_ERASE_TYPE_MASK GENMASK_ULL(SNOR_ERASE_TYPE_MAX - 1, 0) - -#define SNOR_LAST_REGION BIT(4) -#define SNOR_OVERLAID_REGION BIT(5) - -#define SNOR_ERASE_FLAGS_MAX 6 -#define SNOR_ERASE_FLAGS_MASK GENMASK_ULL(SNOR_ERASE_FLAGS_MAX - 1, 0) /** * struct spi_nor_erase_map - Structure to describe the SPI NOR erase map @@ -263,17 +268,13 @@ struct spi_nor_erase_region { * The erase types are sorted in ascending order, with the * smallest Erase Type size being the first member in the * erase_type array. - * @uniform_erase_type: bitmask encoding erase types that can erase the - * entire memory. This member is completed at init by - * uniform and non-uniform SPI NOR flash memories if they - * support at least one erase type that can erase the - * entire memory. + * @n_regions: number of erase regions. */ struct spi_nor_erase_map { struct spi_nor_erase_region *regions; struct spi_nor_erase_region uniform_region; struct spi_nor_erase_type erase_type[SNOR_ERASE_TYPE_MAX]; - u8 uniform_erase_type; + unsigned int n_regions; }; /** @@ -283,9 +284,9 @@ struct spi_nor_erase_map { * @is_locked: check if a region of the SPI NOR is completely locked */ struct spi_nor_locking_ops { - int (*lock)(struct spi_nor *nor, loff_t ofs, uint64_t len); - int (*unlock)(struct spi_nor *nor, loff_t ofs, uint64_t len); - int (*is_locked)(struct spi_nor *nor, loff_t ofs, uint64_t len); + int (*lock)(struct spi_nor *nor, loff_t ofs, u64 len); + int (*unlock)(struct spi_nor *nor, loff_t ofs, u64 len); + int (*is_locked)(struct spi_nor *nor, loff_t ofs, u64 len); }; /** @@ -336,7 +337,8 @@ struct spi_nor_otp { * by the spi_nor_fixups hooks, or dynamically when parsing the JESD216 * Serial Flash Discoverable Parameters (SFDP) tables. * - * @size: the flash memory density in bytes. + * @bank_size: the flash memory bank density in bytes. + * @size: the total flash memory density in bytes. * @writesize Minimal writable flash unit size. Defaults to 1. Set to * ECC unit size for ECC-ed flashes. * @page_size: the page size of the SPI NOR flash memory. @@ -349,6 +351,10 @@ struct spi_nor_otp { * in octal DTR mode. * @rdsr_addr_nbytes: dummy address bytes needed for Read Status Register * command in octal DTR mode. + * @n_banks: number of banks. + * @n_dice: number of dice in the flash memory. + * @die_erase_opcode: die erase opcode. Defaults to SPINOR_OP_CHIP_ERASE. + * @vreg_offset: volatile register offset for each die. * @hwcaps: describes the read and page program hardware * capabilities. * @reads: read capabilities ordered by priority: the higher index @@ -358,22 +364,17 @@ struct spi_nor_otp { * @erase_map: the erase map parsed from the SFDP Sector Map Parameter * Table. * @otp: SPI NOR OTP info. - * @octal_dtr_enable: enables SPI NOR octal DTR mode. + * @set_octal_dtr: enables or disables SPI NOR octal DTR mode. * @quad_enable: enables SPI NOR quad mode. * @set_4byte_addr_mode: puts the SPI NOR in 4 byte addressing mode. - * @convert_addr: converts an absolute address into something the flash - * will understand. Particularly useful when pagesize is - * not a power-of-2. - * @setup: (optional) configures the SPI NOR memory. Useful for - * SPI NOR flashes that have peculiarities to the SPI NOR - * standard e.g. different opcodes, specific address - * calculation, page size, etc. * @ready: (optional) flashes might use a different mechanism * than reading the status register to indicate they * are ready for a new command * @locking_ops: SPI NOR locking methods. + * @priv: flash's private data. */ struct spi_nor_flash_parameter { + u64 bank_size; u64 size; u32 writesize; u32 page_size; @@ -381,6 +382,10 @@ struct spi_nor_flash_parameter { u8 addr_mode_nbytes; u8 rdsr_dummy; u8 rdsr_addr_nbytes; + u8 n_banks; + u8 n_dice; + u8 die_erase_opcode; + u32 *vreg_offset; struct spi_nor_hwcaps hwcaps; struct spi_nor_read_command reads[SNOR_CMD_READ_MAX]; @@ -389,14 +394,13 @@ struct spi_nor_flash_parameter { struct spi_nor_erase_map erase_map; struct spi_nor_otp otp; - int (*octal_dtr_enable)(struct spi_nor *nor, bool enable); + int (*set_octal_dtr)(struct spi_nor *nor, bool enable); int (*quad_enable)(struct spi_nor *nor); int (*set_4byte_addr_mode)(struct spi_nor *nor, bool enable); - u32 (*convert_addr)(struct spi_nor *nor, u32 addr); - int (*setup)(struct spi_nor *nor, const struct spi_nor_hwcaps *hwcaps); int (*ready)(struct spi_nor *nor); const struct spi_nor_locking_ops *locking_ops; + void *priv; }; /** @@ -405,6 +409,10 @@ struct spi_nor_flash_parameter { * flash parameters when information provided by the flash_info * table is incomplete or wrong. * @post_bfpt: called after the BFPT table has been parsed + * @smpt_read_dummy: called during SMPT table is being parsed. Used to fix the + * number of dummy cycles in read register ops. + * @smpt_map_id: called after map ID in SMPT table has been determined for the + * case the map ID is wrong and needs to be fixed. * @post_sfdp: called after SFDP has been parsed (is also called for SPI NORs * that do not support RDSFDP). Typically used to tweak various * parameters that could not be extracted by other means (i.e. @@ -422,25 +430,42 @@ struct spi_nor_fixups { int (*post_bfpt)(struct spi_nor *nor, const struct sfdp_parameter_header *bfpt_header, const struct sfdp_bfpt *bfpt); - void (*post_sfdp)(struct spi_nor *nor); - void (*late_init)(struct spi_nor *nor); + void (*smpt_read_dummy)(const struct spi_nor *nor, u8 *read_dummy); + void (*smpt_map_id)(const struct spi_nor *nor, u8 *map_id); + int (*post_sfdp)(struct spi_nor *nor); + int (*late_init)(struct spi_nor *nor); +}; + +/** + * struct spi_nor_id - SPI NOR flash ID. + * + * @bytes: the bytes returned by the flash when issuing command 9F. Typically, + * the first byte is the manufacturer ID code (see JEP106) and the next + * two bytes are a flash part specific ID. + * @len: the number of bytes of ID. + */ +struct spi_nor_id { + const u8 *bytes; + u8 len; }; /** * struct flash_info - SPI NOR flash_info entry. - * @name: the name of the flash. - * @id: the flash's ID bytes. The first three bytes are the - * JEDIC ID. JEDEC ID zero means "no ID" (mostly older chips). - * @id_len: the number of bytes of ID. - * @sector_size: the size listed here is what works with SPINOR_OP_SE, which - * isn't necessarily called a "sector" by the vendor. - * @n_sectors: the number of sectors. - * @page_size: the flash's page size. + * @id: pointer to struct spi_nor_id or NULL, which means "no ID" (mostly + * older chips). + * @name: (obsolete) the name of the flash. Do not set it for new additions. + * @size: the size of the flash in bytes. The flash size is one + * property parsed by the SFDP. We use it as an indicator + * whether we need SFDP parsing for a particular flash. + * I.e. non-legacy flash entries in flash_info will have + * a size of zero iff SFDP should be used. + * @sector_size: (optional) the size listed here is what works with + * SPINOR_OP_SE, which isn't necessarily called a "sector" by + * the vendor. Defaults to 64k. + * @n_banks: (optional) the number of banks. Defaults to 1. + * @page_size: (optional) the flash's page size. Defaults to 256. * @addr_nbytes: number of address bytes to send. * - * @parse_sfdp: true when flash supports SFDP tables. The false value has no - * meaning. If one wants to skip the SFDP tables, one should - * instead use the SPI_NOR_SKIP_SFDP sfdp_flag. * @flags: flags that indicate support that is not defined by the * JESD216 standard in its SFDP tables. Flag meanings: * SPI_NOR_HAS_LOCK: flash supports lock/unlock via SR @@ -456,9 +481,8 @@ struct spi_nor_fixups { * Usually these will power-up in a write-protected * state. * SPI_NOR_NO_ERASE: no erase command needed. - * NO_CHIP_ERASE: chip does not support chip erase. - * SPI_NOR_NO_FR: can't do fastread. * SPI_NOR_QUAD_PP: flash supports Quad Input Page Program. + * SPI_NOR_RWW: flash supports reads while write. * * @no_sfdp_flags: flags that indicate support that can be discovered via SFDP. * Used when SFDP tables are not defined in the flash. These @@ -490,14 +514,13 @@ struct spi_nor_fixups { */ struct flash_info { char *name; - u8 id[SPI_NOR_MAX_ID_LEN]; - u8 id_len; + const struct spi_nor_id *id; + size_t size; unsigned sector_size; - u16 n_sectors; u16 page_size; + u8 n_banks; u8 addr_nbytes; - bool parse_sfdp; u16 flags; #define SPI_NOR_HAS_LOCK BIT(0) #define SPI_NOR_HAS_TB BIT(1) @@ -506,9 +529,8 @@ struct flash_info { #define SPI_NOR_BP3_SR_BIT6 BIT(4) #define SPI_NOR_SWP_IS_VOLATILE BIT(5) #define SPI_NOR_NO_ERASE BIT(6) -#define NO_CHIP_ERASE BIT(7) -#define SPI_NOR_NO_FR BIT(8) -#define SPI_NOR_QUAD_PP BIT(9) +#define SPI_NOR_QUAD_PP BIT(8) +#define SPI_NOR_RWW BIT(9) u8 no_sfdp_flags; #define SPI_NOR_SKIP_SFDP BIT(0) @@ -525,67 +547,23 @@ struct flash_info { u8 mfr_flags; - const struct spi_nor_otp_organization otp_org; + const struct spi_nor_otp_organization *otp; const struct spi_nor_fixups *fixups; }; -/* Used when the "_ext_id" is two bytes at most */ -#define INFO(_jedec_id, _ext_id, _sector_size, _n_sectors) \ - .id = { \ - ((_jedec_id) >> 16) & 0xff, \ - ((_jedec_id) >> 8) & 0xff, \ - (_jedec_id) & 0xff, \ - ((_ext_id) >> 8) & 0xff, \ - (_ext_id) & 0xff, \ - }, \ - .id_len = (!(_jedec_id) ? 0 : (3 + ((_ext_id) ? 2 : 0))), \ - .sector_size = (_sector_size), \ - .n_sectors = (_n_sectors), \ - .page_size = 256, \ - -#define INFO6(_jedec_id, _ext_id, _sector_size, _n_sectors) \ - .id = { \ - ((_jedec_id) >> 16) & 0xff, \ - ((_jedec_id) >> 8) & 0xff, \ - (_jedec_id) & 0xff, \ - ((_ext_id) >> 16) & 0xff, \ - ((_ext_id) >> 8) & 0xff, \ - (_ext_id) & 0xff, \ - }, \ - .id_len = 6, \ - .sector_size = (_sector_size), \ - .n_sectors = (_n_sectors), \ - .page_size = 256, \ - -#define CAT25_INFO(_sector_size, _n_sectors, _page_size, _addr_nbytes) \ - .sector_size = (_sector_size), \ - .n_sectors = (_n_sectors), \ - .page_size = (_page_size), \ - .addr_nbytes = (_addr_nbytes), \ - .flags = SPI_NOR_NO_ERASE | SPI_NOR_NO_FR, \ - -#define OTP_INFO(_len, _n_regions, _base, _offset) \ - .otp_org = { \ - .len = (_len), \ - .base = (_base), \ - .offset = (_offset), \ - .n_regions = (_n_regions), \ - }, - -#define PARSE_SFDP \ - .parse_sfdp = true, \ - -#define FLAGS(_flags) \ - .flags = (_flags), \ - -#define NO_SFDP_FLAGS(_no_sfdp_flags) \ - .no_sfdp_flags = (_no_sfdp_flags), \ - -#define FIXUP_FLAGS(_fixup_flags) \ - .fixup_flags = (_fixup_flags), \ - -#define MFR_FLAGS(_mfr_flags) \ - .mfr_flags = (_mfr_flags), \ +#define SNOR_ID(...) \ + (&(const struct spi_nor_id){ \ + .bytes = (const u8[]){ __VA_ARGS__ }, \ + .len = sizeof((u8[]){ __VA_ARGS__ }), \ + }) + +#define SNOR_OTP(_len, _n_regions, _base, _offset) \ + (&(const struct spi_nor_otp_organization){ \ + .len = (_len), \ + .base = (_base), \ + .offset = (_offset), \ + .n_regions = (_n_regions), \ + }) /** * struct spi_nor_manufacturer - SPI NOR manufacturer object @@ -613,11 +591,9 @@ struct sfdp { /* Manufacturer drivers. */ extern const struct spi_nor_manufacturer spi_nor_atmel; -extern const struct spi_nor_manufacturer spi_nor_catalyst; extern const struct spi_nor_manufacturer spi_nor_eon; extern const struct spi_nor_manufacturer spi_nor_esmt; extern const struct spi_nor_manufacturer spi_nor_everspin; -extern const struct spi_nor_manufacturer spi_nor_fujitsu; extern const struct spi_nor_manufacturer spi_nor_gigadevice; extern const struct spi_nor_manufacturer spi_nor_intel; extern const struct spi_nor_manufacturer spi_nor_issi; @@ -627,7 +603,6 @@ extern const struct spi_nor_manufacturer spi_nor_st; extern const struct spi_nor_manufacturer spi_nor_spansion; extern const struct spi_nor_manufacturer spi_nor_sst; extern const struct spi_nor_manufacturer spi_nor_winbond; -extern const struct spi_nor_manufacturer spi_nor_xilinx; extern const struct spi_nor_manufacturer spi_nor_xmc; extern const struct attribute_group *spi_nor_sysfs_groups[]; @@ -637,10 +612,14 @@ void spi_nor_spimem_setup_op(const struct spi_nor *nor, const enum spi_nor_protocol proto); int spi_nor_write_enable(struct spi_nor *nor); int spi_nor_write_disable(struct spi_nor *nor); +int spi_nor_set_4byte_addr_mode_en4b_ex4b(struct spi_nor *nor, bool enable); +int spi_nor_set_4byte_addr_mode_wren_en4b_ex4b(struct spi_nor *nor, + bool enable); +int spi_nor_set_4byte_addr_mode_brwr(struct spi_nor *nor, bool enable); int spi_nor_set_4byte_addr_mode(struct spi_nor *nor, bool enable); int spi_nor_wait_till_ready(struct spi_nor *nor); int spi_nor_global_block_unlock(struct spi_nor *nor); -int spi_nor_lock_and_prep(struct spi_nor *nor); +int spi_nor_prep_and_lock(struct spi_nor *nor); void spi_nor_unlock_and_unprep(struct spi_nor *nor); int spi_nor_sr1_bit6_quad_enable(struct spi_nor *nor); int spi_nor_sr2_bit1_quad_enable(struct spi_nor *nor); @@ -684,8 +663,7 @@ void spi_nor_set_pp_settings(struct spi_nor_pp_command *pp, u8 opcode, void spi_nor_set_erase_type(struct spi_nor_erase_type *erase, u32 size, u8 opcode); -struct spi_nor_erase_region * -spi_nor_region_next(struct spi_nor_erase_region *region); +void spi_nor_mask_erase_type(struct spi_nor_erase_type *erase); void spi_nor_init_uniform_erase_map(struct spi_nor_erase_map *map, u8 erase_mask, u64 flash_size); @@ -711,10 +689,28 @@ static inline struct spi_nor *mtd_to_spi_nor(struct mtd_info *mtd) return container_of(mtd, struct spi_nor, mtd); } +/** + * spi_nor_needs_sfdp() - returns true if SFDP parsing is used for this flash. + * + * Return: true if SFDP parsing is needed + */ +static inline bool spi_nor_needs_sfdp(const struct spi_nor *nor) +{ + /* + * The flash size is one property parsed by the SFDP. We use it as an + * indicator whether we need SFDP parsing for a particular flash. I.e. + * non-legacy flash entries in flash_info will have a size of zero iff + * SFDP should be used. + */ + return !nor->info->size; +} + #ifdef CONFIG_DEBUG_FS void spi_nor_debugfs_register(struct spi_nor *nor); +void spi_nor_debugfs_shutdown(void); #else static inline void spi_nor_debugfs_register(struct spi_nor *nor) {} +static inline void spi_nor_debugfs_shutdown(void) {} #endif #endif /* __LINUX_MTD_SPI_NOR_INTERNAL_H */ |
