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		addr_width; | ||||
| 
 | ||||
| 	u16		flags; | ||||
| 	u32		flags; | ||||
| #define SECT_4K			BIT(0)	/* SPINOR_OP_BE_4K works uniformly */ | ||||
| #define SPI_NOR_NO_ERASE	BIT(1)	/* No erase command needed */ | ||||
| #define SST_WRITE		BIT(2)	/* use SST byte programming */ | ||||
|  | @ -66,6 +66,7 @@ struct flash_info { | |||
| #define SPI_NOR_SKIP_SFDP	BIT(13)	/* Skip parsing of SFDP tables */ | ||||
| #define USE_CLSR		BIT(14)	/* use CLSR command */ | ||||
| #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[]; | ||||
|  |  | |||
|  | @ -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_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_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_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_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_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, | ||||
|  | @ -2169,6 +2173,13 @@ static int spi_nor_init_params(struct spi_nor *nor, | |||
| 					  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. */ | ||||
| 	params->hwcaps.mask |= SNOR_HWCAPS_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->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; | ||||
| 
 | ||||
| 		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; | ||||
| 
 | ||||
| 		break; | ||||
| 	case 8: | ||||
| 		if ((tx && (mode & SPI_TX_OCTAL)) || | ||||
| 		    (!tx && (mode & SPI_RX_OCTAL))) | ||||
| 			return 0; | ||||
| 
 | ||||
| 		break; | ||||
| 
 | ||||
| 	default: | ||||
| 		break; | ||||
|  |  | |||
|  | @ -461,6 +461,9 @@ int spi_slave_ofdata_to_platdata(struct udevice *dev, | |||
| 	case 4: | ||||
| 		mode |= SPI_TX_QUAD; | ||||
| 		break; | ||||
| 	case 8: | ||||
| 		mode |= SPI_TX_OCTAL; | ||||
| 		break; | ||||
| 	default: | ||||
| 		warn_non_spl("spi-tx-bus-width %d not supported\n", value); | ||||
| 		break; | ||||
|  | @ -476,6 +479,9 @@ int spi_slave_ofdata_to_platdata(struct udevice *dev, | |||
| 	case 4: | ||||
| 		mode |= SPI_RX_QUAD; | ||||
| 		break; | ||||
| 	case 8: | ||||
| 		mode |= SPI_RX_OCTAL; | ||||
| 		break; | ||||
| 	default: | ||||
| 		warn_non_spl("spi-rx-bus-width %d not supported\n", value); | ||||
| 		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_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_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_1_1_4	0x32	/* 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_PMC	0xd7	/* Erase 4KiB block on PMC chips */ | ||||
| #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_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_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_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_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_32K_4B	0x5c	/* Erase 32KiB block */ | ||||
| #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_DUAL	BIT(12)			/* receive with 2 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 */ | ||||
| #define SPI_PREAMBLE_END_BYTE	0xec | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue