xref: /openbmc/linux/drivers/mtd/spi-nor/spansion.c (revision faffb083)
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 /* flash_info mfr_flag. Used to clear sticky prorietary SR bits. */
12 #define USE_CLSR	BIT(0)
13 
14 #define SPINOR_OP_CLSR		0x30	/* Clear status register 1 */
15 #define SPINOR_OP_RD_ANY_REG			0x65	/* Read any register */
16 #define SPINOR_OP_WR_ANY_REG			0x71	/* Write any register */
17 #define SPINOR_REG_CYPRESS_CFR1V		0x00800002
18 #define SPINOR_REG_CYPRESS_CFR1V_QUAD_EN	BIT(1)	/* Quad Enable */
19 #define SPINOR_REG_CYPRESS_CFR2V		0x00800003
20 #define SPINOR_REG_CYPRESS_CFR2V_MEMLAT_11_24	0xb
21 #define SPINOR_REG_CYPRESS_CFR3V		0x00800004
22 #define SPINOR_REG_CYPRESS_CFR3V_PGSZ		BIT(4) /* Page size. */
23 #define SPINOR_REG_CYPRESS_CFR5V		0x00800006
24 #define SPINOR_REG_CYPRESS_CFR5V_OCT_DTR_EN	0x3
25 #define SPINOR_REG_CYPRESS_CFR5V_OCT_DTR_DS	0
26 #define SPINOR_OP_CYPRESS_RD_FAST		0xee
27 
28 /* Cypress SPI NOR flash operations. */
29 #define CYPRESS_NOR_WR_ANY_REG_OP(naddr, addr, ndata, buf)		\
30 	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WR_ANY_REG, 0),		\
31 		   SPI_MEM_OP_ADDR(naddr, addr, 0),			\
32 		   SPI_MEM_OP_NO_DUMMY,					\
33 		   SPI_MEM_OP_DATA_OUT(ndata, buf, 0))
34 
35 #define CYPRESS_NOR_RD_ANY_REG_OP(naddr, addr, buf)			\
36 	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RD_ANY_REG, 0),		\
37 		   SPI_MEM_OP_ADDR(naddr, addr, 0),			\
38 		   SPI_MEM_OP_NO_DUMMY,					\
39 		   SPI_MEM_OP_DATA_IN(1, buf, 0))
40 
41 #define SPANSION_CLSR_OP						\
42 	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_CLSR, 0),			\
43 		   SPI_MEM_OP_NO_ADDR,					\
44 		   SPI_MEM_OP_NO_DUMMY,					\
45 		   SPI_MEM_OP_NO_DATA)
46 
47 static int cypress_nor_octal_dtr_en(struct spi_nor *nor)
48 {
49 	struct spi_mem_op op;
50 	u8 *buf = nor->bouncebuf;
51 	int ret;
52 	u8 addr_mode_nbytes = nor->params->addr_mode_nbytes;
53 
54 	/* Use 24 dummy cycles for memory array reads. */
55 	*buf = SPINOR_REG_CYPRESS_CFR2V_MEMLAT_11_24;
56 	op = (struct spi_mem_op)
57 		CYPRESS_NOR_WR_ANY_REG_OP(addr_mode_nbytes,
58 					  SPINOR_REG_CYPRESS_CFR2V, 1, buf);
59 
60 	ret = spi_nor_write_any_volatile_reg(nor, &op, nor->reg_proto);
61 	if (ret)
62 		return ret;
63 
64 	nor->read_dummy = 24;
65 
66 	/* Set the octal and DTR enable bits. */
67 	buf[0] = SPINOR_REG_CYPRESS_CFR5V_OCT_DTR_EN;
68 	op = (struct spi_mem_op)
69 		CYPRESS_NOR_WR_ANY_REG_OP(addr_mode_nbytes,
70 					  SPINOR_REG_CYPRESS_CFR5V, 1, buf);
71 
72 	ret = spi_nor_write_any_volatile_reg(nor, &op, nor->reg_proto);
73 	if (ret)
74 		return ret;
75 
76 	/* Read flash ID to make sure the switch was successful. */
77 	ret = spi_nor_read_id(nor, nor->addr_nbytes, 3, buf,
78 			      SNOR_PROTO_8_8_8_DTR);
79 	if (ret) {
80 		dev_dbg(nor->dev, "error %d reading JEDEC ID after enabling 8D-8D-8D mode\n", ret);
81 		return ret;
82 	}
83 
84 	if (memcmp(buf, nor->info->id, nor->info->id_len))
85 		return -EINVAL;
86 
87 	return 0;
88 }
89 
90 static int cypress_nor_octal_dtr_dis(struct spi_nor *nor)
91 {
92 	struct spi_mem_op op;
93 	u8 *buf = nor->bouncebuf;
94 	int ret;
95 
96 	/*
97 	 * The register is 1-byte wide, but 1-byte transactions are not allowed
98 	 * in 8D-8D-8D mode. Since there is no register at the next location,
99 	 * just initialize the value to 0 and let the transaction go on.
100 	 */
101 	buf[0] = SPINOR_REG_CYPRESS_CFR5V_OCT_DTR_DS;
102 	buf[1] = 0;
103 	op = (struct spi_mem_op)
104 		CYPRESS_NOR_WR_ANY_REG_OP(nor->addr_nbytes,
105 					  SPINOR_REG_CYPRESS_CFR5V, 2, buf);
106 	ret = spi_nor_write_any_volatile_reg(nor, &op, SNOR_PROTO_8_8_8_DTR);
107 	if (ret)
108 		return ret;
109 
110 	/* Read flash ID to make sure the switch was successful. */
111 	ret = spi_nor_read_id(nor, 0, 0, buf, SNOR_PROTO_1_1_1);
112 	if (ret) {
113 		dev_dbg(nor->dev, "error %d reading JEDEC ID after disabling 8D-8D-8D mode\n", ret);
114 		return ret;
115 	}
116 
117 	if (memcmp(buf, nor->info->id, nor->info->id_len))
118 		return -EINVAL;
119 
120 	return 0;
121 }
122 
123 /**
124  * cypress_nor_quad_enable_volatile() - enable Quad I/O mode in volatile
125  *                                      register.
126  * @nor:	pointer to a 'struct spi_nor'
127  *
128  * It is recommended to update volatile registers in the field application due
129  * to a risk of the non-volatile registers corruption by power interrupt. This
130  * function sets Quad Enable bit in CFR1 volatile. If users set the Quad Enable
131  * bit in the CFR1 non-volatile in advance (typically by a Flash programmer
132  * before mounting Flash on PCB), the Quad Enable bit in the CFR1 volatile is
133  * also set during Flash power-up.
134  *
135  * Return: 0 on success, -errno otherwise.
136  */
137 static int cypress_nor_quad_enable_volatile(struct spi_nor *nor)
138 {
139 	struct spi_mem_op op;
140 	u8 addr_mode_nbytes = nor->params->addr_mode_nbytes;
141 	u8 cfr1v_written;
142 	int ret;
143 
144 	op = (struct spi_mem_op)
145 		CYPRESS_NOR_RD_ANY_REG_OP(addr_mode_nbytes,
146 					  SPINOR_REG_CYPRESS_CFR1V,
147 					  nor->bouncebuf);
148 
149 	ret = spi_nor_read_any_reg(nor, &op, nor->reg_proto);
150 	if (ret)
151 		return ret;
152 
153 	if (nor->bouncebuf[0] & SPINOR_REG_CYPRESS_CFR1V_QUAD_EN)
154 		return 0;
155 
156 	/* Update the Quad Enable bit. */
157 	nor->bouncebuf[0] |= SPINOR_REG_CYPRESS_CFR1V_QUAD_EN;
158 	op = (struct spi_mem_op)
159 		CYPRESS_NOR_WR_ANY_REG_OP(addr_mode_nbytes,
160 					  SPINOR_REG_CYPRESS_CFR1V, 1,
161 					  nor->bouncebuf);
162 	ret = spi_nor_write_any_volatile_reg(nor, &op, nor->reg_proto);
163 	if (ret)
164 		return ret;
165 
166 	cfr1v_written = nor->bouncebuf[0];
167 
168 	/* Read back and check it. */
169 	op = (struct spi_mem_op)
170 		CYPRESS_NOR_RD_ANY_REG_OP(addr_mode_nbytes,
171 					  SPINOR_REG_CYPRESS_CFR1V,
172 					  nor->bouncebuf);
173 	ret = spi_nor_read_any_reg(nor, &op, nor->reg_proto);
174 	if (ret)
175 		return ret;
176 
177 	if (nor->bouncebuf[0] != cfr1v_written) {
178 		dev_err(nor->dev, "CFR1: Read back test failed\n");
179 		return -EIO;
180 	}
181 
182 	return 0;
183 }
184 
185 /**
186  * cypress_nor_set_page_size() - Set page size which corresponds to the flash
187  *                               configuration.
188  * @nor:	pointer to a 'struct spi_nor'
189  *
190  * The BFPT table advertises a 512B or 256B page size depending on part but the
191  * page size is actually configurable (with the default being 256B). Read from
192  * CFR3V[4] and set the correct size.
193  *
194  * Return: 0 on success, -errno otherwise.
195  */
196 static int cypress_nor_set_page_size(struct spi_nor *nor)
197 {
198 	struct spi_mem_op op =
199 		CYPRESS_NOR_RD_ANY_REG_OP(nor->params->addr_mode_nbytes,
200 					  SPINOR_REG_CYPRESS_CFR3V,
201 					  nor->bouncebuf);
202 	int ret;
203 
204 	ret = spi_nor_read_any_reg(nor, &op, nor->reg_proto);
205 	if (ret)
206 		return ret;
207 
208 	if (nor->bouncebuf[0] & SPINOR_REG_CYPRESS_CFR3V_PGSZ)
209 		nor->params->page_size = 512;
210 	else
211 		nor->params->page_size = 256;
212 
213 	return 0;
214 }
215 
216 static int
217 s25hx_t_post_bfpt_fixup(struct spi_nor *nor,
218 			const struct sfdp_parameter_header *bfpt_header,
219 			const struct sfdp_bfpt *bfpt)
220 {
221 	/* Replace Quad Enable with volatile version */
222 	nor->params->quad_enable = cypress_nor_quad_enable_volatile;
223 
224 	return cypress_nor_set_page_size(nor);
225 }
226 
227 static void s25hx_t_post_sfdp_fixup(struct spi_nor *nor)
228 {
229 	struct spi_nor_erase_type *erase_type =
230 					nor->params->erase_map.erase_type;
231 	unsigned int i;
232 
233 	/*
234 	 * In some parts, 3byte erase opcodes are advertised by 4BAIT.
235 	 * Convert them to 4byte erase opcodes.
236 	 */
237 	for (i = 0; i < SNOR_ERASE_TYPE_MAX; i++) {
238 		switch (erase_type[i].opcode) {
239 		case SPINOR_OP_SE:
240 			erase_type[i].opcode = SPINOR_OP_SE_4B;
241 			break;
242 		case SPINOR_OP_BE_4K:
243 			erase_type[i].opcode = SPINOR_OP_BE_4K_4B;
244 			break;
245 		default:
246 			break;
247 		}
248 	}
249 }
250 
251 static void s25hx_t_late_init(struct spi_nor *nor)
252 {
253 	struct spi_nor_flash_parameter *params = nor->params;
254 
255 	/* Fast Read 4B requires mode cycles */
256 	params->reads[SNOR_CMD_READ_FAST].num_mode_clocks = 8;
257 
258 	/* The writesize should be ECC data unit size */
259 	params->writesize = 16;
260 }
261 
262 static struct spi_nor_fixups s25hx_t_fixups = {
263 	.post_bfpt = s25hx_t_post_bfpt_fixup,
264 	.post_sfdp = s25hx_t_post_sfdp_fixup,
265 	.late_init = s25hx_t_late_init,
266 };
267 
268 /**
269  * cypress_nor_octal_dtr_enable() - Enable octal DTR on Cypress flashes.
270  * @nor:		pointer to a 'struct spi_nor'
271  * @enable:              whether to enable or disable Octal DTR
272  *
273  * This also sets the memory access latency cycles to 24 to allow the flash to
274  * run at up to 200MHz.
275  *
276  * Return: 0 on success, -errno otherwise.
277  */
278 static int cypress_nor_octal_dtr_enable(struct spi_nor *nor, bool enable)
279 {
280 	return enable ? cypress_nor_octal_dtr_en(nor) :
281 			cypress_nor_octal_dtr_dis(nor);
282 }
283 
284 static void s28hx_t_post_sfdp_fixup(struct spi_nor *nor)
285 {
286 	/*
287 	 * On older versions of the flash the xSPI Profile 1.0 table has the
288 	 * 8D-8D-8D Fast Read opcode as 0x00. But it actually should be 0xEE.
289 	 */
290 	if (nor->params->reads[SNOR_CMD_READ_8_8_8_DTR].opcode == 0)
291 		nor->params->reads[SNOR_CMD_READ_8_8_8_DTR].opcode =
292 			SPINOR_OP_CYPRESS_RD_FAST;
293 
294 	/* This flash is also missing the 4-byte Page Program opcode bit. */
295 	spi_nor_set_pp_settings(&nor->params->page_programs[SNOR_CMD_PP],
296 				SPINOR_OP_PP_4B, SNOR_PROTO_1_1_1);
297 	/*
298 	 * Since xSPI Page Program opcode is backward compatible with
299 	 * Legacy SPI, use Legacy SPI opcode there as well.
300 	 */
301 	spi_nor_set_pp_settings(&nor->params->page_programs[SNOR_CMD_PP_8_8_8_DTR],
302 				SPINOR_OP_PP_4B, SNOR_PROTO_8_8_8_DTR);
303 
304 	/*
305 	 * The xSPI Profile 1.0 table advertises the number of additional
306 	 * address bytes needed for Read Status Register command as 0 but the
307 	 * actual value for that is 4.
308 	 */
309 	nor->params->rdsr_addr_nbytes = 4;
310 }
311 
312 static int s28hx_t_post_bfpt_fixup(struct spi_nor *nor,
313 				   const struct sfdp_parameter_header *bfpt_header,
314 				   const struct sfdp_bfpt *bfpt)
315 {
316 	return cypress_nor_set_page_size(nor);
317 }
318 
319 static void s28hx_t_late_init(struct spi_nor *nor)
320 {
321 	nor->params->octal_dtr_enable = cypress_nor_octal_dtr_enable;
322 	nor->params->writesize = 16;
323 }
324 
325 static const struct spi_nor_fixups s28hx_t_fixups = {
326 	.post_sfdp = s28hx_t_post_sfdp_fixup,
327 	.post_bfpt = s28hx_t_post_bfpt_fixup,
328 	.late_init = s28hx_t_late_init,
329 };
330 
331 static int
332 s25fs_s_nor_post_bfpt_fixups(struct spi_nor *nor,
333 			     const struct sfdp_parameter_header *bfpt_header,
334 			     const struct sfdp_bfpt *bfpt)
335 {
336 	/*
337 	 * The S25FS-S chip family reports 512-byte pages in BFPT but
338 	 * in reality the write buffer still wraps at the safe default
339 	 * of 256 bytes.  Overwrite the page size advertised by BFPT
340 	 * to get the writes working.
341 	 */
342 	nor->params->page_size = 256;
343 
344 	return 0;
345 }
346 
347 static const struct spi_nor_fixups s25fs_s_nor_fixups = {
348 	.post_bfpt = s25fs_s_nor_post_bfpt_fixups,
349 };
350 
351 static const struct flash_info spansion_nor_parts[] = {
352 	/* Spansion/Cypress -- single (large) sector size only, at least
353 	 * for the chips listed here (without boot sectors).
354 	 */
355 	{ "s25sl032p",  INFO(0x010215, 0x4d00,  64 * 1024,  64)
356 		NO_SFDP_FLAGS(SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
357 	{ "s25sl064p",  INFO(0x010216, 0x4d00,  64 * 1024, 128)
358 		NO_SFDP_FLAGS(SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
359 	{ "s25fl128s0", INFO6(0x012018, 0x4d0080, 256 * 1024, 64)
360 		NO_SFDP_FLAGS(SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ)
361 		MFR_FLAGS(USE_CLSR)
362 	},
363 	{ "s25fl128s1", INFO6(0x012018, 0x4d0180, 64 * 1024, 256)
364 		NO_SFDP_FLAGS(SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ)
365 		MFR_FLAGS(USE_CLSR)
366 	},
367 	{ "s25fl256s0", INFO6(0x010219, 0x4d0080, 256 * 1024, 128)
368 		NO_SFDP_FLAGS(SPI_NOR_SKIP_SFDP | SPI_NOR_DUAL_READ |
369 			      SPI_NOR_QUAD_READ)
370 		MFR_FLAGS(USE_CLSR)
371 	},
372 	{ "s25fl256s1", INFO6(0x010219, 0x4d0180, 64 * 1024, 512)
373 		NO_SFDP_FLAGS(SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ)
374 		MFR_FLAGS(USE_CLSR)
375 	},
376 	{ "s25fl512s",  INFO6(0x010220, 0x4d0080, 256 * 1024, 256)
377 		FLAGS(SPI_NOR_HAS_LOCK)
378 		NO_SFDP_FLAGS(SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ)
379 		MFR_FLAGS(USE_CLSR)
380 	},
381 	{ "s25fs128s1", INFO6(0x012018, 0x4d0181, 64 * 1024, 256)
382 		NO_SFDP_FLAGS(SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ)
383 		MFR_FLAGS(USE_CLSR)
384 		.fixups = &s25fs_s_nor_fixups, },
385 	{ "s25fs256s0", INFO6(0x010219, 0x4d0081, 256 * 1024, 128)
386 		NO_SFDP_FLAGS(SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ)
387 		MFR_FLAGS(USE_CLSR)
388 	},
389 	{ "s25fs256s1", INFO6(0x010219, 0x4d0181, 64 * 1024, 512)
390 		NO_SFDP_FLAGS(SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ)
391 		MFR_FLAGS(USE_CLSR)
392 	},
393 	{ "s25fs512s",  INFO6(0x010220, 0x4d0081, 256 * 1024, 256)
394 		NO_SFDP_FLAGS(SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ)
395 		MFR_FLAGS(USE_CLSR)
396 		.fixups = &s25fs_s_nor_fixups, },
397 	{ "s25sl12800", INFO(0x012018, 0x0300, 256 * 1024,  64) },
398 	{ "s25sl12801", INFO(0x012018, 0x0301,  64 * 1024, 256) },
399 	{ "s25fl129p0", INFO(0x012018, 0x4d00, 256 * 1024,  64)
400 		NO_SFDP_FLAGS(SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ)
401 		MFR_FLAGS(USE_CLSR)
402 	},
403 	{ "s25fl129p1", INFO(0x012018, 0x4d01,  64 * 1024, 256)
404 		NO_SFDP_FLAGS(SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ)
405 		MFR_FLAGS(USE_CLSR)
406 	},
407 	{ "s25sl004a",  INFO(0x010212,      0,  64 * 1024,   8) },
408 	{ "s25sl008a",  INFO(0x010213,      0,  64 * 1024,  16) },
409 	{ "s25sl016a",  INFO(0x010214,      0,  64 * 1024,  32) },
410 	{ "s25sl032a",  INFO(0x010215,      0,  64 * 1024,  64) },
411 	{ "s25sl064a",  INFO(0x010216,      0,  64 * 1024, 128) },
412 	{ "s25fl004k",  INFO(0xef4013,      0,  64 * 1024,   8)
413 		NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ |
414 			      SPI_NOR_QUAD_READ) },
415 	{ "s25fl008k",  INFO(0xef4014,      0,  64 * 1024,  16)
416 		NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ |
417 			      SPI_NOR_QUAD_READ) },
418 	{ "s25fl016k",  INFO(0xef4015,      0,  64 * 1024,  32)
419 		NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ |
420 			      SPI_NOR_QUAD_READ) },
421 	{ "s25fl064k",  INFO(0xef4017,      0,  64 * 1024, 128)
422 		NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ |
423 			      SPI_NOR_QUAD_READ) },
424 	{ "s25fl116k",  INFO(0x014015,      0,  64 * 1024,  32)
425 		NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ |
426 			      SPI_NOR_QUAD_READ) },
427 	{ "s25fl132k",  INFO(0x014016,      0,  64 * 1024,  64)
428 		NO_SFDP_FLAGS(SECT_4K) },
429 	{ "s25fl164k",  INFO(0x014017,      0,  64 * 1024, 128)
430 		NO_SFDP_FLAGS(SECT_4K) },
431 	{ "s25fl204k",  INFO(0x014013,      0,  64 * 1024,   8)
432 		NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ) },
433 	{ "s25fl208k",  INFO(0x014014,      0,  64 * 1024,  16)
434 		NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ) },
435 	{ "s25fl064l",  INFO(0x016017,      0,  64 * 1024, 128)
436 		NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ)
437 		FIXUP_FLAGS(SPI_NOR_4B_OPCODES) },
438 	{ "s25fl128l",  INFO(0x016018,      0,  64 * 1024, 256)
439 		NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ)
440 		FIXUP_FLAGS(SPI_NOR_4B_OPCODES) },
441 	{ "s25fl256l",  INFO(0x016019,      0,  64 * 1024, 512)
442 		NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ)
443 		FIXUP_FLAGS(SPI_NOR_4B_OPCODES) },
444 	{ "s25hl512t",  INFO6(0x342a1a, 0x0f0390, 256 * 1024, 256)
445 		PARSE_SFDP
446 		MFR_FLAGS(USE_CLSR)
447 		.fixups = &s25hx_t_fixups },
448 	{ "s25hl01gt",  INFO6(0x342a1b, 0x0f0390, 256 * 1024, 512)
449 		PARSE_SFDP
450 		MFR_FLAGS(USE_CLSR)
451 		.fixups = &s25hx_t_fixups },
452 	{ "s25hs512t",  INFO6(0x342b1a, 0x0f0390, 256 * 1024, 256)
453 		PARSE_SFDP
454 		MFR_FLAGS(USE_CLSR)
455 		.fixups = &s25hx_t_fixups },
456 	{ "s25hs01gt",  INFO6(0x342b1b, 0x0f0390, 256 * 1024, 512)
457 		PARSE_SFDP
458 		MFR_FLAGS(USE_CLSR)
459 		.fixups = &s25hx_t_fixups },
460 	{ "cy15x104q",  INFO6(0x042cc2, 0x7f7f7f, 512 * 1024, 1)
461 		FLAGS(SPI_NOR_NO_ERASE) },
462 	{ "s28hl512t",   INFO(0x345a1a,      0, 256 * 1024, 256)
463 		PARSE_SFDP
464 		.fixups = &s28hx_t_fixups,
465 	},
466 	{ "s28hl01gt",   INFO(0x345a1b,      0, 256 * 1024, 512)
467 		PARSE_SFDP
468 		.fixups = &s28hx_t_fixups,
469 	},
470 	{ "s28hs512t",   INFO(0x345b1a,      0, 256 * 1024, 256)
471 		PARSE_SFDP
472 		.fixups = &s28hx_t_fixups,
473 	},
474 	{ "s28hs01gt",   INFO(0x345b1b,      0, 256 * 1024, 512)
475 		PARSE_SFDP
476 		.fixups = &s28hx_t_fixups,
477 	},
478 };
479 
480 /**
481  * spansion_nor_clear_sr() - Clear the Status Register.
482  * @nor:	pointer to 'struct spi_nor'.
483  */
484 static void spansion_nor_clear_sr(struct spi_nor *nor)
485 {
486 	int ret;
487 
488 	if (nor->spimem) {
489 		struct spi_mem_op op = SPANSION_CLSR_OP;
490 
491 		spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
492 
493 		ret = spi_mem_exec_op(nor->spimem, &op);
494 	} else {
495 		ret = spi_nor_controller_ops_write_reg(nor, SPINOR_OP_CLSR,
496 						       NULL, 0);
497 	}
498 
499 	if (ret)
500 		dev_dbg(nor->dev, "error %d clearing SR\n", ret);
501 }
502 
503 /**
504  * spansion_nor_sr_ready_and_clear() - Query the Status Register to see if the
505  * flash is ready for new commands and clear it if there are any errors.
506  * @nor:	pointer to 'struct spi_nor'.
507  *
508  * Return: 1 if ready, 0 if not ready, -errno on errors.
509  */
510 static int spansion_nor_sr_ready_and_clear(struct spi_nor *nor)
511 {
512 	int ret;
513 
514 	ret = spi_nor_read_sr(nor, nor->bouncebuf);
515 	if (ret)
516 		return ret;
517 
518 	if (nor->bouncebuf[0] & (SR_E_ERR | SR_P_ERR)) {
519 		if (nor->bouncebuf[0] & SR_E_ERR)
520 			dev_err(nor->dev, "Erase Error occurred\n");
521 		else
522 			dev_err(nor->dev, "Programming Error occurred\n");
523 
524 		spansion_nor_clear_sr(nor);
525 
526 		/*
527 		 * WEL bit remains set to one when an erase or page program
528 		 * error occurs. Issue a Write Disable command to protect
529 		 * against inadvertent writes that can possibly corrupt the
530 		 * contents of the memory.
531 		 */
532 		ret = spi_nor_write_disable(nor);
533 		if (ret)
534 			return ret;
535 
536 		return -EIO;
537 	}
538 
539 	return !(nor->bouncebuf[0] & SR_WIP);
540 }
541 
542 static void spansion_nor_late_init(struct spi_nor *nor)
543 {
544 	if (nor->params->size > SZ_16M) {
545 		nor->flags |= SNOR_F_4B_OPCODES;
546 		/* No small sector erase for 4-byte command set */
547 		nor->erase_opcode = SPINOR_OP_SE;
548 		nor->mtd.erasesize = nor->info->sector_size;
549 	}
550 
551 	if (nor->info->mfr_flags & USE_CLSR)
552 		nor->params->ready = spansion_nor_sr_ready_and_clear;
553 }
554 
555 static const struct spi_nor_fixups spansion_nor_fixups = {
556 	.late_init = spansion_nor_late_init,
557 };
558 
559 const struct spi_nor_manufacturer spi_nor_spansion = {
560 	.name = "spansion",
561 	.parts = spansion_nor_parts,
562 	.nparts = ARRAY_SIZE(spansion_nor_parts),
563 	.fixups = &spansion_nor_fixups,
564 };
565