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 | 159 +++++++++++++++++++++ 1 file changed, 159 insertions(+) create mode 100644 target/linux/socfpga/patches-4.4/0024-mtd-spi-nor-configure-the-number-of-dummy-clock-cycl.patch (limited to 'target/linux/socfpga/patches-4.4/0024-mtd-spi-nor-configure-the-number-of-dummy-clock-cycl.patch') diff --git a/target/linux/socfpga/patches-4.4/0024-mtd-spi-nor-configure-the-number-of-dummy-clock-cycl.patch b/target/linux/socfpga/patches-4.4/0024-mtd-spi-nor-configure-the-number-of-dummy-clock-cycl.patch new file mode 100644 index 0000000000..c6bf87099a --- /dev/null +++ b/target/linux/socfpga/patches-4.4/0024-mtd-spi-nor-configure-the-number-of-dummy-clock-cycl.patch @@ -0,0 +1,159 @@ +From 77fee227b15835d03517dc34675f72e8963ae882 Mon Sep 17 00:00:00 2001 +From: Cyrille Pitchen +Date: Fri, 8 Jan 2016 17:02:21 +0100 +Subject: [PATCH 24/33] mtd: spi-nor: configure the number of dummy clock + cycles on Micron 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 Micron memories, the number of dummy clock cycles to be used by Fast +Read commands can be safely set to 8 by updating the Volatile +Configuration Register (VCR). + +Also the XIP bit is set at the same time when updating the VCR so the +Continuous Read mode is disabled: this prevents us from entering it by +mistake. + +Signed-off-by: Cyrille Pitchen +--- + drivers/mtd/spi-nor/spi-nor.c | 72 ++++++++++++++++++++++++++++++++++++++----- + include/linux/mtd/spi-nor.h | 2 ++ + 2 files changed, 67 insertions(+), 7 deletions(-) + +diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c +index ae3e9d8..5232984 100644 +--- a/drivers/mtd/spi-nor/spi-nor.c ++++ b/drivers/mtd/spi-nor/spi-nor.c +@@ -1333,6 +1333,53 @@ static int winbond_set_single_mode(struct spi_nor *nor) + return 0; + } + ++static int micron_set_dummy_cycles(struct spi_nor *nor, u8 read_dummy) ++{ ++ u8 vcr, val, mask; ++ int ret; ++ ++ /* Set bit3 (XIP) to disable the Continuous Read mode */ ++ mask = GENMASK(7, 4) | BIT(3); ++ val = ((read_dummy << 4) | BIT(3)) & mask; ++ ++ /* Read the Volatile Configuration Register (VCR). */ ++ ret = nor->read_reg(nor, SPINOR_OP_RD_VCR, &vcr, 1); ++ if (ret < 0) { ++ dev_err(nor->dev, "error while reading VCR register\n"); ++ return ret; ++ } ++ ++ /* Check whether we need to update the number of dummy cycles. */ ++ if ((vcr & mask) == val) { ++ nor->read_dummy = read_dummy; ++ return 0; ++ } ++ ++ /* Update the number of dummy into the VCR. */ ++ write_enable(nor); ++ vcr = (vcr & ~mask) | val; ++ ret = nor->write_reg(nor, SPINOR_OP_WR_VCR, &vcr, 1); ++ if (ret < 0) { ++ dev_err(nor->dev, "error while writing VCR register\n"); ++ return ret; ++ } ++ ++ ret = spi_nor_wait_till_ready(nor); ++ if (ret) ++ return ret; ++ ++ /* Read VCR and check it. */ ++ ret = nor->read_reg(nor, SPINOR_OP_RD_VCR, &vcr, 1); ++ if (ret < 0 || (vcr & mask) != val) { ++ dev_err(nor->dev, "Micron VCR dummy cycles 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 micron_set_protocol(struct spi_nor *nor, u8 mask, u8 val, + enum spi_nor_protocol proto) + { +@@ -1417,12 +1464,15 @@ static int micron_set_quad_mode(struct spi_nor *nor) + /* + * Whatever the Quad mode is enabled or not, the + * Fast Read Quad Output 1-1-4 (0x6b) op code is supported. ++ * Force the number of dummy cycles to 8 and disable the Continuous Read ++ * mode to prevent some drivers from using it by mistake (m25p80). ++ * We can change these settings safely as we write into a volatile ++ * register. + */ + 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; ++ return micron_set_dummy_cycles(nor, 8); + } + + static int micron_set_dual_mode(struct spi_nor *nor) +@@ -1447,12 +1497,15 @@ static int micron_set_dual_mode(struct spi_nor *nor) + /* + * Whatever the Dual mode is enabled or not, the + * Fast Read Dual Output 1-1-2 (0x3b) op code is supported. ++ * Force the number of dummy cycles to 8 and disable the Continuous Read ++ * mode to prevent some drivers from using it by mistake (m25p80). ++ * We can change these settings safely as we write into a volatile ++ * register. + */ + 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; ++ return micron_set_dummy_cycles(nor, 8); + } + + static int micron_set_single_mode(struct spi_nor *nor) +@@ -1475,7 +1528,13 @@ 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. */ ++ /* ++ * Force the number of dummy cycles to 8 for Fast Read, 0 for Read ++ * and disable the Continuous Read mode to prevent some drivers from ++ * using it by mistake (m25p80). ++ * We can change these settings safely as we write into a volatile ++ * register. ++ */ + switch (nor->read_opcode) { + case SPINOR_OP_READ: + case SPINOR_OP_READ4: +@@ -1486,8 +1545,7 @@ static int micron_set_single_mode(struct spi_nor *nor) + read_dummy = 8; + break; + } +- nor->read_dummy = read_dummy; +- return 0; ++ return micron_set_dummy_cycles(nor, read_dummy); + } + + static int spansion_set_quad_mode(struct spi_nor *nor) +diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h +index d0a6f34..2dc0f8b 100644 +--- a/include/linux/mtd/spi-nor.h ++++ b/include/linux/mtd/spi-nor.h +@@ -86,6 +86,8 @@ + + /* Used for Micron flashes only. */ + #define SPINOR_OP_MIO_RDID 0xaf /* Multiple I/O Read JEDEC ID */ ++#define SPINOR_OP_RD_VCR 0x85 /* Read VCR register */ ++#define SPINOR_OP_WR_VCR 0x81 /* Write VCR register */ + #define SPINOR_OP_RD_EVCR 0x65 /* Read EVCR register */ + #define SPINOR_OP_WD_EVCR 0x61 /* Write EVCR register */ + +-- +2.8.1 + -- cgit v1.2.3