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