xref: /rk3399_ARM-atf/drivers/mtd/nor/spi_nor.c (revision 8d9c1b3ca5f11c50150ff368981883c2ea444b66)
1a13550d0SLionel Debieve /*
2*6e86b462SYann Gautier  * Copyright (c) 2019-2022, STMicroelectronics - All Rights Reserved
3a13550d0SLionel Debieve  *
4a13550d0SLionel Debieve  * SPDX-License-Identifier: BSD-3-Clause
5a13550d0SLionel Debieve  */
6a13550d0SLionel Debieve 
7a13550d0SLionel Debieve #include <assert.h>
8a13550d0SLionel Debieve #include <errno.h>
9a13550d0SLionel Debieve #include <stddef.h>
10a13550d0SLionel Debieve 
11a13550d0SLionel Debieve #include <common/debug.h>
12a13550d0SLionel Debieve #include <drivers/delay_timer.h>
13a13550d0SLionel Debieve #include <drivers/spi_nor.h>
14a13550d0SLionel Debieve #include <lib/utils.h>
15a13550d0SLionel Debieve 
16a13550d0SLionel Debieve #define SR_WIP			BIT(0)	/* Write in progress */
17a13550d0SLionel Debieve #define CR_QUAD_EN_SPAN		BIT(1)	/* Spansion Quad I/O */
18a13550d0SLionel Debieve #define SR_QUAD_EN_MX		BIT(6)	/* Macronix Quad I/O */
19a13550d0SLionel Debieve #define FSR_READY		BIT(7)	/* Device status, 0 = Busy, 1 = Ready */
20a13550d0SLionel Debieve 
21a13550d0SLionel Debieve /* Defined IDs for supported memories */
22a13550d0SLionel Debieve #define SPANSION_ID		0x01U
23a13550d0SLionel Debieve #define MACRONIX_ID		0xC2U
24a13550d0SLionel Debieve #define MICRON_ID		0x2CU
25a13550d0SLionel Debieve 
26a13550d0SLionel Debieve #define BANK_SIZE		0x1000000U
27a13550d0SLionel Debieve 
28a13550d0SLionel Debieve #define SPI_READY_TIMEOUT_US	40000U
29a13550d0SLionel Debieve 
30a13550d0SLionel Debieve static struct nor_device nor_dev;
31a13550d0SLionel Debieve 
32a13550d0SLionel Debieve #pragma weak plat_get_nor_data
plat_get_nor_data(struct nor_device * device)33a13550d0SLionel Debieve int plat_get_nor_data(struct nor_device *device)
34a13550d0SLionel Debieve {
35a13550d0SLionel Debieve 	return 0;
36a13550d0SLionel Debieve }
37a13550d0SLionel Debieve 
spi_nor_reg(uint8_t reg,uint8_t * buf,size_t len,enum spi_mem_data_dir dir)38a13550d0SLionel Debieve static int spi_nor_reg(uint8_t reg, uint8_t *buf, size_t len,
39a13550d0SLionel Debieve 		       enum spi_mem_data_dir dir)
40a13550d0SLionel Debieve {
41a13550d0SLionel Debieve 	struct spi_mem_op op;
42a13550d0SLionel Debieve 
43a13550d0SLionel Debieve 	zeromem(&op, sizeof(struct spi_mem_op));
44a13550d0SLionel Debieve 	op.cmd.opcode = reg;
45a13550d0SLionel Debieve 	op.cmd.buswidth = SPI_MEM_BUSWIDTH_1_LINE;
46a13550d0SLionel Debieve 	op.data.buswidth = SPI_MEM_BUSWIDTH_1_LINE;
47a13550d0SLionel Debieve 	op.data.dir = dir;
48a13550d0SLionel Debieve 	op.data.nbytes = len;
49a13550d0SLionel Debieve 	op.data.buf = buf;
50a13550d0SLionel Debieve 
51a13550d0SLionel Debieve 	return spi_mem_exec_op(&op);
52a13550d0SLionel Debieve }
53a13550d0SLionel Debieve 
spi_nor_read_id(uint8_t * id)54a13550d0SLionel Debieve static inline int spi_nor_read_id(uint8_t *id)
55a13550d0SLionel Debieve {
56a13550d0SLionel Debieve 	return spi_nor_reg(SPI_NOR_OP_READ_ID, id, 1U, SPI_MEM_DATA_IN);
57a13550d0SLionel Debieve }
58a13550d0SLionel Debieve 
spi_nor_read_cr(uint8_t * cr)59a13550d0SLionel Debieve static inline int spi_nor_read_cr(uint8_t *cr)
60a13550d0SLionel Debieve {
61a13550d0SLionel Debieve 	return spi_nor_reg(SPI_NOR_OP_READ_CR, cr, 1U, SPI_MEM_DATA_IN);
62a13550d0SLionel Debieve }
63a13550d0SLionel Debieve 
spi_nor_read_sr(uint8_t * sr)64a13550d0SLionel Debieve static inline int spi_nor_read_sr(uint8_t *sr)
65a13550d0SLionel Debieve {
66a13550d0SLionel Debieve 	return spi_nor_reg(SPI_NOR_OP_READ_SR, sr, 1U, SPI_MEM_DATA_IN);
67a13550d0SLionel Debieve }
68a13550d0SLionel Debieve 
spi_nor_read_fsr(uint8_t * fsr)69a13550d0SLionel Debieve static inline int spi_nor_read_fsr(uint8_t *fsr)
70a13550d0SLionel Debieve {
71a13550d0SLionel Debieve 	return spi_nor_reg(SPI_NOR_OP_READ_FSR, fsr, 1U, SPI_MEM_DATA_IN);
72a13550d0SLionel Debieve }
73a13550d0SLionel Debieve 
spi_nor_write_en(void)74a13550d0SLionel Debieve static inline int spi_nor_write_en(void)
75a13550d0SLionel Debieve {
76a13550d0SLionel Debieve 	return spi_nor_reg(SPI_NOR_OP_WREN, NULL, 0U, SPI_MEM_DATA_OUT);
77a13550d0SLionel Debieve }
78a13550d0SLionel Debieve 
79a13550d0SLionel Debieve /*
80a13550d0SLionel Debieve  * Check if device is ready.
81a13550d0SLionel Debieve  *
82a13550d0SLionel Debieve  * Return 0 if ready, 1 if busy or a negative error code otherwise
83a13550d0SLionel Debieve  */
spi_nor_ready(void)84a13550d0SLionel Debieve static int spi_nor_ready(void)
85a13550d0SLionel Debieve {
86a13550d0SLionel Debieve 	uint8_t sr;
87a13550d0SLionel Debieve 	int ret;
88a13550d0SLionel Debieve 
89a13550d0SLionel Debieve 	ret = spi_nor_read_sr(&sr);
90a13550d0SLionel Debieve 	if (ret != 0) {
91a13550d0SLionel Debieve 		return ret;
92a13550d0SLionel Debieve 	}
93a13550d0SLionel Debieve 
94a13550d0SLionel Debieve 	if ((nor_dev.flags & SPI_NOR_USE_FSR) != 0U) {
95a13550d0SLionel Debieve 		uint8_t fsr;
96a13550d0SLionel Debieve 
97a13550d0SLionel Debieve 		ret = spi_nor_read_fsr(&fsr);
98a13550d0SLionel Debieve 		if (ret != 0) {
99a13550d0SLionel Debieve 			return ret;
100a13550d0SLionel Debieve 		}
101a13550d0SLionel Debieve 
102a13550d0SLionel Debieve 		return (((fsr & FSR_READY) != 0U) && ((sr & SR_WIP) == 0U)) ?
103a13550d0SLionel Debieve 			0 : 1;
104a13550d0SLionel Debieve 	}
105a13550d0SLionel Debieve 
1065130ad14SLionel Debieve 	return (((sr & SR_WIP) == 0U) ? 0 : 1);
107a13550d0SLionel Debieve }
108a13550d0SLionel Debieve 
spi_nor_wait_ready(void)109a13550d0SLionel Debieve static int spi_nor_wait_ready(void)
110a13550d0SLionel Debieve {
111a13550d0SLionel Debieve 	int ret;
112a13550d0SLionel Debieve 	uint64_t timeout = timeout_init_us(SPI_READY_TIMEOUT_US);
113a13550d0SLionel Debieve 
114a13550d0SLionel Debieve 	while (!timeout_elapsed(timeout)) {
115a13550d0SLionel Debieve 		ret = spi_nor_ready();
116a13550d0SLionel Debieve 		if (ret <= 0) {
117a13550d0SLionel Debieve 			return ret;
118a13550d0SLionel Debieve 		}
119a13550d0SLionel Debieve 	}
120a13550d0SLionel Debieve 
121a13550d0SLionel Debieve 	return -ETIMEDOUT;
122a13550d0SLionel Debieve }
123a13550d0SLionel Debieve 
spi_nor_macronix_quad_enable(void)124a13550d0SLionel Debieve static int spi_nor_macronix_quad_enable(void)
125a13550d0SLionel Debieve {
126a13550d0SLionel Debieve 	uint8_t sr;
127a13550d0SLionel Debieve 	int ret;
128a13550d0SLionel Debieve 
129a13550d0SLionel Debieve 	ret = spi_nor_read_sr(&sr);
130a13550d0SLionel Debieve 	if (ret != 0) {
131a13550d0SLionel Debieve 		return ret;
132a13550d0SLionel Debieve 	}
133a13550d0SLionel Debieve 
134c3327408SLionel Debieve 	if ((sr & SR_QUAD_EN_MX) != 0U) {
135a13550d0SLionel Debieve 		return 0;
136a13550d0SLionel Debieve 	}
137a13550d0SLionel Debieve 
138a13550d0SLionel Debieve 	ret = spi_nor_write_en();
139a13550d0SLionel Debieve 	if (ret != 0) {
140a13550d0SLionel Debieve 		return ret;
141a13550d0SLionel Debieve 	}
142a13550d0SLionel Debieve 
143a13550d0SLionel Debieve 	sr |= SR_QUAD_EN_MX;
1445130ad14SLionel Debieve 	ret = spi_nor_reg(SPI_NOR_OP_WRSR, &sr, 1U, SPI_MEM_DATA_OUT);
145a13550d0SLionel Debieve 	if (ret != 0) {
146a13550d0SLionel Debieve 		return ret;
147a13550d0SLionel Debieve 	}
148a13550d0SLionel Debieve 
149a13550d0SLionel Debieve 	ret = spi_nor_wait_ready();
150a13550d0SLionel Debieve 	if (ret != 0) {
151a13550d0SLionel Debieve 		return ret;
152a13550d0SLionel Debieve 	}
153a13550d0SLionel Debieve 
154a13550d0SLionel Debieve 	ret = spi_nor_read_sr(&sr);
155a13550d0SLionel Debieve 	if ((ret != 0) || ((sr & SR_QUAD_EN_MX) == 0U)) {
156a13550d0SLionel Debieve 		return -EINVAL;
157a13550d0SLionel Debieve 	}
158a13550d0SLionel Debieve 
159a13550d0SLionel Debieve 	return 0;
160a13550d0SLionel Debieve }
161a13550d0SLionel Debieve 
spi_nor_write_sr_cr(uint8_t * sr_cr)162a13550d0SLionel Debieve static int spi_nor_write_sr_cr(uint8_t *sr_cr)
163a13550d0SLionel Debieve {
164a13550d0SLionel Debieve 	int ret;
165a13550d0SLionel Debieve 
166a13550d0SLionel Debieve 	ret = spi_nor_write_en();
167a13550d0SLionel Debieve 	if (ret != 0) {
168a13550d0SLionel Debieve 		return ret;
169a13550d0SLionel Debieve 	}
170a13550d0SLionel Debieve 
1715130ad14SLionel Debieve 	ret = spi_nor_reg(SPI_NOR_OP_WRSR, sr_cr, 2U, SPI_MEM_DATA_OUT);
172a13550d0SLionel Debieve 	if (ret != 0) {
173a13550d0SLionel Debieve 		return -EINVAL;
174a13550d0SLionel Debieve 	}
175a13550d0SLionel Debieve 
176a13550d0SLionel Debieve 	ret = spi_nor_wait_ready();
177a13550d0SLionel Debieve 	if (ret != 0) {
178a13550d0SLionel Debieve 		return ret;
179a13550d0SLionel Debieve 	}
180a13550d0SLionel Debieve 
181a13550d0SLionel Debieve 	return 0;
182a13550d0SLionel Debieve }
183a13550d0SLionel Debieve 
spi_nor_quad_enable(void)184a13550d0SLionel Debieve static int spi_nor_quad_enable(void)
185a13550d0SLionel Debieve {
186a13550d0SLionel Debieve 	uint8_t sr_cr[2];
187a13550d0SLionel Debieve 	int ret;
188a13550d0SLionel Debieve 
189a13550d0SLionel Debieve 	ret = spi_nor_read_cr(&sr_cr[1]);
190a13550d0SLionel Debieve 	if (ret != 0) {
191a13550d0SLionel Debieve 		return ret;
192a13550d0SLionel Debieve 	}
193a13550d0SLionel Debieve 
194a13550d0SLionel Debieve 	if ((sr_cr[1] & CR_QUAD_EN_SPAN) != 0U) {
195a13550d0SLionel Debieve 		return 0;
196a13550d0SLionel Debieve 	}
197a13550d0SLionel Debieve 
198a13550d0SLionel Debieve 	sr_cr[1] |= CR_QUAD_EN_SPAN;
199a13550d0SLionel Debieve 	ret = spi_nor_read_sr(&sr_cr[0]);
200a13550d0SLionel Debieve 	if (ret != 0) {
201a13550d0SLionel Debieve 		return ret;
202a13550d0SLionel Debieve 	}
203a13550d0SLionel Debieve 
204a13550d0SLionel Debieve 	ret = spi_nor_write_sr_cr(sr_cr);
205a13550d0SLionel Debieve 	if (ret != 0) {
206a13550d0SLionel Debieve 		return ret;
207a13550d0SLionel Debieve 	}
208a13550d0SLionel Debieve 
209a13550d0SLionel Debieve 	ret = spi_nor_read_cr(&sr_cr[1]);
210a13550d0SLionel Debieve 	if ((ret != 0) || ((sr_cr[1] & CR_QUAD_EN_SPAN) == 0U)) {
211a13550d0SLionel Debieve 		return -EINVAL;
212a13550d0SLionel Debieve 	}
213a13550d0SLionel Debieve 
214a13550d0SLionel Debieve 	return 0;
215a13550d0SLionel Debieve }
216a13550d0SLionel Debieve 
spi_nor_clean_bar(void)217a13550d0SLionel Debieve static int spi_nor_clean_bar(void)
218a13550d0SLionel Debieve {
219a13550d0SLionel Debieve 	int ret;
220a13550d0SLionel Debieve 
221a13550d0SLionel Debieve 	if (nor_dev.selected_bank == 0U) {
222a13550d0SLionel Debieve 		return 0;
223a13550d0SLionel Debieve 	}
224a13550d0SLionel Debieve 
225a13550d0SLionel Debieve 	nor_dev.selected_bank = 0U;
226a13550d0SLionel Debieve 
227a13550d0SLionel Debieve 	ret = spi_nor_write_en();
228a13550d0SLionel Debieve 	if (ret != 0) {
229a13550d0SLionel Debieve 		return ret;
230a13550d0SLionel Debieve 	}
231a13550d0SLionel Debieve 
232a13550d0SLionel Debieve 	return spi_nor_reg(nor_dev.bank_write_cmd, &nor_dev.selected_bank,
2335130ad14SLionel Debieve 			   1U, SPI_MEM_DATA_OUT);
234a13550d0SLionel Debieve }
235a13550d0SLionel Debieve 
spi_nor_write_bar(uint32_t offset)236a13550d0SLionel Debieve static int spi_nor_write_bar(uint32_t offset)
237a13550d0SLionel Debieve {
238a13550d0SLionel Debieve 	uint8_t selected_bank = offset / BANK_SIZE;
239a13550d0SLionel Debieve 	int ret;
240a13550d0SLionel Debieve 
241a13550d0SLionel Debieve 	if (selected_bank == nor_dev.selected_bank) {
242a13550d0SLionel Debieve 		return 0;
243a13550d0SLionel Debieve 	}
244a13550d0SLionel Debieve 
245a13550d0SLionel Debieve 	ret = spi_nor_write_en();
246a13550d0SLionel Debieve 	if (ret != 0) {
247a13550d0SLionel Debieve 		return ret;
248a13550d0SLionel Debieve 	}
249a13550d0SLionel Debieve 
250a13550d0SLionel Debieve 	ret = spi_nor_reg(nor_dev.bank_write_cmd, &selected_bank,
2515130ad14SLionel Debieve 			  1U, SPI_MEM_DATA_OUT);
252a13550d0SLionel Debieve 	if (ret != 0) {
253a13550d0SLionel Debieve 		return ret;
254a13550d0SLionel Debieve 	}
255a13550d0SLionel Debieve 
256a13550d0SLionel Debieve 	nor_dev.selected_bank = selected_bank;
257a13550d0SLionel Debieve 
258a13550d0SLionel Debieve 	return 0;
259a13550d0SLionel Debieve }
260a13550d0SLionel Debieve 
spi_nor_read_bar(void)261a13550d0SLionel Debieve static int spi_nor_read_bar(void)
262a13550d0SLionel Debieve {
2635130ad14SLionel Debieve 	uint8_t selected_bank = 0U;
264a13550d0SLionel Debieve 	int ret;
265a13550d0SLionel Debieve 
266a13550d0SLionel Debieve 	ret = spi_nor_reg(nor_dev.bank_read_cmd, &selected_bank,
2675130ad14SLionel Debieve 			  1U, SPI_MEM_DATA_IN);
268a13550d0SLionel Debieve 	if (ret != 0) {
269a13550d0SLionel Debieve 		return ret;
270a13550d0SLionel Debieve 	}
271a13550d0SLionel Debieve 
272a13550d0SLionel Debieve 	nor_dev.selected_bank = selected_bank;
273a13550d0SLionel Debieve 
274a13550d0SLionel Debieve 	return 0;
275a13550d0SLionel Debieve }
276a13550d0SLionel Debieve 
spi_nor_read(unsigned int offset,uintptr_t buffer,size_t length,size_t * length_read)277a13550d0SLionel Debieve int spi_nor_read(unsigned int offset, uintptr_t buffer, size_t length,
278a13550d0SLionel Debieve 		 size_t *length_read)
279a13550d0SLionel Debieve {
280a13550d0SLionel Debieve 	size_t remain_len;
281a13550d0SLionel Debieve 	int ret;
282a13550d0SLionel Debieve 
2835130ad14SLionel Debieve 	*length_read = 0U;
284a13550d0SLionel Debieve 	nor_dev.read_op.addr.val = offset;
285a13550d0SLionel Debieve 	nor_dev.read_op.data.buf = (void *)buffer;
286a13550d0SLionel Debieve 
287*6e86b462SYann Gautier 	VERBOSE("%s offset %u length %zu\n", __func__, offset, length);
288a13550d0SLionel Debieve 
289a13550d0SLionel Debieve 	while (length != 0U) {
290a13550d0SLionel Debieve 		if ((nor_dev.flags & SPI_NOR_USE_BANK) != 0U) {
291a13550d0SLionel Debieve 			ret = spi_nor_write_bar(nor_dev.read_op.addr.val);
292a13550d0SLionel Debieve 			if (ret != 0) {
293a13550d0SLionel Debieve 				return ret;
294a13550d0SLionel Debieve 			}
295a13550d0SLionel Debieve 
296a13550d0SLionel Debieve 			remain_len = (BANK_SIZE * (nor_dev.selected_bank + 1)) -
297a13550d0SLionel Debieve 				nor_dev.read_op.addr.val;
298a13550d0SLionel Debieve 			nor_dev.read_op.data.nbytes = MIN(length, remain_len);
299a13550d0SLionel Debieve 		} else {
300a13550d0SLionel Debieve 			nor_dev.read_op.data.nbytes = length;
301a13550d0SLionel Debieve 		}
302a13550d0SLionel Debieve 
303a13550d0SLionel Debieve 		ret = spi_mem_exec_op(&nor_dev.read_op);
304a13550d0SLionel Debieve 		if (ret != 0) {
305a13550d0SLionel Debieve 			spi_nor_clean_bar();
306a13550d0SLionel Debieve 			return ret;
307a13550d0SLionel Debieve 		}
308a13550d0SLionel Debieve 
309a13550d0SLionel Debieve 		length -= nor_dev.read_op.data.nbytes;
310a13550d0SLionel Debieve 		nor_dev.read_op.addr.val += nor_dev.read_op.data.nbytes;
311a13550d0SLionel Debieve 		nor_dev.read_op.data.buf += nor_dev.read_op.data.nbytes;
312a13550d0SLionel Debieve 		*length_read += nor_dev.read_op.data.nbytes;
313a13550d0SLionel Debieve 	}
314a13550d0SLionel Debieve 
315a13550d0SLionel Debieve 	if ((nor_dev.flags & SPI_NOR_USE_BANK) != 0U) {
316a13550d0SLionel Debieve 		ret = spi_nor_clean_bar();
317a13550d0SLionel Debieve 		if (ret != 0) {
318a13550d0SLionel Debieve 			return ret;
319a13550d0SLionel Debieve 		}
320a13550d0SLionel Debieve 	}
321a13550d0SLionel Debieve 
322a13550d0SLionel Debieve 	return 0;
323a13550d0SLionel Debieve }
324a13550d0SLionel Debieve 
spi_nor_init(unsigned long long * size,unsigned int * erase_size)325a13550d0SLionel Debieve int spi_nor_init(unsigned long long *size, unsigned int *erase_size)
326a13550d0SLionel Debieve {
3275130ad14SLionel Debieve 	int ret;
328a13550d0SLionel Debieve 	uint8_t id;
329a13550d0SLionel Debieve 
330a13550d0SLionel Debieve 	/* Default read command used */
331a13550d0SLionel Debieve 	nor_dev.read_op.cmd.opcode = SPI_NOR_OP_READ;
332a13550d0SLionel Debieve 	nor_dev.read_op.cmd.buswidth = SPI_MEM_BUSWIDTH_1_LINE;
333a13550d0SLionel Debieve 	nor_dev.read_op.addr.nbytes = 3U;
334a13550d0SLionel Debieve 	nor_dev.read_op.addr.buswidth = SPI_MEM_BUSWIDTH_1_LINE;
335a13550d0SLionel Debieve 	nor_dev.read_op.data.buswidth = SPI_MEM_BUSWIDTH_1_LINE;
336a13550d0SLionel Debieve 	nor_dev.read_op.data.dir = SPI_MEM_DATA_IN;
337a13550d0SLionel Debieve 
338a13550d0SLionel Debieve 	if (plat_get_nor_data(&nor_dev) != 0) {
339a13550d0SLionel Debieve 		return -EINVAL;
340a13550d0SLionel Debieve 	}
341a13550d0SLionel Debieve 
3425130ad14SLionel Debieve 	assert(nor_dev.size != 0U);
343a13550d0SLionel Debieve 
344a13550d0SLionel Debieve 	if (nor_dev.size > BANK_SIZE) {
345a13550d0SLionel Debieve 		nor_dev.flags |= SPI_NOR_USE_BANK;
346a13550d0SLionel Debieve 	}
347a13550d0SLionel Debieve 
348a13550d0SLionel Debieve 	*size = nor_dev.size;
349a13550d0SLionel Debieve 
350a13550d0SLionel Debieve 	ret = spi_nor_read_id(&id);
351a13550d0SLionel Debieve 	if (ret != 0) {
352a13550d0SLionel Debieve 		return ret;
353a13550d0SLionel Debieve 	}
354a13550d0SLionel Debieve 
355a13550d0SLionel Debieve 	if ((nor_dev.flags & SPI_NOR_USE_BANK) != 0U) {
356a13550d0SLionel Debieve 		switch (id) {
357a13550d0SLionel Debieve 		case SPANSION_ID:
358a13550d0SLionel Debieve 			nor_dev.bank_read_cmd = SPINOR_OP_BRRD;
359a13550d0SLionel Debieve 			nor_dev.bank_write_cmd = SPINOR_OP_BRWR;
360a13550d0SLionel Debieve 			break;
361a13550d0SLionel Debieve 		default:
362a13550d0SLionel Debieve 			nor_dev.bank_read_cmd = SPINOR_OP_RDEAR;
363a13550d0SLionel Debieve 			nor_dev.bank_write_cmd = SPINOR_OP_WREAR;
364a13550d0SLionel Debieve 			break;
365a13550d0SLionel Debieve 		}
366a13550d0SLionel Debieve 	}
367a13550d0SLionel Debieve 
368a13550d0SLionel Debieve 	if (nor_dev.read_op.data.buswidth == 4U) {
369a13550d0SLionel Debieve 		switch (id) {
370a13550d0SLionel Debieve 		case MACRONIX_ID:
3716751b836SLionel Debieve 			INFO("Enable Macronix quad support\n");
372a13550d0SLionel Debieve 			ret = spi_nor_macronix_quad_enable();
373a13550d0SLionel Debieve 			break;
374a13550d0SLionel Debieve 		case MICRON_ID:
375a13550d0SLionel Debieve 			break;
376a13550d0SLionel Debieve 		default:
377a13550d0SLionel Debieve 			ret = spi_nor_quad_enable();
378a13550d0SLionel Debieve 			break;
379a13550d0SLionel Debieve 		}
380a13550d0SLionel Debieve 	}
381a13550d0SLionel Debieve 
382a13550d0SLionel Debieve 	if ((ret == 0) && ((nor_dev.flags & SPI_NOR_USE_BANK) != 0U)) {
383a13550d0SLionel Debieve 		ret = spi_nor_read_bar();
384a13550d0SLionel Debieve 	}
385a13550d0SLionel Debieve 
386a13550d0SLionel Debieve 	return ret;
387a13550d0SLionel Debieve }
388