aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/socfpga/patches-4.4/0025-mtd-spi-nor-configure-the-number-of-dummy-clock-cycl.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/socfpga/patches-4.4/0025-mtd-spi-nor-configure-the-number-of-dummy-clock-cycl.patch')
-rw-r--r--target/linux/socfpga/patches-4.4/0025-mtd-spi-nor-configure-the-number-of-dummy-clock-cycl.patch237
1 files changed, 237 insertions, 0 deletions
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 <cyrille.pitchen@atmel.com>
+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 <cyrille.pitchen@atmel.com>
+---
+ 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
+