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:
Vignesh Raghavendra 2019-12-05 15:46:05 +05:30 committed by Jagan Teki
parent ffab212123
commit 658df8bd94
6 changed files with 43 additions and 2 deletions

View File

@ -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[];

View File

@ -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(&params->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(&params->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)

View File

@ -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;

View File

@ -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;

View File

@ -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) */

View File

@ -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