mtd: spi: Switch to new SPI NOR framework
Switch spi_flash_* interfaces to call into new SPI NOR framework via MTD layer. Fix up sf_dataflash to work in legacy way. And update sandbox to use new interfaces/definitions Signed-off-by: Vignesh R <vigneshr@ti.com> Tested-by: Simon Goldschmidt <simon.k.r.goldschmidt@gmail.com> Tested-by: Stefan Roese <sr@denx.de> Tested-by: Horatiu Vultur <horatiu.vultur@microchip.com> Reviewed-by: Jagan Teki <jagan@openedev.com> Tested-by: Jagan Teki <jagan@amarulasolutions.com> #zynq-microzed
This commit is contained in:
		
							parent
							
								
									2ee6705be0
								
							
						
					
					
						commit
						c4e8862308
					
				|  | @ -27,6 +27,8 @@ config SPI_FLASH_SANDBOX | |||
| 
 | ||||
| config SPI_FLASH | ||||
| 	bool "Legacy SPI Flash Interface support" | ||||
| 	depends on SPI | ||||
| 	select SPI_MEM | ||||
| 	help | ||||
| 	  Enable the legacy SPI flash support. This will include basic | ||||
| 	  standard support for things like probing, read / write, and | ||||
|  |  | |||
|  | @ -9,7 +9,7 @@ ifdef CONFIG_SPL_BUILD | |||
| obj-$(CONFIG_SPL_SPI_BOOT)	+= fsl_espi_spl.o | ||||
| endif | ||||
| 
 | ||||
| obj-$(CONFIG_SPI_FLASH) += sf_probe.o spi_flash.o spi_flash_ids.o sf.o | ||||
| obj-$(CONFIG_SPI_FLASH_DATAFLASH) += sf_dataflash.o | ||||
| obj-$(CONFIG_SPI_FLASH) += sf_probe.o spi-nor-core.o | ||||
| obj-$(CONFIG_SPI_FLASH_DATAFLASH) += sf_dataflash.o sf.o | ||||
| obj-$(CONFIG_SPI_FLASH_MTD) += sf_mtd.o | ||||
| obj-$(CONFIG_SPI_FLASH_SANDBOX) += sandbox.o | ||||
|  |  | |||
|  | @ -92,7 +92,7 @@ struct sandbox_spi_flash { | |||
| 	/* The current flash status (see STAT_XXX defines above) */ | ||||
| 	u16 status; | ||||
| 	/* Data describing the flash we're emulating */ | ||||
| 	const struct spi_flash_info *data; | ||||
| 	const struct flash_info *data; | ||||
| 	/* The file on disk to serv up data from */ | ||||
| 	int fd; | ||||
| }; | ||||
|  | @ -122,7 +122,7 @@ static int sandbox_sf_probe(struct udevice *dev) | |||
| 	/* spec = idcode:file */ | ||||
| 	struct sandbox_spi_flash *sbsf = dev_get_priv(dev); | ||||
| 	size_t len, idname_len; | ||||
| 	const struct spi_flash_info *data; | ||||
| 	const struct flash_info *data; | ||||
| 	struct sandbox_spi_flash_plat_data *pdata = dev_get_platdata(dev); | ||||
| 	struct sandbox_state *state = state_get_current(); | ||||
| 	struct dm_spi_slave_platdata *slave_plat; | ||||
|  | @ -155,7 +155,7 @@ static int sandbox_sf_probe(struct udevice *dev) | |||
| 	idname_len = strlen(spec); | ||||
| 	debug("%s: device='%s'\n", __func__, spec); | ||||
| 
 | ||||
| 	for (data = spi_flash_ids; data->name; data++) { | ||||
| 	for (data = spi_nor_ids; data->name; data++) { | ||||
| 		len = strlen(data->name); | ||||
| 		if (idname_len != len) | ||||
| 			continue; | ||||
|  | @ -243,43 +243,43 @@ static int sandbox_sf_process_cmd(struct sandbox_spi_flash *sbsf, const u8 *rx, | |||
| 
 | ||||
| 	sbsf->cmd = rx[0]; | ||||
| 	switch (sbsf->cmd) { | ||||
| 	case CMD_READ_ID: | ||||
| 	case SPINOR_OP_RDID: | ||||
| 		sbsf->state = SF_ID; | ||||
| 		sbsf->cmd = SF_ID; | ||||
| 		break; | ||||
| 	case CMD_READ_ARRAY_FAST: | ||||
| 	case SPINOR_OP_READ_FAST: | ||||
| 		sbsf->pad_addr_bytes = 1; | ||||
| 	case CMD_READ_ARRAY_SLOW: | ||||
| 	case CMD_PAGE_PROGRAM: | ||||
| 	case SPINOR_OP_READ: | ||||
| 	case SPINOR_OP_PP: | ||||
| 		sbsf->state = SF_ADDR; | ||||
| 		break; | ||||
| 	case CMD_WRITE_DISABLE: | ||||
| 	case SPINOR_OP_WRDI: | ||||
| 		debug(" write disabled\n"); | ||||
| 		sbsf->status &= ~STAT_WEL; | ||||
| 		break; | ||||
| 	case CMD_READ_STATUS: | ||||
| 	case SPINOR_OP_RDSR: | ||||
| 		sbsf->state = SF_READ_STATUS; | ||||
| 		break; | ||||
| 	case CMD_READ_STATUS1: | ||||
| 	case SPINOR_OP_RDSR2: | ||||
| 		sbsf->state = SF_READ_STATUS1; | ||||
| 		break; | ||||
| 	case CMD_WRITE_ENABLE: | ||||
| 	case SPINOR_OP_WREN: | ||||
| 		debug(" write enabled\n"); | ||||
| 		sbsf->status |= STAT_WEL; | ||||
| 		break; | ||||
| 	case CMD_WRITE_STATUS: | ||||
| 	case SPINOR_OP_WRSR: | ||||
| 		sbsf->state = SF_WRITE_STATUS; | ||||
| 		break; | ||||
| 	default: { | ||||
| 		int flags = sbsf->data->flags; | ||||
| 
 | ||||
| 		/* we only support erase here */ | ||||
| 		if (sbsf->cmd == CMD_ERASE_CHIP) { | ||||
| 		if (sbsf->cmd == SPINOR_OP_CHIP_ERASE) { | ||||
| 			sbsf->erase_size = sbsf->data->sector_size * | ||||
| 				sbsf->data->n_sectors; | ||||
| 		} else if (sbsf->cmd == CMD_ERASE_4K && (flags & SECT_4K)) { | ||||
| 		} else if (sbsf->cmd == SPINOR_OP_BE_4K && (flags & SECT_4K)) { | ||||
| 			sbsf->erase_size = 4 << 10; | ||||
| 		} else if (sbsf->cmd == CMD_ERASE_64K && !(flags & SECT_4K)) { | ||||
| 		} else if (sbsf->cmd == SPINOR_OP_SE && !(flags & SECT_4K)) { | ||||
| 			sbsf->erase_size = 64 << 10; | ||||
| 		} else { | ||||
| 			debug(" cmd unknown: %#x\n", sbsf->cmd); | ||||
|  | @ -380,11 +380,11 @@ static int sandbox_sf_xfer(struct udevice *dev, unsigned int bitlen, | |||
| 				return -EIO; | ||||
| 			} | ||||
| 			switch (sbsf->cmd) { | ||||
| 			case CMD_READ_ARRAY_FAST: | ||||
| 			case CMD_READ_ARRAY_SLOW: | ||||
| 			case SPINOR_OP_READ_FAST: | ||||
| 			case SPINOR_OP_READ: | ||||
| 				sbsf->state = SF_READ; | ||||
| 				break; | ||||
| 			case CMD_PAGE_PROGRAM: | ||||
| 			case SPINOR_OP_PP: | ||||
| 				sbsf->state = SF_WRITE; | ||||
| 				break; | ||||
| 			default: | ||||
|  |  | |||
|  | @ -18,6 +18,7 @@ | |||
| 
 | ||||
| #include "sf_internal.h" | ||||
| 
 | ||||
| #define CMD_READ_ID		0x9f | ||||
| /* reads can bypass the buffers */ | ||||
| #define OP_READ_CONTINUOUS	0xE8 | ||||
| #define OP_READ_PAGE		0xD2 | ||||
|  | @ -441,7 +442,7 @@ static int add_dataflash(struct udevice *dev, char *name, int nr_pages, | |||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| struct flash_info { | ||||
| struct data_flash_info { | ||||
| 	char		*name; | ||||
| 
 | ||||
| 	/*
 | ||||
|  | @ -460,7 +461,7 @@ struct flash_info { | |||
| #define IS_POW2PS	0x0001		/* uses 2^N byte pages */ | ||||
| }; | ||||
| 
 | ||||
| static struct flash_info dataflash_data[] = { | ||||
| static struct data_flash_info dataflash_data[] = { | ||||
| 	/*
 | ||||
| 	 * NOTE:  chips with SUP_POW2PS (rev D and up) need two entries, | ||||
| 	 * one with IS_POW2PS and the other without.  The entry with the | ||||
|  | @ -501,12 +502,12 @@ static struct flash_info dataflash_data[] = { | |||
| 	{ "at45db642d",  0x1f2800, 8192, 1024, 10, SUP_POW2PS | IS_POW2PS}, | ||||
| }; | ||||
| 
 | ||||
| static struct flash_info *jedec_probe(struct spi_slave *spi) | ||||
| static struct data_flash_info *jedec_probe(struct spi_slave *spi) | ||||
| { | ||||
| 	int			tmp; | ||||
| 	uint8_t			id[5]; | ||||
| 	uint32_t		jedec; | ||||
| 	struct flash_info	*info; | ||||
| 	struct data_flash_info	*info; | ||||
| 	int status; | ||||
| 
 | ||||
| 	/*
 | ||||
|  | @ -583,7 +584,7 @@ static int spi_dataflash_probe(struct udevice *dev) | |||
| { | ||||
| 	struct spi_slave *spi = dev_get_parent_priv(dev); | ||||
| 	struct spi_flash *spi_flash; | ||||
| 	struct flash_info *info; | ||||
| 	struct data_flash_info *info; | ||||
| 	int status; | ||||
| 
 | ||||
| 	spi_flash = dev_get_uclass_priv(dev); | ||||
|  |  | |||
|  | @ -12,142 +12,63 @@ | |||
| #include <linux/types.h> | ||||
| #include <linux/compiler.h> | ||||
| 
 | ||||
| /* Dual SPI flash memories - see SPI_COMM_DUAL_... */ | ||||
| enum spi_dual_flash { | ||||
| 	SF_SINGLE_FLASH	= 0, | ||||
| 	SF_DUAL_STACKED_FLASH	= BIT(0), | ||||
| 	SF_DUAL_PARALLEL_FLASH	= BIT(1), | ||||
| }; | ||||
| #define SPI_NOR_MAX_ID_LEN	6 | ||||
| #define SPI_NOR_MAX_ADDR_WIDTH	4 | ||||
| 
 | ||||
| enum spi_nor_option_flags { | ||||
| 	SNOR_F_SST_WR		= BIT(0), | ||||
| 	SNOR_F_USE_FSR		= BIT(1), | ||||
| 	SNOR_F_USE_UPAGE	= BIT(3), | ||||
| }; | ||||
| 
 | ||||
| #define SPI_FLASH_3B_ADDR_LEN		3 | ||||
| #define SPI_FLASH_CMD_LEN		(1 + SPI_FLASH_3B_ADDR_LEN) | ||||
| #define SPI_FLASH_16MB_BOUN		0x1000000 | ||||
| 
 | ||||
| /* CFI Manufacture ID's */ | ||||
| #define SPI_FLASH_CFI_MFR_SPANSION	0x01 | ||||
| #define SPI_FLASH_CFI_MFR_STMICRO	0x20 | ||||
| #define SPI_FLASH_CFI_MFR_MICRON	0x2C | ||||
| #define SPI_FLASH_CFI_MFR_MACRONIX	0xc2 | ||||
| #define SPI_FLASH_CFI_MFR_SST		0xbf | ||||
| #define SPI_FLASH_CFI_MFR_WINBOND	0xef | ||||
| #define SPI_FLASH_CFI_MFR_ATMEL		0x1f | ||||
| 
 | ||||
| /* Erase commands */ | ||||
| #define CMD_ERASE_4K			0x20 | ||||
| #define CMD_ERASE_CHIP			0xc7 | ||||
| #define CMD_ERASE_64K			0xd8 | ||||
| 
 | ||||
| /* Write commands */ | ||||
| #define CMD_WRITE_STATUS		0x01 | ||||
| #define CMD_PAGE_PROGRAM		0x02 | ||||
| #define CMD_WRITE_DISABLE		0x04 | ||||
| #define CMD_WRITE_ENABLE		0x06 | ||||
| #define CMD_QUAD_PAGE_PROGRAM		0x32 | ||||
| 
 | ||||
| /* Read commands */ | ||||
| #define CMD_READ_ARRAY_SLOW		0x03 | ||||
| #define CMD_READ_ARRAY_FAST		0x0b | ||||
| #define CMD_READ_DUAL_OUTPUT_FAST	0x3b | ||||
| #define CMD_READ_DUAL_IO_FAST		0xbb | ||||
| #define CMD_READ_QUAD_OUTPUT_FAST	0x6b | ||||
| #define CMD_READ_QUAD_IO_FAST		0xeb | ||||
| #define CMD_READ_ID			0x9f | ||||
| #define CMD_READ_STATUS			0x05 | ||||
| #define CMD_READ_STATUS1		0x35 | ||||
| #define CMD_READ_CONFIG			0x35 | ||||
| #define CMD_FLAG_STATUS			0x70 | ||||
| 
 | ||||
| /* Bank addr access commands */ | ||||
| #ifdef CONFIG_SPI_FLASH_BAR | ||||
| # define CMD_BANKADDR_BRWR		0x17 | ||||
| # define CMD_BANKADDR_BRRD		0x16 | ||||
| # define CMD_EXTNADDR_WREAR		0xC5 | ||||
| # define CMD_EXTNADDR_RDEAR		0xC8 | ||||
| #endif | ||||
| 
 | ||||
| /* Common status */ | ||||
| #define STATUS_WIP			BIT(0) | ||||
| #define STATUS_QEB_WINSPAN		BIT(1) | ||||
| #define STATUS_QEB_MXIC			BIT(6) | ||||
| #define STATUS_PEC			BIT(7) | ||||
| #define SR_BP0				BIT(2)  /* Block protect 0 */ | ||||
| #define SR_BP1				BIT(3)  /* Block protect 1 */ | ||||
| #define SR_BP2				BIT(4)  /* Block protect 2 */ | ||||
| 
 | ||||
| /* Flash timeout values */ | ||||
| #define SPI_FLASH_PROG_TIMEOUT		(2 * CONFIG_SYS_HZ) | ||||
| #define SPI_FLASH_PAGE_ERASE_TIMEOUT	(5 * CONFIG_SYS_HZ) | ||||
| #define SPI_FLASH_SECTOR_ERASE_TIMEOUT	(10 * CONFIG_SYS_HZ) | ||||
| 
 | ||||
| /* SST specific */ | ||||
| #ifdef CONFIG_SPI_FLASH_SST | ||||
| #define SST26_CMD_READ_BPR		0x72 | ||||
| #define SST26_CMD_WRITE_BPR		0x42 | ||||
| 
 | ||||
| #define SST26_BPR_8K_NUM		4 | ||||
| #define SST26_MAX_BPR_REG_LEN		(18 + 1) | ||||
| #define SST26_BOUND_REG_SIZE		((32 + SST26_BPR_8K_NUM * 8) * SZ_1K) | ||||
| 
 | ||||
| enum lock_ctl { | ||||
| 	SST26_CTL_LOCK, | ||||
| 	SST26_CTL_UNLOCK, | ||||
| 	SST26_CTL_CHECK | ||||
| }; | ||||
| 
 | ||||
| # define CMD_SST_BP		0x02    /* Byte Program */ | ||||
| # define CMD_SST_AAI_WP		0xAD	/* Auto Address Incr Word Program */ | ||||
| 
 | ||||
| int sst_write_wp(struct spi_flash *flash, u32 offset, size_t len, | ||||
| 		const void *buf); | ||||
| int sst_write_bp(struct spi_flash *flash, u32 offset, size_t len, | ||||
| 		const void *buf); | ||||
| #endif | ||||
| 
 | ||||
| #define JEDEC_MFR(info)		((info)->id[0]) | ||||
| #define JEDEC_ID(info)		(((info)->id[1]) << 8 | ((info)->id[2])) | ||||
| #define JEDEC_EXT(info)		(((info)->id[3]) << 8 | ((info)->id[4])) | ||||
| #define SPI_FLASH_MAX_ID_LEN	6 | ||||
| 
 | ||||
| struct spi_flash_info { | ||||
| 	/* Device name ([MANUFLETTER][DEVTYPE][DENSITY][EXTRAINFO]) */ | ||||
| 	const char	*name; | ||||
| 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_FLASH_MAX_ID_LEN]; | ||||
| 	u8		id[SPI_NOR_MAX_ID_LEN]; | ||||
| 	u8		id_len; | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * The size listed here is what works with SPINOR_OP_SE, which isn't | ||||
| 	/* The size listed here is what works with SPINOR_OP_SE, which isn't
 | ||||
| 	 * necessarily called a "sector" by the vendor. | ||||
| 	 */ | ||||
| 	u32		sector_size; | ||||
| 	u32		n_sectors; | ||||
| 	unsigned int	sector_size; | ||||
| 	u16		n_sectors; | ||||
| 
 | ||||
| 	u16		page_size; | ||||
| 	u16		addr_width; | ||||
| 
 | ||||
| 	u16		flags; | ||||
| #define SECT_4K			BIT(0)	/* CMD_ERASE_4K works uniformly */ | ||||
| #define E_FSR			BIT(1)	/* use flag status register for */ | ||||
| #define SST_WR			BIT(2)	/* use SST byte/word programming */ | ||||
| #define WR_QPP			BIT(3)	/* use Quad Page Program */ | ||||
| #define RD_QUAD			BIT(4)	/* use Quad Read */ | ||||
| #define RD_DUAL			BIT(5)	/* use Dual Read */ | ||||
| #define RD_QUADIO		BIT(6)	/* use Quad IO Read */ | ||||
| #define RD_DUALIO		BIT(7)	/* use Dual IO Read */ | ||||
| #define RD_FULL			(RD_QUAD | RD_DUAL | RD_QUADIO | RD_DUALIO) | ||||
| #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_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 */ | ||||
| }; | ||||
| 
 | ||||
| extern const struct spi_flash_info spi_flash_ids[]; | ||||
| extern const struct flash_info spi_nor_ids[]; | ||||
| 
 | ||||
| #define JEDEC_MFR(info)	((info)->id[0]) | ||||
| #define JEDEC_ID(info)		(((info)->id[1]) << 8 | ((info)->id[2])) | ||||
| 
 | ||||
| /* Send a single-byte command to the device and read the response */ | ||||
| int spi_flash_cmd(struct spi_slave *spi, u8 cmd, void *response, size_t len); | ||||
|  | @ -167,78 +88,12 @@ int spi_flash_cmd_write(struct spi_slave *spi, const u8 *cmd, size_t cmd_len, | |||
| 		const void *data, size_t data_len); | ||||
| 
 | ||||
| 
 | ||||
| /* Flash erase(sectors) operation, support all possible erase commands */ | ||||
| int spi_flash_cmd_erase_ops(struct spi_flash *flash, u32 offset, size_t len); | ||||
| 
 | ||||
| /* Get software write-protect value (BP bits) */ | ||||
| int spi_flash_cmd_get_sw_write_prot(struct spi_flash *flash); | ||||
| 
 | ||||
| /* Lock stmicro spi flash region */ | ||||
| int stm_lock(struct spi_flash *flash, u32 ofs, size_t len); | ||||
| 
 | ||||
| /* Unlock stmicro spi flash region */ | ||||
| int stm_unlock(struct spi_flash *flash, u32 ofs, size_t len); | ||||
| 
 | ||||
| /* Check if a stmicro spi flash region is completely locked */ | ||||
| int stm_is_locked(struct spi_flash *flash, u32 ofs, size_t len); | ||||
| 
 | ||||
| /* Enable writing on the SPI flash */ | ||||
| static inline int spi_flash_cmd_write_enable(struct spi_flash *flash) | ||||
| { | ||||
| 	return spi_flash_cmd(flash->spi, CMD_WRITE_ENABLE, NULL, 0); | ||||
| } | ||||
| 
 | ||||
| /* Disable writing on the SPI flash */ | ||||
| static inline int spi_flash_cmd_write_disable(struct spi_flash *flash) | ||||
| { | ||||
| 	return spi_flash_cmd(flash->spi, CMD_WRITE_DISABLE, NULL, 0); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Used for spi_flash write operation | ||||
|  * - SPI claim | ||||
|  * - spi_flash_cmd_write_enable | ||||
|  * - spi_flash_cmd_write | ||||
|  * - spi_flash_wait_till_ready | ||||
|  * - SPI release | ||||
|  */ | ||||
| int spi_flash_write_common(struct spi_flash *flash, const u8 *cmd, | ||||
| 		size_t cmd_len, const void *buf, size_t buf_len); | ||||
| 
 | ||||
| /*
 | ||||
|  * Flash write operation, support all possible write commands. | ||||
|  * Write the requested data out breaking it up into multiple write | ||||
|  * commands as needed per the write size. | ||||
|  */ | ||||
| int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset, | ||||
| 		size_t len, const void *buf); | ||||
| 
 | ||||
| /*
 | ||||
|  * Same as spi_flash_cmd_read() except it also claims/releases the SPI | ||||
|  * bus. Used as common part of the ->read() operation. | ||||
|  */ | ||||
| int spi_flash_read_common(struct spi_flash *flash, const u8 *cmd, | ||||
| 		size_t cmd_len, void *data, size_t data_len); | ||||
| 
 | ||||
| /* Flash read operation, support all possible read commands */ | ||||
| int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 offset, | ||||
| 		size_t len, void *data); | ||||
| 
 | ||||
| #ifdef CONFIG_SPI_FLASH_MTD | ||||
| int spi_flash_mtd_register(struct spi_flash *flash); | ||||
| void spi_flash_mtd_unregister(void); | ||||
| #endif | ||||
| 
 | ||||
| /**
 | ||||
|  * spi_flash_scan - scan the SPI FLASH | ||||
|  * @flash:	the spi flash structure | ||||
|  * | ||||
|  * The drivers can use this fuction to scan the SPI FLASH. | ||||
|  * In the scanning, it will try to get all the necessary information to | ||||
|  * fill the spi_flash{}. | ||||
|  * | ||||
|  * Return: 0 for success, others for failure. | ||||
|  */ | ||||
| int spi_flash_scan(struct spi_flash *flash); | ||||
| 
 | ||||
| #endif /* _SF_INTERNAL_H_ */ | ||||
|  |  | |||
|  | @ -40,7 +40,7 @@ static int spi_flash_probe_slave(struct spi_flash *flash) | |||
| 		return ret; | ||||
| 	} | ||||
| 
 | ||||
| 	ret = spi_flash_scan(flash); | ||||
| 	ret = spi_nor_scan(flash); | ||||
| 	if (ret) | ||||
| 		goto err_read_id; | ||||
| 
 | ||||
|  | @ -96,32 +96,38 @@ static int spi_flash_std_read(struct udevice *dev, u32 offset, size_t len, | |||
| 			      void *buf) | ||||
| { | ||||
| 	struct spi_flash *flash = dev_get_uclass_priv(dev); | ||||
| 	struct mtd_info *mtd = &flash->mtd; | ||||
| 	size_t retlen; | ||||
| 
 | ||||
| 	return log_ret(spi_flash_cmd_read_ops(flash, offset, len, buf)); | ||||
| 	return log_ret(mtd->_read(mtd, offset, len, &retlen, buf)); | ||||
| } | ||||
| 
 | ||||
| static int spi_flash_std_write(struct udevice *dev, u32 offset, size_t len, | ||||
| 			       const void *buf) | ||||
| { | ||||
| 	struct spi_flash *flash = dev_get_uclass_priv(dev); | ||||
| 	struct mtd_info *mtd = &flash->mtd; | ||||
| 	size_t retlen; | ||||
| 
 | ||||
| #if defined(CONFIG_SPI_FLASH_SST) | ||||
| 	if (flash->flags & SNOR_F_SST_WR) { | ||||
| 		if (flash->spi->mode & SPI_TX_BYTE) | ||||
| 			return sst_write_bp(flash, offset, len, buf); | ||||
| 		else | ||||
| 			return sst_write_wp(flash, offset, len, buf); | ||||
| 	} | ||||
| #endif | ||||
| 
 | ||||
| 	return spi_flash_cmd_write_ops(flash, offset, len, buf); | ||||
| 	return mtd->_write(mtd, offset, len, &retlen, buf); | ||||
| } | ||||
| 
 | ||||
| static int spi_flash_std_erase(struct udevice *dev, u32 offset, size_t len) | ||||
| { | ||||
| 	struct spi_flash *flash = dev_get_uclass_priv(dev); | ||||
| 	struct mtd_info *mtd = &flash->mtd; | ||||
| 	struct erase_info instr; | ||||
| 
 | ||||
| 	return spi_flash_cmd_erase_ops(flash, offset, len); | ||||
| 	if (offset % mtd->erasesize || len % mtd->erasesize) { | ||||
| 		printf("SF: Erase offset/length not multiple of erase size\n"); | ||||
| 		return -EINVAL; | ||||
| 	} | ||||
| 
 | ||||
| 	memset(&instr, 0, sizeof(instr)); | ||||
| 	instr.addr = offset; | ||||
| 	instr.len = len; | ||||
| 
 | ||||
| 	return mtd->_erase(mtd, &instr); | ||||
| } | ||||
| 
 | ||||
| static int spi_flash_std_get_sw_write_prot(struct udevice *dev) | ||||
|  |  | |||
|  | @ -21,6 +21,8 @@ | |||
| #include <spi-mem.h> | ||||
| #include <spi.h> | ||||
| 
 | ||||
| #include "sf_internal.h" | ||||
| 
 | ||||
| /* Define max times to check status register before we give up. */ | ||||
| 
 | ||||
| /*
 | ||||
|  | @ -32,63 +34,6 @@ | |||
| 
 | ||||
| #define DEFAULT_READY_WAIT_JIFFIES		(40UL * HZ) | ||||
| 
 | ||||
| #define SPI_NOR_MAX_ID_LEN	6 | ||||
| #define SPI_NOR_MAX_ADDR_WIDTH	4 | ||||
| 
 | ||||
| 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 int	sector_size; | ||||
| 	u16		n_sectors; | ||||
| 
 | ||||
| 	u16		page_size; | ||||
| 	u16		addr_width; | ||||
| 
 | ||||
| 	u16		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_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 */ | ||||
| 
 | ||||
| 	int	(*quad_enable)(struct spi_nor *nor); | ||||
| }; | ||||
| 
 | ||||
| #define JEDEC_MFR(info)	((info)->id[0]) | ||||
| 
 | ||||
| static int spi_nor_read_write_reg(struct spi_nor *nor, struct spi_mem_op | ||||
| 		*op, void *buf) | ||||
| { | ||||
|  |  | |||
|  | @ -271,9 +271,9 @@ static void _stm32_qspi_enable_mmap(struct stm32_qspi_priv *priv, | |||
| { | ||||
| 	unsigned int ccr_reg; | ||||
| 
 | ||||
| 	priv->command = flash->read_cmd | CMD_HAS_ADR | CMD_HAS_DATA | ||||
| 	priv->command = flash->read_opcode | CMD_HAS_ADR | CMD_HAS_DATA | ||||
| 			| CMD_HAS_DUMMY; | ||||
| 	priv->dummycycles = flash->dummy_byte * 8; | ||||
| 	priv->dummycycles = flash->read_dummy; | ||||
| 
 | ||||
| 	ccr_reg = _stm32_qspi_gen_ccr(priv, STM32_QSPI_CCR_MEM_MAP); | ||||
| 
 | ||||
|  |  | |||
|  | @ -11,6 +11,7 @@ | |||
| 
 | ||||
| #include <dm.h>	/* Because we dereference struct udevice here */ | ||||
| #include <linux/types.h> | ||||
| #include <linux/mtd/spi-nor.h> | ||||
| 
 | ||||
| #ifndef CONFIG_SF_DEFAULT_SPEED | ||||
| # define CONFIG_SF_DEFAULT_SPEED	1000000 | ||||
|  | @ -27,86 +28,6 @@ | |||
| 
 | ||||
| struct spi_slave; | ||||
| 
 | ||||
| /**
 | ||||
|  * struct spi_flash - SPI flash structure | ||||
|  * | ||||
|  * @spi:		SPI slave | ||||
|  * @dev:		SPI flash device | ||||
|  * @name:		Name of SPI flash | ||||
|  * @dual_flash:		Indicates dual flash memories - dual stacked, parallel | ||||
|  * @shift:		Flash shift useful in dual parallel | ||||
|  * @flags:		Indication of spi flash flags | ||||
|  * @size:		Total flash size | ||||
|  * @page_size:		Write (page) size | ||||
|  * @sector_size:	Sector size | ||||
|  * @erase_size:		Erase size | ||||
|  * @bank_read_cmd:	Bank read cmd | ||||
|  * @bank_write_cmd:	Bank write cmd | ||||
|  * @bank_curr:		Current flash bank | ||||
|  * @erase_cmd:		Erase cmd 4K, 32K, 64K | ||||
|  * @read_cmd:		Read cmd - Array Fast, Extn read and quad read. | ||||
|  * @write_cmd:		Write cmd - page and quad program. | ||||
|  * @dummy_byte:		Dummy cycles for read operation. | ||||
|  * @memory_map:		Address of read-only SPI flash access | ||||
|  * @flash_lock:		lock a region of the SPI Flash | ||||
|  * @flash_unlock:	unlock a region of the SPI Flash | ||||
|  * @flash_is_locked:	check if a region of the SPI Flash is completely locked | ||||
|  * @read:		Flash read ops: Read len bytes at offset into buf | ||||
|  *			Supported cmds: Fast Array Read | ||||
|  * @write:		Flash write ops: Write len bytes from buf into offset | ||||
|  *			Supported cmds: Page Program | ||||
|  * @erase:		Flash erase ops: Erase len bytes from offset | ||||
|  *			Supported cmds: Sector erase 4K, 32K, 64K | ||||
|  * return 0 - Success, 1 - Failure | ||||
|  */ | ||||
| struct spi_flash { | ||||
| 	struct spi_slave *spi; | ||||
| #ifdef CONFIG_DM_SPI_FLASH | ||||
| 	struct udevice *dev; | ||||
| #endif | ||||
| 	const char *name; | ||||
| 	u8 dual_flash; | ||||
| 	u8 shift; | ||||
| 	u16 flags; | ||||
| 
 | ||||
| 	u32 size; | ||||
| 	u32 page_size; | ||||
| 	u32 sector_size; | ||||
| 	u32 erase_size; | ||||
| #ifdef CONFIG_SPI_FLASH_BAR | ||||
| 	u8 bank_read_cmd; | ||||
| 	u8 bank_write_cmd; | ||||
| 	u8 bank_curr; | ||||
| #endif | ||||
| 	u8 erase_cmd; | ||||
| 	u8 read_cmd; | ||||
| 	u8 write_cmd; | ||||
| 	u8 dummy_byte; | ||||
| 
 | ||||
| 	void *memory_map; | ||||
| 
 | ||||
| 	int (*flash_lock)(struct spi_flash *flash, u32 ofs, size_t len); | ||||
| 	int (*flash_unlock)(struct spi_flash *flash, u32 ofs, size_t len); | ||||
| 	int (*flash_is_locked)(struct spi_flash *flash, u32 ofs, size_t len); | ||||
| #ifndef CONFIG_DM_SPI_FLASH | ||||
| 	/*
 | ||||
| 	 * These are not strictly needed for driver model, but keep them here | ||||
| 	 * while the transition is in progress. | ||||
| 	 * | ||||
| 	 * Normally each driver would provide its own operations, but for | ||||
| 	 * SPI flash most chips use the same algorithms. One approach is | ||||
| 	 * to create a 'common' SPI flash device which knows how to talk | ||||
| 	 * to most devices, and then allow other drivers to be used instead | ||||
| 	 * if required, perhaps with a way of scanning through the list to | ||||
| 	 * find the driver that matches the device. | ||||
| 	 */ | ||||
| 	int (*read)(struct spi_flash *flash, u32 offset, size_t len, void *buf); | ||||
| 	int (*write)(struct spi_flash *flash, u32 offset, size_t len, | ||||
| 			const void *buf); | ||||
| 	int (*erase)(struct spi_flash *flash, u32 offset, size_t len); | ||||
| #endif | ||||
| }; | ||||
| 
 | ||||
| struct dm_spi_flash_ops { | ||||
| 	int (*read)(struct udevice *dev, u32 offset, size_t len, void *buf); | ||||
| 	int (*write)(struct udevice *dev, u32 offset, size_t len, | ||||
|  | @ -225,19 +146,37 @@ void spi_flash_free(struct spi_flash *flash); | |||
| static inline int spi_flash_read(struct spi_flash *flash, u32 offset, | ||||
| 		size_t len, void *buf) | ||||
| { | ||||
| 	return flash->read(flash, offset, len, buf); | ||||
| 	struct mtd_info *mtd = &flash->mtd; | ||||
| 	size_t retlen; | ||||
| 
 | ||||
| 	return mtd->_read(mtd, offset, len, &retlen, buf); | ||||
| } | ||||
| 
 | ||||
| static inline int spi_flash_write(struct spi_flash *flash, u32 offset, | ||||
| 		size_t len, const void *buf) | ||||
| { | ||||
| 	return flash->write(flash, offset, len, buf); | ||||
| 	struct mtd_info *mtd = &flash->mtd; | ||||
| 	size_t retlen; | ||||
| 
 | ||||
| 	return mtd->_write(mtd, offset, len, &retlen, buf); | ||||
| } | ||||
| 
 | ||||
| static inline int spi_flash_erase(struct spi_flash *flash, u32 offset, | ||||
| 		size_t len) | ||||
| { | ||||
| 	return flash->erase(flash, offset, len); | ||||
| 	struct mtd_info *mtd = &flash->mtd; | ||||
| 	struct erase_info instr; | ||||
| 
 | ||||
| 	if (offset % mtd->erasesize || len % mtd->erasesize) { | ||||
| 		printf("SF: Erase offset/length not multiple of erase size\n"); | ||||
| 		return -EINVAL; | ||||
| 	} | ||||
| 
 | ||||
| 	memset(&instr, 0, sizeof(instr)); | ||||
| 	instr.addr = offset; | ||||
| 	instr.len = len; | ||||
| 
 | ||||
| 	return mtd->_erase(mtd, &instr); | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue