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
mx25l25635_post_bfpt_fixups(struct spi_nor * nor,const struct sfdp_parameter_header * bfpt_header,const struct sfdp_bfpt * bfpt)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 int
macronix_qpp4b_post_sfdp_fixups(struct spi_nor * nor)49 macronix_qpp4b_post_sfdp_fixups(struct spi_nor *nor)
50 {
51 	/* PP_1_1_4_4B is supported but missing in 4BAIT. */
52 	struct spi_nor_flash_parameter *params = nor->params;
53 
54 	params->hwcaps.mask |= SNOR_HWCAPS_PP_1_1_4;
55 	spi_nor_set_pp_settings(&params->page_programs[SNOR_CMD_PP_1_1_4],
56 				SPINOR_OP_PP_1_1_4_4B, SNOR_PROTO_1_1_4);
57 
58 	return 0;
59 }
60 
61 static const struct spi_nor_fixups mx25l25635_fixups = {
62 	.post_bfpt = mx25l25635_post_bfpt_fixups,
63 	.post_sfdp = macronix_qpp4b_post_sfdp_fixups,
64 };
65 
66 static const struct spi_nor_fixups macronix_qpp4b_fixups = {
67 	.post_sfdp = macronix_qpp4b_post_sfdp_fixups,
68 };
69 
70 static const struct flash_info macronix_nor_parts[] = {
71 	{
72 		.id = SNOR_ID(0xc2, 0x20, 0x10),
73 		.name = "mx25l512e",
74 		.size = SZ_64K,
75 		.no_sfdp_flags = SECT_4K,
76 	}, {
77 		.id = SNOR_ID(0xc2, 0x20, 0x12),
78 		.name = "mx25l2005a",
79 		.size = SZ_256K,
80 		.no_sfdp_flags = SECT_4K,
81 	}, {
82 		.id = SNOR_ID(0xc2, 0x20, 0x13),
83 		.name = "mx25l4005a",
84 		.size = SZ_512K,
85 		.no_sfdp_flags = SECT_4K,
86 	}, {
87 		.id = SNOR_ID(0xc2, 0x20, 0x14),
88 		.name = "mx25l8005",
89 		.size = SZ_1M,
90 	}, {
91 		.id = SNOR_ID(0xc2, 0x20, 0x15),
92 		.name = "mx25l1606e",
93 		.size = SZ_2M,
94 		.no_sfdp_flags = SECT_4K,
95 	}, {
96 		.id = SNOR_ID(0xc2, 0x20, 0x16),
97 		.name = "mx25l3205d",
98 		.size = SZ_4M,
99 		.no_sfdp_flags = SECT_4K,
100 	}, {
101 		.id = SNOR_ID(0xc2, 0x20, 0x17),
102 		.name = "mx25l6405d",
103 		.size = SZ_8M,
104 		.no_sfdp_flags = SECT_4K,
105 	}, {
106 		.id = SNOR_ID(0xc2, 0x20, 0x18),
107 		.name = "mx25l12805d",
108 		.size = SZ_16M,
109 		.flags = SPI_NOR_HAS_LOCK | SPI_NOR_4BIT_BP,
110 		.no_sfdp_flags = SECT_4K,
111 	}, {
112 		.id = SNOR_ID(0xc2, 0x20, 0x19),
113 		.name = "mx25l25635e",
114 		.size = SZ_32M,
115 		.no_sfdp_flags = SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,
116 		.fixups = &mx25l25635_fixups
117 	}, {
118 		.id = SNOR_ID(0xc2, 0x20, 0x1a),
119 		.name = "mx66l51235f",
120 		.size = SZ_64M,
121 		.no_sfdp_flags = SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,
122 		.fixup_flags = SPI_NOR_4B_OPCODES,
123 		.fixups = &macronix_qpp4b_fixups,
124 	}, {
125 		.id = SNOR_ID(0xc2, 0x20, 0x1b),
126 		.name = "mx66l1g45g",
127 		.size = SZ_128M,
128 		.no_sfdp_flags = SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,
129 		.fixups = &macronix_qpp4b_fixups,
130 	}, {
131 		/* MX66L2G45G */
132 		.id = SNOR_ID(0xc2, 0x20, 0x1c),
133 		.fixups = &macronix_qpp4b_fixups,
134 	}, {
135 		.id = SNOR_ID(0xc2, 0x23, 0x14),
136 		.name = "mx25v8035f",
137 		.size = SZ_1M,
138 		.no_sfdp_flags = SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,
139 	}, {
140 		.id = SNOR_ID(0xc2, 0x25, 0x32),
141 		.name = "mx25u2033e",
142 		.size = SZ_256K,
143 		.no_sfdp_flags = SECT_4K,
144 	}, {
145 		.id = SNOR_ID(0xc2, 0x25, 0x33),
146 		.name = "mx25u4035",
147 		.size = SZ_512K,
148 		.no_sfdp_flags = SECT_4K,
149 	}, {
150 		.id = SNOR_ID(0xc2, 0x25, 0x34),
151 		.name = "mx25u8035",
152 		.size = SZ_1M,
153 		.no_sfdp_flags = SECT_4K,
154 	}, {
155 		.id = SNOR_ID(0xc2, 0x25, 0x36),
156 		.name = "mx25u3235f",
157 		.size = SZ_4M,
158 		.no_sfdp_flags = SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,
159 	}, {
160 		.id = SNOR_ID(0xc2, 0x25, 0x37),
161 		.name = "mx25u6435f",
162 		.size = SZ_8M,
163 		.no_sfdp_flags = SECT_4K,
164 	}, {
165 		.id = SNOR_ID(0xc2, 0x25, 0x38),
166 		.name = "mx25u12835f",
167 		.size = SZ_16M,
168 		.no_sfdp_flags = SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,
169 	}, {
170 		.id = SNOR_ID(0xc2, 0x25, 0x3a),
171 		.name = "mx25u51245g",
172 		.size = SZ_64M,
173 		.no_sfdp_flags = SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,
174 		.fixup_flags = SPI_NOR_4B_OPCODES,
175 		.fixups = &macronix_qpp4b_fixups,
176 	}, {
177 		.id = SNOR_ID(0xc2, 0x25, 0x3a),
178 		.name = "mx66u51235f",
179 		.size = SZ_64M,
180 		.no_sfdp_flags = SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,
181 		.fixup_flags = SPI_NOR_4B_OPCODES,
182 		.fixups = &macronix_qpp4b_fixups,
183 	}, {
184 		/* MX66U1G45G */
185 		.id = SNOR_ID(0xc2, 0x25, 0x3b),
186 		.fixups = &macronix_qpp4b_fixups,
187 	}, {
188 		.id = SNOR_ID(0xc2, 0x25, 0x3c),
189 		.name = "mx66u2g45g",
190 		.size = SZ_256M,
191 		.no_sfdp_flags = SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,
192 		.fixup_flags = SPI_NOR_4B_OPCODES,
193 		.fixups = &macronix_qpp4b_fixups,
194 	}, {
195 		.id = SNOR_ID(0xc2, 0x26, 0x18),
196 		.name = "mx25l12855e",
197 		.size = SZ_16M,
198 	}, {
199 		.id = SNOR_ID(0xc2, 0x26, 0x19),
200 		.name = "mx25l25655e",
201 		.size = SZ_32M,
202 	}, {
203 		.id = SNOR_ID(0xc2, 0x26, 0x1b),
204 		.name = "mx66l1g55g",
205 		.size = SZ_128M,
206 		.no_sfdp_flags = SPI_NOR_QUAD_READ,
207 	}, {
208 		.id = SNOR_ID(0xc2, 0x28, 0x15),
209 		.name = "mx25r1635f",
210 		.size = SZ_2M,
211 		.no_sfdp_flags = SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,
212 	}, {
213 		.id = SNOR_ID(0xc2, 0x28, 0x16),
214 		.name = "mx25r3235f",
215 		.size = SZ_4M,
216 		.no_sfdp_flags = SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,
217 	}, {
218 		.id = SNOR_ID(0xc2, 0x81, 0x3a),
219 		.name = "mx25uw51245g",
220 		.n_banks = 4,
221 		.flags = SPI_NOR_RWW,
222 	}, {
223 		.id = SNOR_ID(0xc2, 0x9e, 0x16),
224 		.name = "mx25l3255e",
225 		.size = SZ_4M,
226 		.no_sfdp_flags = SECT_4K,
227 	},
228 	/*
229 	 * This spares us of adding new flash entries for flashes that can be
230 	 * initialized solely based on the SFDP data, but still need the
231 	 * manufacturer hooks to set parameters that can't be discovered at SFDP
232 	 * parsing time.
233 	 */
234 	{ .id = SNOR_ID(0xc2) }
235 };
236 
macronix_nor_octal_dtr_en(struct spi_nor * nor)237 static int macronix_nor_octal_dtr_en(struct spi_nor *nor)
238 {
239 	struct spi_mem_op op;
240 	u8 *buf = nor->bouncebuf, i;
241 	int ret;
242 
243 	/* Use dummy cycles which is parse by SFDP and convert to bit pattern. */
244 	buf[0] = MXIC_NOR_REG_DC(nor->params->reads[SNOR_CMD_READ_8_8_8_DTR].num_wait_states);
245 	op = (struct spi_mem_op)MXIC_NOR_WR_CR2(MXIC_NOR_ADDR_CR2_DC, 1, buf);
246 	ret = spi_nor_write_any_volatile_reg(nor, &op, nor->reg_proto);
247 	if (ret)
248 		return ret;
249 
250 	/* Set the octal and DTR enable bits. */
251 	buf[0] = MXIC_NOR_REG_DOPI_EN;
252 	op = (struct spi_mem_op)MXIC_NOR_WR_CR2(MXIC_NOR_ADDR_CR2_MODE, 1, buf);
253 	ret = spi_nor_write_any_volatile_reg(nor, &op, nor->reg_proto);
254 	if (ret)
255 		return ret;
256 
257 	/* Read flash ID to make sure the switch was successful. */
258 	ret = spi_nor_read_id(nor, nor->addr_nbytes, 4, buf,
259 			      SNOR_PROTO_8_8_8_DTR);
260 	if (ret) {
261 		dev_dbg(nor->dev, "error %d reading JEDEC ID after enabling 8D-8D-8D mode\n", ret);
262 		return ret;
263 	}
264 
265 	/* Macronix SPI-NOR flash 8D-8D-8D read ID would get 6 bytes data A-A-B-B-C-C */
266 	for (i = 0; i < nor->info->id->len; i++)
267 		if (buf[i * 2] != buf[(i * 2) + 1] || buf[i * 2] != nor->info->id->bytes[i])
268 			return -EINVAL;
269 
270 	return 0;
271 }
272 
macronix_nor_octal_dtr_dis(struct spi_nor * nor)273 static int macronix_nor_octal_dtr_dis(struct spi_nor *nor)
274 {
275 	struct spi_mem_op op;
276 	u8 *buf = nor->bouncebuf;
277 	int ret;
278 
279 	/*
280 	 * The register is 1-byte wide, but 1-byte transactions are not
281 	 * allowed in 8D-8D-8D mode. Since there is no register at the
282 	 * next location, just initialize the value to 0 and let the
283 	 * transaction go on.
284 	 */
285 	buf[0] = MXIC_NOR_REG_SPI_EN;
286 	buf[1] = 0x0;
287 	op = (struct spi_mem_op)MXIC_NOR_WR_CR2(MXIC_NOR_ADDR_CR2_MODE, 2, buf);
288 	ret = spi_nor_write_any_volatile_reg(nor, &op, SNOR_PROTO_8_8_8_DTR);
289 	if (ret)
290 		return ret;
291 
292 	/* Read flash ID to make sure the switch was successful. */
293 	ret = spi_nor_read_id(nor, 0, 0, buf, SNOR_PROTO_1_1_1);
294 	if (ret) {
295 		dev_dbg(nor->dev, "error %d reading JEDEC ID after disabling 8D-8D-8D mode\n", ret);
296 		return ret;
297 	}
298 
299 	if (memcmp(buf, nor->info->id->bytes, nor->info->id->len))
300 		return -EINVAL;
301 
302 	return 0;
303 }
304 
macronix_nor_set_octal_dtr(struct spi_nor * nor,bool enable)305 static int macronix_nor_set_octal_dtr(struct spi_nor *nor, bool enable)
306 {
307 	return enable ? macronix_nor_octal_dtr_en(nor) : macronix_nor_octal_dtr_dis(nor);
308 }
309 
macronix_nor_default_init(struct spi_nor * nor)310 static void macronix_nor_default_init(struct spi_nor *nor)
311 {
312 	nor->params->quad_enable = spi_nor_sr1_bit6_quad_enable;
313 }
314 
macronix_nor_late_init(struct spi_nor * nor)315 static int macronix_nor_late_init(struct spi_nor *nor)
316 {
317 	if (!nor->params->set_4byte_addr_mode)
318 		nor->params->set_4byte_addr_mode = spi_nor_set_4byte_addr_mode_en4b_ex4b;
319 	nor->params->set_octal_dtr = macronix_nor_set_octal_dtr;
320 
321 	return 0;
322 }
323 
324 static const struct spi_nor_fixups macronix_nor_fixups = {
325 	.default_init = macronix_nor_default_init,
326 	.late_init = macronix_nor_late_init,
327 };
328 
329 const struct spi_nor_manufacturer spi_nor_macronix = {
330 	.name = "macronix",
331 	.parts = macronix_nor_parts,
332 	.nparts = ARRAY_SIZE(macronix_nor_parts),
333 	.fixups = &macronix_nor_fixups,
334 };
335