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 | 264 +++++++++++++++++++++ 1 file changed, 264 insertions(+) create mode 100644 target/linux/socfpga/patches-4.4/0023-mtd-spi-nor-configure-the-number-of-dummy-clock-cycl.patch (limited to 'target/linux/socfpga/patches-4.4/0023-mtd-spi-nor-configure-the-number-of-dummy-clock-cycl.patch') diff --git a/target/linux/socfpga/patches-4.4/0023-mtd-spi-nor-configure-the-number-of-dummy-clock-cycl.patch b/target/linux/socfpga/patches-4.4/0023-mtd-spi-nor-configure-the-number-of-dummy-clock-cycl.patch new file mode 100644 index 0000000000..7153a9f171 --- /dev/null +++ b/target/linux/socfpga/patches-4.4/0023-mtd-spi-nor-configure-the-number-of-dummy-clock-cycl.patch @@ -0,0 +1,264 @@ +From 16410a33d6655d6c85c8c522bc6f2cfebf7c06a4 Mon Sep 17 00:00:00 2001 +From: Cyrille Pitchen +Date: Fri, 8 Jan 2016 17:02:20 +0100 +Subject: [PATCH 23/33] mtd: spi-nor: configure the number of dummy clock + cycles by manufacturer + +This is a transitional patch which let us set the number of dummy clock +cycles by manufacturer. + +More patches will follow by manufacturer to actually configure the +relevant number of dummy clock cycles following the dedicated procedure. + +For instance, some manufacturers like Spansion configure the number of +dummy clock cycles to be used by Fast Read command through some +non-volatile register. In such a case, we should avoid updating its value +but instead read it then set the nor->read_dummy accordingly. + +On the other hand, some manufacturers like Micron use some volatile +register. In this case, we'd rather update this register to use a number +of dummy clock cycles, which is a multiple of 8. +Indeed some drivers, like m25p80, only support writing bytes, hence +multiples of 8 bits. + +Signed-off-by: Cyrille Pitchen +--- + drivers/mtd/spi-nor/spi-nor.c | 99 ++++++++++++++++++++++++++++++++----------- + 1 file changed, 74 insertions(+), 25 deletions(-) + +diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c +index 8a042ab..ae3e9d8 100644 +--- a/drivers/mtd/spi-nor/spi-nor.c ++++ b/drivers/mtd/spi-nor/spi-nor.c +@@ -139,24 +139,6 @@ static int read_cr(struct spi_nor *nor) + } + + /* +- * Dummy Cycle calculation for different type of read. +- * It can be used to support more commands with +- * different dummy cycle requirements. +- */ +-static inline int spi_nor_read_dummy_cycles(struct spi_nor *nor) +-{ +- switch (nor->flash_read) { +- case SPI_NOR_FAST: +- case SPI_NOR_DUAL: +- case SPI_NOR_QUAD: +- return 8; +- case SPI_NOR_NORMAL: +- return 0; +- } +- return 0; +-} +- +-/* + * Write status register 1 byte + * Returns negative if error occurred. + */ +@@ -1217,6 +1199,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; + } + +@@ -1238,6 +1221,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; + } + +@@ -1251,12 +1235,27 @@ static int macronix_set_dual_mode(struct spi_nor *nor) + { + nor->read_proto = SNOR_PROTO_1_1_2; + nor->read_opcode = SPINOR_OP_READ_1_1_2; ++ nor->read_dummy = 8; + return 0; + } + + static int macronix_set_single_mode(struct spi_nor *nor) + { ++ u8 read_dummy; ++ ++ switch (nor->read_opcode) { ++ case SPINOR_OP_READ: ++ case SPINOR_OP_READ4: ++ read_dummy = 0; ++ break; ++ ++ default: ++ read_dummy = 8; ++ break; ++ } ++ + nor->read_proto = SNOR_PROTO_1_1_1; ++ nor->read_dummy = read_dummy; + return 0; + } + +@@ -1277,6 +1276,7 @@ static int winbond_set_quad_mode(struct spi_nor *nor) + * Hence the Fast Read 1-1-1 (0x0b) op code is chosen. + */ + nor->read_opcode = SPINOR_OP_READ_FAST; ++ nor->read_dummy = 8; + return 0; + } + +@@ -1295,6 +1295,7 @@ static int winbond_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; + } + +@@ -1308,12 +1309,27 @@ static int winbond_set_dual_mode(struct spi_nor *nor) + { + nor->read_proto = SNOR_PROTO_1_1_2; + nor->read_opcode = SPINOR_OP_READ_1_1_2; ++ nor->read_dummy = 8; + return 0; + } + + static int winbond_set_single_mode(struct spi_nor *nor) + { ++ u8 read_dummy; ++ ++ switch (nor->read_opcode) { ++ case SPINOR_OP_READ: ++ case SPINOR_OP_READ4: ++ read_dummy = 0; ++ break; ++ ++ default: ++ read_dummy = 8; ++ break; ++ } ++ + nor->read_proto = SNOR_PROTO_1_1_1; ++ nor->read_dummy = read_dummy; + return 0; + } + +@@ -1405,6 +1421,7 @@ static int micron_set_quad_mode(struct spi_nor *nor) + if (nor->read_proto != SNOR_PROTO_4_4_4) + nor->read_proto = SNOR_PROTO_1_1_4; + nor->read_opcode = SPINOR_OP_READ_1_1_4; ++ nor->read_dummy = 8; + return 0; + } + +@@ -1434,11 +1451,14 @@ static int micron_set_dual_mode(struct spi_nor *nor) + if (nor->read_proto != SNOR_PROTO_2_2_2) + nor->read_proto = SNOR_PROTO_1_1_2; + nor->read_opcode = SPINOR_OP_READ_1_1_2; ++ nor->read_dummy = 8; + return 0; + } + + static int micron_set_single_mode(struct spi_nor *nor) + { ++ u8 read_dummy; ++ + /* Check whether either the Dual or Quad mode is enabled. */ + if (unlikely(nor->read_proto != SNOR_PROTO_1_1_1)) { + int ret; +@@ -1455,6 +1475,18 @@ static int micron_set_single_mode(struct spi_nor *nor) + nor->read_proto = SNOR_PROTO_1_1_1; + } + ++ /* Force the number of dummy cycles to 8 for Fast Read, 0 for Read. */ ++ switch (nor->read_opcode) { ++ case SPINOR_OP_READ: ++ case SPINOR_OP_READ4: ++ read_dummy = 0; ++ break; ++ ++ default: ++ read_dummy = 8; ++ break; ++ } ++ nor->read_dummy = read_dummy; + return 0; + } + +@@ -1469,6 +1501,7 @@ static int spansion_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; + } + +@@ -1476,12 +1509,27 @@ static int spansion_set_dual_mode(struct spi_nor *nor) + { + nor->read_proto = SNOR_PROTO_1_1_2; + nor->read_opcode = SPINOR_OP_READ_1_1_2; ++ nor->read_dummy = 8; + return 0; + } + + static int spansion_set_single_mode(struct spi_nor *nor) + { ++ u8 read_dummy; ++ ++ switch (nor->read_opcode) { ++ case SPINOR_OP_READ: ++ case SPINOR_OP_READ4: ++ read_dummy = 0; ++ break; ++ ++ default: ++ read_dummy = 8; ++ break; ++ } ++ + nor->read_proto = SNOR_PROTO_1_1_1; ++ nor->read_dummy = read_dummy; + return 0; + } + +@@ -1696,11 +1744,14 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode) + if (info->flags & SPI_NOR_NO_FR) + nor->flash_read = SPI_NOR_NORMAL; + +- /* Default commands */ +- if (nor->flash_read == SPI_NOR_NORMAL) ++ /* Default commands and number of dummy cycles */ ++ if (nor->flash_read == SPI_NOR_NORMAL) { + nor->read_opcode = SPINOR_OP_READ; +- else ++ nor->read_dummy = 0; ++ } else { + nor->read_opcode = SPINOR_OP_READ_FAST; ++ nor->read_dummy = 8; ++ } + + nor->program_opcode = SPINOR_OP_PP; + +@@ -1715,8 +1766,8 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode) + * - SNOR_PROTO_2_2_2 is either: + * + Micron Dual mode enabled + * +- * The opcodes and the protocols are updated depending on the +- * manufacturer. ++ * The opcodes, the protocols and the number of dummy cycles are updated ++ * depending on the manufacturer. + * The read opcode and protocol should be updated by the relevant + * function when entering Quad or Dual mode. + */ +@@ -1780,8 +1831,6 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode) + return -EINVAL; + } + +- nor->read_dummy = spi_nor_read_dummy_cycles(nor); +- + dev_info(dev, "%s (%lld Kbytes)\n", info->name, + (long long)mtd->size >> 10); + +-- +2.8.1 + -- cgit v1.2.3