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 read proprietary FSR register. */
12#define USE_FSR BIT(0)
13
14#define SPINOR_OP_RDFSR 0x70 /* Read flag status register */
15#define SPINOR_OP_CLFSR 0x50 /* Clear flag status register */
16#define SPINOR_OP_MT_DTR_RD 0xfd /* Fast Read opcode in DTR mode */
17#define SPINOR_OP_MT_RD_ANY_REG 0x85 /* Read volatile register */
18#define SPINOR_OP_MT_WR_ANY_REG 0x81 /* Write volatile register */
19#define SPINOR_REG_MT_CFR0V 0x00 /* For setting octal DTR mode */
20#define SPINOR_REG_MT_CFR1V 0x01 /* For setting dummy cycles */
21#define SPINOR_REG_MT_CFR1V_DEF 0x1f /* Default dummy cycles */
22#define SPINOR_MT_OCT_DTR 0xe7 /* Enable Octal DTR. */
23#define SPINOR_MT_EXSPI 0xff /* Enable Extended SPI (default) */
24
25/* Flag Status Register bits */
26#define FSR_READY BIT(7) /* Device status, 0 = Busy, 1 = Ready */
27#define FSR_E_ERR BIT(5) /* Erase operation status */
28#define FSR_P_ERR BIT(4) /* Program operation status */
29#define FSR_PT_ERR BIT(1) /* Protection error bit */
30
31/* Micron ST SPI NOR flash operations. */
32#define MICRON_ST_NOR_WR_ANY_REG_OP(naddr, addr, ndata, buf) \
33 SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_MT_WR_ANY_REG, 0), \
34 SPI_MEM_OP_ADDR(naddr, addr, 0), \
35 SPI_MEM_OP_NO_DUMMY, \
36 SPI_MEM_OP_DATA_OUT(ndata, buf, 0))
37
38#define MICRON_ST_RDFSR_OP(buf) \
39 SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDFSR, 0), \
40 SPI_MEM_OP_NO_ADDR, \
41 SPI_MEM_OP_NO_DUMMY, \
42 SPI_MEM_OP_DATA_IN(1, buf, 0))
43
44#define MICRON_ST_CLFSR_OP \
45 SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_CLFSR, 0), \
46 SPI_MEM_OP_NO_ADDR, \
47 SPI_MEM_OP_NO_DUMMY, \
48 SPI_MEM_OP_NO_DATA)
49
50static int micron_st_nor_octal_dtr_en(struct spi_nor *nor)
51{
52 struct spi_mem_op op;
53 u8 *buf = nor->bouncebuf;
54 int ret;
55 u8 addr_mode_nbytes = nor->params->addr_mode_nbytes;
56
57 /* Use 20 dummy cycles for memory array reads. */
58 *buf = 20;
59 op = (struct spi_mem_op)
60 MICRON_ST_NOR_WR_ANY_REG_OP(addr_mode_nbytes,
61 SPINOR_REG_MT_CFR1V, 1, buf);
62 ret = spi_nor_write_any_volatile_reg(nor, op: &op, proto: nor->reg_proto);
63 if (ret)
64 return ret;
65
66 buf[0] = SPINOR_MT_OCT_DTR;
67 op = (struct spi_mem_op)
68 MICRON_ST_NOR_WR_ANY_REG_OP(addr_mode_nbytes,
69 SPINOR_REG_MT_CFR0V, 1, buf);
70 ret = spi_nor_write_any_volatile_reg(nor, op: &op, proto: nor->reg_proto);
71 if (ret)
72 return ret;
73
74 /* Read flash ID to make sure the switch was successful. */
75 ret = spi_nor_read_id(nor, naddr: 0, ndummy: 8, id: buf, reg_proto: SNOR_PROTO_8_8_8_DTR);
76 if (ret) {
77 dev_dbg(nor->dev, "error %d reading JEDEC ID after enabling 8D-8D-8D mode\n", ret);
78 return ret;
79 }
80
81 if (memcmp(p: buf, q: nor->info->id->bytes, size: nor->info->id->len))
82 return -EINVAL;
83
84 return 0;
85}
86
87static int micron_st_nor_octal_dtr_dis(struct spi_nor *nor)
88{
89 struct spi_mem_op op;
90 u8 *buf = nor->bouncebuf;
91 int ret;
92
93 /*
94 * The register is 1-byte wide, but 1-byte transactions are not allowed
95 * in 8D-8D-8D mode. The next register is the dummy cycle configuration
96 * register. Since the transaction needs to be at least 2 bytes wide,
97 * set the next register to its default value. This also makes sense
98 * because the value was changed when enabling 8D-8D-8D mode, it should
99 * be reset when disabling.
100 */
101 buf[0] = SPINOR_MT_EXSPI;
102 buf[1] = SPINOR_REG_MT_CFR1V_DEF;
103 op = (struct spi_mem_op)
104 MICRON_ST_NOR_WR_ANY_REG_OP(nor->addr_nbytes,
105 SPINOR_REG_MT_CFR0V, 2, buf);
106 ret = spi_nor_write_any_volatile_reg(nor, op: &op, proto: 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, naddr: 0, ndummy: 0, id: buf, reg_proto: 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(p: buf, q: nor->info->id->bytes, size: nor->info->id->len))
118 return -EINVAL;
119
120 return 0;
121}
122
123static int micron_st_nor_set_octal_dtr(struct spi_nor *nor, bool enable)
124{
125 return enable ? micron_st_nor_octal_dtr_en(nor) :
126 micron_st_nor_octal_dtr_dis(nor);
127}
128
129static void mt35xu512aba_default_init(struct spi_nor *nor)
130{
131 nor->params->set_octal_dtr = micron_st_nor_set_octal_dtr;
132}
133
134static int mt35xu512aba_post_sfdp_fixup(struct spi_nor *nor)
135{
136 /* Set the Fast Read settings. */
137 nor->params->hwcaps.mask |= SNOR_HWCAPS_READ_8_8_8_DTR;
138 spi_nor_set_read_settings(read: &nor->params->reads[SNOR_CMD_READ_8_8_8_DTR],
139 num_mode_clocks: 0, num_wait_states: 20, SPINOR_OP_MT_DTR_RD,
140 proto: SNOR_PROTO_8_8_8_DTR);
141
142 nor->cmd_ext_type = SPI_NOR_EXT_REPEAT;
143 nor->params->rdsr_dummy = 8;
144 nor->params->rdsr_addr_nbytes = 0;
145
146 /*
147 * The BFPT quad enable field is set to a reserved value so the quad
148 * enable function is ignored by spi_nor_parse_bfpt(). Make sure we
149 * disable it.
150 */
151 nor->params->quad_enable = NULL;
152
153 return 0;
154}
155
156static const struct spi_nor_fixups mt35xu512aba_fixups = {
157 .default_init = mt35xu512aba_default_init,
158 .post_sfdp = mt35xu512aba_post_sfdp_fixup,
159};
160
161static const struct flash_info micron_nor_parts[] = {
162 {
163 .id = SNOR_ID(0x2c, 0x5b, 0x1a),
164 .name = "mt35xu512aba",
165 .sector_size = SZ_128K,
166 .size = SZ_64M,
167 .no_sfdp_flags = SECT_4K | SPI_NOR_OCTAL_READ |
168 SPI_NOR_OCTAL_DTR_READ | SPI_NOR_OCTAL_DTR_PP,
169 .mfr_flags = USE_FSR,
170 .fixup_flags = SPI_NOR_4B_OPCODES | SPI_NOR_IO_MODE_EN_VOLATILE,
171 .fixups = &mt35xu512aba_fixups,
172 }, {
173 .id = SNOR_ID(0x2c, 0x5b, 0x1c),
174 .name = "mt35xu02g",
175 .sector_size = SZ_128K,
176 .size = SZ_256M,
177 .no_sfdp_flags = SECT_4K | SPI_NOR_OCTAL_READ,
178 .mfr_flags = USE_FSR,
179 .fixup_flags = SPI_NOR_4B_OPCODES,
180 },
181};
182
183static int mt25qu512a_post_bfpt_fixup(struct spi_nor *nor,
184 const struct sfdp_parameter_header *bfpt_header,
185 const struct sfdp_bfpt *bfpt)
186{
187 nor->flags &= ~SNOR_F_HAS_16BIT_SR;
188 return 0;
189}
190
191static struct spi_nor_fixups mt25qu512a_fixups = {
192 .post_bfpt = mt25qu512a_post_bfpt_fixup,
193};
194
195static const struct flash_info st_nor_parts[] = {
196 {
197 .name = "m25p05-nonjedec",
198 .sector_size = SZ_32K,
199 .size = SZ_64K,
200 }, {
201 .name = "m25p10-nonjedec",
202 .sector_size = SZ_32K,
203 .size = SZ_128K,
204 }, {
205 .name = "m25p20-nonjedec",
206 .size = SZ_256K,
207 }, {
208 .name = "m25p40-nonjedec",
209 .size = SZ_512K,
210 }, {
211 .name = "m25p80-nonjedec",
212 .size = SZ_1M,
213 }, {
214 .name = "m25p16-nonjedec",
215 .size = SZ_2M,
216 }, {
217 .name = "m25p32-nonjedec",
218 .size = SZ_4M,
219 }, {
220 .name = "m25p64-nonjedec",
221 .size = SZ_8M,
222 }, {
223 .name = "m25p128-nonjedec",
224 .sector_size = SZ_256K,
225 .size = SZ_16M,
226 }, {
227 .id = SNOR_ID(0x20, 0x20, 0x10),
228 .name = "m25p05",
229 .sector_size = SZ_32K,
230 .size = SZ_64K,
231 }, {
232 .id = SNOR_ID(0x20, 0x20, 0x11),
233 .name = "m25p10",
234 .sector_size = SZ_32K,
235 .size = SZ_128K,
236 }, {
237 .id = SNOR_ID(0x20, 0x20, 0x12),
238 .name = "m25p20",
239 .size = SZ_256K,
240 }, {
241 .id = SNOR_ID(0x20, 0x20, 0x13),
242 .name = "m25p40",
243 .size = SZ_512K,
244 }, {
245 .id = SNOR_ID(0x20, 0x20, 0x14),
246 .name = "m25p80",
247 .size = SZ_1M,
248 }, {
249 .id = SNOR_ID(0x20, 0x20, 0x15),
250 .name = "m25p16",
251 .size = SZ_2M,
252 }, {
253 .id = SNOR_ID(0x20, 0x20, 0x16),
254 .name = "m25p32",
255 .size = SZ_4M,
256 }, {
257 .id = SNOR_ID(0x20, 0x20, 0x17),
258 .name = "m25p64",
259 .size = SZ_8M,
260 }, {
261 .id = SNOR_ID(0x20, 0x20, 0x18),
262 .name = "m25p128",
263 .sector_size = SZ_256K,
264 .size = SZ_16M,
265 }, {
266 .id = SNOR_ID(0x20, 0x40, 0x11),
267 .name = "m45pe10",
268 .size = SZ_128K,
269 }, {
270 .id = SNOR_ID(0x20, 0x40, 0x14),
271 .name = "m45pe80",
272 .size = SZ_1M,
273 }, {
274 .id = SNOR_ID(0x20, 0x40, 0x15),
275 .name = "m45pe16",
276 .size = SZ_2M,
277 }, {
278 .id = SNOR_ID(0x20, 0x63, 0x16),
279 .name = "m25px32-s1",
280 .size = SZ_4M,
281 .no_sfdp_flags = SECT_4K,
282 }, {
283 .id = SNOR_ID(0x20, 0x71, 0x14),
284 .name = "m25px80",
285 .size = SZ_1M,
286 }, {
287 .id = SNOR_ID(0x20, 0x71, 0x15),
288 .name = "m25px16",
289 .size = SZ_2M,
290 .no_sfdp_flags = SECT_4K,
291 }, {
292 .id = SNOR_ID(0x20, 0x71, 0x16),
293 .name = "m25px32",
294 .size = SZ_4M,
295 .no_sfdp_flags = SECT_4K,
296 }, {
297 .id = SNOR_ID(0x20, 0x71, 0x17),
298 .name = "m25px64",
299 .size = SZ_8M,
300 }, {
301 .id = SNOR_ID(0x20, 0x73, 0x16),
302 .name = "m25px32-s0",
303 .size = SZ_4M,
304 .no_sfdp_flags = SECT_4K,
305 }, {
306 .id = SNOR_ID(0x20, 0x80, 0x12),
307 .name = "m25pe20",
308 .size = SZ_256K,
309 }, {
310 .id = SNOR_ID(0x20, 0x80, 0x14),
311 .name = "m25pe80",
312 .size = SZ_1M,
313 }, {
314 .id = SNOR_ID(0x20, 0x80, 0x15),
315 .name = "m25pe16",
316 .size = SZ_2M,
317 .no_sfdp_flags = SECT_4K,
318 }, {
319 .id = SNOR_ID(0x20, 0xba, 0x16),
320 .name = "n25q032",
321 .size = SZ_4M,
322 .no_sfdp_flags = SPI_NOR_QUAD_READ,
323 }, {
324 .id = SNOR_ID(0x20, 0xba, 0x17),
325 .name = "n25q064",
326 .size = SZ_8M,
327 .no_sfdp_flags = SECT_4K | SPI_NOR_QUAD_READ,
328 }, {
329 .id = SNOR_ID(0x20, 0xba, 0x18),
330 .name = "n25q128a13",
331 .size = SZ_16M,
332 .flags = SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | SPI_NOR_4BIT_BP |
333 SPI_NOR_BP3_SR_BIT6,
334 .no_sfdp_flags = SECT_4K | SPI_NOR_QUAD_READ,
335 .mfr_flags = USE_FSR,
336 }, {
337 .id = SNOR_ID(0x20, 0xba, 0x19, 0x10, 0x44, 0x00),
338 .name = "mt25ql256a",
339 .size = SZ_32M,
340 .no_sfdp_flags = SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,
341 .fixup_flags = SPI_NOR_4B_OPCODES,
342 .mfr_flags = USE_FSR,
343 }, {
344 .id = SNOR_ID(0x20, 0xba, 0x19),
345 .name = "n25q256a",
346 .size = SZ_32M,
347 .no_sfdp_flags = SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,
348 .mfr_flags = USE_FSR,
349 }, {
350 .id = SNOR_ID(0x20, 0xba, 0x20, 0x10, 0x44, 0x00),
351 .name = "mt25ql512a",
352 .size = SZ_64M,
353 .no_sfdp_flags = SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,
354 .fixup_flags = SPI_NOR_4B_OPCODES,
355 .mfr_flags = USE_FSR,
356 }, {
357 .id = SNOR_ID(0x20, 0xba, 0x20),
358 .name = "n25q512ax3",
359 .size = SZ_64M,
360 .flags = SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | SPI_NOR_4BIT_BP |
361 SPI_NOR_BP3_SR_BIT6,
362 .no_sfdp_flags = SECT_4K | SPI_NOR_QUAD_READ,
363 .mfr_flags = USE_FSR,
364 }, {
365 .id = SNOR_ID(0x20, 0xba, 0x21),
366 .name = "n25q00",
367 .size = SZ_128M,
368 .flags = SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | SPI_NOR_4BIT_BP |
369 SPI_NOR_BP3_SR_BIT6 | NO_CHIP_ERASE,
370 .no_sfdp_flags = SECT_4K | SPI_NOR_QUAD_READ,
371 .mfr_flags = USE_FSR,
372 }, {
373 .id = SNOR_ID(0x20, 0xba, 0x22),
374 .name = "mt25ql02g",
375 .size = SZ_256M,
376 .flags = NO_CHIP_ERASE,
377 .no_sfdp_flags = SECT_4K | SPI_NOR_QUAD_READ,
378 .mfr_flags = USE_FSR,
379 }, {
380 .id = SNOR_ID(0x20, 0xbb, 0x15),
381 .name = "n25q016a",
382 .size = SZ_2M,
383 .no_sfdp_flags = SECT_4K | SPI_NOR_QUAD_READ,
384 }, {
385 .id = SNOR_ID(0x20, 0xbb, 0x16),
386 .name = "n25q032a",
387 .size = SZ_4M,
388 .no_sfdp_flags = SPI_NOR_QUAD_READ,
389 }, {
390 .id = SNOR_ID(0x20, 0xbb, 0x17),
391 .name = "n25q064a",
392 .size = SZ_8M,
393 .no_sfdp_flags = SECT_4K | SPI_NOR_QUAD_READ,
394 }, {
395 .id = SNOR_ID(0x20, 0xbb, 0x18),
396 .name = "n25q128a11",
397 .size = SZ_16M,
398 .flags = SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | SPI_NOR_4BIT_BP |
399 SPI_NOR_BP3_SR_BIT6,
400 .no_sfdp_flags = SECT_4K | SPI_NOR_QUAD_READ,
401 .mfr_flags = USE_FSR,
402 }, {
403 .id = SNOR_ID(0x20, 0xbb, 0x19, 0x10, 0x44, 0x00),
404 .name = "mt25qu256a",
405 .size = SZ_32M,
406 .flags = SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | SPI_NOR_4BIT_BP |
407 SPI_NOR_BP3_SR_BIT6,
408 .no_sfdp_flags = SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,
409 .fixup_flags = SPI_NOR_4B_OPCODES,
410 .mfr_flags = USE_FSR,
411 }, {
412 .id = SNOR_ID(0x20, 0xbb, 0x19),
413 .name = "n25q256ax1",
414 .size = SZ_32M,
415 .no_sfdp_flags = SECT_4K | SPI_NOR_QUAD_READ,
416 .mfr_flags = USE_FSR,
417 }, {
418 .id = SNOR_ID(0x20, 0xbb, 0x20, 0x10, 0x44, 0x00),
419 .name = "mt25qu512a",
420 .flags = SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | SPI_NOR_4BIT_BP |
421 SPI_NOR_BP3_SR_BIT6,
422 .mfr_flags = USE_FSR,
423 .fixups = &mt25qu512a_fixups,
424 }, {
425 .id = SNOR_ID(0x20, 0xbb, 0x20),
426 .name = "n25q512a",
427 .size = SZ_64M,
428 .flags = SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | SPI_NOR_4BIT_BP |
429 SPI_NOR_BP3_SR_BIT6,
430 .no_sfdp_flags = SECT_4K | SPI_NOR_QUAD_READ,
431 .mfr_flags = USE_FSR,
432 }, {
433 .id = SNOR_ID(0x20, 0xbb, 0x21),
434 .name = "n25q00a",
435 .size = SZ_128M,
436 .flags = NO_CHIP_ERASE,
437 .no_sfdp_flags = SECT_4K | SPI_NOR_QUAD_READ,
438 .mfr_flags = USE_FSR,
439 }, {
440 .id = SNOR_ID(0x20, 0xbb, 0x22),
441 .name = "mt25qu02g",
442 .size = SZ_256M,
443 .flags = NO_CHIP_ERASE,
444 .no_sfdp_flags = SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,
445 .mfr_flags = USE_FSR,
446 }
447};
448
449/**
450 * micron_st_nor_read_fsr() - Read the Flag Status Register.
451 * @nor: pointer to 'struct spi_nor'
452 * @fsr: pointer to a DMA-able buffer where the value of the
453 * Flag Status Register will be written. Should be at least 2
454 * bytes.
455 *
456 * Return: 0 on success, -errno otherwise.
457 */
458static int micron_st_nor_read_fsr(struct spi_nor *nor, u8 *fsr)
459{
460 int ret;
461
462 if (nor->spimem) {
463 struct spi_mem_op op = MICRON_ST_RDFSR_OP(fsr);
464
465 if (nor->reg_proto == SNOR_PROTO_8_8_8_DTR) {
466 op.addr.nbytes = nor->params->rdsr_addr_nbytes;
467 op.dummy.nbytes = nor->params->rdsr_dummy;
468 /*
469 * We don't want to read only one byte in DTR mode. So,
470 * read 2 and then discard the second byte.
471 */
472 op.data.nbytes = 2;
473 }
474
475 spi_nor_spimem_setup_op(nor, op: &op, proto: nor->reg_proto);
476
477 ret = spi_mem_exec_op(mem: nor->spimem, op: &op);
478 } else {
479 ret = spi_nor_controller_ops_read_reg(nor, SPINOR_OP_RDFSR, buf: fsr,
480 len: 1);
481 }
482
483 if (ret)
484 dev_dbg(nor->dev, "error %d reading FSR\n", ret);
485
486 return ret;
487}
488
489/**
490 * micron_st_nor_clear_fsr() - Clear the Flag Status Register.
491 * @nor: pointer to 'struct spi_nor'.
492 */
493static void micron_st_nor_clear_fsr(struct spi_nor *nor)
494{
495 int ret;
496
497 if (nor->spimem) {
498 struct spi_mem_op op = MICRON_ST_CLFSR_OP;
499
500 spi_nor_spimem_setup_op(nor, op: &op, proto: nor->reg_proto);
501
502 ret = spi_mem_exec_op(mem: nor->spimem, op: &op);
503 } else {
504 ret = spi_nor_controller_ops_write_reg(nor, SPINOR_OP_CLFSR,
505 NULL, len: 0);
506 }
507
508 if (ret)
509 dev_dbg(nor->dev, "error %d clearing FSR\n", ret);
510}
511
512/**
513 * micron_st_nor_ready() - Query the Status Register as well as the Flag Status
514 * Register to see if the flash is ready for new commands. If there are any
515 * errors in the FSR clear them.
516 * @nor: pointer to 'struct spi_nor'.
517 *
518 * Return: 1 if ready, 0 if not ready, -errno on errors.
519 */
520static int micron_st_nor_ready(struct spi_nor *nor)
521{
522 int sr_ready, ret;
523
524 sr_ready = spi_nor_sr_ready(nor);
525 if (sr_ready < 0)
526 return sr_ready;
527
528 ret = micron_st_nor_read_fsr(nor, fsr: nor->bouncebuf);
529 if (ret) {
530 /*
531 * Some controllers, such as Intel SPI, do not support low
532 * level operations such as reading the flag status
533 * register. They only expose small amount of high level
534 * operations to the software. If this is the case we use
535 * only the status register value.
536 */
537 return ret == -EOPNOTSUPP ? sr_ready : ret;
538 }
539
540 if (nor->bouncebuf[0] & (FSR_E_ERR | FSR_P_ERR)) {
541 if (nor->bouncebuf[0] & FSR_E_ERR)
542 dev_err(nor->dev, "Erase operation failed.\n");
543 else
544 dev_err(nor->dev, "Program operation failed.\n");
545
546 if (nor->bouncebuf[0] & FSR_PT_ERR)
547 dev_err(nor->dev,
548 "Attempted to modify a protected sector.\n");
549
550 micron_st_nor_clear_fsr(nor);
551
552 /*
553 * WEL bit remains set to one when an erase or page program
554 * error occurs. Issue a Write Disable command to protect
555 * against inadvertent writes that can possibly corrupt the
556 * contents of the memory.
557 */
558 ret = spi_nor_write_disable(nor);
559 if (ret)
560 return ret;
561
562 return -EIO;
563 }
564
565 return sr_ready && !!(nor->bouncebuf[0] & FSR_READY);
566}
567
568static void micron_st_nor_default_init(struct spi_nor *nor)
569{
570 nor->flags |= SNOR_F_HAS_LOCK;
571 nor->flags &= ~SNOR_F_HAS_16BIT_SR;
572 nor->params->quad_enable = NULL;
573}
574
575static int micron_st_nor_late_init(struct spi_nor *nor)
576{
577 struct spi_nor_flash_parameter *params = nor->params;
578
579 if (nor->info->mfr_flags & USE_FSR)
580 params->ready = micron_st_nor_ready;
581
582 if (!params->set_4byte_addr_mode)
583 params->set_4byte_addr_mode = spi_nor_set_4byte_addr_mode_wren_en4b_ex4b;
584
585 return 0;
586}
587
588static const struct spi_nor_fixups micron_st_nor_fixups = {
589 .default_init = micron_st_nor_default_init,
590 .late_init = micron_st_nor_late_init,
591};
592
593const struct spi_nor_manufacturer spi_nor_micron = {
594 .name = "micron",
595 .parts = micron_nor_parts,
596 .nparts = ARRAY_SIZE(micron_nor_parts),
597 .fixups = &micron_st_nor_fixups,
598};
599
600const struct spi_nor_manufacturer spi_nor_st = {
601 .name = "st",
602 .parts = st_nor_parts,
603 .nparts = ARRAY_SIZE(st_nor_parts),
604 .fixups = &micron_st_nor_fixups,
605};
606

source code of linux/drivers/mtd/spi-nor/micron-st.c