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 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, 0x3a),
147 		.name = "mx25u51245g",
148 		.size = SZ_64M,
149 		.no_sfdp_flags = SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,
150 		.fixup_flags = SPI_NOR_4B_OPCODES,
151 	}, {
152 		.id = SNOR_ID(0xc2, 0x25, 0x3a),
153 		.name = "mx66u51235f",
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, 0x3c),
159 		.name = "mx66u2g45g",
160 		.size = SZ_256M,
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, 0x26, 0x18),
165 		.name = "mx25l12855e",
166 		.size = SZ_16M,
167 	}, {
168 		.id = SNOR_ID(0xc2, 0x26, 0x19),
169 		.name = "mx25l25655e",
170 		.size = SZ_32M,
171 	}, {
172 		.id = SNOR_ID(0xc2, 0x26, 0x1b),
173 		.name = "mx66l1g55g",
174 		.size = SZ_128M,
175 		.no_sfdp_flags = SPI_NOR_QUAD_READ,
176 	}, {
177 		.id = SNOR_ID(0xc2, 0x28, 0x15),
178 		.name = "mx25r1635f",
179 		.size = SZ_2M,
180 		.no_sfdp_flags = SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,
181 	}, {
182 		.id = SNOR_ID(0xc2, 0x28, 0x16),
183 		.name = "mx25r3235f",
184 		.size = SZ_4M,
185 		.no_sfdp_flags = SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,
186 	}, {
187 		.id = SNOR_ID(0xc2, 0x81, 0x3a),
188 		.name = "mx25uw51245g",
189 		.n_banks = 4,
190 		.flags = SPI_NOR_RWW,
191 	}, {
192 		.id = SNOR_ID(0xc2, 0x9e, 0x16),
193 		.name = "mx25l3255e",
194 		.size = SZ_4M,
195 		.no_sfdp_flags = SECT_4K,
196 	},
197 	/*
198 	 * This spares us of adding new flash entries for flashes that can be
199 	 * initialized solely based on the SFDP data, but still need the
200 	 * manufacturer hooks to set parameters that can't be discovered at SFDP
201 	 * parsing time.
202 	 */
203 	{ .id = SNOR_ID(0xc2) }
204 };
205 
macronix_nor_octal_dtr_en(struct spi_nor * nor)206 static int macronix_nor_octal_dtr_en(struct spi_nor *nor)
207 {
208 	struct spi_mem_op op;
209 	u8 *buf = nor->bouncebuf, i;
210 	int ret;
211 
212 	/* Use dummy cycles which is parse by SFDP and convert to bit pattern. */
213 	buf[0] = MXIC_NOR_REG_DC(nor->params->reads[SNOR_CMD_READ_8_8_8_DTR].num_wait_states);
214 	op = (struct spi_mem_op)MXIC_NOR_WR_CR2(MXIC_NOR_ADDR_CR2_DC, 1, buf);
215 	ret = spi_nor_write_any_volatile_reg(nor, &op, nor->reg_proto);
216 	if (ret)
217 		return ret;
218 
219 	/* Set the octal and DTR enable bits. */
220 	buf[0] = MXIC_NOR_REG_DOPI_EN;
221 	op = (struct spi_mem_op)MXIC_NOR_WR_CR2(MXIC_NOR_ADDR_CR2_MODE, 1, buf);
222 	ret = spi_nor_write_any_volatile_reg(nor, &op, nor->reg_proto);
223 	if (ret)
224 		return ret;
225 
226 	/* Read flash ID to make sure the switch was successful. */
227 	ret = spi_nor_read_id(nor, nor->addr_nbytes, 4, buf,
228 			      SNOR_PROTO_8_8_8_DTR);
229 	if (ret) {
230 		dev_dbg(nor->dev, "error %d reading JEDEC ID after enabling 8D-8D-8D mode\n", ret);
231 		return ret;
232 	}
233 
234 	/* Macronix SPI-NOR flash 8D-8D-8D read ID would get 6 bytes data A-A-B-B-C-C */
235 	for (i = 0; i < nor->info->id->len; i++)
236 		if (buf[i * 2] != buf[(i * 2) + 1] || buf[i * 2] != nor->info->id->bytes[i])
237 			return -EINVAL;
238 
239 	return 0;
240 }
241 
macronix_nor_octal_dtr_dis(struct spi_nor * nor)242 static int macronix_nor_octal_dtr_dis(struct spi_nor *nor)
243 {
244 	struct spi_mem_op op;
245 	u8 *buf = nor->bouncebuf;
246 	int ret;
247 
248 	/*
249 	 * The register is 1-byte wide, but 1-byte transactions are not
250 	 * allowed in 8D-8D-8D mode. Since there is no register at the
251 	 * next location, just initialize the value to 0 and let the
252 	 * transaction go on.
253 	 */
254 	buf[0] = MXIC_NOR_REG_SPI_EN;
255 	buf[1] = 0x0;
256 	op = (struct spi_mem_op)MXIC_NOR_WR_CR2(MXIC_NOR_ADDR_CR2_MODE, 2, buf);
257 	ret = spi_nor_write_any_volatile_reg(nor, &op, SNOR_PROTO_8_8_8_DTR);
258 	if (ret)
259 		return ret;
260 
261 	/* Read flash ID to make sure the switch was successful. */
262 	ret = spi_nor_read_id(nor, 0, 0, buf, SNOR_PROTO_1_1_1);
263 	if (ret) {
264 		dev_dbg(nor->dev, "error %d reading JEDEC ID after disabling 8D-8D-8D mode\n", ret);
265 		return ret;
266 	}
267 
268 	if (memcmp(buf, nor->info->id->bytes, nor->info->id->len))
269 		return -EINVAL;
270 
271 	return 0;
272 }
273 
macronix_nor_set_octal_dtr(struct spi_nor * nor,bool enable)274 static int macronix_nor_set_octal_dtr(struct spi_nor *nor, bool enable)
275 {
276 	return enable ? macronix_nor_octal_dtr_en(nor) : macronix_nor_octal_dtr_dis(nor);
277 }
278 
macronix_nor_default_init(struct spi_nor * nor)279 static void macronix_nor_default_init(struct spi_nor *nor)
280 {
281 	nor->params->quad_enable = spi_nor_sr1_bit6_quad_enable;
282 }
283 
macronix_nor_late_init(struct spi_nor * nor)284 static int macronix_nor_late_init(struct spi_nor *nor)
285 {
286 	if (!nor->params->set_4byte_addr_mode)
287 		nor->params->set_4byte_addr_mode = spi_nor_set_4byte_addr_mode_en4b_ex4b;
288 	nor->params->set_octal_dtr = macronix_nor_set_octal_dtr;
289 
290 	return 0;
291 }
292 
293 static const struct spi_nor_fixups macronix_nor_fixups = {
294 	.default_init = macronix_nor_default_init,
295 	.late_init = macronix_nor_late_init,
296 };
297 
298 const struct spi_nor_manufacturer spi_nor_macronix = {
299 	.name = "macronix",
300 	.parts = macronix_nor_parts,
301 	.nparts = ARRAY_SIZE(macronix_nor_parts),
302 	.fixups = &macronix_nor_fixups,
303 };
304