1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * (C) Copyright 2000-2003
4  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
5  *
6  * Copyright (C) 2004-2007 Freescale Semiconductor, Inc.
7  * TsiChung Liew (Tsi-Chung.Liew@freescale.com)
8  */
9 
10 #include <common.h>
11 #include <flash.h>
12 #include <init.h>
13 #include <irq_func.h>
14 
15 #include <asm/immap.h>
16 
17 #ifndef CONFIG_SYS_FLASH_CFI
18 typedef unsigned short FLASH_PORT_WIDTH;
19 typedef volatile unsigned short FLASH_PORT_WIDTHV;
20 
21 #define FPW             FLASH_PORT_WIDTH
22 #define FPWV            FLASH_PORT_WIDTHV
23 
24 #define FLASH_CYCLE1    0x5555
25 #define FLASH_CYCLE2    0x2aaa
26 
27 #define SYNC			__asm__("nop")
28 
29 /*-----------------------------------------------------------------------
30  * Functions
31  */
32 
33 ulong flash_get_size(FPWV * addr, flash_info_t * info);
34 int flash_get_offsets(ulong base, flash_info_t * info);
35 int write_word(flash_info_t * info, FPWV * dest, u16 data);
36 static inline void spin_wheel(void);
37 
38 flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS];
39 
flash_init(void)40 ulong flash_init(void)
41 {
42 	ulong size = 0;
43 	ulong fbase = 0;
44 
45 	fbase = (ulong) CONFIG_SYS_FLASH_BASE;
46 	flash_get_size((FPWV *) fbase, &flash_info[0]);
47 	flash_get_offsets((ulong) fbase, &flash_info[0]);
48 	fbase += flash_info[0].size;
49 	size += flash_info[0].size;
50 
51 	/* Protect monitor and environment sectors */
52 	flash_protect(FLAG_PROTECT_SET,
53 		      CONFIG_SYS_MONITOR_BASE,
54 		      CONFIG_SYS_MONITOR_BASE + monitor_flash_len - 1, &flash_info[0]);
55 
56 	return size;
57 }
58 
flash_get_offsets(ulong base,flash_info_t * info)59 int flash_get_offsets(ulong base, flash_info_t * info)
60 {
61 	int i;
62 
63 	if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) {
64 
65 		info->start[0] = base;
66 		info->protect[0] = 0;
67 		for (i = 1; i < CONFIG_SYS_SST_SECT; i++) {
68 			info->start[i] = info->start[i - 1]
69 						+ CONFIG_SYS_SST_SECTSZ;
70 			info->protect[i] = 0;
71 		}
72 	}
73 
74 	return ERR_OK;
75 }
76 
flash_print_info(flash_info_t * info)77 void flash_print_info(flash_info_t * info)
78 {
79 	int i;
80 
81 	switch (info->flash_id & FLASH_VENDMASK) {
82 	case FLASH_MAN_SST:
83 		printf("SST ");
84 		break;
85 	default:
86 		printf("Unknown Vendor ");
87 		break;
88 	}
89 
90 	switch (info->flash_id & FLASH_TYPEMASK) {
91 	case FLASH_SST6401B:
92 		printf("SST39VF6401B\n");
93 		break;
94 	default:
95 		printf("Unknown Chip Type\n");
96 		return;
97 	}
98 
99 	if (info->size > 0x100000) {
100 		int remainder;
101 
102 		printf("  Size: %ld", info->size >> 20);
103 
104 		remainder = (info->size % 0x100000);
105 		if (remainder) {
106 			remainder >>= 10;
107 			remainder = (int)((float)
108 					  (((float)remainder / (float)1024) *
109 					   10000));
110 			printf(".%d ", remainder);
111 		}
112 
113 		printf("MB in %d Sectors\n", info->sector_count);
114 	} else
115 		printf("  Size: %ld KB in %d Sectors\n",
116 		       info->size >> 10, info->sector_count);
117 
118 	printf("  Sector Start Addresses:");
119 	for (i = 0; i < info->sector_count; ++i) {
120 		if ((i % 5) == 0)
121 			printf("\n   ");
122 		printf(" %08lX%s",
123 		       info->start[i], info->protect[i] ? " (RO)" : "     ");
124 	}
125 	printf("\n");
126 }
127 
128 /*
129  * The following code cannot be run from FLASH!
130  */
flash_get_size(FPWV * addr,flash_info_t * info)131 ulong flash_get_size(FPWV * addr, flash_info_t * info)
132 {
133 	u16 value;
134 
135 	addr[FLASH_CYCLE1] = (FPWV) 0x00AA00AA;	/* for Atmel, Intel ignores this */
136 	addr[FLASH_CYCLE2] = (FPWV) 0x00550055;	/* for Atmel, Intel ignores this */
137 	addr[FLASH_CYCLE1] = (FPWV) 0x00900090;	/* selects Intel or Atmel */
138 
139 	switch (addr[0] & 0xffff) {
140 	case (u8) SST_MANUFACT:
141 		info->flash_id = FLASH_MAN_SST;
142 		value = addr[1];
143 		break;
144 	default:
145 		printf("Unknown Flash\n");
146 		info->flash_id = FLASH_UNKNOWN;
147 		info->sector_count = 0;
148 		info->size = 0;
149 
150 		*addr = (FPW) 0x00F000F0;
151 		return (0);	/* no or unknown flash  */
152 	}
153 
154 	switch (value) {
155 	case (u16) SST_ID_xF6401B:
156 		info->flash_id += FLASH_SST6401B;
157 		break;
158 	default:
159 		info->flash_id = FLASH_UNKNOWN;
160 		break;
161 	}
162 
163 	info->sector_count = 0;
164 	info->size = 0;
165 	info->sector_count = CONFIG_SYS_SST_SECT;
166 	info->size = CONFIG_SYS_SST_SECT * CONFIG_SYS_SST_SECTSZ;
167 
168 	/* reset ID mode */
169 	*addr = (FPWV) 0x00F000F0;
170 
171 	if (info->sector_count > CONFIG_SYS_MAX_FLASH_SECT) {
172 		printf("** ERROR: sector count %d > max (%d) **\n",
173 		       info->sector_count, CONFIG_SYS_MAX_FLASH_SECT);
174 		info->sector_count = CONFIG_SYS_MAX_FLASH_SECT;
175 	}
176 
177 	return (info->size);
178 }
179 
flash_erase(flash_info_t * info,int s_first,int s_last)180 int flash_erase(flash_info_t * info, int s_first, int s_last)
181 {
182 	FPWV *addr;
183 	int flag, prot, sect, count;
184 	ulong type, start;
185 	int rcode = 0, flashtype = 0;
186 
187 	if ((s_first < 0) || (s_first > s_last)) {
188 		if (info->flash_id == FLASH_UNKNOWN)
189 			printf("- missing\n");
190 		else
191 			printf("- no sectors to erase\n");
192 		return 1;
193 	}
194 
195 	type = (info->flash_id & FLASH_VENDMASK);
196 
197 	switch (type) {
198 	case FLASH_MAN_SST:
199 		flashtype = 1;
200 		break;
201 	default:
202 		type = (info->flash_id & FLASH_VENDMASK);
203 		printf("Can't erase unknown flash type %08lx - aborted\n",
204 		       info->flash_id);
205 		return 1;
206 	}
207 
208 	prot = 0;
209 	for (sect = s_first; sect <= s_last; ++sect) {
210 		if (info->protect[sect]) {
211 			prot++;
212 		}
213 	}
214 
215 	if (prot)
216 		printf("- Warning: %d protected sectors will not be erased!\n",
217 		       prot);
218 	else
219 		printf("\n");
220 
221 	flag = disable_interrupts();
222 
223 	start = get_timer(0);
224 
225 	if ((s_last - s_first) == (CONFIG_SYS_SST_SECT - 1)) {
226 		if (prot == 0) {
227 			addr = (FPWV *) info->start[0];
228 
229 			addr[FLASH_CYCLE1] = 0x00AA;	/* unlock */
230 			addr[FLASH_CYCLE2] = 0x0055;	/* unlock */
231 			addr[FLASH_CYCLE1] = 0x0080;	/* erase mode */
232 			addr[FLASH_CYCLE1] = 0x00AA;	/* unlock */
233 			addr[FLASH_CYCLE2] = 0x0055;	/* unlock */
234 			*addr = 0x0030;	/* erase chip */
235 
236 			count = 0;
237 			start = get_timer(0);
238 
239 			while ((*addr & 0x0080) != 0x0080) {
240 				if (count++ > 0x10000) {
241 					spin_wheel();
242 					count = 0;
243 				}
244 
245 				if (get_timer(start) > CONFIG_SYS_FLASH_ERASE_TOUT) {
246 					printf("Timeout\n");
247 					*addr = 0x00F0;	/* reset to read mode */
248 
249 					return 1;
250 				}
251 			}
252 
253 			*addr = 0x00F0;	/* reset to read mode */
254 
255 			printf("\b. done\n");
256 
257 			if (flag)
258 				enable_interrupts();
259 
260 			return 0;
261 		} else if (prot == CONFIG_SYS_SST_SECT) {
262 			return 1;
263 		}
264 	}
265 
266 	/* Start erase on unprotected sectors */
267 	for (sect = s_first; sect <= s_last; sect++) {
268 		if (info->protect[sect] == 0) {	/* not protected */
269 
270 			addr = (FPWV *) (info->start[sect]);
271 
272 			printf(".");
273 
274 			/* arm simple, non interrupt dependent timer */
275 			start = get_timer(0);
276 
277 			switch (flashtype) {
278 			case 1:
279 				{
280 					FPWV *base;	/* first address in bank */
281 
282 					flag = disable_interrupts();
283 
284 					base = (FPWV *) (CONFIG_SYS_FLASH_BASE);	/* First sector */
285 
286 					base[FLASH_CYCLE1] = 0x00AA;	/* unlock */
287 					base[FLASH_CYCLE2] = 0x0055;	/* unlock */
288 					base[FLASH_CYCLE1] = 0x0080;	/* erase mode */
289 					base[FLASH_CYCLE1] = 0x00AA;	/* unlock */
290 					base[FLASH_CYCLE2] = 0x0055;	/* unlock */
291 					*addr = 0x0050;	/* erase sector */
292 
293 					if (flag)
294 						enable_interrupts();
295 
296 					while ((*addr & 0x0080) != 0x0080) {
297 						if (get_timer(start) >
298 						    CONFIG_SYS_FLASH_ERASE_TOUT) {
299 							printf("Timeout\n");
300 							*addr = 0x00F0;	/* reset to read mode */
301 
302 							rcode = 1;
303 							break;
304 						}
305 					}
306 
307 					*addr = 0x00F0;	/* reset to read mode */
308 					break;
309 				}
310 			}	/* switch (flashtype) */
311 		}
312 	}
313 	printf(" done\n");
314 
315 	if (flag)
316 		enable_interrupts();
317 
318 	return rcode;
319 }
320 
write_buff(flash_info_t * info,uchar * src,ulong addr,ulong cnt)321 int write_buff(flash_info_t * info, uchar * src, ulong addr, ulong cnt)
322 {
323 	ulong wp, count;
324 	u16 data;
325 	int rc;
326 
327 	if (info->flash_id == FLASH_UNKNOWN)
328 		return 4;
329 
330 	/* get lower word aligned address */
331 	wp = addr;
332 
333 	/* handle unaligned start bytes */
334 	if (wp & 1) {
335 		data = *((FPWV *) wp);
336 		data = (data << 8) | *src;
337 
338 		if ((rc = write_word(info, (FPWV *) wp, data)) != 0)
339 			return (rc);
340 
341 		wp++;
342 		cnt -= 1;
343 		src++;
344 	}
345 
346 	while (cnt >= 2) {
347 		/*
348 		 * handle word aligned part
349 		 */
350 		count = 0;
351 		data = *((FPWV *) src);
352 
353 		if ((rc = write_word(info, (FPWV *) wp, data)) != 0)
354 			return (rc);
355 
356 		wp += 2;
357 		src += 2;
358 		cnt -= 2;
359 
360 		if (count++ > 0x800) {
361 			spin_wheel();
362 			count = 0;
363 		}
364 	}
365 	/* handle word aligned part */
366 	if (cnt) {
367 		/* handle word aligned part */
368 		count = 0;
369 		data = *((FPWV *) wp);
370 
371 		data = (data & 0x00FF) | (*src << 8);
372 
373 		if ((rc = write_word(info, (FPWV *) wp, data)) != 0)
374 			return (rc);
375 
376 		wp++;
377 		src++;
378 		cnt -= 1;
379 		if (count++ > 0x800) {
380 			spin_wheel();
381 			count = 0;
382 		}
383 	}
384 
385 	if (cnt == 0)
386 		return ERR_OK;
387 
388 	return ERR_OK;
389 }
390 
391 /*-----------------------------------------------------------------------
392  * Write a word to Flash
393  * A word is 16 bits, whichever the bus width of the flash bank
394  * (not an individual chip) is.
395  *
396  * returns:
397  * 0 - OK
398  * 1 - write timeout
399  * 2 - Flash not erased
400  */
write_word(flash_info_t * info,FPWV * dest,u16 data)401 int write_word(flash_info_t * info, FPWV * dest, u16 data)
402 {
403 	ulong start;
404 	int flag;
405 	int res = 0;		/* result, assume success */
406 	FPWV *base;		/* first address in flash bank */
407 
408 	/* Check if Flash is (sufficiently) erased */
409 	if ((*dest & (u8) data) != (u8) data) {
410 		return (2);
411 	}
412 
413 	base = (FPWV *) (CONFIG_SYS_FLASH_BASE);
414 
415 	/* Disable interrupts which might cause a timeout here */
416 	flag = disable_interrupts();
417 
418 	base[FLASH_CYCLE1] = (u8) 0x00AA00AA;	/* unlock */
419 	base[FLASH_CYCLE2] = (u8) 0x00550055;	/* unlock */
420 	base[FLASH_CYCLE1] = (u8) 0x00A000A0;	/* selects program mode */
421 
422 	*dest = data;		/* start programming the data */
423 
424 	/* re-enable interrupts if necessary */
425 	if (flag)
426 		enable_interrupts();
427 
428 	start = get_timer(0);
429 
430 	/* data polling for D7 */
431 	while (res == 0
432 	       && (*dest & (u8) 0x00800080) != (data & (u8) 0x00800080)) {
433 		if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
434 			*dest = (u8) 0x00F000F0;	/* reset bank */
435 			res = 1;
436 		}
437 	}
438 
439 	*dest++ = (u8) 0x00F000F0;	/* reset bank */
440 
441 	return (res);
442 }
443 
spin_wheel(void)444 static inline void spin_wheel(void)
445 {
446 	static int p = 0;
447 	static char w[] = "\\/-";
448 
449 	printf("\010%c", w[p]);
450 	(++p == 3) ? (p = 0) : 0;
451 }
452 
453 #endif
454