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