xref: /linux/drivers/mtd/spi-nor/macronix.c (revision 7f4f3b14e8079ecde096bd734af10e30d40c27b7)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (C) 2005, Intec Automation Inc.
4  * Copyright (C) 2014, Freescale Semiconductor, Inc.
5  */
6 
7 #include <linux/mtd/spi-nor.h>
8 
9 #include "core.h"
10 
11 #define MXIC_NOR_OP_RD_CR2	0x71		/* Read configuration register 2 opcode */
12 #define MXIC_NOR_OP_WR_CR2	0x72		/* Write configuration register 2 opcode */
13 #define MXIC_NOR_ADDR_CR2_MODE	0x00000000	/* CR2 address for setting spi/sopi/dopi mode */
14 #define MXIC_NOR_ADDR_CR2_DC	0x00000300	/* CR2 address for setting dummy cycles */
15 #define MXIC_NOR_REG_DOPI_EN	0x2		/* Enable Octal DTR */
16 #define MXIC_NOR_REG_SPI_EN	0x0		/* Enable SPI */
17 
18 /* Convert dummy cycles to bit pattern */
19 #define MXIC_NOR_REG_DC(p) \
20 	((20 - (p)) >> 1)
21 
22 #define MXIC_NOR_WR_CR2(addr, ndata, buf)			\
23 	SPI_MEM_OP(SPI_MEM_OP_CMD(MXIC_NOR_OP_WR_CR2, 0),	\
24 		   SPI_MEM_OP_ADDR(4, addr, 0),			\
25 		   SPI_MEM_OP_NO_DUMMY,				\
26 		   SPI_MEM_OP_DATA_OUT(ndata, buf, 0))
27 
28 static int
29 mx25l25635_post_bfpt_fixups(struct spi_nor *nor,
30 			    const struct sfdp_parameter_header *bfpt_header,
31 			    const struct sfdp_bfpt *bfpt)
32 {
33 	/*
34 	 * MX25L25635F supports 4B opcodes but MX25L25635E does not.
35 	 * Unfortunately, Macronix has re-used the same JEDEC ID for both
36 	 * variants which prevents us from defining a new entry in the parts
37 	 * table.
38 	 * We need a way to differentiate MX25L25635E and MX25L25635F, and it
39 	 * seems that the F version advertises support for Fast Read 4-4-4 in
40 	 * its BFPT table.
41 	 */
42 	if (bfpt->dwords[SFDP_DWORD(5)] & BFPT_DWORD5_FAST_READ_4_4_4)
43 		nor->flags |= SNOR_F_4B_OPCODES;
44 
45 	return 0;
46 }
47 
48 static const struct spi_nor_fixups mx25l25635_fixups = {
49 	.post_bfpt = mx25l25635_post_bfpt_fixups,
50 };
51 
52 static const struct flash_info macronix_nor_parts[] = {
53 	{
54 		.id = SNOR_ID(0xc2, 0x20, 0x10),
55 		.name = "mx25l512e",
56 		.size = SZ_64K,
57 		.no_sfdp_flags = SECT_4K,
58 	}, {
59 		.id = SNOR_ID(0xc2, 0x20, 0x12),
60 		.name = "mx25l2005a",
61 		.size = SZ_256K,
62 		.no_sfdp_flags = SECT_4K,
63 	}, {
64 		.id = SNOR_ID(0xc2, 0x20, 0x13),
65 		.name = "mx25l4005a",
66 		.size = SZ_512K,
67 		.no_sfdp_flags = SECT_4K,
68 	}, {
69 		.id = SNOR_ID(0xc2, 0x20, 0x14),
70 		.name = "mx25l8005",
71 		.size = SZ_1M,
72 	}, {
73 		.id = SNOR_ID(0xc2, 0x20, 0x15),
74 		.name = "mx25l1606e",
75 		.size = SZ_2M,
76 		.no_sfdp_flags = SECT_4K,
77 	}, {
78 		.id = SNOR_ID(0xc2, 0x20, 0x16),
79 		.name = "mx25l3205d",
80 		.size = SZ_4M,
81 		.no_sfdp_flags = SECT_4K,
82 	}, {
83 		.id = SNOR_ID(0xc2, 0x20, 0x17),
84 		.name = "mx25l6405d",
85 		.size = SZ_8M,
86 		.no_sfdp_flags = SECT_4K,
87 	}, {
88 		.id = SNOR_ID(0xc2, 0x20, 0x18),
89 		.name = "mx25l12805d",
90 		.size = SZ_16M,
91 		.flags = SPI_NOR_HAS_LOCK | SPI_NOR_4BIT_BP,
92 		.no_sfdp_flags = SECT_4K,
93 	}, {
94 		.id = SNOR_ID(0xc2, 0x20, 0x19),
95 		.name = "mx25l25635e",
96 		.size = SZ_32M,
97 		.no_sfdp_flags = SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,
98 		.fixups = &mx25l25635_fixups
99 	}, {
100 		.id = SNOR_ID(0xc2, 0x20, 0x1a),
101 		.name = "mx66l51235f",
102 		.size = SZ_64M,
103 		.no_sfdp_flags = SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,
104 		.fixup_flags = SPI_NOR_4B_OPCODES,
105 	}, {
106 		.id = SNOR_ID(0xc2, 0x20, 0x1b),
107 		.name = "mx66l1g45g",
108 		.size = SZ_128M,
109 		.no_sfdp_flags = SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,
110 	}, {
111 		.id = SNOR_ID(0xc2, 0x23, 0x14),
112 		.name = "mx25v8035f",
113 		.size = SZ_1M,
114 		.no_sfdp_flags = SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,
115 	}, {
116 		.id = SNOR_ID(0xc2, 0x25, 0x32),
117 		.name = "mx25u2033e",
118 		.size = SZ_256K,
119 		.no_sfdp_flags = SECT_4K,
120 	}, {
121 		.id = SNOR_ID(0xc2, 0x25, 0x33),
122 		.name = "mx25u4035",
123 		.size = SZ_512K,
124 		.no_sfdp_flags = SECT_4K,
125 	}, {
126 		.id = SNOR_ID(0xc2, 0x25, 0x34),
127 		.name = "mx25u8035",
128 		.size = SZ_1M,
129 		.no_sfdp_flags = SECT_4K,
130 	}, {
131 		.id = SNOR_ID(0xc2, 0x25, 0x36),
132 		.name = "mx25u3235f",
133 		.size = SZ_4M,
134 		.no_sfdp_flags = SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,
135 	}, {
136 		.id = SNOR_ID(0xc2, 0x25, 0x37),
137 		.name = "mx25u6435f",
138 		.size = SZ_8M,
139 		.no_sfdp_flags = SECT_4K,
140 	}, {
141 		.id = SNOR_ID(0xc2, 0x25, 0x38),
142 		.name = "mx25u12835f",
143 		.size = SZ_16M,
144 		.no_sfdp_flags = SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,
145 	}, {
146 		.id = SNOR_ID(0xc2, 0x25, 0x39),
147 		.name = "mx25u25635f",
148 		.size = SZ_32M,
149 		.no_sfdp_flags = SECT_4K,
150 		.fixup_flags = SPI_NOR_4B_OPCODES,
151 	}, {
152 		.id = SNOR_ID(0xc2, 0x25, 0x3a),
153 		.name = "mx25u51245g",
154 		.size = SZ_64M,
155 		.no_sfdp_flags = SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,
156 		.fixup_flags = SPI_NOR_4B_OPCODES,
157 	}, {
158 		.id = SNOR_ID(0xc2, 0x25, 0x3a),
159 		.name = "mx66u51235f",
160 		.size = SZ_64M,
161 		.no_sfdp_flags = SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,
162 		.fixup_flags = SPI_NOR_4B_OPCODES,
163 	}, {
164 		.id = SNOR_ID(0xc2, 0x25, 0x3c),
165 		.name = "mx66u2g45g",
166 		.size = SZ_256M,
167 		.no_sfdp_flags = SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,
168 		.fixup_flags = SPI_NOR_4B_OPCODES,
169 	}, {
170 		.id = SNOR_ID(0xc2, 0x26, 0x18),
171 		.name = "mx25l12855e",
172 		.size = SZ_16M,
173 	}, {
174 		.id = SNOR_ID(0xc2, 0x26, 0x19),
175 		.name = "mx25l25655e",
176 		.size = SZ_32M,
177 	}, {
178 		.id = SNOR_ID(0xc2, 0x26, 0x1b),
179 		.name = "mx66l1g55g",
180 		.size = SZ_128M,
181 		.no_sfdp_flags = SPI_NOR_QUAD_READ,
182 	}, {
183 		.id = SNOR_ID(0xc2, 0x28, 0x15),
184 		.name = "mx25r1635f",
185 		.size = SZ_2M,
186 		.no_sfdp_flags = SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,
187 	}, {
188 		.id = SNOR_ID(0xc2, 0x28, 0x16),
189 		.name = "mx25r3235f",
190 		.size = SZ_4M,
191 		.no_sfdp_flags = SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,
192 	}, {
193 		.id = SNOR_ID(0xc2, 0x81, 0x3a),
194 		.name = "mx25uw51245g",
195 		.n_banks = 4,
196 		.flags = SPI_NOR_RWW,
197 	}, {
198 		.id = SNOR_ID(0xc2, 0x9e, 0x16),
199 		.name = "mx25l3255e",
200 		.size = SZ_4M,
201 		.no_sfdp_flags = SECT_4K,
202 	},
203 	/*
204 	 * This spares us of adding new flash entries for flashes that can be
205 	 * initialized solely based on the SFDP data, but still need the
206 	 * manufacturer hooks to set parameters that can't be discovered at SFDP
207 	 * parsing time.
208 	 */
209 	{ .id = SNOR_ID(0xc2) }
210 };
211 
212 static int macronix_nor_octal_dtr_en(struct spi_nor *nor)
213 {
214 	struct spi_mem_op op;
215 	u8 *buf = nor->bouncebuf, i;
216 	int ret;
217 
218 	/* Use dummy cycles which is parse by SFDP and convert to bit pattern. */
219 	buf[0] = MXIC_NOR_REG_DC(nor->params->reads[SNOR_CMD_READ_8_8_8_DTR].num_wait_states);
220 	op = (struct spi_mem_op)MXIC_NOR_WR_CR2(MXIC_NOR_ADDR_CR2_DC, 1, buf);
221 	ret = spi_nor_write_any_volatile_reg(nor, &op, nor->reg_proto);
222 	if (ret)
223 		return ret;
224 
225 	/* Set the octal and DTR enable bits. */
226 	buf[0] = MXIC_NOR_REG_DOPI_EN;
227 	op = (struct spi_mem_op)MXIC_NOR_WR_CR2(MXIC_NOR_ADDR_CR2_MODE, 1, buf);
228 	ret = spi_nor_write_any_volatile_reg(nor, &op, nor->reg_proto);
229 	if (ret)
230 		return ret;
231 
232 	/* Read flash ID to make sure the switch was successful. */
233 	ret = spi_nor_read_id(nor, 4, 4, buf, SNOR_PROTO_8_8_8_DTR);
234 	if (ret) {
235 		dev_dbg(nor->dev, "error %d reading JEDEC ID after enabling 8D-8D-8D mode\n", ret);
236 		return ret;
237 	}
238 
239 	/* Macronix SPI-NOR flash 8D-8D-8D read ID would get 6 bytes data A-A-B-B-C-C */
240 	for (i = 0; i < nor->info->id->len; i++)
241 		if (buf[i * 2] != buf[(i * 2) + 1] || buf[i * 2] != nor->info->id->bytes[i])
242 			return -EINVAL;
243 
244 	return 0;
245 }
246 
247 static int macronix_nor_octal_dtr_dis(struct spi_nor *nor)
248 {
249 	struct spi_mem_op op;
250 	u8 *buf = nor->bouncebuf;
251 	int ret;
252 
253 	/*
254 	 * The register is 1-byte wide, but 1-byte transactions are not
255 	 * allowed in 8D-8D-8D mode. Since there is no register at the
256 	 * next location, just initialize the value to 0 and let the
257 	 * transaction go on.
258 	 */
259 	buf[0] = MXIC_NOR_REG_SPI_EN;
260 	buf[1] = 0x0;
261 	op = (struct spi_mem_op)MXIC_NOR_WR_CR2(MXIC_NOR_ADDR_CR2_MODE, 2, buf);
262 	ret = spi_nor_write_any_volatile_reg(nor, &op, SNOR_PROTO_8_8_8_DTR);
263 	if (ret)
264 		return ret;
265 
266 	/* Read flash ID to make sure the switch was successful. */
267 	ret = spi_nor_read_id(nor, 0, 0, buf, SNOR_PROTO_1_1_1);
268 	if (ret) {
269 		dev_dbg(nor->dev, "error %d reading JEDEC ID after disabling 8D-8D-8D mode\n", ret);
270 		return ret;
271 	}
272 
273 	if (memcmp(buf, nor->info->id->bytes, nor->info->id->len))
274 		return -EINVAL;
275 
276 	return 0;
277 }
278 
279 static int macronix_nor_set_octal_dtr(struct spi_nor *nor, bool enable)
280 {
281 	return enable ? macronix_nor_octal_dtr_en(nor) : macronix_nor_octal_dtr_dis(nor);
282 }
283 
284 static void macronix_nor_default_init(struct spi_nor *nor)
285 {
286 	nor->params->quad_enable = spi_nor_sr1_bit6_quad_enable;
287 }
288 
289 static int macronix_nor_late_init(struct spi_nor *nor)
290 {
291 	if (!nor->params->set_4byte_addr_mode)
292 		nor->params->set_4byte_addr_mode = spi_nor_set_4byte_addr_mode_en4b_ex4b;
293 	nor->params->set_octal_dtr = macronix_nor_set_octal_dtr;
294 
295 	return 0;
296 }
297 
298 static const struct spi_nor_fixups macronix_nor_fixups = {
299 	.default_init = macronix_nor_default_init,
300 	.late_init = macronix_nor_late_init,
301 };
302 
303 const struct spi_nor_manufacturer spi_nor_macronix = {
304 	.name = "macronix",
305 	.parts = macronix_nor_parts,
306 	.nparts = ARRAY_SIZE(macronix_nor_parts),
307 	.fixups = &macronix_nor_fixups,
308 };
309