927 lines · 31.1 KB · C
RawDownload
/* SPDX-License-Identifier: GPL-2.0 *//* * Copyright (c) 2016-2017 Micron Technology, Inc. * *  Authors: *	Peter Pan <peterpandong@micron.com> */#ifndef __LINUX_MTD_SPINAND_H#define __LINUX_MTD_SPINAND_H #include <linux/mutex.h>#include <linux/bitops.h>#include <linux/device.h>#include <linux/mtd/mtd.h>#include <linux/mtd/nand.h>#include <linux/spi/spi.h>#include <linux/spi/spi-mem.h> /** * Standard SPI NAND flash operations */ #define SPINAND_RESET_1S_0_0_OP						\	SPI_MEM_OP(SPI_MEM_OP_CMD(0xff, 1),				\		   SPI_MEM_OP_NO_ADDR,					\		   SPI_MEM_OP_NO_DUMMY,					\		   SPI_MEM_OP_NO_DATA) #define SPINAND_WR_EN_1S_0_0_OP						\	SPI_MEM_OP(SPI_MEM_OP_CMD(0x06, 1),				\		   SPI_MEM_OP_NO_ADDR,					\		   SPI_MEM_OP_NO_DUMMY,					\		   SPI_MEM_OP_NO_DATA) #define SPINAND_WR_DIS_1S_0_0_OP					\	SPI_MEM_OP(SPI_MEM_OP_CMD(0x04, 1),				\		   SPI_MEM_OP_NO_ADDR,					\		   SPI_MEM_OP_NO_DUMMY,					\		   SPI_MEM_OP_NO_DATA) #define SPINAND_READID_1S_1S_1S_OP(naddr, ndummy, buf, len)		\	SPI_MEM_OP(SPI_MEM_OP_CMD(0x9f, 1),				\		   SPI_MEM_OP_ADDR(naddr, 0, 1),			\		   SPI_MEM_OP_DUMMY(ndummy, 1),				\		   SPI_MEM_OP_DATA_IN(len, buf, 1)) #define SPINAND_SET_FEATURE_1S_1S_1S_OP(reg, valptr)			\	SPI_MEM_OP(SPI_MEM_OP_CMD(0x1f, 1),				\		   SPI_MEM_OP_ADDR(1, reg, 1),				\		   SPI_MEM_OP_NO_DUMMY,					\		   SPI_MEM_OP_DATA_OUT(1, valptr, 1)) #define SPINAND_GET_FEATURE_1S_1S_1S_OP(reg, valptr)			\	SPI_MEM_OP(SPI_MEM_OP_CMD(0x0f, 1),				\		   SPI_MEM_OP_ADDR(1, reg, 1),				\		   SPI_MEM_OP_NO_DUMMY,					\		   SPI_MEM_OP_DATA_IN(1, valptr, 1)) #define SPINAND_BLK_ERASE_1S_1S_0_OP(addr)				\	SPI_MEM_OP(SPI_MEM_OP_CMD(0xd8, 1),				\		   SPI_MEM_OP_ADDR(3, addr, 1),				\		   SPI_MEM_OP_NO_DUMMY,					\		   SPI_MEM_OP_NO_DATA) #define SPINAND_PAGE_READ_1S_1S_0_OP(addr)				\	SPI_MEM_OP(SPI_MEM_OP_CMD(0x13, 1),				\		   SPI_MEM_OP_ADDR(3, addr, 1),				\		   SPI_MEM_OP_NO_DUMMY,					\		   SPI_MEM_OP_NO_DATA) #define SPINAND_PAGE_READ_FROM_CACHE_1S_1S_1S_OP(addr, ndummy, buf, len, freq) \	SPI_MEM_OP(SPI_MEM_OP_CMD(0x03, 1),				\		   SPI_MEM_OP_ADDR(2, addr, 1),				\		   SPI_MEM_OP_DUMMY(ndummy, 1),				\		   SPI_MEM_OP_DATA_IN(len, buf, 1),			\		   SPI_MEM_OP_MAX_FREQ(freq)) #define SPINAND_PAGE_READ_FROM_CACHE_FAST_1S_1S_1S_OP(addr, ndummy, buf, len, freq) \	SPI_MEM_OP(SPI_MEM_OP_CMD(0x0b, 1),				\		   SPI_MEM_OP_ADDR(2, addr, 1),				\		   SPI_MEM_OP_DUMMY(ndummy, 1),				\		   SPI_MEM_OP_DATA_IN(len, buf, 1),			\		   SPI_MEM_OP_MAX_FREQ(freq)) #define SPINAND_PAGE_READ_FROM_CACHE_3A_1S_1S_1S_OP(addr, ndummy, buf, len, freq) \	SPI_MEM_OP(SPI_MEM_OP_CMD(0x03, 1),				\		   SPI_MEM_OP_ADDR(3, addr, 1),				\		   SPI_MEM_OP_DUMMY(ndummy, 1),				\		   SPI_MEM_OP_DATA_IN(len, buf, 1),			\		   SPI_MEM_OP_MAX_FREQ(freq)) #define SPINAND_PAGE_READ_FROM_CACHE_FAST_3A_1S_1S_1S_OP(addr, ndummy, buf, len, freq) \	SPI_MEM_OP(SPI_MEM_OP_CMD(0x0b, 1),				\		   SPI_MEM_OP_ADDR(3, addr, 1),				\		   SPI_MEM_OP_DUMMY(ndummy, 1),				\		   SPI_MEM_OP_DATA_IN(len, buf, 1),			\		   SPI_MEM_OP_MAX_FREQ(freq)) #define SPINAND_PAGE_READ_FROM_CACHE_1S_1D_1D_OP(addr, ndummy, buf, len, freq) \	SPI_MEM_OP(SPI_MEM_OP_CMD(0x0d, 1),				\		   SPI_MEM_DTR_OP_ADDR(2, addr, 1),			\		   SPI_MEM_DTR_OP_DUMMY(ndummy, 1),			\		   SPI_MEM_DTR_OP_DATA_IN(len, buf, 1),			\		   SPI_MEM_OP_MAX_FREQ(freq)) #define SPINAND_PAGE_READ_FROM_CACHE_1S_1S_2S_OP(addr, ndummy, buf, len, freq) \	SPI_MEM_OP(SPI_MEM_OP_CMD(0x3b, 1),				\		   SPI_MEM_OP_ADDR(2, addr, 1),				\		   SPI_MEM_OP_DUMMY(ndummy, 1),				\		   SPI_MEM_OP_DATA_IN(len, buf, 2),			\		   SPI_MEM_OP_MAX_FREQ(freq)) #define SPINAND_PAGE_READ_FROM_CACHE_3A_1S_1S_2S_OP(addr, ndummy, buf, len, freq) \	SPI_MEM_OP(SPI_MEM_OP_CMD(0x3b, 1),				\		   SPI_MEM_OP_ADDR(3, addr, 1),				\		   SPI_MEM_OP_DUMMY(ndummy, 1),				\		   SPI_MEM_OP_DATA_IN(len, buf, 2),			\		   SPI_MEM_OP_MAX_FREQ(freq)) #define SPINAND_PAGE_READ_FROM_CACHE_1S_1D_2D_OP(addr, ndummy, buf, len, freq) \	SPI_MEM_OP(SPI_MEM_OP_CMD(0x3d, 1),				\		   SPI_MEM_DTR_OP_ADDR(2, addr, 1),			\		   SPI_MEM_DTR_OP_DUMMY(ndummy, 1),			\		   SPI_MEM_DTR_OP_DATA_IN(len, buf, 2),			\		   SPI_MEM_OP_MAX_FREQ(freq)) #define SPINAND_PAGE_READ_FROM_CACHE_1S_2S_2S_OP(addr, ndummy, buf, len, freq) \	SPI_MEM_OP(SPI_MEM_OP_CMD(0xbb, 1),				\		   SPI_MEM_OP_ADDR(2, addr, 2),				\		   SPI_MEM_OP_DUMMY(ndummy, 2),				\		   SPI_MEM_OP_DATA_IN(len, buf, 2),			\		   SPI_MEM_OP_MAX_FREQ(freq)) #define SPINAND_PAGE_READ_FROM_CACHE_3A_1S_2S_2S_OP(addr, ndummy, buf, len, freq) \	SPI_MEM_OP(SPI_MEM_OP_CMD(0xbb, 1),				\		   SPI_MEM_OP_ADDR(3, addr, 2),				\		   SPI_MEM_OP_DUMMY(ndummy, 2),				\		   SPI_MEM_OP_DATA_IN(len, buf, 2),			\		   SPI_MEM_OP_MAX_FREQ(freq)) #define SPINAND_PAGE_READ_FROM_CACHE_1S_2D_2D_OP(addr, ndummy, buf, len, freq) \	SPI_MEM_OP(SPI_MEM_OP_CMD(0xbd, 1),				\		   SPI_MEM_DTR_OP_ADDR(2, addr, 2),			\		   SPI_MEM_DTR_OP_DUMMY(ndummy, 2),			\		   SPI_MEM_DTR_OP_DATA_IN(len, buf, 2),			\		   SPI_MEM_OP_MAX_FREQ(freq)) #define SPINAND_PAGE_READ_FROM_CACHE_1S_1S_4S_OP(addr, ndummy, buf, len, freq) \	SPI_MEM_OP(SPI_MEM_OP_CMD(0x6b, 1),				\		   SPI_MEM_OP_ADDR(2, addr, 1),				\		   SPI_MEM_OP_DUMMY(ndummy, 1),				\		   SPI_MEM_OP_DATA_IN(len, buf, 4),			\		   SPI_MEM_OP_MAX_FREQ(freq)) #define SPINAND_PAGE_READ_FROM_CACHE_3A_1S_1S_4S_OP(addr, ndummy, buf, len, freq) \	SPI_MEM_OP(SPI_MEM_OP_CMD(0x6b, 1),				\		   SPI_MEM_OP_ADDR(3, addr, 1),				\		   SPI_MEM_OP_DUMMY(ndummy, 1),				\		   SPI_MEM_OP_DATA_IN(len, buf, 4),			\		   SPI_MEM_OP_MAX_FREQ(freq)) #define SPINAND_PAGE_READ_FROM_CACHE_1S_1D_4D_OP(addr, ndummy, buf, len, freq) \	SPI_MEM_OP(SPI_MEM_OP_CMD(0x6d, 1),				\		   SPI_MEM_DTR_OP_ADDR(2, addr, 1),			\		   SPI_MEM_DTR_OP_DUMMY(ndummy, 1),			\		   SPI_MEM_DTR_OP_DATA_IN(len, buf, 4),			\		   SPI_MEM_OP_MAX_FREQ(freq)) #define SPINAND_PAGE_READ_FROM_CACHE_1S_4S_4S_OP(addr, ndummy, buf, len, freq) \	SPI_MEM_OP(SPI_MEM_OP_CMD(0xeb, 1),				\		   SPI_MEM_OP_ADDR(2, addr, 4),				\		   SPI_MEM_OP_DUMMY(ndummy, 4),				\		   SPI_MEM_OP_DATA_IN(len, buf, 4),			\		   SPI_MEM_OP_MAX_FREQ(freq)) #define SPINAND_PAGE_READ_FROM_CACHE_3A_1S_4S_4S_OP(addr, ndummy, buf, len, freq) \	SPI_MEM_OP(SPI_MEM_OP_CMD(0xeb, 1),				\		   SPI_MEM_OP_ADDR(3, addr, 4),				\		   SPI_MEM_OP_DUMMY(ndummy, 4),				\		   SPI_MEM_OP_DATA_IN(len, buf, 4),			\		   SPI_MEM_OP_MAX_FREQ(freq)) #define SPINAND_PAGE_READ_FROM_CACHE_1S_4D_4D_OP(addr, ndummy, buf, len, freq) \	SPI_MEM_OP(SPI_MEM_OP_CMD(0xed, 1),				\		   SPI_MEM_DTR_OP_ADDR(2, addr, 4),			\		   SPI_MEM_DTR_OP_DUMMY(ndummy, 4),			\		   SPI_MEM_DTR_OP_DATA_IN(len, buf, 4),			\		   SPI_MEM_OP_MAX_FREQ(freq)) #define SPINAND_PAGE_READ_FROM_CACHE_1S_1S_8S_OP(addr, ndummy, buf, len, freq) \	SPI_MEM_OP(SPI_MEM_OP_CMD(0x8b, 1),				\		   SPI_MEM_OP_ADDR(2, addr, 1),				\		   SPI_MEM_OP_DUMMY(ndummy, 1),				\		   SPI_MEM_OP_DATA_IN(len, buf, 8),			\		   SPI_MEM_OP_MAX_FREQ(freq)) #define SPINAND_PAGE_READ_FROM_CACHE_1S_8S_8S_OP(addr, ndummy, buf, len, freq) \	SPI_MEM_OP(SPI_MEM_OP_CMD(0xcb, 1),				\		   SPI_MEM_OP_ADDR(2, addr, 8),				\		   SPI_MEM_OP_DUMMY(ndummy, 8),				\		   SPI_MEM_OP_DATA_IN(len, buf, 8),			\		   SPI_MEM_OP_MAX_FREQ(freq)) #define SPINAND_PAGE_READ_FROM_CACHE_1S_1D_8D_OP(addr, ndummy, buf, len, freq) \	SPI_MEM_OP(SPI_MEM_OP_CMD(0x9d, 1),				\		   SPI_MEM_DTR_OP_ADDR(2, addr, 1),			\		   SPI_MEM_DTR_OP_DUMMY(ndummy, 1),			\		   SPI_MEM_DTR_OP_DATA_IN(len, buf, 8),			\		   SPI_MEM_OP_MAX_FREQ(freq)) #define SPINAND_PROG_EXEC_1S_1S_0_OP(addr)				\	SPI_MEM_OP(SPI_MEM_OP_CMD(0x10, 1),				\		   SPI_MEM_OP_ADDR(3, addr, 1),				\		   SPI_MEM_OP_NO_DUMMY,					\		   SPI_MEM_OP_NO_DATA) #define SPINAND_PROG_LOAD_1S_1S_1S_OP(reset, addr, buf, len)		\	SPI_MEM_OP(SPI_MEM_OP_CMD(reset ? 0x02 : 0x84, 1),		\		   SPI_MEM_OP_ADDR(2, addr, 1),				\		   SPI_MEM_OP_NO_DUMMY,					\		   SPI_MEM_OP_DATA_OUT(len, buf, 1)) #define SPINAND_PROG_LOAD_1S_1S_4S_OP(reset, addr, buf, len)		\	SPI_MEM_OP(SPI_MEM_OP_CMD(reset ? 0x32 : 0x34, 1),		\		   SPI_MEM_OP_ADDR(2, addr, 1),				\		   SPI_MEM_OP_NO_DUMMY,					\		   SPI_MEM_OP_DATA_OUT(len, buf, 4)) #define SPINAND_PROG_LOAD_1S_1S_8S_OP(addr, buf, len)			\	SPI_MEM_OP(SPI_MEM_OP_CMD(0x82, 1),				\		   SPI_MEM_OP_ADDR(2, addr, 1),				\		   SPI_MEM_OP_NO_DUMMY,					\		   SPI_MEM_OP_DATA_OUT(len, buf, 8)) #define SPINAND_PROG_LOAD_1S_8S_8S_OP(reset, addr, buf, len)		\	SPI_MEM_OP(SPI_MEM_OP_CMD(reset ? 0xc2 : 0xc4, 1),		\		   SPI_MEM_OP_ADDR(2, addr, 8),				\		   SPI_MEM_OP_NO_DUMMY,					\		   SPI_MEM_OP_DATA_OUT(len, buf, 8)) /** * Octal DDR SPI NAND flash operations */ #define SPINAND_RESET_8D_0_0_OP						\	SPI_MEM_OP(SPI_MEM_DTR_OP_RPT_CMD(0xff, 8),			\		   SPI_MEM_OP_NO_ADDR,					\		   SPI_MEM_OP_NO_DUMMY,					\		   SPI_MEM_OP_NO_DATA) #define SPINAND_READID_8D_8D_8D_OP(naddr, ndummy, buf, len)		\	SPI_MEM_OP(SPI_MEM_DTR_OP_RPT_CMD(0x9f, 8),			\		   SPI_MEM_DTR_OP_ADDR(naddr, 0, 8),			\		   SPI_MEM_DTR_OP_DUMMY(ndummy, 8),			\		   SPI_MEM_DTR_OP_DATA_IN(len, buf, 8)) #define SPINAND_WR_EN_8D_0_0_OP						\	SPI_MEM_OP(SPI_MEM_DTR_OP_RPT_CMD(0x06, 8),			\		   SPI_MEM_OP_NO_ADDR,					\		   SPI_MEM_OP_NO_DUMMY,					\		   SPI_MEM_OP_NO_DATA) #define SPINAND_WR_DIS_8D_0_0_OP					\	SPI_MEM_OP(SPI_MEM_DTR_OP_RPT_CMD(0x04, 8),			\		   SPI_MEM_OP_NO_ADDR,					\		   SPI_MEM_OP_NO_DUMMY,					\		   SPI_MEM_OP_NO_DATA) #define SPINAND_SET_FEATURE_8D_8D_8D_OP(reg, valptr)			\	SPI_MEM_OP(SPI_MEM_DTR_OP_RPT_CMD(0x1f, 8),			\		   SPI_MEM_DTR_OP_RPT_ADDR(reg, 8),			\		   SPI_MEM_OP_NO_DUMMY,					\		   SPI_MEM_DTR_OP_DATA_OUT(2, valptr, 8)) #define SPINAND_GET_FEATURE_8D_8D_8D_OP(reg, valptr)			\	SPI_MEM_OP(SPI_MEM_DTR_OP_RPT_CMD(0x0f, 8),			\		   SPI_MEM_DTR_OP_RPT_ADDR(reg, 8),			\		   SPI_MEM_DTR_OP_DUMMY(14, 8),				\		   SPI_MEM_DTR_OP_DATA_IN(2, valptr, 8)) #define SPINAND_BLK_ERASE_8D_8D_0_OP(addr)				\	SPI_MEM_OP(SPI_MEM_DTR_OP_RPT_CMD(0xd8, 8),			\		   SPI_MEM_DTR_OP_ADDR(2, addr, 8),			\		   SPI_MEM_OP_NO_DUMMY,					\		   SPI_MEM_OP_NO_DATA) #define SPINAND_PAGE_READ_8D_8D_0_OP(addr)				\	SPI_MEM_OP(SPI_MEM_DTR_OP_RPT_CMD(0x13, 8),			\		   SPI_MEM_DTR_OP_ADDR(2, addr, 8),			\		   SPI_MEM_OP_NO_DUMMY,					\		   SPI_MEM_OP_NO_DATA) #define SPINAND_PAGE_READ_PACKED_8D_8D_0_OP(addr)			\	SPI_MEM_OP(SPI_MEM_DTR_OP_PACKED_CMD(0x13, addr >> 16, 8),	\		   SPI_MEM_DTR_OP_ADDR(2, addr & 0xffff, 8),		\		   SPI_MEM_OP_NO_DUMMY,					\		   SPI_MEM_OP_NO_DATA) #define SPINAND_PAGE_READ_FROM_CACHE_8D_8D_8D_OP(addr, ndummy, buf, len, freq) \	SPI_MEM_OP(SPI_MEM_DTR_OP_RPT_CMD(0x9d, 8),			\		   SPI_MEM_DTR_OP_ADDR(2, addr, 8),			\		   SPI_MEM_DTR_OP_DUMMY(ndummy, 8),			\		   SPI_MEM_DTR_OP_DATA_IN(len, buf, 8),			\		   SPI_MEM_OP_MAX_FREQ(freq)) #define SPINAND_PROG_EXEC_8D_8D_0_OP(addr)				\	SPI_MEM_OP(SPI_MEM_DTR_OP_RPT_CMD(0x10, 8),			\		   SPI_MEM_DTR_OP_ADDR(2, addr, 8),			\		   SPI_MEM_OP_NO_DUMMY,					\		   SPI_MEM_OP_NO_DATA) #define SPINAND_PROG_LOAD_8D_8D_8D_OP(reset, addr, buf, len)		\	SPI_MEM_OP(SPI_MEM_DTR_OP_RPT_CMD((reset ? 0xc2 : 0xc4), 8),	\		   SPI_MEM_DTR_OP_ADDR(2, addr, 8),			\		   SPI_MEM_OP_NO_DUMMY,					\		   SPI_MEM_DTR_OP_DATA_OUT(len, buf, 8)) /* feature register */#define REG_BLOCK_LOCK		0xa0#define BL_ALL_UNLOCKED		0x00 /* configuration register */#define REG_CFG			0xb0#define CFG_OTP_ENABLE		BIT(6)#define CFG_ECC_ENABLE		BIT(4)#define CFG_QUAD_ENABLE		BIT(0) /* status register */#define REG_STATUS		0xc0#define STATUS_BUSY		BIT(0)#define STATUS_ERASE_FAILED	BIT(2)#define STATUS_PROG_FAILED	BIT(3)#define STATUS_ECC_MASK		GENMASK(5, 4)#define STATUS_ECC_NO_BITFLIPS	(0 << 4)#define STATUS_ECC_HAS_BITFLIPS	(1 << 4)#define STATUS_ECC_UNCOR_ERROR	(2 << 4) struct spinand_op;struct spinand_device; #define SPINAND_MAX_ID_LEN	6/* * For erase, write and read operation, we got the following timings : * tBERS (erase) 1ms to 4ms * tPROG 300us to 400us * tREAD 25us to 100us * In order to minimize latency, the min value is divided by 4 for the * initial delay, and dividing by 20 for the poll delay. * For reset, 5us/10us/500us if the device is respectively * reading/programming/erasing when the RESET occurs. Since we always * issue a RESET when the device is IDLE, 5us is selected for both initial * and poll delay. */#define SPINAND_READ_INITIAL_DELAY_US	6#define SPINAND_READ_POLL_DELAY_US	5#define SPINAND_RESET_INITIAL_DELAY_US	5#define SPINAND_RESET_POLL_DELAY_US	5#define SPINAND_WRITE_INITIAL_DELAY_US	75#define SPINAND_WRITE_POLL_DELAY_US	15#define SPINAND_ERASE_INITIAL_DELAY_US	250#define SPINAND_ERASE_POLL_DELAY_US	50 #define SPINAND_WAITRDY_TIMEOUT_MS	400 /** * struct spinand_id - SPI NAND id structure * @data: buffer containing the id bytes. Currently 6 bytes large, but can *	  be extended if required * @len: ID length */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 * @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 initialized properly. */struct spinand_manufacturer_ops {	int (*init)(struct spinand_device *spinand);	void (*cleanup)(struct spinand_device *spinand);}; /** * 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;}; /* SPI NAND manufacturers */extern const struct spinand_manufacturer alliancememory_spinand_manufacturer;extern const struct spinand_manufacturer ato_spinand_manufacturer;extern const struct spinand_manufacturer dosilicon_spinand_manufacturer;extern const struct spinand_manufacturer esmt_8c_spinand_manufacturer;extern const struct spinand_manufacturer esmt_c8_spinand_manufacturer;extern const struct spinand_manufacturer fmsh_spinand_manufacturer;extern const struct spinand_manufacturer foresee_spinand_manufacturer;extern const struct spinand_manufacturer gigadevice_spinand_manufacturer;extern const struct spinand_manufacturer heyangtek_spinand_manufacturer;extern const struct spinand_manufacturer macronix_spinand_manufacturer;extern const struct spinand_manufacturer micron_spinand_manufacturer;extern const struct spinand_manufacturer paragon_spinand_manufacturer;extern const struct spinand_manufacturer skyhigh_spinand_manufacturer;extern const struct spinand_manufacturer toshiba_spinand_manufacturer;extern const struct spinand_manufacturer winbond_spinand_manufacturer;extern const struct spinand_manufacturer xtx_spinand_manufacturer; /** * struct spinand_op_variants - SPI NAND operation variants * @ops: the list of variants for a given operation * @nops: the number of variants * * Some operations like read-from-cache/write-to-cache have several variants * depending on the number of IO lines you use to transfer data or address * cycles. This structure is a way to describe the different variants supported * by a chip and let the core pick the best one based on the SPI mem controller * capabilities. */struct spinand_op_variants {	const struct spi_mem_op *ops;	unsigned int nops;}; #define SPINAND_OP_VARIANTS(name, ...)					\	const struct spinand_op_variants name = {			\		.ops = (struct spi_mem_op[]) { __VA_ARGS__ },		\		.nops = sizeof((struct spi_mem_op[]){ __VA_ARGS__ }) /	\			sizeof(struct spi_mem_op),			\	} /** * spinand_ecc_info - description of the on-die ECC implemented by a SPI NAND *		      chip * @get_status: get the ECC status. Should return a positive number encoding *		the number of corrected bitflips if correction was possible or *		-EBADMSG if there are uncorrectable errors. I can also return *		other negative error codes if the error is not caused by *		uncorrectable bitflips * @ooblayout: the OOB layout used by the on-die ECC implementation */struct spinand_ecc_info {	int (*get_status)(struct spinand_device *spinand, u8 status);	const struct mtd_ooblayout_ops *ooblayout;}; /* SPI NAND flags */#define SPINAND_HAS_QE_BIT				BIT(0)#define SPINAND_HAS_CR_FEAT_BIT				BIT(1)#define SPINAND_HAS_PROG_PLANE_SELECT_BIT		BIT(2)#define SPINAND_HAS_READ_PLANE_SELECT_BIT		BIT(3)#define SPINAND_NO_RAW_ACCESS				BIT(4)#define SPINAND_ODTR_PACKED_PAGE_READ			BIT(5) /** * struct spinand_ondie_ecc_conf - private SPI-NAND on-die ECC engine structure * @status: status of the last wait operation that will be used in case *          ->get_status() is not populated by the spinand device. */struct spinand_ondie_ecc_conf {

Lines 1–500 of 927.