linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Cyrille Pitchen <cyrille.pitchen@atmel.com>
To: <computersforpeace@gmail.com>, <linux-mtd@lists.infradead.org>
Cc: <nicolas.ferre@atmel.com>, <boris.brezillon@free-electrons.com>,
	<marex@denx.de>, <vigneshr@ti.com>, <beanhuo@micron.com>,
	<linux-kernel@vger.kernel.org>,
	<linux-arm-kernel@lists.infradead.org>,
	<devicetree@vger.kernel.org>, <robh+dt@kernel.org>,
	<pawel.moll@arm.com>, <mark.rutland@arm.com>,
	<ijc+devicetree@hellion.org.uk>, <galak@codeaurora.org>,
	Cyrille Pitchen <cyrille.pitchen@atmel.com>
Subject: [PATCH v3 06/14] mtd: spi-nor: fix support of Micron memories
Date: Wed, 3 Feb 2016 14:26:51 +0100	[thread overview]
Message-ID: <00471284afedfd58a6b3bb17dbd4e51ea509de03.1454505161.git.cyrille.pitchen@atmel.com> (raw)
In-Reply-To: <cover.1454505161.git.cyrille.pitchen@atmel.com>

This patch adds missing mode transitions. Indeed depending on both the
current memory mode and the new protocol wanted by the user, we may need
to perform a switch back to the Extended SPI mode.

However when the current mode is the Quad mode and the user has asked for
a Quad SPI protocol, we'd rather stay in Quad mode and use the Fast Read
4-4-4 command than switch to the Extended SPI mode and use the Fast Read
1-1-4 command.

Also we'd rather stay in Dual mode than swith to the Extended SPI mode
whenever the user has asked for Dual SPI protocol.

Signed-off-by: Cyrille Pitchen <cyrille.pitchen@atmel.com>
---
 drivers/mtd/spi-nor/spi-nor.c | 154 +++++++++++++++++++++++++++++++++++++++---
 include/linux/mtd/spi-nor.h   |   1 +
 2 files changed, 147 insertions(+), 8 deletions(-)

diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
index 980da91e84a4..6785e699106d 100644
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -1298,6 +1298,147 @@ static int winbond_set_single_mode(struct spi_nor *nor)
 	return 0;
 }
 
+static int micron_set_protocol(struct spi_nor *nor, u8 mask, u8 val,
+			       enum spi_nor_protocol proto)
+{
+	u8 evcr;
+	int ret;
+
+	/* Read the Enhanced Volatile Configuration Register (EVCR). */
+	ret = nor->read_reg(nor, SPINOR_OP_RD_EVCR, &evcr, 1);
+	if (ret < 0) {
+		dev_err(nor->dev, "error while reading EVCR register\n");
+		return ret;
+	}
+
+	/* Check whether we need to update the protocol bits. */
+	if ((evcr & mask) == val)
+		return 0;
+
+	/* Set EVCR protocol bits. */
+	write_enable(nor);
+	evcr = (evcr & ~mask) | val;
+	ret = nor->write_reg(nor, SPINOR_OP_WD_EVCR, &evcr, 1);
+	if (ret < 0) {
+		dev_err(nor->dev, "error while writing EVCR register\n");
+		return ret;
+	}
+
+	/* Switch reg protocol now before accessing any other registers. */
+	nor->reg_proto = proto;
+
+	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, &evcr, 1);
+	if (ret < 0 || (evcr & mask) != val) {
+		dev_err(nor->dev, "Micron EVCR protocol bits not updated\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int micron_set_extended_spi_protocol(struct spi_nor *nor)
+{
+	int ret;
+
+	/* Set Quad/Dual bits to 11 to select the Extended SPI mode */
+	ret = micron_set_protocol(nor,
+				  EVCR_QUAD_EN_MICRON | EVCR_DUAL_EN_MICRON,
+				  EVCR_QUAD_EN_MICRON | EVCR_DUAL_EN_MICRON,
+				  SNOR_PROTO_1_1_1);
+	if (ret) {
+		dev_err(nor->dev, "Failed to set Micron Extended SPI mode\n");
+		return ret;
+	}
+
+	nor->write_proto = SNOR_PROTO_1_1_1;
+	nor->erase_proto = SNOR_PROTO_1_1_1;
+	return 0;
+}
+
+static int micron_set_quad_mode(struct spi_nor *nor)
+{
+	/* Check whether the Dual SPI mode is enabled. */
+	if (unlikely(nor->read_proto == SNOR_PROTO_2_2_2)) {
+		int ret;
+
+		/*
+		 * Exit Micron Dual mode and switch to the Extended SPI mode:
+		 * we can change the mode safely as we write into a volatile
+		 * register.
+		 * Also the Quad mode is not worth it for MTD usages: it
+		 * should only be relevant for eXecution In Place (XIP) usages,
+		 * which are out of the scope of the spi-nor framework.
+		 */
+		ret = micron_set_extended_spi_protocol(nor);
+		if (ret)
+			return ret;
+	}
+
+	/*
+	 * Whatever the Quad mode is enabled or not, the
+	 * Fast Read Quad Output 1-1-4 (0x6b) op code is supported.
+	 */
+	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;
+	return 0;
+}
+
+static int micron_set_dual_mode(struct spi_nor *nor)
+{
+	/* Check whether Quad mode is enabled. */
+	if (unlikely(nor->read_proto == SNOR_PROTO_4_4_4)) {
+		int ret;
+
+		/*
+		 * Exit Micron Quad mode and switch to the Extended SPI mode:
+		 * we can change the mode safely as we write into a volatile
+		 * register.
+		 * Also the Dual mode is not worth it for MTD usages: it
+		 * should only be relevant for eXecution In Place (XIP) usages,
+		 * which are out of the scope of the spi-nor framework.
+		 */
+		ret = micron_set_extended_spi_protocol(nor);
+		if (ret)
+			return ret;
+	}
+
+	/*
+	 * Whatever the Dual mode is enabled or not, the
+	 * Fast Read Dual Output 1-1-2 (0x3b) op code is supported.
+	 */
+	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;
+	return 0;
+}
+
+static int micron_set_single_mode(struct spi_nor *nor)
+{
+	/* Check whether either the Dual or Quad mode is enabled. */
+	if (unlikely(nor->read_proto != SNOR_PROTO_1_1_1)) {
+		int ret;
+
+		/*
+		 * Exit Micron Dual or Quad mode and switch to the Extended SPI
+		 * mode: we can change the mode safely as we write into a
+		 * volatile register.
+		 */
+		ret = micron_set_extended_spi_protocol(nor);
+		if (ret)
+			return ret;
+
+		nor->read_proto = SNOR_PROTO_1_1_1;
+	}
+
+	return 0;
+}
+
 static int set_quad_mode(struct spi_nor *nor, const struct flash_info *info)
 {
 	int status;
@@ -1310,10 +1451,7 @@ static int set_quad_mode(struct spi_nor *nor, const struct flash_info *info)
 		return winbond_set_quad_mode(nor);
 
 	case SNOR_MFR_MICRON:
-		/* Check whether Micron Quad mode is enabled. */
-		if (nor->read_proto != SNOR_PROTO_4_4_4)
-			nor->read_proto = SNOR_PROTO_1_1_4;
-		break;
+		return micron_set_quad_mode(nor);
 
 	case SNOR_MFR_SPANSION:
 		status = spansion_quad_enable(nor);
@@ -1342,10 +1480,7 @@ static int set_dual_mode(struct spi_nor *nor, const struct flash_info *info)
 		return winbond_set_dual_mode(nor);
 
 	case SNOR_MFR_MICRON:
-		/* Check whether Micron Dual mode is enabled. */
-		if (nor->read_proto != SNOR_PROTO_2_2_2)
-			nor->read_proto = SNOR_PROTO_1_1_2;
-		break;
+		return micron_set_dual_mode(nor);
 
 	default:
 		nor->read_proto = SNOR_PROTO_1_1_2;
@@ -1365,6 +1500,9 @@ static int set_single_mode(struct spi_nor *nor, const struct flash_info *info)
 	case SNOR_MFR_WINBOND:
 		return winbond_set_single_mode(nor);
 
+	case SNOR_MFR_MICRON:
+		return micron_set_single_mode(nor);
+
 	default:
 		nor->read_proto = SNOR_PROTO_1_1_1;
 		break;
diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h
index 46343f5a8162..d0a6f343a063 100644
--- a/include/linux/mtd/spi-nor.h
+++ b/include/linux/mtd/spi-nor.h
@@ -102,6 +102,7 @@
 
 /* Enhanced Volatile Configuration Register bits */
 #define EVCR_QUAD_EN_MICRON	BIT(7)	/* Micron Quad I/O */
+#define EVCR_DUAL_EN_MICRON	BIT(6)	/* Micron Dual I/O */
 
 /* Flag Status Register bits */
 #define FSR_READY		BIT(7)
-- 
1.8.2.2

  parent reply	other threads:[~2016-02-03 13:29 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-02-03 13:26 [PATCH v3 00/14] mtd: spi-nor: add driver for Atmel QSPI controller Cyrille Pitchen
2016-02-03 13:26 ` [PATCH v3 01/14] mtd: spi-nor: remove micron_quad_enable() Cyrille Pitchen
2016-02-12 21:00   ` Brian Norris
2016-02-03 13:26 ` [PATCH v3 02/14] mtd: spi-nor: properly detect the memory when it boots in Quad or Dual mode Cyrille Pitchen
2016-02-03 13:26 ` [PATCH v3 03/14] mtd: spi-nor: select op codes and SPI NOR protocols by manufacturer Cyrille Pitchen
2016-02-03 13:26 ` [PATCH v3 04/14] mtd: spi-nor: fix support of Macronix memories Cyrille Pitchen
2016-02-03 13:26 ` [PATCH v3 05/14] mtd: spi-nor: fix support of Winbond memories Cyrille Pitchen
2016-02-03 13:26 ` Cyrille Pitchen [this message]
2016-02-03 13:26 ` [PATCH v3 07/14] mtd: spi-nor: fix support of Spansion memories Cyrille Pitchen
2016-02-03 13:26 ` [PATCH v3 08/14] mtd: spi-nor: configure the number of dummy clock cycles by manufacturer Cyrille Pitchen
2016-02-03 13:26 ` [PATCH v3 09/14] mtd: spi-nor: configure the number of dummy clock cycles on Micron memories Cyrille Pitchen
2016-02-03 13:26 ` [PATCH v3 10/14] mtd: spi-nor: configure the number of dummy clock cycles on Macronix memories Cyrille Pitchen
2016-02-03 13:26 ` [PATCH v3 11/14] mtd: spi-nor: configure the number of dummy clock cycles on Spansion memories Cyrille Pitchen
2016-02-03 13:26 ` [PATCH v3 12/14] mtd: m25p80: add support of dual and quad spi protocols to all commands Cyrille Pitchen
2016-02-03 13:26 ` [PATCH v3 13/14] Documentation: atmel-quadspi: add binding file for Atmel QSPI driver Cyrille Pitchen
2016-02-03 13:26 ` [PATCH v3 14/14] mtd: atmel-quadspi: add driver for Atmel QSPI controller Cyrille Pitchen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=00471284afedfd58a6b3bb17dbd4e51ea509de03.1454505161.git.cyrille.pitchen@atmel.com \
    --to=cyrille.pitchen@atmel.com \
    --cc=beanhuo@micron.com \
    --cc=boris.brezillon@free-electrons.com \
    --cc=computersforpeace@gmail.com \
    --cc=devicetree@vger.kernel.org \
    --cc=galak@codeaurora.org \
    --cc=ijc+devicetree@hellion.org.uk \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mtd@lists.infradead.org \
    --cc=marex@denx.de \
    --cc=mark.rutland@arm.com \
    --cc=nicolas.ferre@atmel.com \
    --cc=pawel.moll@arm.com \
    --cc=robh+dt@kernel.org \
    --cc=vigneshr@ti.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).