From 870678baa7f8b9a65945237704d84d7724f42459 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Mon, 20 Jun 2016 15:28:36 +0200 Subject: target: socfpga: Add support for QSPI NOR boot Add necessary kernel backports to support the Cadence QSPI controller present on the Altera SoCFPGA SoC. Signed-off-by: Marek Vasut --- ...-configure-the-number-of-dummy-clock-cycl.patch | 237 +++++++++++++++++++++ 1 file changed, 237 insertions(+) create mode 100644 target/linux/socfpga/patches-4.4/0025-mtd-spi-nor-configure-the-number-of-dummy-clock-cycl.patch (limited to 'target/linux/socfpga/patches-4.4/0025-mtd-spi-nor-configure-the-number-of-dummy-clock-cycl.patch') diff --git a/target/linux/socfpga/patches-4.4/0025-mtd-spi-nor-configure-the-number-of-dummy-clock-cycl.patch b/target/linux/socfpga/patches-4.4/0025-mtd-spi-nor-configure-the-number-of-dummy-clock-cycl.patch new file mode 100644 index 0000000000..a9c3afd98d --- /dev/null +++ b/target/linux/socfpga/patches-4.4/0025-mtd-spi-nor-configure-the-number-of-dummy-clock-cycl.patch @@ -0,0 +1,237 @@ +From a714a2af12d0de527be168b821373f29f4343cb7 Mon Sep 17 00:00:00 2001 +From: Cyrille Pitchen +Date: Fri, 8 Jan 2016 17:02:22 +0100 +Subject: [PATCH 25/33] mtd: spi-nor: configure the number of dummy clock + cycles on Macronix memories + +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 +--- + 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 5232984..55a1d74 100644 +--- a/drivers/mtd/spi-nor/spi-nor.c ++++ b/drivers/mtd/spi-nor/spi-nor.c +@@ -1182,6 +1182,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; +@@ -1199,8 +1329,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); + } + + /* +@@ -1213,6 +1342,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) { +@@ -1221,8 +1353,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); + } + + /* +@@ -1233,16 +1364,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: +@@ -1255,8 +1395,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) +-- +2.8.1 + -- cgit v1.2.3