xref: /rk3399_rockchip-uboot/drivers/mtd/spi/spi_flash.c (revision cba65a77c4e75d6e1e3dcaa65b7d509f1a2bb95e)
1*cba65a77SJagan Teki /*
2*cba65a77SJagan Teki  * SPI Flash Core
3*cba65a77SJagan Teki  *
4*cba65a77SJagan Teki  * Copyright (C) 2015 Jagan Teki <jteki@openedev.com>
5*cba65a77SJagan Teki  * Copyright (C) 2013 Jagannadha Sutradharudu Teki, Xilinx Inc.
6*cba65a77SJagan Teki  * Copyright (C) 2010 Reinhard Meyer, EMK Elektronik
7*cba65a77SJagan Teki  * Copyright (C) 2008 Atmel Corporation
8*cba65a77SJagan Teki  *
9*cba65a77SJagan Teki  * SPDX-License-Identifier:	GPL-2.0+
10*cba65a77SJagan Teki  */
11*cba65a77SJagan Teki 
12*cba65a77SJagan Teki #include <common.h>
13*cba65a77SJagan Teki #include <errno.h>
14*cba65a77SJagan Teki #include <malloc.h>
15*cba65a77SJagan Teki #include <mapmem.h>
16*cba65a77SJagan Teki #include <spi.h>
17*cba65a77SJagan Teki #include <spi_flash.h>
18*cba65a77SJagan Teki #include <linux/log2.h>
19*cba65a77SJagan Teki 
20*cba65a77SJagan Teki #include "sf_internal.h"
21*cba65a77SJagan Teki 
22*cba65a77SJagan Teki DECLARE_GLOBAL_DATA_PTR;
23*cba65a77SJagan Teki 
24*cba65a77SJagan Teki static void spi_flash_addr(u32 addr, u8 *cmd)
25*cba65a77SJagan Teki {
26*cba65a77SJagan Teki 	/* cmd[0] is actual command */
27*cba65a77SJagan Teki 	cmd[1] = addr >> 16;
28*cba65a77SJagan Teki 	cmd[2] = addr >> 8;
29*cba65a77SJagan Teki 	cmd[3] = addr >> 0;
30*cba65a77SJagan Teki }
31*cba65a77SJagan Teki 
32*cba65a77SJagan Teki /* Read commands array */
33*cba65a77SJagan Teki static u8 spi_read_cmds_array[] = {
34*cba65a77SJagan Teki 	CMD_READ_ARRAY_SLOW,
35*cba65a77SJagan Teki 	CMD_READ_ARRAY_FAST,
36*cba65a77SJagan Teki 	CMD_READ_DUAL_OUTPUT_FAST,
37*cba65a77SJagan Teki 	CMD_READ_DUAL_IO_FAST,
38*cba65a77SJagan Teki 	CMD_READ_QUAD_OUTPUT_FAST,
39*cba65a77SJagan Teki 	CMD_READ_QUAD_IO_FAST,
40*cba65a77SJagan Teki };
41*cba65a77SJagan Teki 
42*cba65a77SJagan Teki static int read_sr(struct spi_flash *flash, u8 *rs)
43*cba65a77SJagan Teki {
44*cba65a77SJagan Teki 	int ret;
45*cba65a77SJagan Teki 	u8 cmd;
46*cba65a77SJagan Teki 
47*cba65a77SJagan Teki 	cmd = CMD_READ_STATUS;
48*cba65a77SJagan Teki 	ret = spi_flash_read_common(flash, &cmd, 1, rs, 1);
49*cba65a77SJagan Teki 	if (ret < 0) {
50*cba65a77SJagan Teki 		debug("SF: fail to read status register\n");
51*cba65a77SJagan Teki 		return ret;
52*cba65a77SJagan Teki 	}
53*cba65a77SJagan Teki 
54*cba65a77SJagan Teki 	return 0;
55*cba65a77SJagan Teki }
56*cba65a77SJagan Teki 
57*cba65a77SJagan Teki static int read_fsr(struct spi_flash *flash, u8 *fsr)
58*cba65a77SJagan Teki {
59*cba65a77SJagan Teki 	int ret;
60*cba65a77SJagan Teki 	const u8 cmd = CMD_FLAG_STATUS;
61*cba65a77SJagan Teki 
62*cba65a77SJagan Teki 	ret = spi_flash_read_common(flash, &cmd, 1, fsr, 1);
63*cba65a77SJagan Teki 	if (ret < 0) {
64*cba65a77SJagan Teki 		debug("SF: fail to read flag status register\n");
65*cba65a77SJagan Teki 		return ret;
66*cba65a77SJagan Teki 	}
67*cba65a77SJagan Teki 
68*cba65a77SJagan Teki 	return 0;
69*cba65a77SJagan Teki }
70*cba65a77SJagan Teki 
71*cba65a77SJagan Teki static int write_sr(struct spi_flash *flash, u8 ws)
72*cba65a77SJagan Teki {
73*cba65a77SJagan Teki 	u8 cmd;
74*cba65a77SJagan Teki 	int ret;
75*cba65a77SJagan Teki 
76*cba65a77SJagan Teki 	cmd = CMD_WRITE_STATUS;
77*cba65a77SJagan Teki 	ret = spi_flash_write_common(flash, &cmd, 1, &ws, 1);
78*cba65a77SJagan Teki 	if (ret < 0) {
79*cba65a77SJagan Teki 		debug("SF: fail to write status register\n");
80*cba65a77SJagan Teki 		return ret;
81*cba65a77SJagan Teki 	}
82*cba65a77SJagan Teki 
83*cba65a77SJagan Teki 	return 0;
84*cba65a77SJagan Teki }
85*cba65a77SJagan Teki 
86*cba65a77SJagan Teki #if defined(CONFIG_SPI_FLASH_SPANSION) || defined(CONFIG_SPI_FLASH_WINBOND)
87*cba65a77SJagan Teki static int read_cr(struct spi_flash *flash, u8 *rc)
88*cba65a77SJagan Teki {
89*cba65a77SJagan Teki 	int ret;
90*cba65a77SJagan Teki 	u8 cmd;
91*cba65a77SJagan Teki 
92*cba65a77SJagan Teki 	cmd = CMD_READ_CONFIG;
93*cba65a77SJagan Teki 	ret = spi_flash_read_common(flash, &cmd, 1, rc, 1);
94*cba65a77SJagan Teki 	if (ret < 0) {
95*cba65a77SJagan Teki 		debug("SF: fail to read config register\n");
96*cba65a77SJagan Teki 		return ret;
97*cba65a77SJagan Teki 	}
98*cba65a77SJagan Teki 
99*cba65a77SJagan Teki 	return 0;
100*cba65a77SJagan Teki }
101*cba65a77SJagan Teki 
102*cba65a77SJagan Teki static int write_cr(struct spi_flash *flash, u8 wc)
103*cba65a77SJagan Teki {
104*cba65a77SJagan Teki 	u8 data[2];
105*cba65a77SJagan Teki 	u8 cmd;
106*cba65a77SJagan Teki 	int ret;
107*cba65a77SJagan Teki 
108*cba65a77SJagan Teki 	ret = read_sr(flash, &data[0]);
109*cba65a77SJagan Teki 	if (ret < 0)
110*cba65a77SJagan Teki 		return ret;
111*cba65a77SJagan Teki 
112*cba65a77SJagan Teki 	cmd = CMD_WRITE_STATUS;
113*cba65a77SJagan Teki 	data[1] = wc;
114*cba65a77SJagan Teki 	ret = spi_flash_write_common(flash, &cmd, 1, &data, 2);
115*cba65a77SJagan Teki 	if (ret) {
116*cba65a77SJagan Teki 		debug("SF: fail to write config register\n");
117*cba65a77SJagan Teki 		return ret;
118*cba65a77SJagan Teki 	}
119*cba65a77SJagan Teki 
120*cba65a77SJagan Teki 	return 0;
121*cba65a77SJagan Teki }
122*cba65a77SJagan Teki #endif
123*cba65a77SJagan Teki 
124*cba65a77SJagan Teki #ifdef CONFIG_SPI_FLASH_BAR
125*cba65a77SJagan Teki static int spi_flash_write_bar(struct spi_flash *flash, u32 offset)
126*cba65a77SJagan Teki {
127*cba65a77SJagan Teki 	u8 cmd, bank_sel;
128*cba65a77SJagan Teki 	int ret;
129*cba65a77SJagan Teki 
130*cba65a77SJagan Teki 	bank_sel = offset / (SPI_FLASH_16MB_BOUN << flash->shift);
131*cba65a77SJagan Teki 	if (bank_sel == flash->bank_curr)
132*cba65a77SJagan Teki 		goto bar_end;
133*cba65a77SJagan Teki 
134*cba65a77SJagan Teki 	cmd = flash->bank_write_cmd;
135*cba65a77SJagan Teki 	ret = spi_flash_write_common(flash, &cmd, 1, &bank_sel, 1);
136*cba65a77SJagan Teki 	if (ret < 0) {
137*cba65a77SJagan Teki 		debug("SF: fail to write bank register\n");
138*cba65a77SJagan Teki 		return ret;
139*cba65a77SJagan Teki 	}
140*cba65a77SJagan Teki 
141*cba65a77SJagan Teki bar_end:
142*cba65a77SJagan Teki 	flash->bank_curr = bank_sel;
143*cba65a77SJagan Teki 	return flash->bank_curr;
144*cba65a77SJagan Teki }
145*cba65a77SJagan Teki 
146*cba65a77SJagan Teki static int spi_flash_read_bar(struct spi_flash *flash, u8 idcode0)
147*cba65a77SJagan Teki {
148*cba65a77SJagan Teki 	u8 curr_bank = 0;
149*cba65a77SJagan Teki 	int ret;
150*cba65a77SJagan Teki 
151*cba65a77SJagan Teki 	if (flash->size <= SPI_FLASH_16MB_BOUN)
152*cba65a77SJagan Teki 		goto bank_end;
153*cba65a77SJagan Teki 
154*cba65a77SJagan Teki 	switch (idcode0) {
155*cba65a77SJagan Teki 	case SPI_FLASH_CFI_MFR_SPANSION:
156*cba65a77SJagan Teki 		flash->bank_read_cmd = CMD_BANKADDR_BRRD;
157*cba65a77SJagan Teki 		flash->bank_write_cmd = CMD_BANKADDR_BRWR;
158*cba65a77SJagan Teki 		break;
159*cba65a77SJagan Teki 	default:
160*cba65a77SJagan Teki 		flash->bank_read_cmd = CMD_EXTNADDR_RDEAR;
161*cba65a77SJagan Teki 		flash->bank_write_cmd = CMD_EXTNADDR_WREAR;
162*cba65a77SJagan Teki 	}
163*cba65a77SJagan Teki 
164*cba65a77SJagan Teki 	ret = spi_flash_read_common(flash, &flash->bank_read_cmd, 1,
165*cba65a77SJagan Teki 				    &curr_bank, 1);
166*cba65a77SJagan Teki 	if (ret) {
167*cba65a77SJagan Teki 		debug("SF: fail to read bank addr register\n");
168*cba65a77SJagan Teki 		return ret;
169*cba65a77SJagan Teki 	}
170*cba65a77SJagan Teki 
171*cba65a77SJagan Teki bank_end:
172*cba65a77SJagan Teki 	flash->bank_curr = curr_bank;
173*cba65a77SJagan Teki 	return 0;
174*cba65a77SJagan Teki }
175*cba65a77SJagan Teki #endif
176*cba65a77SJagan Teki 
177*cba65a77SJagan Teki #ifdef CONFIG_SF_DUAL_FLASH
178*cba65a77SJagan Teki static void spi_flash_dual(struct spi_flash *flash, u32 *addr)
179*cba65a77SJagan Teki {
180*cba65a77SJagan Teki 	switch (flash->dual_flash) {
181*cba65a77SJagan Teki 	case SF_DUAL_STACKED_FLASH:
182*cba65a77SJagan Teki 		if (*addr >= (flash->size >> 1)) {
183*cba65a77SJagan Teki 			*addr -= flash->size >> 1;
184*cba65a77SJagan Teki 			flash->spi->flags |= SPI_XFER_U_PAGE;
185*cba65a77SJagan Teki 		} else {
186*cba65a77SJagan Teki 			flash->spi->flags &= ~SPI_XFER_U_PAGE;
187*cba65a77SJagan Teki 		}
188*cba65a77SJagan Teki 		break;
189*cba65a77SJagan Teki 	case SF_DUAL_PARALLEL_FLASH:
190*cba65a77SJagan Teki 		*addr >>= flash->shift;
191*cba65a77SJagan Teki 		break;
192*cba65a77SJagan Teki 	default:
193*cba65a77SJagan Teki 		debug("SF: Unsupported dual_flash=%d\n", flash->dual_flash);
194*cba65a77SJagan Teki 		break;
195*cba65a77SJagan Teki 	}
196*cba65a77SJagan Teki }
197*cba65a77SJagan Teki #endif
198*cba65a77SJagan Teki 
199*cba65a77SJagan Teki static int spi_flash_sr_ready(struct spi_flash *flash)
200*cba65a77SJagan Teki {
201*cba65a77SJagan Teki 	u8 sr;
202*cba65a77SJagan Teki 	int ret;
203*cba65a77SJagan Teki 
204*cba65a77SJagan Teki 	ret = read_sr(flash, &sr);
205*cba65a77SJagan Teki 	if (ret < 0)
206*cba65a77SJagan Teki 		return ret;
207*cba65a77SJagan Teki 
208*cba65a77SJagan Teki 	return !(sr & STATUS_WIP);
209*cba65a77SJagan Teki }
210*cba65a77SJagan Teki 
211*cba65a77SJagan Teki static int spi_flash_fsr_ready(struct spi_flash *flash)
212*cba65a77SJagan Teki {
213*cba65a77SJagan Teki 	u8 fsr;
214*cba65a77SJagan Teki 	int ret;
215*cba65a77SJagan Teki 
216*cba65a77SJagan Teki 	ret = read_fsr(flash, &fsr);
217*cba65a77SJagan Teki 	if (ret < 0)
218*cba65a77SJagan Teki 		return ret;
219*cba65a77SJagan Teki 
220*cba65a77SJagan Teki 	return fsr & STATUS_PEC;
221*cba65a77SJagan Teki }
222*cba65a77SJagan Teki 
223*cba65a77SJagan Teki static int spi_flash_ready(struct spi_flash *flash)
224*cba65a77SJagan Teki {
225*cba65a77SJagan Teki 	int sr, fsr;
226*cba65a77SJagan Teki 
227*cba65a77SJagan Teki 	sr = spi_flash_sr_ready(flash);
228*cba65a77SJagan Teki 	if (sr < 0)
229*cba65a77SJagan Teki 		return sr;
230*cba65a77SJagan Teki 
231*cba65a77SJagan Teki 	fsr = 1;
232*cba65a77SJagan Teki 	if (flash->flags & SNOR_F_USE_FSR) {
233*cba65a77SJagan Teki 		fsr = spi_flash_fsr_ready(flash);
234*cba65a77SJagan Teki 		if (fsr < 0)
235*cba65a77SJagan Teki 			return fsr;
236*cba65a77SJagan Teki 	}
237*cba65a77SJagan Teki 
238*cba65a77SJagan Teki 	return sr && fsr;
239*cba65a77SJagan Teki }
240*cba65a77SJagan Teki 
241*cba65a77SJagan Teki static int spi_flash_cmd_wait_ready(struct spi_flash *flash,
242*cba65a77SJagan Teki 					unsigned long timeout)
243*cba65a77SJagan Teki {
244*cba65a77SJagan Teki 	int timebase, ret;
245*cba65a77SJagan Teki 
246*cba65a77SJagan Teki 	timebase = get_timer(0);
247*cba65a77SJagan Teki 
248*cba65a77SJagan Teki 	while (get_timer(timebase) < timeout) {
249*cba65a77SJagan Teki 		ret = spi_flash_ready(flash);
250*cba65a77SJagan Teki 		if (ret < 0)
251*cba65a77SJagan Teki 			return ret;
252*cba65a77SJagan Teki 		if (ret)
253*cba65a77SJagan Teki 			return 0;
254*cba65a77SJagan Teki 	}
255*cba65a77SJagan Teki 
256*cba65a77SJagan Teki 	printf("SF: Timeout!\n");
257*cba65a77SJagan Teki 
258*cba65a77SJagan Teki 	return -ETIMEDOUT;
259*cba65a77SJagan Teki }
260*cba65a77SJagan Teki 
261*cba65a77SJagan Teki int spi_flash_write_common(struct spi_flash *flash, const u8 *cmd,
262*cba65a77SJagan Teki 		size_t cmd_len, const void *buf, size_t buf_len)
263*cba65a77SJagan Teki {
264*cba65a77SJagan Teki 	struct spi_slave *spi = flash->spi;
265*cba65a77SJagan Teki 	unsigned long timeout = SPI_FLASH_PROG_TIMEOUT;
266*cba65a77SJagan Teki 	int ret;
267*cba65a77SJagan Teki 
268*cba65a77SJagan Teki 	if (buf == NULL)
269*cba65a77SJagan Teki 		timeout = SPI_FLASH_PAGE_ERASE_TIMEOUT;
270*cba65a77SJagan Teki 
271*cba65a77SJagan Teki 	ret = spi_claim_bus(flash->spi);
272*cba65a77SJagan Teki 	if (ret) {
273*cba65a77SJagan Teki 		debug("SF: unable to claim SPI bus\n");
274*cba65a77SJagan Teki 		return ret;
275*cba65a77SJagan Teki 	}
276*cba65a77SJagan Teki 
277*cba65a77SJagan Teki 	ret = spi_flash_cmd_write_enable(flash);
278*cba65a77SJagan Teki 	if (ret < 0) {
279*cba65a77SJagan Teki 		debug("SF: enabling write failed\n");
280*cba65a77SJagan Teki 		return ret;
281*cba65a77SJagan Teki 	}
282*cba65a77SJagan Teki 
283*cba65a77SJagan Teki 	ret = spi_flash_cmd_write(spi, cmd, cmd_len, buf, buf_len);
284*cba65a77SJagan Teki 	if (ret < 0) {
285*cba65a77SJagan Teki 		debug("SF: write cmd failed\n");
286*cba65a77SJagan Teki 		return ret;
287*cba65a77SJagan Teki 	}
288*cba65a77SJagan Teki 
289*cba65a77SJagan Teki 	ret = spi_flash_cmd_wait_ready(flash, timeout);
290*cba65a77SJagan Teki 	if (ret < 0) {
291*cba65a77SJagan Teki 		debug("SF: write %s timed out\n",
292*cba65a77SJagan Teki 		      timeout == SPI_FLASH_PROG_TIMEOUT ?
293*cba65a77SJagan Teki 			"program" : "page erase");
294*cba65a77SJagan Teki 		return ret;
295*cba65a77SJagan Teki 	}
296*cba65a77SJagan Teki 
297*cba65a77SJagan Teki 	spi_release_bus(spi);
298*cba65a77SJagan Teki 
299*cba65a77SJagan Teki 	return ret;
300*cba65a77SJagan Teki }
301*cba65a77SJagan Teki 
302*cba65a77SJagan Teki int spi_flash_cmd_erase_ops(struct spi_flash *flash, u32 offset, size_t len)
303*cba65a77SJagan Teki {
304*cba65a77SJagan Teki 	u32 erase_size, erase_addr;
305*cba65a77SJagan Teki 	u8 cmd[SPI_FLASH_CMD_LEN];
306*cba65a77SJagan Teki 	int ret = -1;
307*cba65a77SJagan Teki 
308*cba65a77SJagan Teki 	erase_size = flash->erase_size;
309*cba65a77SJagan Teki 	if (offset % erase_size || len % erase_size) {
310*cba65a77SJagan Teki 		debug("SF: Erase offset/length not multiple of erase size\n");
311*cba65a77SJagan Teki 		return -1;
312*cba65a77SJagan Teki 	}
313*cba65a77SJagan Teki 
314*cba65a77SJagan Teki 	if (flash->flash_is_locked) {
315*cba65a77SJagan Teki 		if (flash->flash_is_locked(flash, offset, len) > 0) {
316*cba65a77SJagan Teki 			printf("offset 0x%x is protected and cannot be erased\n",
317*cba65a77SJagan Teki 			       offset);
318*cba65a77SJagan Teki 			return -EINVAL;
319*cba65a77SJagan Teki 		}
320*cba65a77SJagan Teki 	}
321*cba65a77SJagan Teki 
322*cba65a77SJagan Teki 	cmd[0] = flash->erase_cmd;
323*cba65a77SJagan Teki 	while (len) {
324*cba65a77SJagan Teki 		erase_addr = offset;
325*cba65a77SJagan Teki 
326*cba65a77SJagan Teki #ifdef CONFIG_SF_DUAL_FLASH
327*cba65a77SJagan Teki 		if (flash->dual_flash > SF_SINGLE_FLASH)
328*cba65a77SJagan Teki 			spi_flash_dual(flash, &erase_addr);
329*cba65a77SJagan Teki #endif
330*cba65a77SJagan Teki #ifdef CONFIG_SPI_FLASH_BAR
331*cba65a77SJagan Teki 		ret = spi_flash_write_bar(flash, erase_addr);
332*cba65a77SJagan Teki 		if (ret < 0)
333*cba65a77SJagan Teki 			return ret;
334*cba65a77SJagan Teki #endif
335*cba65a77SJagan Teki 		spi_flash_addr(erase_addr, cmd);
336*cba65a77SJagan Teki 
337*cba65a77SJagan Teki 		debug("SF: erase %2x %2x %2x %2x (%x)\n", cmd[0], cmd[1],
338*cba65a77SJagan Teki 		      cmd[2], cmd[3], erase_addr);
339*cba65a77SJagan Teki 
340*cba65a77SJagan Teki 		ret = spi_flash_write_common(flash, cmd, sizeof(cmd), NULL, 0);
341*cba65a77SJagan Teki 		if (ret < 0) {
342*cba65a77SJagan Teki 			debug("SF: erase failed\n");
343*cba65a77SJagan Teki 			break;
344*cba65a77SJagan Teki 		}
345*cba65a77SJagan Teki 
346*cba65a77SJagan Teki 		offset += erase_size;
347*cba65a77SJagan Teki 		len -= erase_size;
348*cba65a77SJagan Teki 	}
349*cba65a77SJagan Teki 
350*cba65a77SJagan Teki 	return ret;
351*cba65a77SJagan Teki }
352*cba65a77SJagan Teki 
353*cba65a77SJagan Teki int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset,
354*cba65a77SJagan Teki 		size_t len, const void *buf)
355*cba65a77SJagan Teki {
356*cba65a77SJagan Teki 	unsigned long byte_addr, page_size;
357*cba65a77SJagan Teki 	u32 write_addr;
358*cba65a77SJagan Teki 	size_t chunk_len, actual;
359*cba65a77SJagan Teki 	u8 cmd[SPI_FLASH_CMD_LEN];
360*cba65a77SJagan Teki 	int ret = -1;
361*cba65a77SJagan Teki 
362*cba65a77SJagan Teki 	page_size = flash->page_size;
363*cba65a77SJagan Teki 
364*cba65a77SJagan Teki 	if (flash->flash_is_locked) {
365*cba65a77SJagan Teki 		if (flash->flash_is_locked(flash, offset, len) > 0) {
366*cba65a77SJagan Teki 			printf("offset 0x%x is protected and cannot be written\n",
367*cba65a77SJagan Teki 			       offset);
368*cba65a77SJagan Teki 			return -EINVAL;
369*cba65a77SJagan Teki 		}
370*cba65a77SJagan Teki 	}
371*cba65a77SJagan Teki 
372*cba65a77SJagan Teki 	cmd[0] = flash->write_cmd;
373*cba65a77SJagan Teki 	for (actual = 0; actual < len; actual += chunk_len) {
374*cba65a77SJagan Teki 		write_addr = offset;
375*cba65a77SJagan Teki 
376*cba65a77SJagan Teki #ifdef CONFIG_SF_DUAL_FLASH
377*cba65a77SJagan Teki 		if (flash->dual_flash > SF_SINGLE_FLASH)
378*cba65a77SJagan Teki 			spi_flash_dual(flash, &write_addr);
379*cba65a77SJagan Teki #endif
380*cba65a77SJagan Teki #ifdef CONFIG_SPI_FLASH_BAR
381*cba65a77SJagan Teki 		ret = spi_flash_write_bar(flash, write_addr);
382*cba65a77SJagan Teki 		if (ret < 0)
383*cba65a77SJagan Teki 			return ret;
384*cba65a77SJagan Teki #endif
385*cba65a77SJagan Teki 		byte_addr = offset % page_size;
386*cba65a77SJagan Teki 		chunk_len = min(len - actual, (size_t)(page_size - byte_addr));
387*cba65a77SJagan Teki 
388*cba65a77SJagan Teki 		if (flash->spi->max_write_size)
389*cba65a77SJagan Teki 			chunk_len = min(chunk_len,
390*cba65a77SJagan Teki 					(size_t)flash->spi->max_write_size);
391*cba65a77SJagan Teki 
392*cba65a77SJagan Teki 		spi_flash_addr(write_addr, cmd);
393*cba65a77SJagan Teki 
394*cba65a77SJagan Teki 		debug("SF: 0x%p => cmd = { 0x%02x 0x%02x%02x%02x } chunk_len = %zu\n",
395*cba65a77SJagan Teki 		      buf + actual, cmd[0], cmd[1], cmd[2], cmd[3], chunk_len);
396*cba65a77SJagan Teki 
397*cba65a77SJagan Teki 		ret = spi_flash_write_common(flash, cmd, sizeof(cmd),
398*cba65a77SJagan Teki 					buf + actual, chunk_len);
399*cba65a77SJagan Teki 		if (ret < 0) {
400*cba65a77SJagan Teki 			debug("SF: write failed\n");
401*cba65a77SJagan Teki 			break;
402*cba65a77SJagan Teki 		}
403*cba65a77SJagan Teki 
404*cba65a77SJagan Teki 		offset += chunk_len;
405*cba65a77SJagan Teki 	}
406*cba65a77SJagan Teki 
407*cba65a77SJagan Teki 	return ret;
408*cba65a77SJagan Teki }
409*cba65a77SJagan Teki 
410*cba65a77SJagan Teki int spi_flash_read_common(struct spi_flash *flash, const u8 *cmd,
411*cba65a77SJagan Teki 		size_t cmd_len, void *data, size_t data_len)
412*cba65a77SJagan Teki {
413*cba65a77SJagan Teki 	struct spi_slave *spi = flash->spi;
414*cba65a77SJagan Teki 	int ret;
415*cba65a77SJagan Teki 
416*cba65a77SJagan Teki 	ret = spi_claim_bus(flash->spi);
417*cba65a77SJagan Teki 	if (ret) {
418*cba65a77SJagan Teki 		debug("SF: unable to claim SPI bus\n");
419*cba65a77SJagan Teki 		return ret;
420*cba65a77SJagan Teki 	}
421*cba65a77SJagan Teki 
422*cba65a77SJagan Teki 	ret = spi_flash_cmd_read(spi, cmd, cmd_len, data, data_len);
423*cba65a77SJagan Teki 	if (ret < 0) {
424*cba65a77SJagan Teki 		debug("SF: read cmd failed\n");
425*cba65a77SJagan Teki 		return ret;
426*cba65a77SJagan Teki 	}
427*cba65a77SJagan Teki 
428*cba65a77SJagan Teki 	spi_release_bus(spi);
429*cba65a77SJagan Teki 
430*cba65a77SJagan Teki 	return ret;
431*cba65a77SJagan Teki }
432*cba65a77SJagan Teki 
433*cba65a77SJagan Teki void __weak spi_flash_copy_mmap(void *data, void *offset, size_t len)
434*cba65a77SJagan Teki {
435*cba65a77SJagan Teki 	memcpy(data, offset, len);
436*cba65a77SJagan Teki }
437*cba65a77SJagan Teki 
438*cba65a77SJagan Teki int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 offset,
439*cba65a77SJagan Teki 		size_t len, void *data)
440*cba65a77SJagan Teki {
441*cba65a77SJagan Teki 	u8 *cmd, cmdsz;
442*cba65a77SJagan Teki 	u32 remain_len, read_len, read_addr;
443*cba65a77SJagan Teki 	int bank_sel = 0;
444*cba65a77SJagan Teki 	int ret = -1;
445*cba65a77SJagan Teki 
446*cba65a77SJagan Teki 	/* Handle memory-mapped SPI */
447*cba65a77SJagan Teki 	if (flash->memory_map) {
448*cba65a77SJagan Teki 		ret = spi_claim_bus(flash->spi);
449*cba65a77SJagan Teki 		if (ret) {
450*cba65a77SJagan Teki 			debug("SF: unable to claim SPI bus\n");
451*cba65a77SJagan Teki 			return ret;
452*cba65a77SJagan Teki 		}
453*cba65a77SJagan Teki 		spi_xfer(flash->spi, 0, NULL, NULL, SPI_XFER_MMAP);
454*cba65a77SJagan Teki 		spi_flash_copy_mmap(data, flash->memory_map + offset, len);
455*cba65a77SJagan Teki 		spi_xfer(flash->spi, 0, NULL, NULL, SPI_XFER_MMAP_END);
456*cba65a77SJagan Teki 		spi_release_bus(flash->spi);
457*cba65a77SJagan Teki 		return 0;
458*cba65a77SJagan Teki 	}
459*cba65a77SJagan Teki 
460*cba65a77SJagan Teki 	cmdsz = SPI_FLASH_CMD_LEN + flash->dummy_byte;
461*cba65a77SJagan Teki 	cmd = calloc(1, cmdsz);
462*cba65a77SJagan Teki 	if (!cmd) {
463*cba65a77SJagan Teki 		debug("SF: Failed to allocate cmd\n");
464*cba65a77SJagan Teki 		return -ENOMEM;
465*cba65a77SJagan Teki 	}
466*cba65a77SJagan Teki 
467*cba65a77SJagan Teki 	cmd[0] = flash->read_cmd;
468*cba65a77SJagan Teki 	while (len) {
469*cba65a77SJagan Teki 		read_addr = offset;
470*cba65a77SJagan Teki 
471*cba65a77SJagan Teki #ifdef CONFIG_SF_DUAL_FLASH
472*cba65a77SJagan Teki 		if (flash->dual_flash > SF_SINGLE_FLASH)
473*cba65a77SJagan Teki 			spi_flash_dual(flash, &read_addr);
474*cba65a77SJagan Teki #endif
475*cba65a77SJagan Teki #ifdef CONFIG_SPI_FLASH_BAR
476*cba65a77SJagan Teki 		ret = spi_flash_write_bar(flash, read_addr);
477*cba65a77SJagan Teki 		if (ret < 0)
478*cba65a77SJagan Teki 			return ret;
479*cba65a77SJagan Teki 		bank_sel = flash->bank_curr;
480*cba65a77SJagan Teki #endif
481*cba65a77SJagan Teki 		remain_len = ((SPI_FLASH_16MB_BOUN << flash->shift) *
482*cba65a77SJagan Teki 				(bank_sel + 1)) - offset;
483*cba65a77SJagan Teki 		if (len < remain_len)
484*cba65a77SJagan Teki 			read_len = len;
485*cba65a77SJagan Teki 		else
486*cba65a77SJagan Teki 			read_len = remain_len;
487*cba65a77SJagan Teki 
488*cba65a77SJagan Teki 		spi_flash_addr(read_addr, cmd);
489*cba65a77SJagan Teki 
490*cba65a77SJagan Teki 		ret = spi_flash_read_common(flash, cmd, cmdsz, data, read_len);
491*cba65a77SJagan Teki 		if (ret < 0) {
492*cba65a77SJagan Teki 			debug("SF: read failed\n");
493*cba65a77SJagan Teki 			break;
494*cba65a77SJagan Teki 		}
495*cba65a77SJagan Teki 
496*cba65a77SJagan Teki 		offset += read_len;
497*cba65a77SJagan Teki 		len -= read_len;
498*cba65a77SJagan Teki 		data += read_len;
499*cba65a77SJagan Teki 	}
500*cba65a77SJagan Teki 
501*cba65a77SJagan Teki 	free(cmd);
502*cba65a77SJagan Teki 	return ret;
503*cba65a77SJagan Teki }
504*cba65a77SJagan Teki 
505*cba65a77SJagan Teki #ifdef CONFIG_SPI_FLASH_SST
506*cba65a77SJagan Teki static int sst_byte_write(struct spi_flash *flash, u32 offset, const void *buf)
507*cba65a77SJagan Teki {
508*cba65a77SJagan Teki 	int ret;
509*cba65a77SJagan Teki 	u8 cmd[4] = {
510*cba65a77SJagan Teki 		CMD_SST_BP,
511*cba65a77SJagan Teki 		offset >> 16,
512*cba65a77SJagan Teki 		offset >> 8,
513*cba65a77SJagan Teki 		offset,
514*cba65a77SJagan Teki 	};
515*cba65a77SJagan Teki 
516*cba65a77SJagan Teki 	debug("BP[%02x]: 0x%p => cmd = { 0x%02x 0x%06x }\n",
517*cba65a77SJagan Teki 	      spi_w8r8(flash->spi, CMD_READ_STATUS), buf, cmd[0], offset);
518*cba65a77SJagan Teki 
519*cba65a77SJagan Teki 	ret = spi_flash_cmd_write_enable(flash);
520*cba65a77SJagan Teki 	if (ret)
521*cba65a77SJagan Teki 		return ret;
522*cba65a77SJagan Teki 
523*cba65a77SJagan Teki 	ret = spi_flash_cmd_write(flash->spi, cmd, sizeof(cmd), buf, 1);
524*cba65a77SJagan Teki 	if (ret)
525*cba65a77SJagan Teki 		return ret;
526*cba65a77SJagan Teki 
527*cba65a77SJagan Teki 	return spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT);
528*cba65a77SJagan Teki }
529*cba65a77SJagan Teki 
530*cba65a77SJagan Teki int sst_write_wp(struct spi_flash *flash, u32 offset, size_t len,
531*cba65a77SJagan Teki 		const void *buf)
532*cba65a77SJagan Teki {
533*cba65a77SJagan Teki 	size_t actual, cmd_len;
534*cba65a77SJagan Teki 	int ret;
535*cba65a77SJagan Teki 	u8 cmd[4];
536*cba65a77SJagan Teki 
537*cba65a77SJagan Teki 	ret = spi_claim_bus(flash->spi);
538*cba65a77SJagan Teki 	if (ret) {
539*cba65a77SJagan Teki 		debug("SF: Unable to claim SPI bus\n");
540*cba65a77SJagan Teki 		return ret;
541*cba65a77SJagan Teki 	}
542*cba65a77SJagan Teki 
543*cba65a77SJagan Teki 	/* If the data is not word aligned, write out leading single byte */
544*cba65a77SJagan Teki 	actual = offset % 2;
545*cba65a77SJagan Teki 	if (actual) {
546*cba65a77SJagan Teki 		ret = sst_byte_write(flash, offset, buf);
547*cba65a77SJagan Teki 		if (ret)
548*cba65a77SJagan Teki 			goto done;
549*cba65a77SJagan Teki 	}
550*cba65a77SJagan Teki 	offset += actual;
551*cba65a77SJagan Teki 
552*cba65a77SJagan Teki 	ret = spi_flash_cmd_write_enable(flash);
553*cba65a77SJagan Teki 	if (ret)
554*cba65a77SJagan Teki 		goto done;
555*cba65a77SJagan Teki 
556*cba65a77SJagan Teki 	cmd_len = 4;
557*cba65a77SJagan Teki 	cmd[0] = CMD_SST_AAI_WP;
558*cba65a77SJagan Teki 	cmd[1] = offset >> 16;
559*cba65a77SJagan Teki 	cmd[2] = offset >> 8;
560*cba65a77SJagan Teki 	cmd[3] = offset;
561*cba65a77SJagan Teki 
562*cba65a77SJagan Teki 	for (; actual < len - 1; actual += 2) {
563*cba65a77SJagan Teki 		debug("WP[%02x]: 0x%p => cmd = { 0x%02x 0x%06x }\n",
564*cba65a77SJagan Teki 		      spi_w8r8(flash->spi, CMD_READ_STATUS), buf + actual,
565*cba65a77SJagan Teki 		      cmd[0], offset);
566*cba65a77SJagan Teki 
567*cba65a77SJagan Teki 		ret = spi_flash_cmd_write(flash->spi, cmd, cmd_len,
568*cba65a77SJagan Teki 					buf + actual, 2);
569*cba65a77SJagan Teki 		if (ret) {
570*cba65a77SJagan Teki 			debug("SF: sst word program failed\n");
571*cba65a77SJagan Teki 			break;
572*cba65a77SJagan Teki 		}
573*cba65a77SJagan Teki 
574*cba65a77SJagan Teki 		ret = spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT);
575*cba65a77SJagan Teki 		if (ret)
576*cba65a77SJagan Teki 			break;
577*cba65a77SJagan Teki 
578*cba65a77SJagan Teki 		cmd_len = 1;
579*cba65a77SJagan Teki 		offset += 2;
580*cba65a77SJagan Teki 	}
581*cba65a77SJagan Teki 
582*cba65a77SJagan Teki 	if (!ret)
583*cba65a77SJagan Teki 		ret = spi_flash_cmd_write_disable(flash);
584*cba65a77SJagan Teki 
585*cba65a77SJagan Teki 	/* If there is a single trailing byte, write it out */
586*cba65a77SJagan Teki 	if (!ret && actual != len)
587*cba65a77SJagan Teki 		ret = sst_byte_write(flash, offset, buf + actual);
588*cba65a77SJagan Teki 
589*cba65a77SJagan Teki  done:
590*cba65a77SJagan Teki 	debug("SF: sst: program %s %zu bytes @ 0x%zx\n",
591*cba65a77SJagan Teki 	      ret ? "failure" : "success", len, offset - actual);
592*cba65a77SJagan Teki 
593*cba65a77SJagan Teki 	spi_release_bus(flash->spi);
594*cba65a77SJagan Teki 	return ret;
595*cba65a77SJagan Teki }
596*cba65a77SJagan Teki 
597*cba65a77SJagan Teki int sst_write_bp(struct spi_flash *flash, u32 offset, size_t len,
598*cba65a77SJagan Teki 		const void *buf)
599*cba65a77SJagan Teki {
600*cba65a77SJagan Teki 	size_t actual;
601*cba65a77SJagan Teki 	int ret;
602*cba65a77SJagan Teki 
603*cba65a77SJagan Teki 	ret = spi_claim_bus(flash->spi);
604*cba65a77SJagan Teki 	if (ret) {
605*cba65a77SJagan Teki 		debug("SF: Unable to claim SPI bus\n");
606*cba65a77SJagan Teki 		return ret;
607*cba65a77SJagan Teki 	}
608*cba65a77SJagan Teki 
609*cba65a77SJagan Teki 	for (actual = 0; actual < len; actual++) {
610*cba65a77SJagan Teki 		ret = sst_byte_write(flash, offset, buf + actual);
611*cba65a77SJagan Teki 		if (ret) {
612*cba65a77SJagan Teki 			debug("SF: sst byte program failed\n");
613*cba65a77SJagan Teki 			break;
614*cba65a77SJagan Teki 		}
615*cba65a77SJagan Teki 		offset++;
616*cba65a77SJagan Teki 	}
617*cba65a77SJagan Teki 
618*cba65a77SJagan Teki 	if (!ret)
619*cba65a77SJagan Teki 		ret = spi_flash_cmd_write_disable(flash);
620*cba65a77SJagan Teki 
621*cba65a77SJagan Teki 	debug("SF: sst: program %s %zu bytes @ 0x%zx\n",
622*cba65a77SJagan Teki 	      ret ? "failure" : "success", len, offset - actual);
623*cba65a77SJagan Teki 
624*cba65a77SJagan Teki 	spi_release_bus(flash->spi);
625*cba65a77SJagan Teki 	return ret;
626*cba65a77SJagan Teki }
627*cba65a77SJagan Teki #endif
628*cba65a77SJagan Teki 
629*cba65a77SJagan Teki #if defined(CONFIG_SPI_FLASH_STMICRO) || defined(CONFIG_SPI_FLASH_SST)
630*cba65a77SJagan Teki static void stm_get_locked_range(struct spi_flash *flash, u8 sr, loff_t *ofs,
631*cba65a77SJagan Teki 				 u32 *len)
632*cba65a77SJagan Teki {
633*cba65a77SJagan Teki 	u8 mask = SR_BP2 | SR_BP1 | SR_BP0;
634*cba65a77SJagan Teki 	int shift = ffs(mask) - 1;
635*cba65a77SJagan Teki 	int pow;
636*cba65a77SJagan Teki 
637*cba65a77SJagan Teki 	if (!(sr & mask)) {
638*cba65a77SJagan Teki 		/* No protection */
639*cba65a77SJagan Teki 		*ofs = 0;
640*cba65a77SJagan Teki 		*len = 0;
641*cba65a77SJagan Teki 	} else {
642*cba65a77SJagan Teki 		pow = ((sr & mask) ^ mask) >> shift;
643*cba65a77SJagan Teki 		*len = flash->size >> pow;
644*cba65a77SJagan Teki 		*ofs = flash->size - *len;
645*cba65a77SJagan Teki 	}
646*cba65a77SJagan Teki }
647*cba65a77SJagan Teki 
648*cba65a77SJagan Teki /*
649*cba65a77SJagan Teki  * Return 1 if the entire region is locked, 0 otherwise
650*cba65a77SJagan Teki  */
651*cba65a77SJagan Teki static int stm_is_locked_sr(struct spi_flash *flash, u32 ofs, u32 len,
652*cba65a77SJagan Teki 			    u8 sr)
653*cba65a77SJagan Teki {
654*cba65a77SJagan Teki 	loff_t lock_offs;
655*cba65a77SJagan Teki 	u32 lock_len;
656*cba65a77SJagan Teki 
657*cba65a77SJagan Teki 	stm_get_locked_range(flash, sr, &lock_offs, &lock_len);
658*cba65a77SJagan Teki 
659*cba65a77SJagan Teki 	return (ofs + len <= lock_offs + lock_len) && (ofs >= lock_offs);
660*cba65a77SJagan Teki }
661*cba65a77SJagan Teki 
662*cba65a77SJagan Teki /*
663*cba65a77SJagan Teki  * Check if a region of the flash is (completely) locked. See stm_lock() for
664*cba65a77SJagan Teki  * more info.
665*cba65a77SJagan Teki  *
666*cba65a77SJagan Teki  * Returns 1 if entire region is locked, 0 if any portion is unlocked, and
667*cba65a77SJagan Teki  * negative on errors.
668*cba65a77SJagan Teki  */
669*cba65a77SJagan Teki int stm_is_locked(struct spi_flash *flash, u32 ofs, size_t len)
670*cba65a77SJagan Teki {
671*cba65a77SJagan Teki 	int status;
672*cba65a77SJagan Teki 	u8 sr;
673*cba65a77SJagan Teki 
674*cba65a77SJagan Teki 	status = read_sr(flash, &sr);
675*cba65a77SJagan Teki 	if (status < 0)
676*cba65a77SJagan Teki 		return status;
677*cba65a77SJagan Teki 
678*cba65a77SJagan Teki 	return stm_is_locked_sr(flash, ofs, len, sr);
679*cba65a77SJagan Teki }
680*cba65a77SJagan Teki 
681*cba65a77SJagan Teki /*
682*cba65a77SJagan Teki  * Lock a region of the flash. Compatible with ST Micro and similar flash.
683*cba65a77SJagan Teki  * Supports only the block protection bits BP{0,1,2} in the status register
684*cba65a77SJagan Teki  * (SR). Does not support these features found in newer SR bitfields:
685*cba65a77SJagan Teki  *   - TB: top/bottom protect - only handle TB=0 (top protect)
686*cba65a77SJagan Teki  *   - SEC: sector/block protect - only handle SEC=0 (block protect)
687*cba65a77SJagan Teki  *   - CMP: complement protect - only support CMP=0 (range is not complemented)
688*cba65a77SJagan Teki  *
689*cba65a77SJagan Teki  * Sample table portion for 8MB flash (Winbond w25q64fw):
690*cba65a77SJagan Teki  *
691*cba65a77SJagan Teki  *   SEC  |  TB   |  BP2  |  BP1  |  BP0  |  Prot Length  | Protected Portion
692*cba65a77SJagan Teki  *  --------------------------------------------------------------------------
693*cba65a77SJagan Teki  *    X   |   X   |   0   |   0   |   0   |  NONE         | NONE
694*cba65a77SJagan Teki  *    0   |   0   |   0   |   0   |   1   |  128 KB       | Upper 1/64
695*cba65a77SJagan Teki  *    0   |   0   |   0   |   1   |   0   |  256 KB       | Upper 1/32
696*cba65a77SJagan Teki  *    0   |   0   |   0   |   1   |   1   |  512 KB       | Upper 1/16
697*cba65a77SJagan Teki  *    0   |   0   |   1   |   0   |   0   |  1 MB         | Upper 1/8
698*cba65a77SJagan Teki  *    0   |   0   |   1   |   0   |   1   |  2 MB         | Upper 1/4
699*cba65a77SJagan Teki  *    0   |   0   |   1   |   1   |   0   |  4 MB         | Upper 1/2
700*cba65a77SJagan Teki  *    X   |   X   |   1   |   1   |   1   |  8 MB         | ALL
701*cba65a77SJagan Teki  *
702*cba65a77SJagan Teki  * Returns negative on errors, 0 on success.
703*cba65a77SJagan Teki  */
704*cba65a77SJagan Teki int stm_lock(struct spi_flash *flash, u32 ofs, size_t len)
705*cba65a77SJagan Teki {
706*cba65a77SJagan Teki 	u8 status_old, status_new;
707*cba65a77SJagan Teki 	u8 mask = SR_BP2 | SR_BP1 | SR_BP0;
708*cba65a77SJagan Teki 	u8 shift = ffs(mask) - 1, pow, val;
709*cba65a77SJagan Teki 	int ret;
710*cba65a77SJagan Teki 
711*cba65a77SJagan Teki 	ret = read_sr(flash, &status_old);
712*cba65a77SJagan Teki 	if (ret < 0)
713*cba65a77SJagan Teki 		return ret;
714*cba65a77SJagan Teki 
715*cba65a77SJagan Teki 	/* SPI NOR always locks to the end */
716*cba65a77SJagan Teki 	if (ofs + len != flash->size) {
717*cba65a77SJagan Teki 		/* Does combined region extend to end? */
718*cba65a77SJagan Teki 		if (!stm_is_locked_sr(flash, ofs + len, flash->size - ofs - len,
719*cba65a77SJagan Teki 				      status_old))
720*cba65a77SJagan Teki 			return -EINVAL;
721*cba65a77SJagan Teki 		len = flash->size - ofs;
722*cba65a77SJagan Teki 	}
723*cba65a77SJagan Teki 
724*cba65a77SJagan Teki 	/*
725*cba65a77SJagan Teki 	 * Need smallest pow such that:
726*cba65a77SJagan Teki 	 *
727*cba65a77SJagan Teki 	 *   1 / (2^pow) <= (len / size)
728*cba65a77SJagan Teki 	 *
729*cba65a77SJagan Teki 	 * so (assuming power-of-2 size) we do:
730*cba65a77SJagan Teki 	 *
731*cba65a77SJagan Teki 	 *   pow = ceil(log2(size / len)) = log2(size) - floor(log2(len))
732*cba65a77SJagan Teki 	 */
733*cba65a77SJagan Teki 	pow = ilog2(flash->size) - ilog2(len);
734*cba65a77SJagan Teki 	val = mask - (pow << shift);
735*cba65a77SJagan Teki 	if (val & ~mask)
736*cba65a77SJagan Teki 		return -EINVAL;
737*cba65a77SJagan Teki 
738*cba65a77SJagan Teki 	/* Don't "lock" with no region! */
739*cba65a77SJagan Teki 	if (!(val & mask))
740*cba65a77SJagan Teki 		return -EINVAL;
741*cba65a77SJagan Teki 
742*cba65a77SJagan Teki 	status_new = (status_old & ~mask) | val;
743*cba65a77SJagan Teki 
744*cba65a77SJagan Teki 	/* Only modify protection if it will not unlock other areas */
745*cba65a77SJagan Teki 	if ((status_new & mask) <= (status_old & mask))
746*cba65a77SJagan Teki 		return -EINVAL;
747*cba65a77SJagan Teki 
748*cba65a77SJagan Teki 	write_sr(flash, status_new);
749*cba65a77SJagan Teki 
750*cba65a77SJagan Teki 	return 0;
751*cba65a77SJagan Teki }
752*cba65a77SJagan Teki 
753*cba65a77SJagan Teki /*
754*cba65a77SJagan Teki  * Unlock a region of the flash. See stm_lock() for more info
755*cba65a77SJagan Teki  *
756*cba65a77SJagan Teki  * Returns negative on errors, 0 on success.
757*cba65a77SJagan Teki  */
758*cba65a77SJagan Teki int stm_unlock(struct spi_flash *flash, u32 ofs, size_t len)
759*cba65a77SJagan Teki {
760*cba65a77SJagan Teki 	uint8_t status_old, status_new;
761*cba65a77SJagan Teki 	u8 mask = SR_BP2 | SR_BP1 | SR_BP0;
762*cba65a77SJagan Teki 	u8 shift = ffs(mask) - 1, pow, val;
763*cba65a77SJagan Teki 	int ret;
764*cba65a77SJagan Teki 
765*cba65a77SJagan Teki 	ret = read_sr(flash, &status_old);
766*cba65a77SJagan Teki 	if (ret < 0)
767*cba65a77SJagan Teki 		return ret;
768*cba65a77SJagan Teki 
769*cba65a77SJagan Teki 	/* Cannot unlock; would unlock larger region than requested */
770*cba65a77SJagan Teki 	if (stm_is_locked_sr(flash, status_old, ofs - flash->erase_size,
771*cba65a77SJagan Teki 			     flash->erase_size))
772*cba65a77SJagan Teki 		return -EINVAL;
773*cba65a77SJagan Teki 	/*
774*cba65a77SJagan Teki 	 * Need largest pow such that:
775*cba65a77SJagan Teki 	 *
776*cba65a77SJagan Teki 	 *   1 / (2^pow) >= (len / size)
777*cba65a77SJagan Teki 	 *
778*cba65a77SJagan Teki 	 * so (assuming power-of-2 size) we do:
779*cba65a77SJagan Teki 	 *
780*cba65a77SJagan Teki 	 *   pow = floor(log2(size / len)) = log2(size) - ceil(log2(len))
781*cba65a77SJagan Teki 	 */
782*cba65a77SJagan Teki 	pow = ilog2(flash->size) - order_base_2(flash->size - (ofs + len));
783*cba65a77SJagan Teki 	if (ofs + len == flash->size) {
784*cba65a77SJagan Teki 		val = 0; /* fully unlocked */
785*cba65a77SJagan Teki 	} else {
786*cba65a77SJagan Teki 		val = mask - (pow << shift);
787*cba65a77SJagan Teki 		/* Some power-of-two sizes are not supported */
788*cba65a77SJagan Teki 		if (val & ~mask)
789*cba65a77SJagan Teki 			return -EINVAL;
790*cba65a77SJagan Teki 	}
791*cba65a77SJagan Teki 
792*cba65a77SJagan Teki 	status_new = (status_old & ~mask) | val;
793*cba65a77SJagan Teki 
794*cba65a77SJagan Teki 	/* Only modify protection if it will not lock other areas */
795*cba65a77SJagan Teki 	if ((status_new & mask) >= (status_old & mask))
796*cba65a77SJagan Teki 		return -EINVAL;
797*cba65a77SJagan Teki 
798*cba65a77SJagan Teki 	write_sr(flash, status_new);
799*cba65a77SJagan Teki 
800*cba65a77SJagan Teki 	return 0;
801*cba65a77SJagan Teki }
802*cba65a77SJagan Teki #endif
803*cba65a77SJagan Teki 
804*cba65a77SJagan Teki 
805*cba65a77SJagan Teki #ifdef CONFIG_SPI_FLASH_MACRONIX
806*cba65a77SJagan Teki static int spi_flash_set_qeb_mxic(struct spi_flash *flash)
807*cba65a77SJagan Teki {
808*cba65a77SJagan Teki 	u8 qeb_status;
809*cba65a77SJagan Teki 	int ret;
810*cba65a77SJagan Teki 
811*cba65a77SJagan Teki 	ret = read_sr(flash, &qeb_status);
812*cba65a77SJagan Teki 	if (ret < 0)
813*cba65a77SJagan Teki 		return ret;
814*cba65a77SJagan Teki 
815*cba65a77SJagan Teki 	if (qeb_status & STATUS_QEB_MXIC) {
816*cba65a77SJagan Teki 		debug("SF: mxic: QEB is already set\n");
817*cba65a77SJagan Teki 	} else {
818*cba65a77SJagan Teki 		ret = write_sr(flash, STATUS_QEB_MXIC);
819*cba65a77SJagan Teki 		if (ret < 0)
820*cba65a77SJagan Teki 			return ret;
821*cba65a77SJagan Teki 	}
822*cba65a77SJagan Teki 
823*cba65a77SJagan Teki 	return ret;
824*cba65a77SJagan Teki }
825*cba65a77SJagan Teki #endif
826*cba65a77SJagan Teki 
827*cba65a77SJagan Teki #if defined(CONFIG_SPI_FLASH_SPANSION) || defined(CONFIG_SPI_FLASH_WINBOND)
828*cba65a77SJagan Teki static int spi_flash_set_qeb_winspan(struct spi_flash *flash)
829*cba65a77SJagan Teki {
830*cba65a77SJagan Teki 	u8 qeb_status;
831*cba65a77SJagan Teki 	int ret;
832*cba65a77SJagan Teki 
833*cba65a77SJagan Teki 	ret = read_cr(flash, &qeb_status);
834*cba65a77SJagan Teki 	if (ret < 0)
835*cba65a77SJagan Teki 		return ret;
836*cba65a77SJagan Teki 
837*cba65a77SJagan Teki 	if (qeb_status & STATUS_QEB_WINSPAN) {
838*cba65a77SJagan Teki 		debug("SF: winspan: QEB is already set\n");
839*cba65a77SJagan Teki 	} else {
840*cba65a77SJagan Teki 		ret = write_cr(flash, STATUS_QEB_WINSPAN);
841*cba65a77SJagan Teki 		if (ret < 0)
842*cba65a77SJagan Teki 			return ret;
843*cba65a77SJagan Teki 	}
844*cba65a77SJagan Teki 
845*cba65a77SJagan Teki 	return ret;
846*cba65a77SJagan Teki }
847*cba65a77SJagan Teki #endif
848*cba65a77SJagan Teki 
849*cba65a77SJagan Teki static int spi_flash_set_qeb(struct spi_flash *flash, u8 idcode0)
850*cba65a77SJagan Teki {
851*cba65a77SJagan Teki 	switch (idcode0) {
852*cba65a77SJagan Teki #ifdef CONFIG_SPI_FLASH_MACRONIX
853*cba65a77SJagan Teki 	case SPI_FLASH_CFI_MFR_MACRONIX:
854*cba65a77SJagan Teki 		return spi_flash_set_qeb_mxic(flash);
855*cba65a77SJagan Teki #endif
856*cba65a77SJagan Teki #if defined(CONFIG_SPI_FLASH_SPANSION) || defined(CONFIG_SPI_FLASH_WINBOND)
857*cba65a77SJagan Teki 	case SPI_FLASH_CFI_MFR_SPANSION:
858*cba65a77SJagan Teki 	case SPI_FLASH_CFI_MFR_WINBOND:
859*cba65a77SJagan Teki 		return spi_flash_set_qeb_winspan(flash);
860*cba65a77SJagan Teki #endif
861*cba65a77SJagan Teki #ifdef CONFIG_SPI_FLASH_STMICRO
862*cba65a77SJagan Teki 	case SPI_FLASH_CFI_MFR_STMICRO:
863*cba65a77SJagan Teki 		debug("SF: QEB is volatile for %02x flash\n", idcode0);
864*cba65a77SJagan Teki 		return 0;
865*cba65a77SJagan Teki #endif
866*cba65a77SJagan Teki 	default:
867*cba65a77SJagan Teki 		printf("SF: Need set QEB func for %02x flash\n", idcode0);
868*cba65a77SJagan Teki 		return -1;
869*cba65a77SJagan Teki 	}
870*cba65a77SJagan Teki }
871*cba65a77SJagan Teki 
872*cba65a77SJagan Teki #if CONFIG_IS_ENABLED(OF_CONTROL)
873*cba65a77SJagan Teki int spi_flash_decode_fdt(const void *blob, struct spi_flash *flash)
874*cba65a77SJagan Teki {
875*cba65a77SJagan Teki 	fdt_addr_t addr;
876*cba65a77SJagan Teki 	fdt_size_t size;
877*cba65a77SJagan Teki 	int node;
878*cba65a77SJagan Teki 
879*cba65a77SJagan Teki 	/* If there is no node, do nothing */
880*cba65a77SJagan Teki 	node = fdtdec_next_compatible(blob, 0, COMPAT_GENERIC_SPI_FLASH);
881*cba65a77SJagan Teki 	if (node < 0)
882*cba65a77SJagan Teki 		return 0;
883*cba65a77SJagan Teki 
884*cba65a77SJagan Teki 	addr = fdtdec_get_addr_size(blob, node, "memory-map", &size);
885*cba65a77SJagan Teki 	if (addr == FDT_ADDR_T_NONE) {
886*cba65a77SJagan Teki 		debug("%s: Cannot decode address\n", __func__);
887*cba65a77SJagan Teki 		return 0;
888*cba65a77SJagan Teki 	}
889*cba65a77SJagan Teki 
890*cba65a77SJagan Teki 	if (flash->size != size) {
891*cba65a77SJagan Teki 		debug("%s: Memory map must cover entire device\n", __func__);
892*cba65a77SJagan Teki 		return -1;
893*cba65a77SJagan Teki 	}
894*cba65a77SJagan Teki 	flash->memory_map = map_sysmem(addr, size);
895*cba65a77SJagan Teki 
896*cba65a77SJagan Teki 	return 0;
897*cba65a77SJagan Teki }
898*cba65a77SJagan Teki #endif /* CONFIG_IS_ENABLED(OF_CONTROL) */
899*cba65a77SJagan Teki 
900*cba65a77SJagan Teki int spi_flash_scan(struct spi_flash *flash)
901*cba65a77SJagan Teki {
902*cba65a77SJagan Teki 	struct spi_slave *spi = flash->spi;
903*cba65a77SJagan Teki 	const struct spi_flash_params *params;
904*cba65a77SJagan Teki 	u16 jedec, ext_jedec;
905*cba65a77SJagan Teki 	u8 idcode[5];
906*cba65a77SJagan Teki 	u8 cmd;
907*cba65a77SJagan Teki 	int ret;
908*cba65a77SJagan Teki 
909*cba65a77SJagan Teki 	/* Read the ID codes */
910*cba65a77SJagan Teki 	ret = spi_flash_cmd(spi, CMD_READ_ID, idcode, sizeof(idcode));
911*cba65a77SJagan Teki 	if (ret) {
912*cba65a77SJagan Teki 		printf("SF: Failed to get idcodes\n");
913*cba65a77SJagan Teki 		return -EINVAL;
914*cba65a77SJagan Teki 	}
915*cba65a77SJagan Teki 
916*cba65a77SJagan Teki #ifdef DEBUG
917*cba65a77SJagan Teki 	printf("SF: Got idcodes\n");
918*cba65a77SJagan Teki 	print_buffer(0, idcode, 1, sizeof(idcode), 0);
919*cba65a77SJagan Teki #endif
920*cba65a77SJagan Teki 
921*cba65a77SJagan Teki 	jedec = idcode[1] << 8 | idcode[2];
922*cba65a77SJagan Teki 	ext_jedec = idcode[3] << 8 | idcode[4];
923*cba65a77SJagan Teki 
924*cba65a77SJagan Teki 	/* Validate params from spi_flash_params table */
925*cba65a77SJagan Teki 	params = spi_flash_params_table;
926*cba65a77SJagan Teki 	for (; params->name != NULL; params++) {
927*cba65a77SJagan Teki 		if ((params->jedec >> 16) == idcode[0]) {
928*cba65a77SJagan Teki 			if ((params->jedec & 0xFFFF) == jedec) {
929*cba65a77SJagan Teki 				if (params->ext_jedec == 0)
930*cba65a77SJagan Teki 					break;
931*cba65a77SJagan Teki 				else if (params->ext_jedec == ext_jedec)
932*cba65a77SJagan Teki 					break;
933*cba65a77SJagan Teki 			}
934*cba65a77SJagan Teki 		}
935*cba65a77SJagan Teki 	}
936*cba65a77SJagan Teki 
937*cba65a77SJagan Teki 	if (!params->name) {
938*cba65a77SJagan Teki 		printf("SF: Unsupported flash IDs: ");
939*cba65a77SJagan Teki 		printf("manuf %02x, jedec %04x, ext_jedec %04x\n",
940*cba65a77SJagan Teki 		       idcode[0], jedec, ext_jedec);
941*cba65a77SJagan Teki 		return -EPROTONOSUPPORT;
942*cba65a77SJagan Teki 	}
943*cba65a77SJagan Teki 
944*cba65a77SJagan Teki 	/* Flash powers up read-only, so clear BP# bits */
945*cba65a77SJagan Teki 	if (idcode[0] == SPI_FLASH_CFI_MFR_ATMEL ||
946*cba65a77SJagan Teki 	    idcode[0] == SPI_FLASH_CFI_MFR_MACRONIX ||
947*cba65a77SJagan Teki 	    idcode[0] == SPI_FLASH_CFI_MFR_SST)
948*cba65a77SJagan Teki 		write_sr(flash, 0);
949*cba65a77SJagan Teki 
950*cba65a77SJagan Teki 	/* Assign spi data */
951*cba65a77SJagan Teki 	flash->name = params->name;
952*cba65a77SJagan Teki 	flash->memory_map = spi->memory_map;
953*cba65a77SJagan Teki 	flash->dual_flash = flash->spi->option;
954*cba65a77SJagan Teki 
955*cba65a77SJagan Teki 	/* Assign spi flash flags */
956*cba65a77SJagan Teki 	if (params->flags & SST_WR)
957*cba65a77SJagan Teki 		flash->flags |= SNOR_F_SST_WR;
958*cba65a77SJagan Teki 
959*cba65a77SJagan Teki 	/* Assign spi_flash ops */
960*cba65a77SJagan Teki #ifndef CONFIG_DM_SPI_FLASH
961*cba65a77SJagan Teki 	flash->write = spi_flash_cmd_write_ops;
962*cba65a77SJagan Teki #if defined(CONFIG_SPI_FLASH_SST)
963*cba65a77SJagan Teki 	if (flash->flags & SNOR_F_SST_WR) {
964*cba65a77SJagan Teki 		if (flash->spi->op_mode_tx & SPI_OPM_TX_BP)
965*cba65a77SJagan Teki 			flash->write = sst_write_bp;
966*cba65a77SJagan Teki 		else
967*cba65a77SJagan Teki 			flash->write = sst_write_wp;
968*cba65a77SJagan Teki 	}
969*cba65a77SJagan Teki #endif
970*cba65a77SJagan Teki 	flash->erase = spi_flash_cmd_erase_ops;
971*cba65a77SJagan Teki 	flash->read = spi_flash_cmd_read_ops;
972*cba65a77SJagan Teki #endif
973*cba65a77SJagan Teki 
974*cba65a77SJagan Teki 	/* lock hooks are flash specific - assign them based on idcode0 */
975*cba65a77SJagan Teki 	switch (idcode[0]) {
976*cba65a77SJagan Teki #if defined(CONFIG_SPI_FLASH_STMICRO) || defined(CONFIG_SPI_FLASH_SST)
977*cba65a77SJagan Teki 	case SPI_FLASH_CFI_MFR_STMICRO:
978*cba65a77SJagan Teki 	case SPI_FLASH_CFI_MFR_SST:
979*cba65a77SJagan Teki 		flash->flash_lock = stm_lock;
980*cba65a77SJagan Teki 		flash->flash_unlock = stm_unlock;
981*cba65a77SJagan Teki 		flash->flash_is_locked = stm_is_locked;
982*cba65a77SJagan Teki #endif
983*cba65a77SJagan Teki 		break;
984*cba65a77SJagan Teki 	default:
985*cba65a77SJagan Teki 		debug("SF: Lock ops not supported for %02x flash\n", idcode[0]);
986*cba65a77SJagan Teki 	}
987*cba65a77SJagan Teki 
988*cba65a77SJagan Teki 	/* Compute the flash size */
989*cba65a77SJagan Teki 	flash->shift = (flash->dual_flash & SF_DUAL_PARALLEL_FLASH) ? 1 : 0;
990*cba65a77SJagan Teki 	/*
991*cba65a77SJagan Teki 	 * The Spansion S25FL032P and S25FL064P have 256b pages, yet use the
992*cba65a77SJagan Teki 	 * 0x4d00 Extended JEDEC code. The rest of the Spansion flashes with
993*cba65a77SJagan Teki 	 * the 0x4d00 Extended JEDEC code have 512b pages. All of the others
994*cba65a77SJagan Teki 	 * have 256b pages.
995*cba65a77SJagan Teki 	 */
996*cba65a77SJagan Teki 	if (ext_jedec == 0x4d00) {
997*cba65a77SJagan Teki 		if ((jedec == 0x0215) || (jedec == 0x216))
998*cba65a77SJagan Teki 			flash->page_size = 256;
999*cba65a77SJagan Teki 		else
1000*cba65a77SJagan Teki 			flash->page_size = 512;
1001*cba65a77SJagan Teki 	} else {
1002*cba65a77SJagan Teki 		flash->page_size = 256;
1003*cba65a77SJagan Teki 	}
1004*cba65a77SJagan Teki 	flash->page_size <<= flash->shift;
1005*cba65a77SJagan Teki 	flash->sector_size = params->sector_size << flash->shift;
1006*cba65a77SJagan Teki 	flash->size = flash->sector_size * params->nr_sectors << flash->shift;
1007*cba65a77SJagan Teki #ifdef CONFIG_SF_DUAL_FLASH
1008*cba65a77SJagan Teki 	if (flash->dual_flash & SF_DUAL_STACKED_FLASH)
1009*cba65a77SJagan Teki 		flash->size <<= 1;
1010*cba65a77SJagan Teki #endif
1011*cba65a77SJagan Teki 
1012*cba65a77SJagan Teki 	/* Compute erase sector and command */
1013*cba65a77SJagan Teki 	if (params->flags & SECT_4K) {
1014*cba65a77SJagan Teki 		flash->erase_cmd = CMD_ERASE_4K;
1015*cba65a77SJagan Teki 		flash->erase_size = 4096 << flash->shift;
1016*cba65a77SJagan Teki 	} else if (params->flags & SECT_32K) {
1017*cba65a77SJagan Teki 		flash->erase_cmd = CMD_ERASE_32K;
1018*cba65a77SJagan Teki 		flash->erase_size = 32768 << flash->shift;
1019*cba65a77SJagan Teki 	} else {
1020*cba65a77SJagan Teki 		flash->erase_cmd = CMD_ERASE_64K;
1021*cba65a77SJagan Teki 		flash->erase_size = flash->sector_size;
1022*cba65a77SJagan Teki 	}
1023*cba65a77SJagan Teki 
1024*cba65a77SJagan Teki 	/* Now erase size becomes valid sector size */
1025*cba65a77SJagan Teki 	flash->sector_size = flash->erase_size;
1026*cba65a77SJagan Teki 
1027*cba65a77SJagan Teki 	/* Look for the fastest read cmd */
1028*cba65a77SJagan Teki 	cmd = fls(params->e_rd_cmd & flash->spi->op_mode_rx);
1029*cba65a77SJagan Teki 	if (cmd) {
1030*cba65a77SJagan Teki 		cmd = spi_read_cmds_array[cmd - 1];
1031*cba65a77SJagan Teki 		flash->read_cmd = cmd;
1032*cba65a77SJagan Teki 	} else {
1033*cba65a77SJagan Teki 		/* Go for default supported read cmd */
1034*cba65a77SJagan Teki 		flash->read_cmd = CMD_READ_ARRAY_FAST;
1035*cba65a77SJagan Teki 	}
1036*cba65a77SJagan Teki 
1037*cba65a77SJagan Teki 	/* Not require to look for fastest only two write cmds yet */
1038*cba65a77SJagan Teki 	if (params->flags & WR_QPP && flash->spi->op_mode_tx & SPI_OPM_TX_QPP)
1039*cba65a77SJagan Teki 		flash->write_cmd = CMD_QUAD_PAGE_PROGRAM;
1040*cba65a77SJagan Teki 	else
1041*cba65a77SJagan Teki 		/* Go for default supported write cmd */
1042*cba65a77SJagan Teki 		flash->write_cmd = CMD_PAGE_PROGRAM;
1043*cba65a77SJagan Teki 
1044*cba65a77SJagan Teki 	/* Set the quad enable bit - only for quad commands */
1045*cba65a77SJagan Teki 	if ((flash->read_cmd == CMD_READ_QUAD_OUTPUT_FAST) ||
1046*cba65a77SJagan Teki 	    (flash->read_cmd == CMD_READ_QUAD_IO_FAST) ||
1047*cba65a77SJagan Teki 	    (flash->write_cmd == CMD_QUAD_PAGE_PROGRAM)) {
1048*cba65a77SJagan Teki 		ret = spi_flash_set_qeb(flash, idcode[0]);
1049*cba65a77SJagan Teki 		if (ret) {
1050*cba65a77SJagan Teki 			debug("SF: Fail to set QEB for %02x\n", idcode[0]);
1051*cba65a77SJagan Teki 			return -EINVAL;
1052*cba65a77SJagan Teki 		}
1053*cba65a77SJagan Teki 	}
1054*cba65a77SJagan Teki 
1055*cba65a77SJagan Teki 	/* Read dummy_byte: dummy byte is determined based on the
1056*cba65a77SJagan Teki 	 * dummy cycles of a particular command.
1057*cba65a77SJagan Teki 	 * Fast commands - dummy_byte = dummy_cycles/8
1058*cba65a77SJagan Teki 	 * I/O commands- dummy_byte = (dummy_cycles * no.of lines)/8
1059*cba65a77SJagan Teki 	 * For I/O commands except cmd[0] everything goes on no.of lines
1060*cba65a77SJagan Teki 	 * based on particular command but incase of fast commands except
1061*cba65a77SJagan Teki 	 * data all go on single line irrespective of command.
1062*cba65a77SJagan Teki 	 */
1063*cba65a77SJagan Teki 	switch (flash->read_cmd) {
1064*cba65a77SJagan Teki 	case CMD_READ_QUAD_IO_FAST:
1065*cba65a77SJagan Teki 		flash->dummy_byte = 2;
1066*cba65a77SJagan Teki 		break;
1067*cba65a77SJagan Teki 	case CMD_READ_ARRAY_SLOW:
1068*cba65a77SJagan Teki 		flash->dummy_byte = 0;
1069*cba65a77SJagan Teki 		break;
1070*cba65a77SJagan Teki 	default:
1071*cba65a77SJagan Teki 		flash->dummy_byte = 1;
1072*cba65a77SJagan Teki 	}
1073*cba65a77SJagan Teki 
1074*cba65a77SJagan Teki #ifdef CONFIG_SPI_FLASH_STMICRO
1075*cba65a77SJagan Teki 	if (params->flags & E_FSR)
1076*cba65a77SJagan Teki 		flash->flags |= SNOR_F_USE_FSR;
1077*cba65a77SJagan Teki #endif
1078*cba65a77SJagan Teki 
1079*cba65a77SJagan Teki 	/* Configure the BAR - discover bank cmds and read current bank */
1080*cba65a77SJagan Teki #ifdef CONFIG_SPI_FLASH_BAR
1081*cba65a77SJagan Teki 	ret = spi_flash_read_bar(flash, idcode[0]);
1082*cba65a77SJagan Teki 	if (ret < 0)
1083*cba65a77SJagan Teki 		return ret;
1084*cba65a77SJagan Teki #endif
1085*cba65a77SJagan Teki 
1086*cba65a77SJagan Teki #if CONFIG_IS_ENABLED(OF_CONTROL)
1087*cba65a77SJagan Teki 	ret = spi_flash_decode_fdt(gd->fdt_blob, flash);
1088*cba65a77SJagan Teki 	if (ret) {
1089*cba65a77SJagan Teki 		debug("SF: FDT decode error\n");
1090*cba65a77SJagan Teki 		return -EINVAL;
1091*cba65a77SJagan Teki 	}
1092*cba65a77SJagan Teki #endif
1093*cba65a77SJagan Teki 
1094*cba65a77SJagan Teki #ifndef CONFIG_SPL_BUILD
1095*cba65a77SJagan Teki 	printf("SF: Detected %s with page size ", flash->name);
1096*cba65a77SJagan Teki 	print_size(flash->page_size, ", erase size ");
1097*cba65a77SJagan Teki 	print_size(flash->erase_size, ", total ");
1098*cba65a77SJagan Teki 	print_size(flash->size, "");
1099*cba65a77SJagan Teki 	if (flash->memory_map)
1100*cba65a77SJagan Teki 		printf(", mapped at %p", flash->memory_map);
1101*cba65a77SJagan Teki 	puts("\n");
1102*cba65a77SJagan Teki #endif
1103*cba65a77SJagan Teki 
1104*cba65a77SJagan Teki #ifndef CONFIG_SPI_FLASH_BAR
1105*cba65a77SJagan Teki 	if (((flash->dual_flash == SF_SINGLE_FLASH) &&
1106*cba65a77SJagan Teki 	     (flash->size > SPI_FLASH_16MB_BOUN)) ||
1107*cba65a77SJagan Teki 	     ((flash->dual_flash > SF_SINGLE_FLASH) &&
1108*cba65a77SJagan Teki 	     (flash->size > SPI_FLASH_16MB_BOUN << 1))) {
1109*cba65a77SJagan Teki 		puts("SF: Warning - Only lower 16MiB accessible,");
1110*cba65a77SJagan Teki 		puts(" Full access #define CONFIG_SPI_FLASH_BAR\n");
1111*cba65a77SJagan Teki 	}
1112*cba65a77SJagan Teki #endif
1113*cba65a77SJagan Teki 
1114*cba65a77SJagan Teki 	return ret;
1115*cba65a77SJagan Teki }
1116