MTD core changes:
* Fix issue where write_cached_data() fails but write() still returns success
* maps: sa1100-flash: Replace zero-length array with flexible-array member
* phram: Fix a double free issue in error path
* Convert fallthrough comments into statements
* MAINTAINERS: Add the IRC channel to the MTD related subsystems
Raw NAND core changes:
* Add support for manufacturer specific suspend/resume operation
* Add support for manufacturer specific lock/unlock operation
* Replace zero-length array with flexible-array member
* Fix a typo ("manufecturer")
* Ensure nand_soft_waitrdy wait period is enough
Raw NAND controller driver changes:
* Brcmnand:
- Add support for flash-edu for dma transfers (+ bindings)
* Cadence:
- Reinit completion before executing a new command
- Change bad block marker size
- Fix the calculation of the avaialble OOB size
- Get meta data size from registers
* Qualcom:
- Use dma_request_chan() instead dma_request_slave_channel()
- Release resources on failure within qcom_nandc_alloc()
* Allwinner:
- Use dma_request_chan() instead dma_request_slave_channel()
* Marvell:
- Use dma_request_chan() instead dma_request_slave_channel()
- Release DMA channel on error
* Freescale:
- Use dma_request_chan() instead dma_request_slave_channel()
* Macronix:
- Add support for Macronix NAND randomizer (+ bindings)
* Ams-delta:
- Rename structures and functions to gpio_nand*
- Make the driver custom I/O ready
- Drop useless local variable
- Support custom driver initialisation
- Add module device tables
- Handle more GPIO pins as optional
- Make read pulses optional
- Don't hardcode read/write pulse widths
- Push inversion handling to gpiolib
- Enable OF partition info support
- Drop board specific partition info
- Use struct gpio_nand_platdata
- Write protect device during probe
* Ingenic:
- Use devm_platform_ioremap_resource()
- Add dependency on MIPS || COMPILE_TEST
* Denali:
- Deassert write protect pin
* ST:
- Use dma_request_chan() instead dma_request_slave_channel()
Raw NAND chip driver changes:
* Toshiba:
- Support reading the number of bitflips for BENAND (Built-in ECC NAND)
* Macronix:
- Add support for deep power down mode
- Add support for block protection
SPI-NAND core changes:
* Do not erase the block before writing a bad block marker
* Explicitly use MTD_OPS_RAW to write the bad block marker to OOB
* Stop using spinand->oobbuf for buffering bad block markers
* Rework detect procedure for different READ_ID operation
SPI-NAND driver changes:
* Toshiba:
- Support for new Kioxia Serial NAND
- Rename function name to change suffix and prefix (8Gbit)
- Add comment about Kioxia ID
* Micron:
- Add new Micron SPI NAND devices with multiple dies
- Add M70A series Micron SPI NAND devices
- identify SPI NAND device with Continuous Read mode
- Add new Micron SPI NAND devices
- Describe the SPI NAND device MT29F2G01ABAGD
- Generalize the OOB layout structure and function names
SPI NOR core changes:
* Move all the manufacturer specific quirks/code out of the core,
to make the core logic more readable and thus ease maintenance.
* Move the SFDP logic out of the core, it provides a better
separation between the SFDP parsing and core logic.
* Trim what is exposed in spi-nor.h. The SPI NOR controllers drivers
must not be able to use structures that are meant just for the
SPI NOR core.
* Use the spi-mem direct mapping API to let advanced controllers
optimize the read/write operations when they support direct mapping.
* Add generic formula for the Status Register block protection
handling. It fixes some long standing locking limitations and eases
the addition of the 4bit block protection support.
* Add block protection support for flashes with 4 block protection
bits in the Status Register.
SPI NOR controller drivers changes:
* The mtk-quadspi driver is replaced by the new spi-mem spi-mtk-nor
driver.
* Merge tag 'mtk-mtd-spi-move' into spi-nor/next to avoid conflicts.
HyperBus changes:
* Print error msg when compatible is wrong or missing
* Move mapping of direct access window from core to individual drivers
-----BEGIN PGP SIGNATURE-----
iQEzBAABCgAdFiEE9HuaYnbmDhq/XIDIJWrqGEe9VoQFAl6GEU8ACgkQJWrqGEe9
VoSQ8gf/WV1vfxfAlgKRQ6WGkdrI+EndmciKx/sqf9KfAu6uNLHx3qcxQeibqvgC
KmIgJbCLXhgCUBZQLqyjqHtO3zImgPI2WWWR/tkieNaT9NT5jrAunYZpiqkCkjVD
HjML4iVcLwDJoHPZWTTTsFWd2cDLA8nFVXJQeaGRgdsx3j3D9OSOnfLGTUGfcg2H
lC0BxA6JRO7tdZlErqzy9BXUasjO5C7rsRzqgTiGT4h/H2yhYmDQhMW+Kz86zWiB
XdZsZJ2qLlTKntQmzR+30vbolId3iZqsO9q0mVkqWd2UQn5TpmmzNqLoYA6ys8KK
lW/1E53E3/Pq0+5ejGbD5m4afff+nw==
=/p2x
-----END PGP SIGNATURE-----
Merge tag 'mtd/for-5.7' of git://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux
Pull MTD updates from Miquel Raynal:
"MTD core changes:
- Fix issue where write_cached_data() fails but write() still returns
success
- maps: sa1100-flash: Replace zero-length array with flexible-array
member
- phram: Fix a double free issue in error path
- Convert fallthrough comments into statements
- MAINTAINERS: Add the IRC channel to the MTD related subsystems
Raw NAND core changes:
- Add support for manufacturer specific suspend/resume operation
- Add support for manufacturer specific lock/unlock operation
- Replace zero-length array with flexible-array member
- Fix a typo ("manufecturer")
- Ensure nand_soft_waitrdy wait period is enough
Raw NAND controller driver changes:
- Brcmnand:
* Add support for flash-edu for dma transfers (+ bindings)
- Cadence:
* Reinit completion before executing a new command
* Change bad block marker size
* Fix the calculation of the avaialble OOB size
* Get meta data size from registers
- Qualcom:
* Use dma_request_chan() instead dma_request_slave_channel()
* Release resources on failure within qcom_nandc_alloc()
- Allwinner:
* Use dma_request_chan() instead dma_request_slave_channel()
- Marvell:
* Use dma_request_chan() instead dma_request_slave_channel()
* Release DMA channel on error
- Freescale:
* Use dma_request_chan() instead dma_request_slave_channel()
- Macronix:
* Add support for Macronix NAND randomizer (+ bindings)
- Ams-delta:
* Rename structures and functions to gpio_nand*
* Make the driver custom I/O ready
* Drop useless local variable
* Support custom driver initialisation
* Add module device tables
* Handle more GPIO pins as optional
* Make read pulses optional
* Don't hardcode read/write pulse widths
* Push inversion handling to gpiolib
* Enable OF partition info support
* Drop board specific partition info
* Use struct gpio_nand_platdata
* Write protect device during probe
- Ingenic:
* Use devm_platform_ioremap_resource()
* Add dependency on MIPS || COMPILE_TEST
- Denali:
* Deassert write protect pin
- ST:
* Use dma_request_chan() instead dma_request_slave_channel()
Raw NAND chip driver changes:
- Toshiba:
* Support reading the number of bitflips for BENAND (Built-in ECC NAND)
- Macronix:
* Add support for deep power down mode
* Add support for block protection
SPI-NAND core changes:
- Do not erase the block before writing a bad block marker
- Explicitly use MTD_OPS_RAW to write the bad block marker to OOB
- Stop using spinand->oobbuf for buffering bad block markers
- Rework detect procedure for different READ_ID operation
SPI-NAND driver changes:
- Toshiba:
* Support for new Kioxia Serial NAND
* Rename function name to change suffix and prefix (8Gbit)
* Add comment about Kioxia ID
- Micron:
* Add new Micron SPI NAND devices with multiple dies
* Add M70A series Micron SPI NAND devices
* identify SPI NAND device with Continuous Read mode
* Add new Micron SPI NAND devices
* Describe the SPI NAND device MT29F2G01ABAGD
* Generalize the OOB layout structure and function names
SPI NOR core changes:
- Move all the manufacturer specific quirks/code out of the core, to
make the core logic more readable and thus ease maintenance.
- Move the SFDP logic out of the core, it provides a better
separation between the SFDP parsing and core logic.
- Trim what is exposed in spi-nor.h. The SPI NOR controllers drivers
must not be able to use structures that are meant just for the SPI
NOR core.
- Use the spi-mem direct mapping API to let advanced controllers
optimize the read/write operations when they support direct
mapping.
- Add generic formula for the Status Register block protection
handling. It fixes some long standing locking limitations and eases
the addition of the 4bit block protection support.
- Add block protection support for flashes with 4 block protection
bits in the Status Register.
SPI NOR controller drivers changes:
- The mtk-quadspi driver is replaced by the new spi-mem spi-mtk-nor
driver.
- Merge tag 'mtk-mtd-spi-move' into spi-nor/next to avoid conflicts.
HyperBus changes:
- Print error msg when compatible is wrong or missing
- Move mapping of direct access window from core to individual
drivers"
* tag 'mtd/for-5.7' of git://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux: (103 commits)
mtd: Convert fallthrough comments into statements
mtd: rawnand: toshiba: Support reading the number of bitflips for BENAND (Built-in ECC NAND)
MAINTAINERS: Add the IRC channel to the MTD related subsystems
mtd: Fix issue where write_cached_data() fails but write() still returns success
mtd: maps: sa1100-flash: Replace zero-length array with flexible-array member
mtd: phram: fix a double free issue in error path
mtd: spinand: toshiba: Support for new Kioxia Serial NAND
mtd: spinand: toshiba: Rename function name to change suffix and prefix (8Gbit)
mtd: rawnand: macronix: Add support for deep power down mode
mtd: rawnand: Add support for manufacturer specific suspend/resume operation
mtd: spi-nor: Enable locking for n25q512ax3/n25q512a
mtd: spi-nor: Add SR 4bit block protection support
mtd: spi-nor: Add generic formula for SR block protection handling
mtd: spi-nor: Set all BP bits to one when lock_len == mtd->size
mtd: spi-nor: controllers: aspeed-smc: Replace zero-length array with flexible-array member
mtd: spi-nor: Clear WEL bit when erase or program errors occur
MAINTAINERS: update entry after SPI NOR controller move
mtd: spi-nor: Trim what is exposed in spi-nor.h
mtd: spi-nor: Drop the MFR definitions
mtd: spi-nor: Get rid of the now empty spi_nor_ids[] table
...
This commit is contained in:
commit
e109f50607
95 changed files with 8454 additions and 6931 deletions
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#include <linux/types.h>
|
||||
#include <linux/uio.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/of.h>
|
||||
|
|
@ -194,10 +195,43 @@ struct mtd_debug_info {
|
|||
const char *partid;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct mtd_part - MTD partition specific fields
|
||||
*
|
||||
* @node: list node used to add an MTD partition to the parent partition list
|
||||
* @offset: offset of the partition relatively to the parent offset
|
||||
* @flags: original flags (before the mtdpart logic decided to tweak them based
|
||||
* on flash constraints, like eraseblock/pagesize alignment)
|
||||
*
|
||||
* This struct is embedded in mtd_info and contains partition-specific
|
||||
* properties/fields.
|
||||
*/
|
||||
struct mtd_part {
|
||||
struct list_head node;
|
||||
u64 offset;
|
||||
u32 flags;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct mtd_master - MTD master specific fields
|
||||
*
|
||||
* @partitions_lock: lock protecting accesses to the partition list. Protects
|
||||
* not only the master partition list, but also all
|
||||
* sub-partitions.
|
||||
* @suspended: et to 1 when the device is suspended, 0 otherwise
|
||||
*
|
||||
* This struct is embedded in mtd_info and contains master-specific
|
||||
* properties/fields. The master is the root MTD device from the MTD partition
|
||||
* point of view.
|
||||
*/
|
||||
struct mtd_master {
|
||||
struct mutex partitions_lock;
|
||||
unsigned int suspended : 1;
|
||||
};
|
||||
|
||||
struct mtd_info {
|
||||
u_char type;
|
||||
uint32_t flags;
|
||||
uint32_t orig_flags; /* Flags as before running mtd checks */
|
||||
uint64_t size; // Total size of the MTD
|
||||
|
||||
/* "Major" erase size for the device. Naïve users may take this
|
||||
|
|
@ -339,8 +373,52 @@ struct mtd_info {
|
|||
int usecount;
|
||||
struct mtd_debug_info dbg;
|
||||
struct nvmem_device *nvmem;
|
||||
|
||||
/*
|
||||
* Parent device from the MTD partition point of view.
|
||||
*
|
||||
* MTD masters do not have any parent, MTD partitions do. The parent
|
||||
* MTD device can itself be a partition.
|
||||
*/
|
||||
struct mtd_info *parent;
|
||||
|
||||
/* List of partitions attached to this MTD device */
|
||||
struct list_head partitions;
|
||||
|
||||
union {
|
||||
struct mtd_part part;
|
||||
struct mtd_master master;
|
||||
};
|
||||
};
|
||||
|
||||
static inline struct mtd_info *mtd_get_master(struct mtd_info *mtd)
|
||||
{
|
||||
while (mtd->parent)
|
||||
mtd = mtd->parent;
|
||||
|
||||
return mtd;
|
||||
}
|
||||
|
||||
static inline u64 mtd_get_master_ofs(struct mtd_info *mtd, u64 ofs)
|
||||
{
|
||||
while (mtd->parent) {
|
||||
ofs += mtd->part.offset;
|
||||
mtd = mtd->parent;
|
||||
}
|
||||
|
||||
return ofs;
|
||||
}
|
||||
|
||||
static inline bool mtd_is_partition(const struct mtd_info *mtd)
|
||||
{
|
||||
return mtd->parent;
|
||||
}
|
||||
|
||||
static inline bool mtd_has_partitions(const struct mtd_info *mtd)
|
||||
{
|
||||
return !list_empty(&mtd->partitions);
|
||||
}
|
||||
|
||||
int mtd_ooblayout_ecc(struct mtd_info *mtd, int section,
|
||||
struct mtd_oob_region *oobecc);
|
||||
int mtd_ooblayout_find_eccregion(struct mtd_info *mtd, int eccbyte,
|
||||
|
|
@ -392,13 +470,16 @@ static inline u32 mtd_oobavail(struct mtd_info *mtd, struct mtd_oob_ops *ops)
|
|||
static inline int mtd_max_bad_blocks(struct mtd_info *mtd,
|
||||
loff_t ofs, size_t len)
|
||||
{
|
||||
if (!mtd->_max_bad_blocks)
|
||||
struct mtd_info *master = mtd_get_master(mtd);
|
||||
|
||||
if (!master->_max_bad_blocks)
|
||||
return -ENOTSUPP;
|
||||
|
||||
if (mtd->size < (len + ofs) || ofs < 0)
|
||||
return -EINVAL;
|
||||
|
||||
return mtd->_max_bad_blocks(mtd, ofs, len);
|
||||
return master->_max_bad_blocks(master, mtd_get_master_ofs(mtd, ofs),
|
||||
len);
|
||||
}
|
||||
|
||||
int mtd_wunit_to_pairing_info(struct mtd_info *mtd, int wunit,
|
||||
|
|
@ -439,8 +520,10 @@ int mtd_writev(struct mtd_info *mtd, const struct kvec *vecs,
|
|||
|
||||
static inline void mtd_sync(struct mtd_info *mtd)
|
||||
{
|
||||
if (mtd->_sync)
|
||||
mtd->_sync(mtd);
|
||||
struct mtd_info *master = mtd_get_master(mtd);
|
||||
|
||||
if (master->_sync)
|
||||
master->_sync(master);
|
||||
}
|
||||
|
||||
int mtd_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len);
|
||||
|
|
@ -452,13 +535,31 @@ int mtd_block_markbad(struct mtd_info *mtd, loff_t ofs);
|
|||
|
||||
static inline int mtd_suspend(struct mtd_info *mtd)
|
||||
{
|
||||
return mtd->_suspend ? mtd->_suspend(mtd) : 0;
|
||||
struct mtd_info *master = mtd_get_master(mtd);
|
||||
int ret;
|
||||
|
||||
if (master->master.suspended)
|
||||
return 0;
|
||||
|
||||
ret = master->_suspend ? master->_suspend(master) : 0;
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
master->master.suspended = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void mtd_resume(struct mtd_info *mtd)
|
||||
{
|
||||
if (mtd->_resume)
|
||||
mtd->_resume(mtd);
|
||||
struct mtd_info *master = mtd_get_master(mtd);
|
||||
|
||||
if (!master->master.suspended)
|
||||
return;
|
||||
|
||||
if (master->_resume)
|
||||
master->_resume(master);
|
||||
|
||||
master->master.suspended = 0;
|
||||
}
|
||||
|
||||
static inline uint32_t mtd_div_by_eb(uint64_t sz, struct mtd_info *mtd)
|
||||
|
|
@ -538,7 +639,9 @@ static inline loff_t mtd_wunit_to_offset(struct mtd_info *mtd, loff_t base,
|
|||
|
||||
static inline int mtd_has_oob(const struct mtd_info *mtd)
|
||||
{
|
||||
return mtd->_read_oob && mtd->_write_oob;
|
||||
struct mtd_info *master = mtd_get_master((struct mtd_info *)mtd);
|
||||
|
||||
return master->_read_oob && master->_write_oob;
|
||||
}
|
||||
|
||||
static inline int mtd_type_is_nand(const struct mtd_info *mtd)
|
||||
|
|
@ -548,7 +651,9 @@ static inline int mtd_type_is_nand(const struct mtd_info *mtd)
|
|||
|
||||
static inline int mtd_can_have_bb(const struct mtd_info *mtd)
|
||||
{
|
||||
return !!mtd->_block_isbad;
|
||||
struct mtd_info *master = mtd_get_master((struct mtd_info *)mtd);
|
||||
|
||||
return !!master->_block_isbad;
|
||||
}
|
||||
|
||||
/* Kernel-side ioctl definitions */
|
||||
|
|
|
|||
|
|
@ -105,7 +105,6 @@ extern void deregister_mtd_parser(struct mtd_part_parser *parser);
|
|||
module_driver(__mtd_part_parser, register_mtd_parser, \
|
||||
deregister_mtd_parser)
|
||||
|
||||
int mtd_is_partition(const struct mtd_info *mtd);
|
||||
int mtd_add_partition(struct mtd_info *master, const char *name,
|
||||
long long offset, long long length);
|
||||
int mtd_del_partition(struct mtd_info *master, int partno);
|
||||
|
|
|
|||
|
|
@ -1064,6 +1064,8 @@ struct nand_legacy {
|
|||
* @lock: lock protecting the suspended field. Also used to
|
||||
* serialize accesses to the NAND device.
|
||||
* @suspended: set to 1 when the device is suspended, 0 when it's not.
|
||||
* @suspend: [REPLACEABLE] specific NAND device suspend operation
|
||||
* @resume: [REPLACEABLE] specific NAND device resume operation
|
||||
* @bbt: [INTERN] bad block table pointer
|
||||
* @bbt_td: [REPLACEABLE] bad block table descriptor for flash
|
||||
* lookup.
|
||||
|
|
@ -1077,6 +1079,8 @@ struct nand_legacy {
|
|||
* @manufacturer: [INTERN] Contains manufacturer information
|
||||
* @manufacturer.desc: [INTERN] Contains manufacturer's description
|
||||
* @manufacturer.priv: [INTERN] Contains manufacturer private information
|
||||
* @lock_area: [REPLACEABLE] specific NAND chip lock operation
|
||||
* @unlock_area: [REPLACEABLE] specific NAND chip unlock operation
|
||||
*/
|
||||
|
||||
struct nand_chip {
|
||||
|
|
@ -1117,6 +1121,8 @@ struct nand_chip {
|
|||
|
||||
struct mutex lock;
|
||||
unsigned int suspended : 1;
|
||||
int (*suspend)(struct nand_chip *chip);
|
||||
void (*resume)(struct nand_chip *chip);
|
||||
|
||||
uint8_t *oob_poi;
|
||||
struct nand_controller *controller;
|
||||
|
|
@ -1136,6 +1142,9 @@ struct nand_chip {
|
|||
const struct nand_manufacturer *desc;
|
||||
void *priv;
|
||||
} manufacturer;
|
||||
|
||||
int (*lock_area)(struct nand_chip *chip, loff_t ofs, uint64_t len);
|
||||
int (*unlock_area)(struct nand_chip *chip, loff_t ofs, uint64_t len);
|
||||
};
|
||||
|
||||
extern const struct mtd_ooblayout_ops nand_ooblayout_sp_ops;
|
||||
|
|
@ -1215,7 +1224,7 @@ static inline struct device_node *nand_get_flash_node(struct nand_chip *chip)
|
|||
* struct nand_flash_dev - NAND Flash Device ID Structure
|
||||
* @name: a human-readable name of the NAND chip
|
||||
* @dev_id: the device ID (the second byte of the full chip ID array)
|
||||
* @mfr_id: manufecturer ID part of the full chip ID array (refers the same
|
||||
* @mfr_id: manufacturer ID part of the full chip ID array (refers the same
|
||||
* memory address as ``id[0]``)
|
||||
* @dev_id: device ID part of the full chip ID array (refers the same memory
|
||||
* address as ``id[1]``)
|
||||
|
|
|
|||
|
|
@ -11,23 +11,6 @@
|
|||
#include <linux/mtd/mtd.h>
|
||||
#include <linux/spi/spi-mem.h>
|
||||
|
||||
/*
|
||||
* Manufacturer IDs
|
||||
*
|
||||
* The first byte returned from the flash after sending opcode SPINOR_OP_RDID.
|
||||
* Sometimes these are the same as CFI IDs, but sometimes they aren't.
|
||||
*/
|
||||
#define SNOR_MFR_ATMEL CFI_MFR_ATMEL
|
||||
#define SNOR_MFR_GIGADEVICE 0xc8
|
||||
#define SNOR_MFR_INTEL CFI_MFR_INTEL
|
||||
#define SNOR_MFR_ST CFI_MFR_ST /* ST Micro */
|
||||
#define SNOR_MFR_MICRON CFI_MFR_MICRON /* Micron */
|
||||
#define SNOR_MFR_ISSI CFI_MFR_PMC
|
||||
#define SNOR_MFR_MACRONIX CFI_MFR_MACRONIX
|
||||
#define SNOR_MFR_SPANSION CFI_MFR_AMD
|
||||
#define SNOR_MFR_SST CFI_MFR_SST
|
||||
#define SNOR_MFR_WINBOND 0xef /* Also used by some Spansion */
|
||||
|
||||
/*
|
||||
* Note on opcode nomenclature: some opcodes have a format like
|
||||
* SPINOR_OP_FUNCTION{4,}_x_y_z. The numbers x, y, and z stand for the number
|
||||
|
|
@ -128,7 +111,9 @@
|
|||
#define SR_BP0 BIT(2) /* Block protect 0 */
|
||||
#define SR_BP1 BIT(3) /* Block protect 1 */
|
||||
#define SR_BP2 BIT(4) /* Block protect 2 */
|
||||
#define SR_BP3 BIT(5) /* Block protect 3 */
|
||||
#define SR_TB_BIT5 BIT(5) /* Top/Bottom protect */
|
||||
#define SR_BP3_BIT6 BIT(6) /* Block protect 3 */
|
||||
#define SR_TB_BIT6 BIT(6) /* Top/Bottom protect */
|
||||
#define SR_SRWD BIT(7) /* SR write protect */
|
||||
/* Spansion/Cypress specific status bits */
|
||||
|
|
@ -137,6 +122,8 @@
|
|||
|
||||
#define SR1_QUAD_EN_BIT6 BIT(6)
|
||||
|
||||
#define SR_BP_SHIFT 2
|
||||
|
||||
/* Enhanced Volatile Configuration Register bits */
|
||||
#define EVCR_QUAD_EN_MICRON BIT(7) /* Micron Quad I/O */
|
||||
|
||||
|
|
@ -225,110 +212,6 @@ static inline u8 spi_nor_get_protocol_width(enum spi_nor_protocol proto)
|
|||
return spi_nor_get_protocol_data_nbits(proto);
|
||||
}
|
||||
|
||||
enum spi_nor_option_flags {
|
||||
SNOR_F_USE_FSR = BIT(0),
|
||||
SNOR_F_HAS_SR_TB = BIT(1),
|
||||
SNOR_F_NO_OP_CHIP_ERASE = BIT(2),
|
||||
SNOR_F_READY_XSR_RDY = BIT(3),
|
||||
SNOR_F_USE_CLSR = BIT(4),
|
||||
SNOR_F_BROKEN_RESET = BIT(5),
|
||||
SNOR_F_4B_OPCODES = BIT(6),
|
||||
SNOR_F_HAS_4BAIT = BIT(7),
|
||||
SNOR_F_HAS_LOCK = BIT(8),
|
||||
SNOR_F_HAS_16BIT_SR = BIT(9),
|
||||
SNOR_F_NO_READ_CR = BIT(10),
|
||||
SNOR_F_HAS_SR_TB_BIT6 = BIT(11),
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* struct spi_nor_erase_type - Structure to describe a SPI NOR erase type
|
||||
* @size: the size of the sector/block erased by the erase type.
|
||||
* JEDEC JESD216B imposes erase sizes to be a power of 2.
|
||||
* @size_shift: @size is a power of 2, the shift is stored in
|
||||
* @size_shift.
|
||||
* @size_mask: the size mask based on @size_shift.
|
||||
* @opcode: the SPI command op code to erase the sector/block.
|
||||
* @idx: Erase Type index as sorted in the Basic Flash Parameter
|
||||
* Table. It will be used to synchronize the supported
|
||||
* Erase Types with the ones identified in the SFDP
|
||||
* optional tables.
|
||||
*/
|
||||
struct spi_nor_erase_type {
|
||||
u32 size;
|
||||
u32 size_shift;
|
||||
u32 size_mask;
|
||||
u8 opcode;
|
||||
u8 idx;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct spi_nor_erase_command - Used for non-uniform erases
|
||||
* The structure is used to describe a list of erase commands to be executed
|
||||
* once we validate that the erase can be performed. The elements in the list
|
||||
* are run-length encoded.
|
||||
* @list: for inclusion into the list of erase commands.
|
||||
* @count: how many times the same erase command should be
|
||||
* consecutively used.
|
||||
* @size: the size of the sector/block erased by the command.
|
||||
* @opcode: the SPI command op code to erase the sector/block.
|
||||
*/
|
||||
struct spi_nor_erase_command {
|
||||
struct list_head list;
|
||||
u32 count;
|
||||
u32 size;
|
||||
u8 opcode;
|
||||
};
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
struct spi_nor_erase_region {
|
||||
u64 offset;
|
||||
u64 size;
|
||||
};
|
||||
|
||||
#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
|
||||
* @regions: array of erase regions. The regions are consecutive in
|
||||
* address space. Walking through the regions is done
|
||||
* incrementally.
|
||||
* @uniform_region: a pre-allocated erase region for SPI NOR with a uniform
|
||||
* sector size (legacy implementation).
|
||||
* @erase_type: an array of erase types shared by all the regions.
|
||||
* 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.
|
||||
*/
|
||||
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;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct spi_nor_hwcaps - Structure for describing the hardware capabilies
|
||||
* supported by the SPI controller (bus master).
|
||||
|
|
@ -404,61 +287,7 @@ struct spi_nor_hwcaps {
|
|||
#define SNOR_HWCAPS_ALL (SNOR_HWCAPS_READ_MASK | \
|
||||
SNOR_HWCAPS_PP_MASK)
|
||||
|
||||
struct spi_nor_read_command {
|
||||
u8 num_mode_clocks;
|
||||
u8 num_wait_states;
|
||||
u8 opcode;
|
||||
enum spi_nor_protocol proto;
|
||||
};
|
||||
|
||||
struct spi_nor_pp_command {
|
||||
u8 opcode;
|
||||
enum spi_nor_protocol proto;
|
||||
};
|
||||
|
||||
enum spi_nor_read_command_index {
|
||||
SNOR_CMD_READ,
|
||||
SNOR_CMD_READ_FAST,
|
||||
SNOR_CMD_READ_1_1_1_DTR,
|
||||
|
||||
/* Dual SPI */
|
||||
SNOR_CMD_READ_1_1_2,
|
||||
SNOR_CMD_READ_1_2_2,
|
||||
SNOR_CMD_READ_2_2_2,
|
||||
SNOR_CMD_READ_1_2_2_DTR,
|
||||
|
||||
/* Quad SPI */
|
||||
SNOR_CMD_READ_1_1_4,
|
||||
SNOR_CMD_READ_1_4_4,
|
||||
SNOR_CMD_READ_4_4_4,
|
||||
SNOR_CMD_READ_1_4_4_DTR,
|
||||
|
||||
/* Octal SPI */
|
||||
SNOR_CMD_READ_1_1_8,
|
||||
SNOR_CMD_READ_1_8_8,
|
||||
SNOR_CMD_READ_8_8_8,
|
||||
SNOR_CMD_READ_1_8_8_DTR,
|
||||
|
||||
SNOR_CMD_READ_MAX
|
||||
};
|
||||
|
||||
enum spi_nor_pp_command_index {
|
||||
SNOR_CMD_PP,
|
||||
|
||||
/* Quad SPI */
|
||||
SNOR_CMD_PP_1_1_4,
|
||||
SNOR_CMD_PP_1_4_4,
|
||||
SNOR_CMD_PP_4_4_4,
|
||||
|
||||
/* Octal SPI */
|
||||
SNOR_CMD_PP_1_1_8,
|
||||
SNOR_CMD_PP_1_8_8,
|
||||
SNOR_CMD_PP_8_8_8,
|
||||
|
||||
SNOR_CMD_PP_MAX
|
||||
};
|
||||
|
||||
/* Forward declaration that will be used in 'struct spi_nor_flash_parameter' */
|
||||
/* Forward declaration that is used in 'struct spi_nor_controller_ops' */
|
||||
struct spi_nor;
|
||||
|
||||
/**
|
||||
|
|
@ -489,68 +318,13 @@ struct spi_nor_controller_ops {
|
|||
int (*erase)(struct spi_nor *nor, loff_t offs);
|
||||
};
|
||||
|
||||
/**
|
||||
* struct spi_nor_locking_ops - SPI NOR locking methods
|
||||
* @lock: lock a region of the SPI NOR.
|
||||
* @unlock: unlock a region of the SPI NOR.
|
||||
* @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);
|
||||
};
|
||||
|
||||
/**
|
||||
* struct spi_nor_flash_parameter - SPI NOR flash parameters and settings.
|
||||
* Includes legacy flash parameters and settings that can be overwritten
|
||||
* 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.
|
||||
* @page_size: the page size of the SPI NOR flash memory.
|
||||
* @hwcaps: describes the read and page program hardware
|
||||
* capabilities.
|
||||
* @reads: read capabilities ordered by priority: the higher index
|
||||
* in the array, the higher priority.
|
||||
* @page_programs: page program capabilities ordered by priority: the
|
||||
* higher index in the array, the higher priority.
|
||||
* @erase_map: the erase map parsed from the SFDP Sector Map Parameter
|
||||
* Table.
|
||||
* @quad_enable: enables SPI NOR quad mode.
|
||||
* @set_4byte: 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: 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.
|
||||
* @locking_ops: SPI NOR locking methods.
|
||||
*/
|
||||
struct spi_nor_flash_parameter {
|
||||
u64 size;
|
||||
u32 page_size;
|
||||
|
||||
struct spi_nor_hwcaps hwcaps;
|
||||
struct spi_nor_read_command reads[SNOR_CMD_READ_MAX];
|
||||
struct spi_nor_pp_command page_programs[SNOR_CMD_PP_MAX];
|
||||
|
||||
struct spi_nor_erase_map erase_map;
|
||||
|
||||
int (*quad_enable)(struct spi_nor *nor);
|
||||
int (*set_4byte)(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);
|
||||
|
||||
const struct spi_nor_locking_ops *locking_ops;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct flash_info - Forward declaration of a structure used internally by
|
||||
* spi_nor_scan()
|
||||
/*
|
||||
* Forward declarations that are used internally by the core and manufacturer
|
||||
* drivers.
|
||||
*/
|
||||
struct flash_info;
|
||||
struct spi_nor_manufacturer;
|
||||
struct spi_nor_flash_parameter;
|
||||
|
||||
/**
|
||||
* struct spi_nor - Structure for defining a the SPI NOR layer
|
||||
|
|
@ -562,6 +336,7 @@ struct flash_info;
|
|||
* layer is not DMA-able
|
||||
* @bouncebuf_size: size of the bounce buffer
|
||||
* @info: spi-nor part JDEC MFR id and other info
|
||||
* @manufacturer: spi-nor manufacturer
|
||||
* @page_size: the page size of the SPI NOR
|
||||
* @addr_width: number of address bytes
|
||||
* @erase_opcode: the opcode for erasing a sector
|
||||
|
|
@ -578,6 +353,7 @@ struct flash_info;
|
|||
* The structure includes legacy flash parameters and
|
||||
* settings that can be overwritten by the spi_nor_fixups
|
||||
* hooks, or dynamically when parsing the SFDP tables.
|
||||
* @dirmap: pointers to struct spi_mem_dirmap_desc for reads/writes.
|
||||
* @priv: the private data
|
||||
*/
|
||||
struct spi_nor {
|
||||
|
|
@ -588,6 +364,7 @@ struct spi_nor {
|
|||
u8 *bouncebuf;
|
||||
size_t bouncebuf_size;
|
||||
const struct flash_info *info;
|
||||
const struct spi_nor_manufacturer *manufacturer;
|
||||
u32 page_size;
|
||||
u8 addr_width;
|
||||
u8 erase_opcode;
|
||||
|
|
@ -602,40 +379,16 @@ struct spi_nor {
|
|||
|
||||
const struct spi_nor_controller_ops *controller_ops;
|
||||
|
||||
struct spi_nor_flash_parameter params;
|
||||
struct spi_nor_flash_parameter *params;
|
||||
|
||||
struct {
|
||||
struct spi_mem_dirmap_desc *rdesc;
|
||||
struct spi_mem_dirmap_desc *wdesc;
|
||||
} dirmap;
|
||||
|
||||
void *priv;
|
||||
};
|
||||
|
||||
static u64 __maybe_unused
|
||||
spi_nor_region_is_last(const struct spi_nor_erase_region *region)
|
||||
{
|
||||
return region->offset & SNOR_LAST_REGION;
|
||||
}
|
||||
|
||||
static u64 __maybe_unused
|
||||
spi_nor_region_end(const struct spi_nor_erase_region *region)
|
||||
{
|
||||
return (region->offset & ~SNOR_ERASE_FLAGS_MASK) + region->size;
|
||||
}
|
||||
|
||||
static void __maybe_unused
|
||||
spi_nor_region_mark_end(struct spi_nor_erase_region *region)
|
||||
{
|
||||
region->offset |= SNOR_LAST_REGION;
|
||||
}
|
||||
|
||||
static void __maybe_unused
|
||||
spi_nor_region_mark_overlay(struct spi_nor_erase_region *region)
|
||||
{
|
||||
region->offset |= SNOR_OVERLAID_REGION;
|
||||
}
|
||||
|
||||
static bool __maybe_unused spi_nor_has_uniform_erase(const struct spi_nor *nor)
|
||||
{
|
||||
return !!nor->params.erase_map.uniform_erase_type;
|
||||
}
|
||||
|
||||
static inline void spi_nor_set_flash_node(struct spi_nor *nor,
|
||||
struct device_node *np)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -32,9 +32,9 @@
|
|||
SPI_MEM_OP_NO_DUMMY, \
|
||||
SPI_MEM_OP_NO_DATA)
|
||||
|
||||
#define SPINAND_READID_OP(ndummy, buf, len) \
|
||||
#define SPINAND_READID_OP(naddr, ndummy, buf, len) \
|
||||
SPI_MEM_OP(SPI_MEM_OP_CMD(0x9f, 1), \
|
||||
SPI_MEM_OP_NO_ADDR, \
|
||||
SPI_MEM_OP_ADDR(naddr, 0, 1), \
|
||||
SPI_MEM_OP_DUMMY(ndummy, 1), \
|
||||
SPI_MEM_OP_DATA_IN(len, buf, 1))
|
||||
|
||||
|
|
@ -176,37 +176,46 @@ struct spinand_device;
|
|||
* @data: buffer containing the id bytes. Currently 4 bytes large, but can
|
||||
* be extended if required
|
||||
* @len: ID length
|
||||
*
|
||||
* struct_spinand_id->data contains all bytes returned after a READ_ID command,
|
||||
* including dummy bytes if the chip does not emit ID bytes right after the
|
||||
* READ_ID command. The responsibility to extract real ID bytes is left to
|
||||
* struct_manufacurer_ops->detect().
|
||||
*/
|
||||
struct spinand_id {
|
||||
u8 data[SPINAND_MAX_ID_LEN];
|
||||
int len;
|
||||
};
|
||||
|
||||
enum spinand_readid_method {
|
||||
SPINAND_READID_METHOD_OPCODE,
|
||||
SPINAND_READID_METHOD_OPCODE_ADDR,
|
||||
SPINAND_READID_METHOD_OPCODE_DUMMY,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct spinand_devid - SPI NAND device id structure
|
||||
* @id: device id of current chip
|
||||
* @len: number of bytes in device id
|
||||
* @method: method to read chip id
|
||||
* There are 3 possible variants:
|
||||
* SPINAND_READID_METHOD_OPCODE: chip id is returned immediately
|
||||
* after read_id opcode.
|
||||
* SPINAND_READID_METHOD_OPCODE_ADDR: chip id is returned after
|
||||
* read_id opcode + 1-byte address.
|
||||
* SPINAND_READID_METHOD_OPCODE_DUMMY: chip id is returned after
|
||||
* read_id opcode + 1 dummy byte.
|
||||
*/
|
||||
struct spinand_devid {
|
||||
const u8 *id;
|
||||
const u8 len;
|
||||
const enum spinand_readid_method method;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct manufacurer_ops - SPI NAND manufacturer specific operations
|
||||
* @detect: detect a SPI NAND device. Every time a SPI NAND device is probed
|
||||
* the core calls the struct_manufacurer_ops->detect() hook of each
|
||||
* registered manufacturer until one of them return 1. Note that
|
||||
* the first thing to check in this hook is that the manufacturer ID
|
||||
* in struct_spinand_device->id matches the manufacturer whose
|
||||
* ->detect() hook has been called. Should return 1 if there's a
|
||||
* match, 0 if the manufacturer ID does not match and a negative
|
||||
* error code otherwise. When true is returned, the core assumes
|
||||
* that properties of the NAND chip (spinand->base.memorg and
|
||||
* spinand->base.eccreq) have been filled
|
||||
* @init: initialize a SPI NAND device
|
||||
* @cleanup: cleanup a SPI NAND device
|
||||
*
|
||||
* Each SPI NAND manufacturer driver should implement this interface so that
|
||||
* NAND chips coming from this vendor can be detected and initialized properly.
|
||||
* NAND chips coming from this vendor can be initialized properly.
|
||||
*/
|
||||
struct spinand_manufacturer_ops {
|
||||
int (*detect)(struct spinand_device *spinand);
|
||||
int (*init)(struct spinand_device *spinand);
|
||||
void (*cleanup)(struct spinand_device *spinand);
|
||||
};
|
||||
|
|
@ -215,11 +224,16 @@ struct spinand_manufacturer_ops {
|
|||
* struct spinand_manufacturer - SPI NAND manufacturer instance
|
||||
* @id: manufacturer ID
|
||||
* @name: manufacturer name
|
||||
* @devid_len: number of bytes in device ID
|
||||
* @chips: supported SPI NANDs under current manufacturer
|
||||
* @nchips: number of SPI NANDs available in chips array
|
||||
* @ops: manufacturer operations
|
||||
*/
|
||||
struct spinand_manufacturer {
|
||||
u8 id;
|
||||
char *name;
|
||||
const struct spinand_info *chips;
|
||||
const size_t nchips;
|
||||
const struct spinand_manufacturer_ops *ops;
|
||||
};
|
||||
|
||||
|
|
@ -270,6 +284,7 @@ struct spinand_ecc_info {
|
|||
};
|
||||
|
||||
#define SPINAND_HAS_QE_BIT BIT(0)
|
||||
#define SPINAND_HAS_CR_FEAT_BIT BIT(1)
|
||||
|
||||
/**
|
||||
* struct spinand_info - Structure used to describe SPI NAND chips
|
||||
|
|
@ -291,7 +306,7 @@ struct spinand_ecc_info {
|
|||
*/
|
||||
struct spinand_info {
|
||||
const char *model;
|
||||
u16 devid;
|
||||
struct spinand_devid devid;
|
||||
u32 flags;
|
||||
struct nand_memory_organization memorg;
|
||||
struct nand_ecc_req eccreq;
|
||||
|
|
@ -305,6 +320,13 @@ struct spinand_info {
|
|||
unsigned int target);
|
||||
};
|
||||
|
||||
#define SPINAND_ID(__method, ...) \
|
||||
{ \
|
||||
.id = (const u8[]){ __VA_ARGS__ }, \
|
||||
.len = sizeof((u8[]){ __VA_ARGS__ }), \
|
||||
.method = __method, \
|
||||
}
|
||||
|
||||
#define SPINAND_INFO_OP_VARIANTS(__read, __write, __update) \
|
||||
{ \
|
||||
.read_cache = __read, \
|
||||
|
|
@ -451,9 +473,10 @@ static inline void spinand_set_of_node(struct spinand_device *spinand,
|
|||
nanddev_set_of_node(&spinand->base, np);
|
||||
}
|
||||
|
||||
int spinand_match_and_init(struct spinand_device *dev,
|
||||
int spinand_match_and_init(struct spinand_device *spinand,
|
||||
const struct spinand_info *table,
|
||||
unsigned int table_size, u16 devid);
|
||||
unsigned int table_size,
|
||||
enum spinand_readid_method rdid_method);
|
||||
|
||||
int spinand_upd_cfg(struct spinand_device *spinand, u8 mask, u8 val);
|
||||
int spinand_select_target(struct spinand_device *spinand, unsigned int target);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue