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 i;
60 
61 	if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) {
62 
63 		info->start[0] = base;
64 		info->protect[0] = 0;
65 		for (i = 1; i < CONFIG_SYS_SST_SECT; i++) {
66 			info->start[i] = info->start[i - 1]
67 						+ CONFIG_SYS_SST_SECTSZ;
68 			info->protect[i] = 0;
69 		}
70 	}
71 
72 	return ERR_OK;
73 }
74 
75 void flash_print_info(flash_info_t * info)
76 {
77 	int i;
78 
79 	switch (info->flash_id & FLASH_VENDMASK) {
80 	case FLASH_MAN_SST:
81 		printf("SST ");
82 		break;
83 	default:
84 		printf("Unknown Vendor ");
85 		break;
86 	}
87 
88 	switch (info->flash_id & FLASH_TYPEMASK) {
89 	case FLASH_SST6401B:
90 		printf("SST39VF6401B\n");
91 		break;
92 	default:
93 		printf("Unknown Chip Type\n");
94 		return;
95 	}
96 
97 	if (info->size > 0x100000) {
98 		int remainder;
99 
100 		printf("  Size: %ld", info->size >> 20);
101 
102 		remainder = (info->size % 0x100000);
103 		if (remainder) {
104 			remainder >>= 10;
105 			remainder = (int)((float)
106 					  (((float)remainder / (float)1024) *
107 					   10000));
108 			printf(".%d ", remainder);
109 		}
110 
111 		printf("MB in %d Sectors\n", info->sector_count);
112 	} else
113 		printf("  Size: %ld KB in %d Sectors\n",
114 		       info->size >> 10, info->sector_count);
115 
116 	printf("  Sector Start Addresses:");
117 	for (i = 0; i < info->sector_count; ++i) {
118 		if ((i % 5) == 0)
119 			printf("\n   ");
120 		printf(" %08lX%s",
121 		       info->start[i], info->protect[i] ? " (RO)" : "     ");
122 	}
123 	printf("\n");
124 }
125 
126 /*
127  * The following code cannot be run from FLASH!
128  */
129 ulong flash_get_size(FPWV * addr, flash_info_t * info)
130 {
131 	u16 value;
132 
133 	addr[FLASH_CYCLE1] = (FPWV) 0x00AA00AA;	/* for Atmel, Intel ignores this */
134 	addr[FLASH_CYCLE2] = (FPWV) 0x00550055;	/* for Atmel, Intel ignores this */
135 	addr[FLASH_CYCLE1] = (FPWV) 0x00900090;	/* selects Intel or Atmel */
136 
137 	switch (addr[0] & 0xffff) {
138 	case (u8) SST_MANUFACT:
139 		info->flash_id = FLASH_MAN_SST;
140 		value = addr[1];
141 		break;
142 	default:
143 		printf("Unknown Flash\n");
144 		info->flash_id = FLASH_UNKNOWN;
145 		info->sector_count = 0;
146 		info->size = 0;
147 
148 		*addr = (FPW) 0x00F000F0;
149 		return (0);	/* no or unknown flash  */
150 	}
151 
152 	switch (value) {
153 	case (u16) SST_ID_xF6401B:
154 		info->flash_id += FLASH_SST6401B;
155 		break;
156 	default:
157 		info->flash_id = FLASH_UNKNOWN;
158 		break;
159 	}
160 
161 	info->sector_count = 0;
162 	info->size = 0;
163 	info->sector_count = CONFIG_SYS_SST_SECT;
164 	info->size = CONFIG_SYS_SST_SECT * CONFIG_SYS_SST_SECTSZ;
165 
166 	/* reset ID mode */
167 	*addr = (FPWV) 0x00F000F0;
168 
169 	if (info->sector_count > CONFIG_SYS_MAX_FLASH_SECT) {
170 		printf("** ERROR: sector count %d > max (%d) **\n",
171 		       info->sector_count, CONFIG_SYS_MAX_FLASH_SECT);
172 		info->sector_count = CONFIG_SYS_MAX_FLASH_SECT;
173 	}
174 
175 	return (info->size);
176 }
177 
178 int flash_erase(flash_info_t * info, int s_first, int s_last)
179 {
180 	FPWV *addr;
181 	int flag, prot, sect, count;
182 	ulong type, start;
183 	int rcode = 0, flashtype = 0;
184 
185 	if ((s_first < 0) || (s_first > s_last)) {
186 		if (info->flash_id == FLASH_UNKNOWN)
187 			printf("- missing\n");
188 		else
189 			printf("- no sectors to erase\n");
190 		return 1;
191 	}
192 
193 	type = (info->flash_id & FLASH_VENDMASK);
194 
195 	switch (type) {
196 	case FLASH_MAN_SST:
197 		flashtype = 1;
198 		break;
199 	default:
200 		type = (info->flash_id & FLASH_VENDMASK);
201 		printf("Can't erase unknown flash type %08lx - aborted\n",
202 		       info->flash_id);
203 		return 1;
204 	}
205 
206 	prot = 0;
207 	for (sect = s_first; sect <= s_last; ++sect) {
208 		if (info->protect[sect]) {
209 			prot++;
210 		}
211 	}
212 
213 	if (prot)
214 		printf("- Warning: %d protected sectors will not be erased!\n",
215 		       prot);
216 	else
217 		printf("\n");
218 
219 	flag = disable_interrupts();
220 
221 	start = get_timer(0);
222 
223 	if ((s_last - s_first) == (CONFIG_SYS_SST_SECT - 1)) {
224 		if (prot == 0) {
225 			addr = (FPWV *) info->start[0];
226 
227 			addr[FLASH_CYCLE1] = 0x00AA;	/* unlock */
228 			addr[FLASH_CYCLE2] = 0x0055;	/* unlock */
229 			addr[FLASH_CYCLE1] = 0x0080;	/* erase mode */
230 			addr[FLASH_CYCLE1] = 0x00AA;	/* unlock */
231 			addr[FLASH_CYCLE2] = 0x0055;	/* unlock */
232 			*addr = 0x0030;	/* erase chip */
233 
234 			count = 0;
235 			start = get_timer(0);
236 
237 			while ((*addr & 0x0080) != 0x0080) {
238 				if (count++ > 0x10000) {
239 					spin_wheel();
240 					count = 0;
241 				}
242 
243 				if (get_timer(start) > CONFIG_SYS_FLASH_ERASE_TOUT) {
244 					printf("Timeout\n");
245 					*addr = 0x00F0;	/* reset to read mode */
246 
247 					return 1;
248 				}
249 			}
250 
251 			*addr = 0x00F0;	/* reset to read mode */
252 
253 			printf("\b. done\n");
254 
255 			if (flag)
256 				enable_interrupts();
257 
258 			return 0;
259 		} else if (prot == CONFIG_SYS_SST_SECT) {
260 			return 1;
261 		}
262 	}
263 
264 	/* Start erase on unprotected sectors */
265 	for (sect = s_first; sect <= s_last; sect++) {
266 		if (info->protect[sect] == 0) {	/* not protected */
267 
268 			addr = (FPWV *) (info->start[sect]);
269 
270 			printf(".");
271 
272 			/* arm simple, non interrupt dependent timer */
273 			start = get_timer(0);
274 
275 			switch (flashtype) {
276 			case 1:
277 				{
278 					FPWV *base;	/* first address in bank */
279 
280 					flag = disable_interrupts();
281 
282 					base = (FPWV *) (CONFIG_SYS_FLASH_BASE);	/* First sector */
283 
284 					base[FLASH_CYCLE1] = 0x00AA;	/* unlock */
285 					base[FLASH_CYCLE2] = 0x0055;	/* unlock */
286 					base[FLASH_CYCLE1] = 0x0080;	/* erase mode */
287 					base[FLASH_CYCLE1] = 0x00AA;	/* unlock */
288 					base[FLASH_CYCLE2] = 0x0055;	/* unlock */
289 					*addr = 0x0050;	/* erase sector */
290 
291 					if (flag)
292 						enable_interrupts();
293 
294 					while ((*addr & 0x0080) != 0x0080) {
295 						if (get_timer(start) >
296 						    CONFIG_SYS_FLASH_ERASE_TOUT) {
297 							printf("Timeout\n");
298 							*addr = 0x00F0;	/* reset to read mode */
299 
300 							rcode = 1;
301 							break;
302 						}
303 					}
304 
305 					*addr = 0x00F0;	/* reset to read mode */
306 					break;
307 				}
308 			}	/* switch (flashtype) */
309 		}
310 	}
311 	printf(" done\n");
312 
313 	if (flag)
314 		enable_interrupts();
315 
316 	return rcode;
317 }
318 
319 int write_buff(flash_info_t * info, uchar * src, ulong addr, ulong cnt)
320 {
321 	ulong wp, count;
322 	u16 data;
323 	int rc;
324 
325 	if (info->flash_id == FLASH_UNKNOWN)
326 		return 4;
327 
328 	/* get lower word aligned address */
329 	wp = addr;
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