aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBean Huo 霍斌斌 (beanhuo) <beanhuo@micron.com>2014-12-17 02:35:45 -0500
committerBrian Norris <computersforpeace@gmail.com>2015-01-07 14:33:22 -0500
commit548cd3ab54da10f896daa7ca422236847a915734 (patch)
treeb639d9d85db919c3ddfbf4be097cd25ab08f7e87
parented0215cc3b5292fc0f4af70e29dc61fa2d0aa76c (diff)
mtd: spi-nor: Add quad I/O support for Micron SPI NOR
This patch adds code which enables Quad I/O mode on Micron SPI NOR flashes. For Micron SPI NOR flash, enabling or disabling quad I/O protocol can be done By two methods, which are to use EVCR (Enhanced Volatile Configuration Register) and the ENTER QUAD I/O MODE command. There is no difference between these two methods. Unfortunately, for some Micron SPI NOR flashes, there no ENTER Quad I/O command (35h), such as n25q064. But for all current Micron SPI NOR, if it support quad I/O mode, using EVCR definitely be supported. It is a recommended method to enable Quad I/O mode by EVCR, Quad I/O protocol bit 7. When EVCR bit 7 is reset to 0, the SPI NOR flash will operate in quad I/O mode. This patch has been tested on N25Q512A and MT25TL256BAA1ESF. Micron SPI NOR of spi_nor_ids[] table all support this method. Signed-off-by: Bean Huo <beanhuo@micron.com> Acked-by: Marek Vasut <marex@denx.de> Signed-off-by: Brian Norris <computersforpeace@gmail.com>
-rw-r--r--drivers/mtd/spi-nor/spi-nor.c62
-rw-r--r--include/linux/mtd/spi-nor.h7
2 files changed, 61 insertions, 8 deletions
diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
index 0f8ec3c2d015..ea196c18dec9 100644
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -560,14 +560,14 @@ static const struct spi_device_id spi_nor_ids[] = {
560 { "mx66l1g55g", INFO(0xc2261b, 0, 64 * 1024, 2048, SPI_NOR_QUAD_READ) }, 560 { "mx66l1g55g", INFO(0xc2261b, 0, 64 * 1024, 2048, SPI_NOR_QUAD_READ) },
561 561
562 /* Micron */ 562 /* Micron */
563 { "n25q032", INFO(0x20ba16, 0, 64 * 1024, 64, 0) }, 563 { "n25q032", INFO(0x20ba16, 0, 64 * 1024, 64, SPI_NOR_QUAD_READ) },
564 { "n25q064", INFO(0x20ba17, 0, 64 * 1024, 128, 0) }, 564 { "n25q064", INFO(0x20ba17, 0, 64 * 1024, 128, SPI_NOR_QUAD_READ) },
565 { "n25q128a11", INFO(0x20bb18, 0, 64 * 1024, 256, 0) }, 565 { "n25q128a11", INFO(0x20bb18, 0, 64 * 1024, 256, SPI_NOR_QUAD_READ) },
566 { "n25q128a13", INFO(0x20ba18, 0, 64 * 1024, 256, 0) }, 566 { "n25q128a13", INFO(0x20ba18, 0, 64 * 1024, 256, SPI_NOR_QUAD_READ) },
567 { "n25q256a", INFO(0x20ba19, 0, 64 * 1024, 512, SECT_4K) }, 567 { "n25q256a", INFO(0x20ba19, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_QUAD_READ) },
568 { "n25q512a", INFO(0x20bb20, 0, 64 * 1024, 1024, SECT_4K) }, 568 { "n25q512a", INFO(0x20bb20, 0, 64 * 1024, 1024, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) },
569 { "n25q512ax3", INFO(0x20ba20, 0, 64 * 1024, 1024, USE_FSR) }, 569 { "n25q512ax3", INFO(0x20ba20, 0, 64 * 1024, 1024, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) },
570 { "n25q00", INFO(0x20ba21, 0, 64 * 1024, 2048, USE_FSR) }, 570 { "n25q00", INFO(0x20ba21, 0, 64 * 1024, 2048, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) },
571 571
572 /* PMC */ 572 /* PMC */
573 { "pm25lv512", INFO(0, 0, 32 * 1024, 2, SECT_4K_PMC) }, 573 { "pm25lv512", INFO(0, 0, 32 * 1024, 2, SECT_4K_PMC) },
@@ -891,6 +891,45 @@ static int spansion_quad_enable(struct spi_nor *nor)
891 return 0; 891 return 0;
892} 892}
893 893
894static int micron_quad_enable(struct spi_nor *nor)
895{
896 int ret;
897 u8 val;
898
899 ret = nor->read_reg(nor, SPINOR_OP_RD_EVCR, &val, 1);
900 if (ret < 0) {
901 dev_err(nor->dev, "error %d reading EVCR\n", ret);
902 return ret;
903 }
904
905 write_enable(nor);
906
907 /* set EVCR, enable quad I/O */
908 nor->cmd_buf[0] = val & ~EVCR_QUAD_EN_MICRON;
909 ret = nor->write_reg(nor, SPINOR_OP_WD_EVCR, nor->cmd_buf, 1, 0);
910 if (ret < 0) {
911 dev_err(nor->dev, "error while writing EVCR register\n");
912 return ret;
913 }
914
915 ret = spi_nor_wait_till_ready(nor);
916 if (ret)
917 return ret;
918
919 /* read EVCR and check it */
920 ret = nor->read_reg(nor, SPINOR_OP_RD_EVCR, &val, 1);
921 if (ret < 0) {
922 dev_err(nor->dev, "error %d reading EVCR\n", ret);
923 return ret;
924 }
925 if (val & EVCR_QUAD_EN_MICRON) {
926 dev_err(nor->dev, "Micron EVCR Quad bit not clear\n");
927 return -EINVAL;
928 }
929
930 return 0;
931}
932
894static int set_quad_mode(struct spi_nor *nor, struct flash_info *info) 933static int set_quad_mode(struct spi_nor *nor, struct flash_info *info)
895{ 934{
896 int status; 935 int status;
@@ -903,6 +942,13 @@ static int set_quad_mode(struct spi_nor *nor, struct flash_info *info)
903 return -EINVAL; 942 return -EINVAL;
904 } 943 }
905 return status; 944 return status;
945 case CFI_MFR_ST:
946 status = micron_quad_enable(nor);
947 if (status) {
948 dev_err(nor->dev, "Micron quad-read not enabled\n");
949 return -EINVAL;
950 }
951 return status;
906 default: 952 default:
907 status = spansion_quad_enable(nor); 953 status = spansion_quad_enable(nor);
908 if (status) { 954 if (status) {
diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h
index 63aeccf9ddc8..4720b86ee73d 100644
--- a/include/linux/mtd/spi-nor.h
+++ b/include/linux/mtd/spi-nor.h
@@ -56,6 +56,10 @@
56/* Used for Spansion flashes only. */ 56/* Used for Spansion flashes only. */
57#define SPINOR_OP_BRWR 0x17 /* Bank register write */ 57#define SPINOR_OP_BRWR 0x17 /* Bank register write */
58 58
59/* Used for Micron flashes only. */
60#define SPINOR_OP_RD_EVCR 0x65 /* Read EVCR register */
61#define SPINOR_OP_WD_EVCR 0x61 /* Write EVCR register */
62
59/* Status Register bits. */ 63/* Status Register bits. */
60#define SR_WIP 1 /* Write in progress */ 64#define SR_WIP 1 /* Write in progress */
61#define SR_WEL 2 /* Write enable latch */ 65#define SR_WEL 2 /* Write enable latch */
@@ -67,6 +71,9 @@
67 71
68#define SR_QUAD_EN_MX 0x40 /* Macronix Quad I/O */ 72#define SR_QUAD_EN_MX 0x40 /* Macronix Quad I/O */
69 73
74/* Enhanced Volatile Configuration Register bits */
75#define EVCR_QUAD_EN_MICRON 0x80 /* Micron Quad I/O */
76
70/* Flag Status Register bits */ 77/* Flag Status Register bits */
71#define FSR_READY 0x80 78#define FSR_READY 0x80
72 79