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