mtd: spi-nor: Expose stuctures and functions to manufacturer drivers

Expose the flash_info struct and some function prototypes that
will be used by manufacturers.

Signed-off-by: Boris Brezillon <bbrezillon@kernel.org>
Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
Reviewed-by: Vignesh Raghavendra <vigneshr@ti.com>
This commit is contained in:
Boris Brezillon 2020-03-13 19:42:38 +00:00 committed by Tudor Ambarus
parent cb481b92d1
commit 4f50e102e2
No known key found for this signature in database
GPG Key ID: 4B554F47A58D14E9
2 changed files with 169 additions and 158 deletions

View File

@ -38,101 +38,9 @@
*/
#define CHIP_ERASE_2MB_READY_WAIT_JIFFIES (40UL * HZ)
#define SPI_NOR_MAX_ID_LEN 6
#define SPI_NOR_MAX_ADDR_WIDTH 4
/**
* struct spi_nor_fixups - SPI NOR fixup hooks
* @default_init: called after default flash parameters init. Used to tweak
* flash parameters when information provided by the flash_info
* table is incomplete or wrong.
* @post_bfpt: called after the BFPT table has been parsed
* @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.
* when information provided by the SFDP/flash_info tables are
* incomplete or wrong).
*
* Those hooks can be used to tweak the SPI NOR configuration when the SFDP
* table is broken or not available.
*/
struct spi_nor_fixups {
void (*default_init)(struct spi_nor *nor);
int (*post_bfpt)(struct spi_nor *nor,
const struct sfdp_parameter_header *bfpt_header,
const struct sfdp_bfpt *bfpt,
struct spi_nor_flash_parameter *params);
void (*post_sfdp)(struct spi_nor *nor);
};
struct flash_info {
char *name;
/*
* This array stores the ID bytes.
* The first three bytes are the JEDIC ID.
* JEDEC ID zero means "no ID" (mostly older chips).
*/
u8 id[SPI_NOR_MAX_ID_LEN];
u8 id_len;
/* The size listed here is what works with SPINOR_OP_SE, which isn't
* necessarily called a "sector" by the vendor.
*/
unsigned sector_size;
u16 n_sectors;
u16 page_size;
u16 addr_width;
u32 flags;
#define SECT_4K BIT(0) /* SPINOR_OP_BE_4K works uniformly */
#define SPI_NOR_NO_ERASE BIT(1) /* No erase command needed */
#define SST_WRITE BIT(2) /* use SST byte programming */
#define SPI_NOR_NO_FR BIT(3) /* Can't do fastread */
#define SECT_4K_PMC BIT(4) /* SPINOR_OP_BE_4K_PMC works uniformly */
#define SPI_NOR_DUAL_READ BIT(5) /* Flash supports Dual Read */
#define SPI_NOR_QUAD_READ BIT(6) /* Flash supports Quad Read */
#define USE_FSR BIT(7) /* use flag status register */
#define SPI_NOR_HAS_LOCK BIT(8) /* Flash supports lock/unlock via SR */
#define SPI_NOR_HAS_TB BIT(9) /*
* Flash SR has Top/Bottom (TB) protect
* bit. Must be used with
* SPI_NOR_HAS_LOCK.
*/
#define SPI_NOR_XSR_RDY BIT(10) /*
* S3AN flashes have specific opcode to
* read the status register.
* Flags SPI_NOR_XSR_RDY and SPI_S3AN
* use the same bit as one implies the
* other, but we will get rid of
* SPI_S3AN soon.
*/
#define SPI_S3AN BIT(10) /*
* Xilinx Spartan 3AN In-System Flash
* (MFR cannot be used for probing
* because it has the same value as
* ATMEL flashes)
*/
#define SPI_NOR_4B_OPCODES BIT(11) /*
* Use dedicated 4byte address op codes
* to support memory size above 128Mib.
*/
#define NO_CHIP_ERASE BIT(12) /* Chip does not support chip erase */
#define SPI_NOR_SKIP_SFDP BIT(13) /* Skip parsing of SFDP tables */
#define USE_CLSR BIT(14) /* use CLSR command */
#define SPI_NOR_OCTAL_READ BIT(15) /* Flash supports Octal Read */
#define SPI_NOR_TB_SR_BIT6 BIT(16) /*
* Top/Bottom (TB) is bit 6 of
* status register. Must be used with
* SPI_NOR_HAS_TB.
*/
/* Part specific fixup hooks. */
const struct spi_nor_fixups *fixups;
};
#define JEDEC_MFR(info) ((info)->id[0])
#define JEDEC_MFR(info) ((info)->id[0])
/**
* spi_nor_spimem_bounce() - check if a bounce buffer is needed for the data
@ -295,8 +203,8 @@ static ssize_t spi_nor_spimem_write_data(struct spi_nor *nor, loff_t to,
*
* Return: number of bytes written successfully, -errno otherwise
*/
static ssize_t spi_nor_write_data(struct spi_nor *nor, loff_t to, size_t len,
const u8 *buf)
ssize_t spi_nor_write_data(struct spi_nor *nor, loff_t to, size_t len,
const u8 *buf)
{
if (nor->spimem)
return spi_nor_spimem_write_data(nor, to, len, buf);
@ -310,7 +218,7 @@ static ssize_t spi_nor_write_data(struct spi_nor *nor, loff_t to, size_t len,
*
* Return: 0 on success, -errno otherwise.
*/
static int spi_nor_write_enable(struct spi_nor *nor)
int spi_nor_write_enable(struct spi_nor *nor)
{
int ret;
@ -339,7 +247,7 @@ static int spi_nor_write_enable(struct spi_nor *nor)
*
* Return: 0 on success, -errno otherwise.
*/
static int spi_nor_write_disable(struct spi_nor *nor)
int spi_nor_write_disable(struct spi_nor *nor)
{
int ret;
@ -463,7 +371,7 @@ static int spi_nor_read_cr(struct spi_nor *nor, u8 *cr)
*
* Return: 0 on success, -errno otherwise.
*/
static int spi_nor_set_4byte_addr_mode(struct spi_nor *nor, bool enable)
int spi_nor_set_4byte_addr_mode(struct spi_nor *nor, bool enable)
{
int ret;
@ -556,7 +464,7 @@ static int spansion_set_4byte_addr_mode(struct spi_nor *nor, bool enable)
*
* Return: 0 on success, -errno otherwise.
*/
static int spi_nor_write_ear(struct spi_nor *nor, u8 ear)
int spi_nor_write_ear(struct spi_nor *nor, u8 ear)
{
int ret;
@ -621,7 +529,7 @@ static int winbond_set_4byte_addr_mode(struct spi_nor *nor, bool enable)
*
* Return: 0 on success, -errno otherwise.
*/
static int spi_nor_xread_sr(struct spi_nor *nor, u8 *sr)
int spi_nor_xread_sr(struct spi_nor *nor, u8 *sr)
{
int ret;
@ -834,7 +742,7 @@ static int spi_nor_wait_till_ready_with_timeout(struct spi_nor *nor,
*
* Return: 0 on success, -errno otherwise.
*/
static int spi_nor_wait_till_ready(struct spi_nor *nor)
int spi_nor_wait_till_ready(struct spi_nor *nor)
{
return spi_nor_wait_till_ready_with_timeout(nor,
DEFAULT_READY_WAIT_JIFFIES);
@ -1142,11 +1050,6 @@ static int spi_nor_erase_chip(struct spi_nor *nor)
return ret;
}
static struct spi_nor *mtd_to_spi_nor(struct mtd_info *mtd)
{
return mtd->priv;
}
static u8 spi_nor_convert_opcode(u8 opcode, const u8 table[][2], size_t size)
{
size_t i;
@ -1225,7 +1128,7 @@ static void spi_nor_set_4byte_opcodes(struct spi_nor *nor)
}
}
static int spi_nor_lock_and_prep(struct spi_nor *nor)
int spi_nor_lock_and_prep(struct spi_nor *nor)
{
int ret = 0;
@ -1241,7 +1144,7 @@ static int spi_nor_lock_and_prep(struct spi_nor *nor)
return ret;
}
static void spi_nor_unlock_and_unprep(struct spi_nor *nor)
void spi_nor_unlock_and_unprep(struct spi_nor *nor)
{
if (nor->controller_ops && nor->controller_ops->unprepare)
nor->controller_ops->unprepare(nor);
@ -2104,56 +2007,6 @@ int spi_nor_sr2_bit7_quad_enable(struct spi_nor *nor)
return 0;
}
/* Used when the "_ext_id" is two bytes at most */
#define INFO(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \
.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, \
.flags = (_flags),
#define INFO6(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \
.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, \
.flags = (_flags),
#define CAT25_INFO(_sector_size, _n_sectors, _page_size, _addr_width, _flags) \
.sector_size = (_sector_size), \
.n_sectors = (_n_sectors), \
.page_size = (_page_size), \
.addr_width = (_addr_width), \
.flags = (_flags),
#define S3AN_INFO(_jedec_id, _n_sectors, _page_size) \
.id = { \
((_jedec_id) >> 16) & 0xff, \
((_jedec_id) >> 8) & 0xff, \
(_jedec_id) & 0xff \
}, \
.id_len = 3, \
.sector_size = (8*_page_size), \
.n_sectors = (_n_sectors), \
.page_size = _page_size, \
.addr_width = 3, \
.flags = SPI_NOR_NO_FR | SPI_S3AN,
static int
is25lp256_post_bfpt_fixups(struct spi_nor *nor,
const struct sfdp_parameter_header *bfpt_header,

View File

@ -9,12 +9,165 @@
#include "sfdp.h"
#define SPI_NOR_MAX_ID_LEN 6
/**
* struct spi_nor_fixups - SPI NOR fixup hooks
* @default_init: called after default flash parameters init. Used to tweak
* flash parameters when information provided by the flash_info
* table is incomplete or wrong.
* @post_bfpt: called after the BFPT table has been parsed
* @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.
* when information provided by the SFDP/flash_info tables are
* incomplete or wrong).
*
* Those hooks can be used to tweak the SPI NOR configuration when the SFDP
* table is broken or not available.
*/
struct spi_nor_fixups {
void (*default_init)(struct spi_nor *nor);
int (*post_bfpt)(struct spi_nor *nor,
const struct sfdp_parameter_header *bfpt_header,
const struct sfdp_bfpt *bfpt,
struct spi_nor_flash_parameter *params);
void (*post_sfdp)(struct spi_nor *nor);
};
struct flash_info {
char *name;
/*
* This array stores the ID bytes.
* The first three bytes are the JEDIC ID.
* JEDEC ID zero means "no ID" (mostly older chips).
*/
u8 id[SPI_NOR_MAX_ID_LEN];
u8 id_len;
/* The size listed here is what works with SPINOR_OP_SE, which isn't
* necessarily called a "sector" by the vendor.
*/
unsigned sector_size;
u16 n_sectors;
u16 page_size;
u16 addr_width;
u32 flags;
#define SECT_4K BIT(0) /* SPINOR_OP_BE_4K works uniformly */
#define SPI_NOR_NO_ERASE BIT(1) /* No erase command needed */
#define SST_WRITE BIT(2) /* use SST byte programming */
#define SPI_NOR_NO_FR BIT(3) /* Can't do fastread */
#define SECT_4K_PMC BIT(4) /* SPINOR_OP_BE_4K_PMC works uniformly */
#define SPI_NOR_DUAL_READ BIT(5) /* Flash supports Dual Read */
#define SPI_NOR_QUAD_READ BIT(6) /* Flash supports Quad Read */
#define USE_FSR BIT(7) /* use flag status register */
#define SPI_NOR_HAS_LOCK BIT(8) /* Flash supports lock/unlock via SR */
#define SPI_NOR_HAS_TB BIT(9) /*
* Flash SR has Top/Bottom (TB) protect
* bit. Must be used with
* SPI_NOR_HAS_LOCK.
*/
#define SPI_NOR_XSR_RDY BIT(10) /*
* S3AN flashes have specific opcode to
* read the status register.
* Flags SPI_NOR_XSR_RDY and SPI_S3AN
* use the same bit as one implies the
* other, but we will get rid of
* SPI_S3AN soon.
*/
#define SPI_S3AN BIT(10) /*
* Xilinx Spartan 3AN In-System Flash
* (MFR cannot be used for probing
* because it has the same value as
* ATMEL flashes)
*/
#define SPI_NOR_4B_OPCODES BIT(11) /*
* Use dedicated 4byte address op codes
* to support memory size above 128Mib.
*/
#define NO_CHIP_ERASE BIT(12) /* Chip does not support chip erase */
#define SPI_NOR_SKIP_SFDP BIT(13) /* Skip parsing of SFDP tables */
#define USE_CLSR BIT(14) /* use CLSR command */
#define SPI_NOR_OCTAL_READ BIT(15) /* Flash supports Octal Read */
#define SPI_NOR_TB_SR_BIT6 BIT(16) /*
* Top/Bottom (TB) is bit 6 of
* status register. Must be used with
* SPI_NOR_HAS_TB.
*/
/* Part specific fixup hooks. */
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, _flags) \
.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, \
.flags = (_flags),
#define INFO6(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \
.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, \
.flags = (_flags),
#define CAT25_INFO(_sector_size, _n_sectors, _page_size, _addr_width, _flags) \
.sector_size = (_sector_size), \
.n_sectors = (_n_sectors), \
.page_size = (_page_size), \
.addr_width = (_addr_width), \
.flags = (_flags),
#define S3AN_INFO(_jedec_id, _n_sectors, _page_size) \
.id = { \
((_jedec_id) >> 16) & 0xff, \
((_jedec_id) >> 8) & 0xff, \
(_jedec_id) & 0xff \
}, \
.id_len = 3, \
.sector_size = (8*_page_size), \
.n_sectors = (_n_sectors), \
.page_size = _page_size, \
.addr_width = 3, \
.flags = SPI_NOR_NO_FR | SPI_S3AN,
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(struct spi_nor *nor, bool enable);
int spi_nor_write_ear(struct spi_nor *nor, u8 ear);
int spi_nor_wait_till_ready(struct spi_nor *nor);
int spi_nor_lock_and_prep(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);
int spi_nor_sr2_bit7_quad_enable(struct spi_nor *nor);
int spi_nor_xread_sr(struct spi_nor *nor, u8 *sr);
ssize_t spi_nor_read_data(struct spi_nor *nor, loff_t from, size_t len,
u8 *buf);
ssize_t spi_nor_write_data(struct spi_nor *nor, loff_t to, size_t len,
const u8 *buf);
int spi_nor_hwcaps_read2cmd(u32 hwcaps);
u8 spi_nor_convert_3to4_read(u8 opcode);
@ -33,4 +186,9 @@ int spi_nor_post_bfpt_fixups(struct spi_nor *nor,
const struct sfdp_bfpt *bfpt,
struct spi_nor_flash_parameter *params);
static struct spi_nor __maybe_unused *mtd_to_spi_nor(struct mtd_info *mtd)
{
return mtd->priv;
}
#endif /* __LINUX_MTD_SPI_NOR_INTERNAL_H */