mtd: spi-nor-core: Add octal mode support
Add support for Octal flash devices. Octal flash devices use 8 IO lines for data transfer. Currently only 1-1-8 Octal Read mode is supported. Signed-off-by: Vignesh Raghavendra <vigneshr@ti.com> Reviewed-by: Jagan Teki <jagan@amarulasolutions.com>
This commit is contained in:
		
							parent
							
								
									ffab212123
								
							
						
					
					
						commit
						658df8bd94
					
				|  | @ -37,7 +37,7 @@ struct flash_info { | ||||||
| 	u16		page_size; | 	u16		page_size; | ||||||
| 	u16		addr_width; | 	u16		addr_width; | ||||||
| 
 | 
 | ||||||
| 	u16		flags; | 	u32		flags; | ||||||
| #define SECT_4K			BIT(0)	/* SPINOR_OP_BE_4K works uniformly */ | #define SECT_4K			BIT(0)	/* SPINOR_OP_BE_4K works uniformly */ | ||||||
| #define SPI_NOR_NO_ERASE	BIT(1)	/* No erase command needed */ | #define SPI_NOR_NO_ERASE	BIT(1)	/* No erase command needed */ | ||||||
| #define SST_WRITE		BIT(2)	/* use SST byte programming */ | #define SST_WRITE		BIT(2)	/* use SST byte programming */ | ||||||
|  | @ -66,6 +66,7 @@ struct flash_info { | ||||||
| #define SPI_NOR_SKIP_SFDP	BIT(13)	/* Skip parsing of SFDP tables */ | #define SPI_NOR_SKIP_SFDP	BIT(13)	/* Skip parsing of SFDP tables */ | ||||||
| #define USE_CLSR		BIT(14)	/* use CLSR command */ | #define USE_CLSR		BIT(14)	/* use CLSR command */ | ||||||
| #define SPI_NOR_HAS_SST26LOCK	BIT(15)	/* Flash supports lock/unlock via BPR */ | #define SPI_NOR_HAS_SST26LOCK	BIT(15)	/* Flash supports lock/unlock via BPR */ | ||||||
|  | #define SPI_NOR_OCTAL_READ      BIT(16) /* Flash supports Octal Read */ | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| extern const struct flash_info spi_nor_ids[]; | extern const struct flash_info spi_nor_ids[]; | ||||||
|  |  | ||||||
|  | @ -251,6 +251,8 @@ static u8 spi_nor_convert_3to4_read(u8 opcode) | ||||||
| 		{ SPINOR_OP_READ_1_2_2,	SPINOR_OP_READ_1_2_2_4B }, | 		{ SPINOR_OP_READ_1_2_2,	SPINOR_OP_READ_1_2_2_4B }, | ||||||
| 		{ SPINOR_OP_READ_1_1_4,	SPINOR_OP_READ_1_1_4_4B }, | 		{ SPINOR_OP_READ_1_1_4,	SPINOR_OP_READ_1_1_4_4B }, | ||||||
| 		{ SPINOR_OP_READ_1_4_4,	SPINOR_OP_READ_1_4_4_4B }, | 		{ SPINOR_OP_READ_1_4_4,	SPINOR_OP_READ_1_4_4_4B }, | ||||||
|  | 		{ SPINOR_OP_READ_1_1_8,	SPINOR_OP_READ_1_1_8_4B }, | ||||||
|  | 		{ SPINOR_OP_READ_1_8_8,	SPINOR_OP_READ_1_8_8_4B }, | ||||||
| 
 | 
 | ||||||
| 		{ SPINOR_OP_READ_1_1_1_DTR,	SPINOR_OP_READ_1_1_1_DTR_4B }, | 		{ SPINOR_OP_READ_1_1_1_DTR,	SPINOR_OP_READ_1_1_1_DTR_4B }, | ||||||
| 		{ SPINOR_OP_READ_1_2_2_DTR,	SPINOR_OP_READ_1_2_2_DTR_4B }, | 		{ SPINOR_OP_READ_1_2_2_DTR,	SPINOR_OP_READ_1_2_2_DTR_4B }, | ||||||
|  | @ -267,6 +269,8 @@ static u8 spi_nor_convert_3to4_program(u8 opcode) | ||||||
| 		{ SPINOR_OP_PP,		SPINOR_OP_PP_4B }, | 		{ SPINOR_OP_PP,		SPINOR_OP_PP_4B }, | ||||||
| 		{ SPINOR_OP_PP_1_1_4,	SPINOR_OP_PP_1_1_4_4B }, | 		{ SPINOR_OP_PP_1_1_4,	SPINOR_OP_PP_1_1_4_4B }, | ||||||
| 		{ SPINOR_OP_PP_1_4_4,	SPINOR_OP_PP_1_4_4_4B }, | 		{ SPINOR_OP_PP_1_4_4,	SPINOR_OP_PP_1_4_4_4B }, | ||||||
|  | 		{ SPINOR_OP_PP_1_1_8,	SPINOR_OP_PP_1_1_8_4B }, | ||||||
|  | 		{ SPINOR_OP_PP_1_8_8,	SPINOR_OP_PP_1_8_8_4B }, | ||||||
| 	}; | 	}; | ||||||
| 
 | 
 | ||||||
| 	return spi_nor_convert_opcode(opcode, spi_nor_3to4_program, | 	return spi_nor_convert_opcode(opcode, spi_nor_3to4_program, | ||||||
|  | @ -2169,6 +2173,13 @@ static int spi_nor_init_params(struct spi_nor *nor, | ||||||
| 					  SNOR_PROTO_1_1_4); | 					  SNOR_PROTO_1_1_4); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	if (info->flags & SPI_NOR_OCTAL_READ) { | ||||||
|  | 		params->hwcaps.mask |= SNOR_HWCAPS_READ_1_1_8; | ||||||
|  | 		spi_nor_set_read_settings(¶ms->reads[SNOR_CMD_READ_1_1_8], | ||||||
|  | 					  0, 8, SPINOR_OP_READ_1_1_8, | ||||||
|  | 					  SNOR_PROTO_1_1_8); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	/* Page Program settings. */ | 	/* Page Program settings. */ | ||||||
| 	params->hwcaps.mask |= SNOR_HWCAPS_PP; | 	params->hwcaps.mask |= SNOR_HWCAPS_PP; | ||||||
| 	spi_nor_set_pp_settings(¶ms->page_programs[SNOR_CMD_PP], | 	spi_nor_set_pp_settings(¶ms->page_programs[SNOR_CMD_PP], | ||||||
|  | @ -2476,7 +2487,14 @@ int spi_nor_scan(struct spi_nor *nor) | ||||||
| 	nor->read_reg = spi_nor_read_reg; | 	nor->read_reg = spi_nor_read_reg; | ||||||
| 	nor->write_reg = spi_nor_write_reg; | 	nor->write_reg = spi_nor_write_reg; | ||||||
| 
 | 
 | ||||||
| 	if (spi->mode & SPI_RX_QUAD) { | 	if (spi->mode & SPI_RX_OCTAL) { | ||||||
|  | 		hwcaps.mask |= SNOR_HWCAPS_READ_1_1_8; | ||||||
|  | 
 | ||||||
|  | 		if (spi->mode & SPI_TX_OCTAL) | ||||||
|  | 			hwcaps.mask |= (SNOR_HWCAPS_READ_1_8_8 | | ||||||
|  | 					SNOR_HWCAPS_PP_1_1_8 | | ||||||
|  | 					SNOR_HWCAPS_PP_1_8_8); | ||||||
|  | 	} else if (spi->mode & SPI_RX_QUAD) { | ||||||
| 		hwcaps.mask |= SNOR_HWCAPS_READ_1_1_4; | 		hwcaps.mask |= SNOR_HWCAPS_READ_1_1_4; | ||||||
| 
 | 
 | ||||||
| 		if (spi->mode & SPI_TX_QUAD) | 		if (spi->mode & SPI_TX_QUAD) | ||||||
|  |  | ||||||
|  | @ -123,6 +123,12 @@ static int spi_check_buswidth_req(struct spi_slave *slave, u8 buswidth, bool tx) | ||||||
| 			return 0; | 			return 0; | ||||||
| 
 | 
 | ||||||
| 		break; | 		break; | ||||||
|  | 	case 8: | ||||||
|  | 		if ((tx && (mode & SPI_TX_OCTAL)) || | ||||||
|  | 		    (!tx && (mode & SPI_RX_OCTAL))) | ||||||
|  | 			return 0; | ||||||
|  | 
 | ||||||
|  | 		break; | ||||||
| 
 | 
 | ||||||
| 	default: | 	default: | ||||||
| 		break; | 		break; | ||||||
|  |  | ||||||
|  | @ -461,6 +461,9 @@ int spi_slave_ofdata_to_platdata(struct udevice *dev, | ||||||
| 	case 4: | 	case 4: | ||||||
| 		mode |= SPI_TX_QUAD; | 		mode |= SPI_TX_QUAD; | ||||||
| 		break; | 		break; | ||||||
|  | 	case 8: | ||||||
|  | 		mode |= SPI_TX_OCTAL; | ||||||
|  | 		break; | ||||||
| 	default: | 	default: | ||||||
| 		warn_non_spl("spi-tx-bus-width %d not supported\n", value); | 		warn_non_spl("spi-tx-bus-width %d not supported\n", value); | ||||||
| 		break; | 		break; | ||||||
|  | @ -476,6 +479,9 @@ int spi_slave_ofdata_to_platdata(struct udevice *dev, | ||||||
| 	case 4: | 	case 4: | ||||||
| 		mode |= SPI_RX_QUAD; | 		mode |= SPI_RX_QUAD; | ||||||
| 		break; | 		break; | ||||||
|  | 	case 8: | ||||||
|  | 		mode |= SPI_RX_OCTAL; | ||||||
|  | 		break; | ||||||
| 	default: | 	default: | ||||||
| 		warn_non_spl("spi-rx-bus-width %d not supported\n", value); | 		warn_non_spl("spi-rx-bus-width %d not supported\n", value); | ||||||
| 		break; | 		break; | ||||||
|  |  | ||||||
|  | @ -47,9 +47,13 @@ | ||||||
| #define SPINOR_OP_READ_1_2_2	0xbb	/* Read data bytes (Dual I/O SPI) */ | #define SPINOR_OP_READ_1_2_2	0xbb	/* Read data bytes (Dual I/O SPI) */ | ||||||
| #define SPINOR_OP_READ_1_1_4	0x6b	/* Read data bytes (Quad Output SPI) */ | #define SPINOR_OP_READ_1_1_4	0x6b	/* Read data bytes (Quad Output SPI) */ | ||||||
| #define SPINOR_OP_READ_1_4_4	0xeb	/* Read data bytes (Quad I/O SPI) */ | #define SPINOR_OP_READ_1_4_4	0xeb	/* Read data bytes (Quad I/O SPI) */ | ||||||
|  | #define SPINOR_OP_READ_1_1_8	0x8b    /* Read data bytes (Octal Output SPI) */ | ||||||
|  | #define SPINOR_OP_READ_1_8_8	0xcb    /* Read data bytes (Octal I/O SPI) */ | ||||||
| #define SPINOR_OP_PP		0x02	/* Page program (up to 256 bytes) */ | #define SPINOR_OP_PP		0x02	/* Page program (up to 256 bytes) */ | ||||||
| #define SPINOR_OP_PP_1_1_4	0x32	/* Quad page program */ | #define SPINOR_OP_PP_1_1_4	0x32	/* Quad page program */ | ||||||
| #define SPINOR_OP_PP_1_4_4	0x38	/* Quad page program */ | #define SPINOR_OP_PP_1_4_4	0x38	/* Quad page program */ | ||||||
|  | #define SPINOR_OP_PP_1_1_8	0x82    /* Octal page program */ | ||||||
|  | #define SPINOR_OP_PP_1_8_8	0xc2    /* Octal page program */ | ||||||
| #define SPINOR_OP_BE_4K		0x20	/* Erase 4KiB block */ | #define SPINOR_OP_BE_4K		0x20	/* Erase 4KiB block */ | ||||||
| #define SPINOR_OP_BE_4K_PMC	0xd7	/* Erase 4KiB block on PMC chips */ | #define SPINOR_OP_BE_4K_PMC	0xd7	/* Erase 4KiB block on PMC chips */ | ||||||
| #define SPINOR_OP_BE_32K	0x52	/* Erase 32KiB block */ | #define SPINOR_OP_BE_32K	0x52	/* Erase 32KiB block */ | ||||||
|  | @ -70,9 +74,13 @@ | ||||||
| #define SPINOR_OP_READ_1_2_2_4B	0xbc	/* Read data bytes (Dual I/O SPI) */ | #define SPINOR_OP_READ_1_2_2_4B	0xbc	/* Read data bytes (Dual I/O SPI) */ | ||||||
| #define SPINOR_OP_READ_1_1_4_4B	0x6c	/* Read data bytes (Quad Output SPI) */ | #define SPINOR_OP_READ_1_1_4_4B	0x6c	/* Read data bytes (Quad Output SPI) */ | ||||||
| #define SPINOR_OP_READ_1_4_4_4B	0xec	/* Read data bytes (Quad I/O SPI) */ | #define SPINOR_OP_READ_1_4_4_4B	0xec	/* Read data bytes (Quad I/O SPI) */ | ||||||
|  | #define SPINOR_OP_READ_1_1_8_4B	0x7c    /* Read data bytes (Octal Output SPI) */ | ||||||
|  | #define SPINOR_OP_READ_1_8_8_4B	0xcc    /* Read data bytes (Octal I/O SPI) */ | ||||||
| #define SPINOR_OP_PP_4B		0x12	/* Page program (up to 256 bytes) */ | #define SPINOR_OP_PP_4B		0x12	/* Page program (up to 256 bytes) */ | ||||||
| #define SPINOR_OP_PP_1_1_4_4B	0x34	/* Quad page program */ | #define SPINOR_OP_PP_1_1_4_4B	0x34	/* Quad page program */ | ||||||
| #define SPINOR_OP_PP_1_4_4_4B	0x3e	/* Quad page program */ | #define SPINOR_OP_PP_1_4_4_4B	0x3e	/* Quad page program */ | ||||||
|  | #define SPINOR_OP_PP_1_1_8_4B	0x84    /* Octal page program */ | ||||||
|  | #define SPINOR_OP_PP_1_8_8_4B	0x8e    /* Octal page program */ | ||||||
| #define SPINOR_OP_BE_4K_4B	0x21	/* Erase 4KiB block */ | #define SPINOR_OP_BE_4K_4B	0x21	/* Erase 4KiB block */ | ||||||
| #define SPINOR_OP_BE_32K_4B	0x5c	/* Erase 32KiB block */ | #define SPINOR_OP_BE_32K_4B	0x5c	/* Erase 32KiB block */ | ||||||
| #define SPINOR_OP_SE_4B		0xdc	/* Sector erase (usually 64KiB) */ | #define SPINOR_OP_SE_4B		0xdc	/* Sector erase (usually 64KiB) */ | ||||||
|  |  | ||||||
|  | @ -30,6 +30,8 @@ | ||||||
| #define SPI_RX_SLOW	BIT(11)			/* receive with 1 wire slow */ | #define SPI_RX_SLOW	BIT(11)			/* receive with 1 wire slow */ | ||||||
| #define SPI_RX_DUAL	BIT(12)			/* receive with 2 wires */ | #define SPI_RX_DUAL	BIT(12)			/* receive with 2 wires */ | ||||||
| #define SPI_RX_QUAD	BIT(13)			/* receive with 4 wires */ | #define SPI_RX_QUAD	BIT(13)			/* receive with 4 wires */ | ||||||
|  | #define SPI_TX_OCTAL	BIT(14)			/* transmit with 8 wires */ | ||||||
|  | #define SPI_RX_OCTAL	BIT(15)			/* receive with 8 wires */ | ||||||
| 
 | 
 | ||||||
| /* Header byte that marks the start of the message */ | /* Header byte that marks the start of the message */ | ||||||
| #define SPI_PREAMBLE_END_BYTE	0xec | #define SPI_PREAMBLE_END_BYTE	0xec | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue