The spi-nor framework currently expects all Fast Read operations to use 8 dummy clock cycles. Especially some drivers like m25p80 can only support multiple of 8 dummy clock cycles. On Macronix memories, the number of dummy clock cycles to be used by Fast Read commands can be safely set to 8 by updating the DC0 and DC1 volatile bits inside the Configuration Register. According to the mx66l1g45g datasheet from Macronix, using 8 dummy clock cycles should be enough to set the SPI bus clock frequency up to: - 133 MHz for Fast Read 1-1-1, 1-1-2, 1-1-4 and 1-2-2 commands in Single Transfer Rate (STR) - 104 MHz for Fast Read 1-4-4 (or 4-4-4 in QPI mode) commands (STR) Signed-off-by: Cyrille Pitchen <cyrille.pitchen@xxxxxxxxx> --- drivers/mtd/spi-nor/spi-nor.c | 155 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 147 insertions(+), 8 deletions(-) diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index 3f79619aea52..68abae5c72e9 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -1190,6 +1190,136 @@ static int winbond_quad_enable(struct spi_nor *nor) return 0; } +static int macronix_dummy2code(u8 read_opcode, u8 read_dummy, u8 *dc) +{ + switch (read_opcode) { + case SPINOR_OP_READ: + case SPINOR_OP_READ4: + *dc = 0; + break; + + case SPINOR_OP_READ_FAST: + case SPINOR_OP_READ_1_1_2: + case SPINOR_OP_READ_1_1_4: + case SPINOR_OP_READ4_FAST: + case SPINOR_OP_READ4_1_1_2: + case SPINOR_OP_READ4_1_1_4: + switch (read_dummy) { + case 6: + *dc = 1; + break; + case 8: + *dc = 0; + break; + case 10: + *dc = 3; + break; + default: + return -EINVAL; + } + break; + + case SPINOR_OP_READ_1_2_2: + case SPINOR_OP_READ4_1_2_2: + switch (read_dummy) { + case 4: + *dc = 0; + break; + case 6: + *dc = 1; + break; + case 8: + *dc = 2; + break; + case 10: + *dc = 3; + default: + return -EINVAL; + } + break; + + case SPINOR_OP_READ_1_4_4: + case SPINOR_OP_READ4_1_4_4: + switch (read_dummy) { + case 4: + *dc = 1; + break; + case 6: + *dc = 0; + break; + case 8: + *dc = 2; + break; + case 10: + *dc = 3; + default: + return -EINVAL; + } + break; + + default: + return -EINVAL; + } + + return 0; +} + +static int macronix_set_dummy_cycles(struct spi_nor *nor, u8 read_dummy) +{ + int ret, sr, cr, mask, val; + u16 sr_cr; + u8 dc; + + /* Convert the number of dummy cycles into Macronix DC volatile bits */ + ret = macronix_dummy2code(nor->read_opcode, read_dummy, &dc); + if (ret) + return ret; + + mask = GENMASK(7, 6); + val = (dc << 6) & mask; + + cr = read_cr(nor); + if (cr < 0) { + dev_err(nor->dev, "error while reading the config register\n"); + return cr; + } + + if ((cr & mask) == val) { + nor->read_dummy = read_dummy; + return 0; + } + + sr = read_sr(nor); + if (sr < 0) { + dev_err(nor->dev, "error while reading the status register\n"); + return sr; + } + + cr = (cr & ~mask) | val; + sr_cr = (sr & 0xff) | ((cr & 0xff) << 8); + write_enable(nor); + ret = write_sr_cr(nor, sr_cr); + if (ret) { + dev_err(nor->dev, + "error while writing the SR and CR registers\n"); + return ret; + } + + ret = spi_nor_wait_till_ready(nor); + if (ret) + return ret; + + cr = read_cr(nor); + if (cr < 0 || (cr & mask) != val) { + dev_err(nor->dev, "Macronix Dummy Cycle bits not updated\n"); + return -EINVAL; + } + + /* Save the number of dummy cycles to use with Fast Read commands */ + nor->read_dummy = read_dummy; + return 0; +} + static int macronix_set_quad_mode(struct spi_nor *nor) { int status; @@ -1207,8 +1337,7 @@ static int macronix_set_quad_mode(struct spi_nor *nor) * read (performance enhance) mode by mistake! */ nor->read_opcode = SPINOR_OP_READ_1_4_4; - nor->read_dummy = 8; - return 0; + return macronix_set_dummy_cycles(nor, 8); } /* @@ -1221,6 +1350,9 @@ static int macronix_set_quad_mode(struct spi_nor *nor) * entering the continuous read mode by mistake if some * performance enhance toggling bits P0-P7 were written during * dummy/mode cycles. + * + * Use the Fast Read Quad Output 1-1-4 (0x6b) command with 8 dummy + * cycles (up to 133MHz for STR and 66MHz for DTR). */ status = macronix_quad_enable(nor); if (status) { @@ -1229,8 +1361,7 @@ static int macronix_set_quad_mode(struct spi_nor *nor) } nor->read_proto = SNOR_PROTO_1_1_4; nor->read_opcode = SPINOR_OP_READ_1_1_4; - nor->read_dummy = 8; - return 0; + return macronix_set_dummy_cycles(nor, 8); } /* @@ -1241,16 +1372,25 @@ static int macronix_set_quad_mode(struct spi_nor *nor) static int macronix_set_dual_mode(struct spi_nor *nor) { + /* + * Use the Fast Read Dual Output 1-1-2 (0x3b) command with 8 dummy + * cycles (up to 133MHz for STR and 66MHz for DTR). + */ nor->read_proto = SNOR_PROTO_1_1_2; nor->read_opcode = SPINOR_OP_READ_1_1_2; - nor->read_dummy = 8; - return 0; + return macronix_set_dummy_cycles(nor, 8); } static int macronix_set_single_mode(struct spi_nor *nor) { u8 read_dummy; + /* + * Configure 8 dummy cycles for Fast Read 1-1-1 (0x0b) command (up to + * 133MHz for STR and 66MHz for DTR). The Read 1-1-1 (0x03) command + * expects no dummy cycle. + * read_opcode should not be overridden here! + */ switch (nor->read_opcode) { case SPINOR_OP_READ: case SPINOR_OP_READ4: @@ -1263,8 +1403,7 @@ static int macronix_set_single_mode(struct spi_nor *nor) } nor->read_proto = SNOR_PROTO_1_1_1; - nor->read_dummy = read_dummy; - return 0; + return macronix_set_dummy_cycles(nor, read_dummy); } static int winbond_set_quad_mode(struct spi_nor *nor) -- 1.8.2.2 -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html