lkml.org 
[lkml]   [2016]   [Feb]   [3]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
From
Subject[PATCH v3 04/14] mtd: spi-nor: fix support of Macronix memories
Date
This patch fixes the support of Macronix memories. Especially we avoid
updating the Status Register when not needed as the Quad Enable (QE) bit
is a non-volatile bit.

Also we add comments to explain why we use some Fast Read op codes rather
than others.

Signed-off-by: Cyrille Pitchen <cyrille.pitchen@atmel.com>
---
drivers/mtd/spi-nor/spi-nor.c | 81 ++++++++++++++++++++++++++++++++++++++-----
1 file changed, 72 insertions(+), 9 deletions(-)

diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
index e6438d63246d..2b2572e58a91 100644
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -1088,6 +1088,11 @@ static int macronix_quad_enable(struct spi_nor *nor)
val = read_sr(nor);
if (val < 0)
return val;
+
+ if (likely(val & SR_QUAD_EN_MX))
+ return 0;
+ dev_warn(nor->dev, "Macronix Quad mode disabled, enable it\n");
+
write_enable(nor);

write_sr(nor, val | SR_QUAD_EN_MX);
@@ -1142,21 +1147,73 @@ static int spansion_quad_enable(struct spi_nor *nor)
return 0;
}

+static int macronix_set_quad_mode(struct spi_nor *nor)
+{
+ int status;
+
+ /* Check whether the QPI mode is enabled. */
+ if (nor->read_proto == SNOR_PROTO_4_4_4) {
+ /*
+ * Since the QPI mode is enabled, the Quad Enabled (QE)
+ * non-volatile bit is already set.
+ * However in QPI mode, only the Fast Read 1-4-4 (0xeb)
+ * op code is supported.
+ * WARNING: we should take care about the performance
+ * enhance toggling bits P0-P7 written during the
+ * dummy/mode cycles to avoid entering the continuous
+ * read (performance enhance) mode by mistake!
+ */
+ nor->read_opcode = SPINOR_OP_READ_1_4_4;
+ return 0;
+ }
+
+ /*
+ * The QPI mode is disabled but we still need to set the QE bit:
+ * this disables the reset and write protect features and
+ * frees the associated pins so they can be used as the 3rd
+ * and 4th I/O lines required by Quad SPI commands.
+ * Also we'd rather use the Fast Read 1-1-4 (0x6b) op code than
+ * the Fast Read 1-4-4 (0xeb) op code so we don't care about
+ * entering the continuous read mode by mistake if some
+ * performance enhance toggling bits P0-P7 were written during
+ * dummy/mode cycles.
+ */
+ status = macronix_quad_enable(nor);
+ if (status) {
+ dev_err(nor->dev, "Macronix quad-read not enabled\n");
+ return status;
+ }
+ nor->read_proto = SNOR_PROTO_1_1_4;
+ nor->read_opcode = SPINOR_OP_READ_1_1_4;
+ return 0;
+}
+
+/*
+ * For both Macronix Dual and Single modes, we don't care about the value of
+ * the Quad Enabled (QE) bit since the memory still replies to Dual or Single
+ * SPI commands.
+ */
+
+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;
+ return 0;
+}
+
+static int macronix_set_single_mode(struct spi_nor *nor)
+{
+ 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;

switch (JEDEC_MFR(info)) {
case SNOR_MFR_MACRONIX:
- status = macronix_quad_enable(nor);
- if (status) {
- dev_err(nor->dev, "Macronix quad-read not enabled\n");
- return -EINVAL;
- }
- /* Check whether Macronix QPI mode is enabled. */
- if (nor->read_proto != SNOR_PROTO_4_4_4)
- nor->read_proto = SNOR_PROTO_1_1_4;
- break;
+ return macronix_set_quad_mode(nor);

case SNOR_MFR_MICRON:
/* Check whether Micron Quad mode is enabled. */
@@ -1184,6 +1241,9 @@ static int set_quad_mode(struct spi_nor *nor, const struct flash_info *info)
static int set_dual_mode(struct spi_nor *nor, const struct flash_info *info)
{
switch (JEDEC_MFR(info)) {
+ case SNOR_MFR_MACRONIX:
+ return macronix_set_dual_mode(nor);
+
case SNOR_MFR_MICRON:
/* Check whether Micron Dual mode is enabled. */
if (nor->read_proto != SNOR_PROTO_2_2_2)
@@ -1202,6 +1262,9 @@ static int set_dual_mode(struct spi_nor *nor, const struct flash_info *info)
static int set_single_mode(struct spi_nor *nor, const struct flash_info *info)
{
switch (JEDEC_MFR(info)) {
+ case SNOR_MFR_MACRONIX:
+ return macronix_set_single_mode(nor);
+
default:
nor->read_proto = SNOR_PROTO_1_1_1;
break;
--
1.8.2.2
\
 
 \ /
  Last update: 2016-02-03 15:21    [W:0.109 / U:1.448 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site