aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/socfpga/patches-4.4/0019-mtd-spi-nor-fix-support-of-Macronix-memories.patch
blob: 087b6715d0eafd1b2a983bab91fe7b41912dd8e4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
From 4e094634d1995e279f8bc5eb92463295cb894c76 Mon Sep 17 00:00:00 2001
From: Cyrille Pitchen <cyrille.pitchen@atmel.com>
Date: Fri, 8 Jan 2016 17:02:16 +0100
Subject: [PATCH 19/33] mtd: spi-nor: fix support of Macronix memories

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 889af12..1b1f5a6 100644
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -1107,6 +1107,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);
@@ -1161,21 +1166,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. */
@@ -1203,6 +1260,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)
@@ -1221,6 +1281,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;
-- 
2.8.1