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;
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 
221 	if ((s_last - s_first) == (CONFIG_SYS_SST_SECT - 1)) {
222 		if (prot == 0) {
223 			addr = (FPWV *) info->start[0];
224 
225 			addr[FLASH_CYCLE1] = 0x00AA;	/* unlock */
226 			addr[FLASH_CYCLE2] = 0x0055;	/* unlock */
227 			addr[FLASH_CYCLE1] = 0x0080;	/* erase mode */
228 			addr[FLASH_CYCLE1] = 0x00AA;	/* unlock */
229 			addr[FLASH_CYCLE2] = 0x0055;	/* unlock */
230 			*addr = 0x0030;	/* erase chip */
231 
232 			count = 0;
233 			start = get_timer(0);
234 
235 			while ((*addr & 0x0080) != 0x0080) {
236 				if (count++ > 0x10000) {
237 					spin_wheel();
238 					count = 0;
239 				}
240 
241 				if (get_timer(start) > CONFIG_SYS_FLASH_ERASE_TOUT) {
242 					printf("Timeout\n");
243 					*addr = 0x00F0;	/* reset to read mode */
244 
245 					return 1;
246 				}
247 			}
248 
249 			*addr = 0x00F0;	/* reset to read mode */
250 
251 			printf("\b. done\n");
252 
253 			if (flag)
254 				enable_interrupts();
255 
256 			return 0;
257 		} else if (prot == CONFIG_SYS_SST_SECT) {
258 			return 1;
259 		}
260 	}
261 
262 	/* Start erase on unprotected sectors */
263 	for (sect = s_first; sect <= s_last; sect++) {
264 		if (info->protect[sect] == 0) {	/* not protected */
265 
266 			addr = (FPWV *) (info->start[sect]);
267 
268 			printf(".");
269 
270 			/* arm simple, non interrupt dependent timer */
271 			start = get_timer(0);
272 
273 			switch (flashtype) {
274 			case 1:
275 				{
276 					FPWV *base;	/* first address in bank */
277 
278 					flag = disable_interrupts();
279 
280 					base = (FPWV *) (CONFIG_SYS_FLASH_BASE);	/* First sector */
281 
282 					base[FLASH_CYCLE1] = 0x00AA;	/* unlock */
283 					base[FLASH_CYCLE2] = 0x0055;	/* unlock */
284 					base[FLASH_CYCLE1] = 0x0080;	/* erase mode */
285 					base[FLASH_CYCLE1] = 0x00AA;	/* unlock */
286 					base[FLASH_CYCLE2] = 0x0055;	/* unlock */
287 					*addr = 0x0050;	/* erase sector */
288 
289 					if (flag)
290 						enable_interrupts();
291 
292 					while ((*addr & 0x0080) != 0x0080) {
293 						if (get_timer(start) >
294 						    CONFIG_SYS_FLASH_ERASE_TOUT) {
295 							printf("Timeout\n");
296 							*addr = 0x00F0;	/* reset to read mode */
297 
298 							rcode = 1;
299 							break;
300 						}
301 					}
302 
303 					*addr = 0x00F0;	/* reset to read mode */
304 					break;
305 				}
306 			}	/* switch (flashtype) */
307 		}
308 	}
309 	printf(" done\n");
310 
311 	if (flag)
312 		enable_interrupts();
313 
314 	return rcode;
315 }
316 
317 int write_buff(flash_info_t * info, uchar * src, ulong addr, ulong cnt)
318 {
319 	ulong wp, count;
320 	u16 data;
321 	int rc;
322 
323 	if (info->flash_id == FLASH_UNKNOWN)
324 		return 4;
325 
326 	/* get lower word aligned address */
327 	wp = addr;
328 
329 	/* handle unaligned start bytes */
330 	if (wp & 1) {
331 		data = *((FPWV *) wp);
332 		data = (data << 8) | *src;
333 
334 		if ((rc = write_word(info, (FPWV *) wp, data)) != 0)
335 			return (rc);
336 
337 		wp++;
338 		cnt -= 1;
339 		src++;
340 	}
341 
342 	while (cnt >= 2) {
343 		/*
344 		 * handle word aligned part
345 		 */
346 		count = 0;
347 		data = *((FPWV *) src);
348 
349 		if ((rc = write_word(info, (FPWV *) wp, data)) != 0)
350 			return (rc);
351 
352 		wp += 2;
353 		src += 2;
354 		cnt -= 2;
355 
356 		if (count++ > 0x800) {
357 			spin_wheel();
358 			count = 0;
359 		}
360 	}
361 	/* handle word aligned part */
362 	if (cnt) {
363 		/* handle word aligned part */
364 		count = 0;
365 		data = *((FPWV *) wp);
366 
367 		data = (data & 0x00FF) | (*src << 8);
368 
369 		if ((rc = write_word(info, (FPWV *) wp, data)) != 0)
370 			return (rc);
371 
372 		wp++;
373 		src++;
374 		cnt -= 1;
375 		if (count++ > 0x800) {
376 			spin_wheel();
377 			count = 0;
378 		}
379 	}
380 
381 	if (cnt == 0)
382 		return ERR_OK;
383 
384 	return ERR_OK;
385 }
386 
387 /*-----------------------------------------------------------------------
388  * Write a word to Flash
389  * A word is 16 bits, whichever the bus width of the flash bank
390  * (not an individual chip) is.
391  *
392  * returns:
393  * 0 - OK
394  * 1 - write timeout
395  * 2 - Flash not erased
396  */
397 int write_word(flash_info_t * info, FPWV * dest, u16 data)
398 {
399 	ulong start;
400 	int flag;
401 	int res = 0;		/* result, assume success */
402 	FPWV *base;		/* first address in flash bank */
403 
404 	/* Check if Flash is (sufficiently) erased */
405 	if ((*dest & (u8) data) != (u8) data) {
406 		return (2);
407 	}
408 
409 	base = (FPWV *) (CONFIG_SYS_FLASH_BASE);
410 
411 	/* Disable interrupts which might cause a timeout here */
412 	flag = disable_interrupts();
413 
414 	base[FLASH_CYCLE1] = (u8) 0x00AA00AA;	/* unlock */
415 	base[FLASH_CYCLE2] = (u8) 0x00550055;	/* unlock */
416 	base[FLASH_CYCLE1] = (u8) 0x00A000A0;	/* selects program mode */
417 
418 	*dest = data;		/* start programming the data */
419 
420 	/* re-enable interrupts if necessary */
421 	if (flag)
422 		enable_interrupts();
423 
424 	start = get_timer(0);
425 
426 	/* data polling for D7 */
427 	while (res == 0
428 	       && (*dest & (u8) 0x00800080) != (data & (u8) 0x00800080)) {
429 		if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
430 			*dest = (u8) 0x00F000F0;	/* reset bank */
431 			res = 1;
432 		}
433 	}
434 
435 	*dest++ = (u8) 0x00F000F0;	/* reset bank */
436 
437 	return (res);
438 }
439 
440 void inline spin_wheel(void)
441 {
442 	static int p = 0;
443 	static char w[] = "\\/-";
444 
445 	printf("\010%c", w[p]);
446 	(++p == 3) ? (p = 0) : 0;
447 }
448 
449 #endif
450