bcm53xx: backport spi-nor changes to add gd25q128 support
Signed-off-by: Rafał Miłecki <zajec5@gmail.com> SVN-Revision: 44069
This commit is contained in:
		@@ -0,0 +1,116 @@
 | 
			
		||||
--- a/drivers/mtd/spi-nor/spi-nor.c
 | 
			
		||||
+++ b/drivers/mtd/spi-nor/spi-nor.c
 | 
			
		||||
@@ -538,6 +538,7 @@ static const struct spi_device_id spi_no
 | 
			
		||||
 	/* GigaDevice */
 | 
			
		||||
 	{ "gd25q32", INFO(0xc84016, 0, 64 * 1024,  64, SECT_4K) },
 | 
			
		||||
 	{ "gd25q64", INFO(0xc84017, 0, 64 * 1024, 128, SECT_4K) },
 | 
			
		||||
+	{ "gd25q128", INFO(0xc84018, 0, 64 * 1024, 256, SECT_4K) },
 | 
			
		||||
 
 | 
			
		||||
 	/* Intel/Numonyx -- xxxs33b */
 | 
			
		||||
 	{ "160s33b",  INFO(0x898911, 0, 64 * 1024,  32, 0) },
 | 
			
		||||
@@ -560,14 +561,14 @@ static const struct spi_device_id spi_no
 | 
			
		||||
 	{ "mx66l1g55g",  INFO(0xc2261b, 0, 64 * 1024, 2048, SPI_NOR_QUAD_READ) },
 | 
			
		||||
 
 | 
			
		||||
 	/* Micron */
 | 
			
		||||
-	{ "n25q032",	 INFO(0x20ba16, 0, 64 * 1024,   64, 0) },
 | 
			
		||||
-	{ "n25q064",     INFO(0x20ba17, 0, 64 * 1024,  128, 0) },
 | 
			
		||||
-	{ "n25q128a11",  INFO(0x20bb18, 0, 64 * 1024,  256, 0) },
 | 
			
		||||
-	{ "n25q128a13",  INFO(0x20ba18, 0, 64 * 1024,  256, 0) },
 | 
			
		||||
-	{ "n25q256a",    INFO(0x20ba19, 0, 64 * 1024,  512, SECT_4K) },
 | 
			
		||||
-	{ "n25q512a",    INFO(0x20bb20, 0, 64 * 1024, 1024, SECT_4K) },
 | 
			
		||||
-	{ "n25q512ax3",  INFO(0x20ba20, 0, 64 * 1024, 1024, USE_FSR) },
 | 
			
		||||
-	{ "n25q00",      INFO(0x20ba21, 0, 64 * 1024, 2048, USE_FSR) },
 | 
			
		||||
+	{ "n25q032",	 INFO(0x20ba16, 0, 64 * 1024,   64, SPI_NOR_QUAD_READ) },
 | 
			
		||||
+	{ "n25q064",     INFO(0x20ba17, 0, 64 * 1024,  128, SPI_NOR_QUAD_READ) },
 | 
			
		||||
+	{ "n25q128a11",  INFO(0x20bb18, 0, 64 * 1024,  256, SPI_NOR_QUAD_READ) },
 | 
			
		||||
+	{ "n25q128a13",  INFO(0x20ba18, 0, 64 * 1024,  256, SPI_NOR_QUAD_READ) },
 | 
			
		||||
+	{ "n25q256a",    INFO(0x20ba19, 0, 64 * 1024,  512, SECT_4K | SPI_NOR_QUAD_READ) },
 | 
			
		||||
+	{ "n25q512a",    INFO(0x20bb20, 0, 64 * 1024, 1024, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) },
 | 
			
		||||
+	{ "n25q512ax3",  INFO(0x20ba20, 0, 64 * 1024, 1024, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) },
 | 
			
		||||
+	{ "n25q00",      INFO(0x20ba21, 0, 64 * 1024, 2048, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) },
 | 
			
		||||
 
 | 
			
		||||
 	/* PMC */
 | 
			
		||||
 	{ "pm25lv512",   INFO(0,        0, 32 * 1024,    2, SECT_4K_PMC) },
 | 
			
		||||
@@ -890,6 +891,45 @@ static int spansion_quad_enable(struct s
 | 
			
		||||
 	return 0;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
+static int micron_quad_enable(struct spi_nor *nor)
 | 
			
		||||
+{
 | 
			
		||||
+	int ret;
 | 
			
		||||
+	u8 val;
 | 
			
		||||
+
 | 
			
		||||
+	ret = nor->read_reg(nor, SPINOR_OP_RD_EVCR, &val, 1);
 | 
			
		||||
+	if (ret < 0) {
 | 
			
		||||
+		dev_err(nor->dev, "error %d reading EVCR\n", ret);
 | 
			
		||||
+		return ret;
 | 
			
		||||
+	}
 | 
			
		||||
+
 | 
			
		||||
+	write_enable(nor);
 | 
			
		||||
+
 | 
			
		||||
+	/* set EVCR, enable quad I/O */
 | 
			
		||||
+	nor->cmd_buf[0] = val & ~EVCR_QUAD_EN_MICRON;
 | 
			
		||||
+	ret = nor->write_reg(nor, SPINOR_OP_WD_EVCR, nor->cmd_buf, 1, 0);
 | 
			
		||||
+	if (ret < 0) {
 | 
			
		||||
+		dev_err(nor->dev, "error while writing EVCR register\n");
 | 
			
		||||
+		return ret;
 | 
			
		||||
+	}
 | 
			
		||||
+
 | 
			
		||||
+	ret = spi_nor_wait_till_ready(nor);
 | 
			
		||||
+	if (ret)
 | 
			
		||||
+		return ret;
 | 
			
		||||
+
 | 
			
		||||
+	/* read EVCR and check it */
 | 
			
		||||
+	ret = nor->read_reg(nor, SPINOR_OP_RD_EVCR, &val, 1);
 | 
			
		||||
+	if (ret < 0) {
 | 
			
		||||
+		dev_err(nor->dev, "error %d reading EVCR\n", ret);
 | 
			
		||||
+		return ret;
 | 
			
		||||
+	}
 | 
			
		||||
+	if (val & EVCR_QUAD_EN_MICRON) {
 | 
			
		||||
+		dev_err(nor->dev, "Micron EVCR Quad bit not clear\n");
 | 
			
		||||
+		return -EINVAL;
 | 
			
		||||
+	}
 | 
			
		||||
+
 | 
			
		||||
+	return 0;
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
 static int set_quad_mode(struct spi_nor *nor, struct flash_info *info)
 | 
			
		||||
 {
 | 
			
		||||
 	int status;
 | 
			
		||||
@@ -902,6 +942,13 @@ static int set_quad_mode(struct spi_nor
 | 
			
		||||
 			return -EINVAL;
 | 
			
		||||
 		}
 | 
			
		||||
 		return status;
 | 
			
		||||
+	case CFI_MFR_ST:
 | 
			
		||||
+		status = micron_quad_enable(nor);
 | 
			
		||||
+		if (status) {
 | 
			
		||||
+			dev_err(nor->dev, "Micron quad-read not enabled\n");
 | 
			
		||||
+			return -EINVAL;
 | 
			
		||||
+		}
 | 
			
		||||
+		return status;
 | 
			
		||||
 	default:
 | 
			
		||||
 		status = spansion_quad_enable(nor);
 | 
			
		||||
 		if (status) {
 | 
			
		||||
--- a/include/linux/mtd/spi-nor.h
 | 
			
		||||
+++ b/include/linux/mtd/spi-nor.h
 | 
			
		||||
@@ -56,6 +56,10 @@
 | 
			
		||||
 /* Used for Spansion flashes only. */
 | 
			
		||||
 #define SPINOR_OP_BRWR		0x17	/* Bank register write */
 | 
			
		||||
 
 | 
			
		||||
+/* Used for Micron flashes only. */
 | 
			
		||||
+#define SPINOR_OP_RD_EVCR      0x65    /* Read EVCR register */
 | 
			
		||||
+#define SPINOR_OP_WD_EVCR      0x61    /* Write EVCR register */
 | 
			
		||||
+
 | 
			
		||||
 /* Status Register bits. */
 | 
			
		||||
 #define SR_WIP			1	/* Write in progress */
 | 
			
		||||
 #define SR_WEL			2	/* Write enable latch */
 | 
			
		||||
@@ -67,6 +71,9 @@
 | 
			
		||||
 
 | 
			
		||||
 #define SR_QUAD_EN_MX		0x40	/* Macronix Quad I/O */
 | 
			
		||||
 
 | 
			
		||||
+/* Enhanced Volatile Configuration Register bits */
 | 
			
		||||
+#define EVCR_QUAD_EN_MICRON    0x80    /* Micron Quad I/O */
 | 
			
		||||
+
 | 
			
		||||
 /* Flag Status Register bits */
 | 
			
		||||
 #define FSR_READY		0x80
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,116 @@
 | 
			
		||||
--- a/drivers/mtd/spi-nor/spi-nor.c
 | 
			
		||||
+++ b/drivers/mtd/spi-nor/spi-nor.c
 | 
			
		||||
@@ -538,6 +538,7 @@ static const struct spi_device_id spi_no
 | 
			
		||||
 	/* GigaDevice */
 | 
			
		||||
 	{ "gd25q32", INFO(0xc84016, 0, 64 * 1024,  64, SECT_4K) },
 | 
			
		||||
 	{ "gd25q64", INFO(0xc84017, 0, 64 * 1024, 128, SECT_4K) },
 | 
			
		||||
+	{ "gd25q128", INFO(0xc84018, 0, 64 * 1024, 256, SECT_4K) },
 | 
			
		||||
 
 | 
			
		||||
 	/* Intel/Numonyx -- xxxs33b */
 | 
			
		||||
 	{ "160s33b",  INFO(0x898911, 0, 64 * 1024,  32, 0) },
 | 
			
		||||
@@ -560,14 +561,14 @@ static const struct spi_device_id spi_no
 | 
			
		||||
 	{ "mx66l1g55g",  INFO(0xc2261b, 0, 64 * 1024, 2048, SPI_NOR_QUAD_READ) },
 | 
			
		||||
 
 | 
			
		||||
 	/* Micron */
 | 
			
		||||
-	{ "n25q032",	 INFO(0x20ba16, 0, 64 * 1024,   64, 0) },
 | 
			
		||||
-	{ "n25q064",     INFO(0x20ba17, 0, 64 * 1024,  128, 0) },
 | 
			
		||||
-	{ "n25q128a11",  INFO(0x20bb18, 0, 64 * 1024,  256, 0) },
 | 
			
		||||
-	{ "n25q128a13",  INFO(0x20ba18, 0, 64 * 1024,  256, 0) },
 | 
			
		||||
-	{ "n25q256a",    INFO(0x20ba19, 0, 64 * 1024,  512, SECT_4K) },
 | 
			
		||||
-	{ "n25q512a",    INFO(0x20bb20, 0, 64 * 1024, 1024, SECT_4K) },
 | 
			
		||||
-	{ "n25q512ax3",  INFO(0x20ba20, 0, 64 * 1024, 1024, USE_FSR) },
 | 
			
		||||
-	{ "n25q00",      INFO(0x20ba21, 0, 64 * 1024, 2048, USE_FSR) },
 | 
			
		||||
+	{ "n25q032",	 INFO(0x20ba16, 0, 64 * 1024,   64, SPI_NOR_QUAD_READ) },
 | 
			
		||||
+	{ "n25q064",     INFO(0x20ba17, 0, 64 * 1024,  128, SPI_NOR_QUAD_READ) },
 | 
			
		||||
+	{ "n25q128a11",  INFO(0x20bb18, 0, 64 * 1024,  256, SPI_NOR_QUAD_READ) },
 | 
			
		||||
+	{ "n25q128a13",  INFO(0x20ba18, 0, 64 * 1024,  256, SPI_NOR_QUAD_READ) },
 | 
			
		||||
+	{ "n25q256a",    INFO(0x20ba19, 0, 64 * 1024,  512, SECT_4K | SPI_NOR_QUAD_READ) },
 | 
			
		||||
+	{ "n25q512a",    INFO(0x20bb20, 0, 64 * 1024, 1024, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) },
 | 
			
		||||
+	{ "n25q512ax3",  INFO(0x20ba20, 0, 64 * 1024, 1024, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) },
 | 
			
		||||
+	{ "n25q00",      INFO(0x20ba21, 0, 64 * 1024, 2048, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) },
 | 
			
		||||
 
 | 
			
		||||
 	/* PMC */
 | 
			
		||||
 	{ "pm25lv512",   INFO(0,        0, 32 * 1024,    2, SECT_4K_PMC) },
 | 
			
		||||
@@ -891,6 +892,45 @@ static int spansion_quad_enable(struct s
 | 
			
		||||
 	return 0;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
+static int micron_quad_enable(struct spi_nor *nor)
 | 
			
		||||
+{
 | 
			
		||||
+	int ret;
 | 
			
		||||
+	u8 val;
 | 
			
		||||
+
 | 
			
		||||
+	ret = nor->read_reg(nor, SPINOR_OP_RD_EVCR, &val, 1);
 | 
			
		||||
+	if (ret < 0) {
 | 
			
		||||
+		dev_err(nor->dev, "error %d reading EVCR\n", ret);
 | 
			
		||||
+		return ret;
 | 
			
		||||
+	}
 | 
			
		||||
+
 | 
			
		||||
+	write_enable(nor);
 | 
			
		||||
+
 | 
			
		||||
+	/* set EVCR, enable quad I/O */
 | 
			
		||||
+	nor->cmd_buf[0] = val & ~EVCR_QUAD_EN_MICRON;
 | 
			
		||||
+	ret = nor->write_reg(nor, SPINOR_OP_WD_EVCR, nor->cmd_buf, 1, 0);
 | 
			
		||||
+	if (ret < 0) {
 | 
			
		||||
+		dev_err(nor->dev, "error while writing EVCR register\n");
 | 
			
		||||
+		return ret;
 | 
			
		||||
+	}
 | 
			
		||||
+
 | 
			
		||||
+	ret = spi_nor_wait_till_ready(nor);
 | 
			
		||||
+	if (ret)
 | 
			
		||||
+		return ret;
 | 
			
		||||
+
 | 
			
		||||
+	/* read EVCR and check it */
 | 
			
		||||
+	ret = nor->read_reg(nor, SPINOR_OP_RD_EVCR, &val, 1);
 | 
			
		||||
+	if (ret < 0) {
 | 
			
		||||
+		dev_err(nor->dev, "error %d reading EVCR\n", ret);
 | 
			
		||||
+		return ret;
 | 
			
		||||
+	}
 | 
			
		||||
+	if (val & EVCR_QUAD_EN_MICRON) {
 | 
			
		||||
+		dev_err(nor->dev, "Micron EVCR Quad bit not clear\n");
 | 
			
		||||
+		return -EINVAL;
 | 
			
		||||
+	}
 | 
			
		||||
+
 | 
			
		||||
+	return 0;
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
 static int set_quad_mode(struct spi_nor *nor, struct flash_info *info)
 | 
			
		||||
 {
 | 
			
		||||
 	int status;
 | 
			
		||||
@@ -903,6 +943,13 @@ static int set_quad_mode(struct spi_nor
 | 
			
		||||
 			return -EINVAL;
 | 
			
		||||
 		}
 | 
			
		||||
 		return status;
 | 
			
		||||
+	case CFI_MFR_ST:
 | 
			
		||||
+		status = micron_quad_enable(nor);
 | 
			
		||||
+		if (status) {
 | 
			
		||||
+			dev_err(nor->dev, "Micron quad-read not enabled\n");
 | 
			
		||||
+			return -EINVAL;
 | 
			
		||||
+		}
 | 
			
		||||
+		return status;
 | 
			
		||||
 	default:
 | 
			
		||||
 		status = spansion_quad_enable(nor);
 | 
			
		||||
 		if (status) {
 | 
			
		||||
--- a/include/linux/mtd/spi-nor.h
 | 
			
		||||
+++ b/include/linux/mtd/spi-nor.h
 | 
			
		||||
@@ -56,6 +56,10 @@
 | 
			
		||||
 /* Used for Spansion flashes only. */
 | 
			
		||||
 #define SPINOR_OP_BRWR		0x17	/* Bank register write */
 | 
			
		||||
 
 | 
			
		||||
+/* Used for Micron flashes only. */
 | 
			
		||||
+#define SPINOR_OP_RD_EVCR      0x65    /* Read EVCR register */
 | 
			
		||||
+#define SPINOR_OP_WD_EVCR      0x61    /* Write EVCR register */
 | 
			
		||||
+
 | 
			
		||||
 /* Status Register bits. */
 | 
			
		||||
 #define SR_WIP			1	/* Write in progress */
 | 
			
		||||
 #define SR_WEL			2	/* Write enable latch */
 | 
			
		||||
@@ -67,6 +71,9 @@
 | 
			
		||||
 
 | 
			
		||||
 #define SR_QUAD_EN_MX		0x40	/* Macronix Quad I/O */
 | 
			
		||||
 
 | 
			
		||||
+/* Enhanced Volatile Configuration Register bits */
 | 
			
		||||
+#define EVCR_QUAD_EN_MICRON    0x80    /* Micron Quad I/O */
 | 
			
		||||
+
 | 
			
		||||
 /* Flag Status Register bits */
 | 
			
		||||
 #define FSR_READY		0x80
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user