blob: 0377c8970c5e6db8e1531d422f36988f8d5164d2 [file] [log] [blame]
wdenk3bac3512003-03-12 10:41:04 +00001/*
2**=====================================================================
3**
4** Copyright (C) 2000, 2001, 2002, 2003
5** The LEOX team <team@leox.org>, http://www.leox.org
6**
7** LEOX.org is about the development of free hardware and software resources
8** for system on chip.
9**
10** Description: U-Boot port on the LEOX's ELPT860 CPU board
11** ~~~~~~~~~~~
12**
13**=====================================================================
14**
Wolfgang Denk1a459662013-07-08 09:37:19 +020015 * SPDX-License-Identifier: GPL-2.0+
wdenk3bac3512003-03-12 10:41:04 +000016**
17**=====================================================================
18*/
19
20/*
21** Note 1: In this file, you have to provide the following variable:
22** ------
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020023** flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS]
wdenk3bac3512003-03-12 10:41:04 +000024** 'flash_info_t' structure is defined into 'include/flash.h'
25** and defined as extern into 'common/cmd_flash.c'
26**
27** Note 2: In this file, you have to provide the following functions:
28** ------
29** unsigned long flash_init(void)
30** called from 'board_init_r()' into 'common/board.c'
31**
32** void flash_print_info(flash_info_t *info)
33** called from 'do_flinfo()' into 'common/cmd_flash.c'
34**
35** int flash_erase(flash_info_t *info,
36** int s_first,
37** int s_last)
38** called from 'do_flerase()' & 'flash_sect_erase()' into 'common/cmd_flash.c'
39**
40** int write_buff (flash_info_t *info,
41** uchar *src,
42** ulong addr,
43** ulong cnt)
44** called from 'flash_write()' into 'common/cmd_flash.c'
45*/
46
47#include <common.h>
48#include <mpc8xx.h>
49
50
Jean-Christophe PLAGNIOL-VILLARD0e8d1582008-09-10 22:48:06 +020051#ifndef CONFIG_ENV_ADDR
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020052# define CONFIG_ENV_ADDR (CONFIG_SYS_FLASH_BASE + CONFIG_ENV_OFFSET)
wdenk3bac3512003-03-12 10:41:04 +000053#endif
54
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020055flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; /* info for FLASH chips */
wdenk3bac3512003-03-12 10:41:04 +000056
57/*-----------------------------------------------------------------------
58 * Internal Functions
59 */
60static void flash_get_offsets (ulong base, flash_info_t *info);
61static ulong flash_get_size (volatile unsigned char *addr, flash_info_t *info);
62
63static int write_word (flash_info_t *info, ulong dest, ulong data);
64static int write_byte (flash_info_t *info, ulong dest, uchar data);
65
66/*-----------------------------------------------------------------------
67 */
68
wdenk8bde7f72003-06-27 21:31:46 +000069unsigned long
wdenk3bac3512003-03-12 10:41:04 +000070flash_init (void)
71{
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020072 volatile immap_t *immap = (immap_t *)CONFIG_SYS_IMMR;
wdenk3bac3512003-03-12 10:41:04 +000073 volatile memctl8xx_t *memctl = &immap->im_memctl;
74 unsigned long size_b0;
75 int i;
wdenk8bde7f72003-06-27 21:31:46 +000076
wdenk3bac3512003-03-12 10:41:04 +000077 /* Init: no FLASHes known */
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020078 for (i=0; i<CONFIG_SYS_MAX_FLASH_BANKS; ++i)
wdenk3bac3512003-03-12 10:41:04 +000079 {
80 flash_info[i].flash_id = FLASH_UNKNOWN;
81 }
wdenk8bde7f72003-06-27 21:31:46 +000082
wdenk3bac3512003-03-12 10:41:04 +000083 /* Static FLASH Bank configuration here - FIXME XXX */
wdenk8bde7f72003-06-27 21:31:46 +000084
85 size_b0 = flash_get_size ((volatile unsigned char *)FLASH_BASE0_PRELIM,
wdenk3bac3512003-03-12 10:41:04 +000086 &flash_info[0]);
wdenk8bde7f72003-06-27 21:31:46 +000087
88 if ( flash_info[0].flash_id == FLASH_UNKNOWN )
wdenk3bac3512003-03-12 10:41:04 +000089 {
90 printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
91 size_b0, size_b0<<20);
92 }
wdenk8bde7f72003-06-27 21:31:46 +000093
wdenk3bac3512003-03-12 10:41:04 +000094 /* Remap FLASH according to real size */
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020095 memctl->memc_or0 = CONFIG_SYS_OR_TIMING_FLASH | (-size_b0 & OR_AM_MSK);
96 memctl->memc_br0 = (CONFIG_SYS_FLASH_BASE & BR_BA_MSK) | BR_MS_GPCM | BR_PS_8 | BR_V;
wdenk8bde7f72003-06-27 21:31:46 +000097
wdenk3bac3512003-03-12 10:41:04 +000098 /* Re-do sizing to get full correct info */
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020099 size_b0 = flash_get_size ((volatile unsigned char *)CONFIG_SYS_FLASH_BASE,
wdenk3bac3512003-03-12 10:41:04 +0000100 &flash_info[0]);
wdenk8bde7f72003-06-27 21:31:46 +0000101
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200102 flash_get_offsets (CONFIG_SYS_FLASH_BASE, &flash_info[0]);
wdenk8bde7f72003-06-27 21:31:46 +0000103
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200104#if CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE
wdenk3bac3512003-03-12 10:41:04 +0000105 /* monitor protection ON by default */
106 flash_protect (FLAG_PROTECT_SET,
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200107 CONFIG_SYS_MONITOR_BASE,
108 CONFIG_SYS_MONITOR_BASE + monitor_flash_len-1,
wdenk3bac3512003-03-12 10:41:04 +0000109 &flash_info[0]);
110#endif
wdenk8bde7f72003-06-27 21:31:46 +0000111
Jean-Christophe PLAGNIOL-VILLARD5a1aceb2008-09-10 22:48:04 +0200112#ifdef CONFIG_ENV_IS_IN_FLASH
wdenk3bac3512003-03-12 10:41:04 +0000113 /* ENV protection ON by default */
114 flash_protect(FLAG_PROTECT_SET,
Jean-Christophe PLAGNIOL-VILLARD0e8d1582008-09-10 22:48:06 +0200115 CONFIG_ENV_ADDR,
116 CONFIG_ENV_ADDR + CONFIG_ENV_SIZE-1,
wdenk3bac3512003-03-12 10:41:04 +0000117 &flash_info[0]);
118#endif
119
120 flash_info[0].size = size_b0;
wdenk8bde7f72003-06-27 21:31:46 +0000121
wdenk3bac3512003-03-12 10:41:04 +0000122 return (size_b0);
123}
124
125/*-----------------------------------------------------------------------
126 */
wdenk8bde7f72003-06-27 21:31:46 +0000127static void
128flash_get_offsets (ulong base,
wdenk3bac3512003-03-12 10:41:04 +0000129 flash_info_t *info)
130{
131 int i;
132
133#define SECTOR_64KB 0x00010000
134
135 /* set up sector start adress table */
wdenk8bde7f72003-06-27 21:31:46 +0000136 for (i = 0; i < info->sector_count; i++)
wdenk3bac3512003-03-12 10:41:04 +0000137 {
138 info->start[i] = base + (i * SECTOR_64KB);
139 }
140}
141
142/*-----------------------------------------------------------------------
143 */
wdenk8bde7f72003-06-27 21:31:46 +0000144void
wdenk3bac3512003-03-12 10:41:04 +0000145flash_print_info (flash_info_t *info)
146{
147 int i;
wdenk8bde7f72003-06-27 21:31:46 +0000148
149 if ( info->flash_id == FLASH_UNKNOWN )
wdenk3bac3512003-03-12 10:41:04 +0000150 {
151 printf ("missing or unknown FLASH type\n");
152 return;
153 }
154
wdenk8bde7f72003-06-27 21:31:46 +0000155 switch ( info->flash_id & FLASH_VENDMASK )
wdenk3bac3512003-03-12 10:41:04 +0000156 {
157 case FLASH_MAN_AMD: printf ("AMD "); break;
158 case FLASH_MAN_FUJ: printf ("FUJITSU "); break;
159 case FLASH_MAN_STM: printf ("STM (Thomson) "); break;
160 default: printf ("Unknown Vendor "); break;
161 }
wdenk8bde7f72003-06-27 21:31:46 +0000162
163 switch ( info->flash_id & FLASH_TYPEMASK )
wdenk3bac3512003-03-12 10:41:04 +0000164 {
165 case FLASH_AM040: printf ("AM29F040 (4 Mbits)\n");
166 break;
167 default: printf ("Unknown Chip Type\n");
168 break;
169 }
wdenk8bde7f72003-06-27 21:31:46 +0000170
171 printf (" Size: %ld KB in %d Sectors\n",
wdenk3bac3512003-03-12 10:41:04 +0000172 info->size >> 10, info->sector_count);
wdenk8bde7f72003-06-27 21:31:46 +0000173
wdenk3bac3512003-03-12 10:41:04 +0000174 printf (" Sector Start Addresses:");
wdenk8bde7f72003-06-27 21:31:46 +0000175 for (i=0; i<info->sector_count; ++i)
wdenk3bac3512003-03-12 10:41:04 +0000176 {
177 if ((i % 5) == 0)
178 printf ("\n ");
179 printf (" %08lX%s",
180 info->start[i],
181 info->protect[i] ? " (RO)" : " "
182 );
183 }
184 printf ("\n");
185
186 return;
187}
188
189/*-----------------------------------------------------------------------
190 */
191
192
193/*-----------------------------------------------------------------------
194 */
195
196/*
197 * The following code cannot be run from FLASH!
198 */
199
wdenk8bde7f72003-06-27 21:31:46 +0000200static ulong
201flash_get_size (volatile unsigned char *addr,
202 flash_info_t *info)
wdenk3bac3512003-03-12 10:41:04 +0000203{
204 short i;
205 uchar value;
206 ulong base = (ulong)addr;
207
208 /* Write auto select command: read Manufacturer ID */
209 addr[0x0555] = 0xAA;
210 addr[0x02AA] = 0x55;
211 addr[0x0555] = 0x90;
wdenk8bde7f72003-06-27 21:31:46 +0000212
wdenk3bac3512003-03-12 10:41:04 +0000213 value = addr[0];
214
wdenk8bde7f72003-06-27 21:31:46 +0000215 switch ( value )
wdenk3bac3512003-03-12 10:41:04 +0000216 {
217 /* case AMD_MANUFACT: */
218 case 0x01:
219 info->flash_id = FLASH_MAN_AMD;
220 break;
221 /* case FUJ_MANUFACT: */
222 case 0x04:
223 info->flash_id = FLASH_MAN_FUJ;
224 break;
225 /* case STM_MANUFACT: */
226 case 0x20:
227 info->flash_id = FLASH_MAN_STM;
228 break;
229
230 default:
231 info->flash_id = FLASH_UNKNOWN;
232 info->sector_count = 0;
233 info->size = 0;
234 return (0); /* no or unknown flash */
235 }
wdenk8bde7f72003-06-27 21:31:46 +0000236
wdenk3bac3512003-03-12 10:41:04 +0000237 value = addr[1]; /* device ID */
wdenk8bde7f72003-06-27 21:31:46 +0000238
239 switch ( value )
wdenk3bac3512003-03-12 10:41:04 +0000240 {
241 case STM_ID_F040B:
242 case AMD_ID_F040B:
243 info->flash_id += FLASH_AM040; /* 4 Mbits = 512k * 8 */
244 info->sector_count = 8;
245 info->size = 0x00080000;
246 break;
247
248 default:
249 info->flash_id = FLASH_UNKNOWN;
250 return (0); /* => no or unknown flash */
251 }
252
253 /* set up sector start adress table */
wdenk8bde7f72003-06-27 21:31:46 +0000254 for (i = 0; i < info->sector_count; i++)
wdenk3bac3512003-03-12 10:41:04 +0000255 {
256 info->start[i] = base + (i * 0x00010000);
257 }
wdenk8bde7f72003-06-27 21:31:46 +0000258
wdenk3bac3512003-03-12 10:41:04 +0000259 /* check for protected sectors */
wdenk8bde7f72003-06-27 21:31:46 +0000260 for (i = 0; i < info->sector_count; i++)
wdenk3bac3512003-03-12 10:41:04 +0000261 {
262 /* read sector protection at sector address, (A7 .. A0) = 0x02 */
263 /* D0 = 1 if protected */
264 addr = (volatile unsigned char *)(info->start[i]);
265 info->protect[i] = addr[2] & 1;
266 }
267
268 /*
269 * Prevent writes to uninitialized FLASH.
270 */
wdenk8bde7f72003-06-27 21:31:46 +0000271 if ( info->flash_id != FLASH_UNKNOWN )
wdenk3bac3512003-03-12 10:41:04 +0000272 {
273 addr = (volatile unsigned char *)info->start[0];
wdenk8bde7f72003-06-27 21:31:46 +0000274
wdenk3bac3512003-03-12 10:41:04 +0000275 *addr = 0xF0; /* reset bank */
276 }
wdenk8bde7f72003-06-27 21:31:46 +0000277
wdenk3bac3512003-03-12 10:41:04 +0000278 return (info->size);
279}
280
281
282/*-----------------------------------------------------------------------
283 */
284
285int
wdenk8bde7f72003-06-27 21:31:46 +0000286flash_erase (flash_info_t *info,
287 int s_first,
wdenk3bac3512003-03-12 10:41:04 +0000288 int s_last)
289{
290 volatile unsigned char *addr = (volatile unsigned char *)(info->start[0]);
291 int flag, prot, sect, l_sect;
292 ulong start, now, last;
wdenk8bde7f72003-06-27 21:31:46 +0000293
294 if ( (s_first < 0) || (s_first > s_last) )
wdenk3bac3512003-03-12 10:41:04 +0000295 {
wdenk8bde7f72003-06-27 21:31:46 +0000296 if ( info->flash_id == FLASH_UNKNOWN )
wdenk3bac3512003-03-12 10:41:04 +0000297 {
298 printf ("- missing\n");
wdenk8bde7f72003-06-27 21:31:46 +0000299 }
300 else
wdenk3bac3512003-03-12 10:41:04 +0000301 {
302 printf ("- no sectors to erase\n");
303 }
304 return ( 1 );
305 }
306
307 if ( (info->flash_id == FLASH_UNKNOWN) ||
wdenk8bde7f72003-06-27 21:31:46 +0000308 (info->flash_id > FLASH_AMD_COMP) )
wdenk3bac3512003-03-12 10:41:04 +0000309 {
310 printf ("Can't erase unknown flash type %08lx - aborted\n",
311 info->flash_id);
312 return ( 1 );
313 }
wdenk8bde7f72003-06-27 21:31:46 +0000314
wdenk3bac3512003-03-12 10:41:04 +0000315 prot = 0;
wdenk8bde7f72003-06-27 21:31:46 +0000316 for (sect=s_first; sect<=s_last; ++sect)
wdenk3bac3512003-03-12 10:41:04 +0000317 {
wdenk8bde7f72003-06-27 21:31:46 +0000318 if ( info->protect[sect] )
wdenk3bac3512003-03-12 10:41:04 +0000319 {
320 prot++;
321 }
322 }
wdenk8bde7f72003-06-27 21:31:46 +0000323
324 if ( prot )
wdenk3bac3512003-03-12 10:41:04 +0000325 {
326 printf ("- Warning: %d protected sectors will not be erased!\n", prot);
wdenk8bde7f72003-06-27 21:31:46 +0000327 }
328 else
wdenk3bac3512003-03-12 10:41:04 +0000329 {
330 printf ("\n");
331 }
wdenk8bde7f72003-06-27 21:31:46 +0000332
wdenk3bac3512003-03-12 10:41:04 +0000333 l_sect = -1;
wdenk8bde7f72003-06-27 21:31:46 +0000334
wdenk3bac3512003-03-12 10:41:04 +0000335 /* Disable interrupts which might cause a timeout here */
336 flag = disable_interrupts();
wdenk8bde7f72003-06-27 21:31:46 +0000337
wdenk3bac3512003-03-12 10:41:04 +0000338 addr[0x0555] = 0xAA;
339 addr[0x02AA] = 0x55;
340 addr[0x0555] = 0x80;
341 addr[0x0555] = 0xAA;
342 addr[0x02AA] = 0x55;
wdenk8bde7f72003-06-27 21:31:46 +0000343
wdenk3bac3512003-03-12 10:41:04 +0000344 /* Start erase on unprotected sectors */
wdenk8bde7f72003-06-27 21:31:46 +0000345 for (sect = s_first; sect<=s_last; sect++)
wdenk3bac3512003-03-12 10:41:04 +0000346 {
347 if (info->protect[sect] == 0) /* not protected */
348 {
349 addr = (volatile unsigned char *)(info->start[sect]);
350 addr[0] = 0x30;
351 l_sect = sect;
352 }
353 }
wdenk8bde7f72003-06-27 21:31:46 +0000354
wdenk3bac3512003-03-12 10:41:04 +0000355 /* re-enable interrupts if necessary */
356 if ( flag )
357 enable_interrupts();
wdenk8bde7f72003-06-27 21:31:46 +0000358
wdenk3bac3512003-03-12 10:41:04 +0000359 /* wait at least 80us - let's wait 1 ms */
360 udelay (1000);
wdenk8bde7f72003-06-27 21:31:46 +0000361
wdenk3bac3512003-03-12 10:41:04 +0000362 /*
363 * We wait for the last triggered sector
364 */
365 if ( l_sect < 0 )
366 goto DONE;
wdenk8bde7f72003-06-27 21:31:46 +0000367
wdenk3bac3512003-03-12 10:41:04 +0000368 start = get_timer (0);
369 last = start;
370 addr = (volatile unsigned char *)(info->start[l_sect]);
wdenk8bde7f72003-06-27 21:31:46 +0000371 while ( (addr[0] & 0x80) != 0x80 )
wdenk3bac3512003-03-12 10:41:04 +0000372 {
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200373 if ( (now = get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT )
wdenk3bac3512003-03-12 10:41:04 +0000374 {
375 printf ("Timeout\n");
376 return ( 1 );
377 }
378 /* show that we're waiting */
379 if ( (now - last) > 1000 ) /* every second */
380 {
381 putc ('.');
382 last = now;
383 }
384 }
wdenk8bde7f72003-06-27 21:31:46 +0000385
wdenk3bac3512003-03-12 10:41:04 +0000386DONE:
387 /* reset to read mode */
388 addr = (volatile unsigned char *)info->start[0];
389 addr[0] = 0xF0; /* reset bank */
wdenk8bde7f72003-06-27 21:31:46 +0000390
wdenk3bac3512003-03-12 10:41:04 +0000391 printf (" done\n");
wdenk8bde7f72003-06-27 21:31:46 +0000392
wdenk3bac3512003-03-12 10:41:04 +0000393 return ( 0 );
394}
395
396/*-----------------------------------------------------------------------
397 * Copy memory to flash, returns:
398 * 0 - OK
399 * 1 - write timeout
400 * 2 - Flash not erased
401 */
402
wdenk8bde7f72003-06-27 21:31:46 +0000403int
404write_buff (flash_info_t *info,
405 uchar *src,
406 ulong addr,
wdenk3bac3512003-03-12 10:41:04 +0000407 ulong cnt)
408{
409 ulong cp, wp, data;
410 uchar bdata;
411 int i, l, rc;
412
413 if ( (info->flash_id & FLASH_TYPEMASK) == FLASH_AM040 )
414 {
415 /* Width of the data bus: 8 bits */
416
417 wp = addr;
wdenk8bde7f72003-06-27 21:31:46 +0000418
wdenk3bac3512003-03-12 10:41:04 +0000419 while ( cnt )
420 {
421 bdata = *src++;
wdenk8bde7f72003-06-27 21:31:46 +0000422
wdenk3bac3512003-03-12 10:41:04 +0000423 if ( (rc = write_byte(info, wp, bdata)) != 0 )
424 {
425 return (rc);
426 }
wdenk8bde7f72003-06-27 21:31:46 +0000427
wdenk3bac3512003-03-12 10:41:04 +0000428 ++wp;
429 --cnt;
430 }
431
432 return ( 0 );
433 }
434 else
435 {
436 /* Width of the data bus: 32 bits */
437
438 wp = (addr & ~3); /* get lower word aligned address */
wdenk8bde7f72003-06-27 21:31:46 +0000439
wdenk3bac3512003-03-12 10:41:04 +0000440 /*
441 * handle unaligned start bytes
442 */
wdenk8bde7f72003-06-27 21:31:46 +0000443 if ( (l = addr - wp) != 0 )
wdenk3bac3512003-03-12 10:41:04 +0000444 {
445 data = 0;
wdenk8bde7f72003-06-27 21:31:46 +0000446 for (i=0, cp=wp; i<l; ++i, ++cp)
wdenk3bac3512003-03-12 10:41:04 +0000447 {
448 data = (data << 8) | (*(uchar *)cp);
449 }
wdenk8bde7f72003-06-27 21:31:46 +0000450 for (; i<4 && cnt>0; ++i)
wdenk3bac3512003-03-12 10:41:04 +0000451 {
452 data = (data << 8) | *src++;
453 --cnt;
454 ++cp;
455 }
wdenk8bde7f72003-06-27 21:31:46 +0000456 for (; cnt==0 && i<4; ++i, ++cp)
wdenk3bac3512003-03-12 10:41:04 +0000457 {
458 data = (data << 8) | (*(uchar *)cp);
459 }
wdenk8bde7f72003-06-27 21:31:46 +0000460
461 if ( (rc = write_word(info, wp, data)) != 0 )
wdenk3bac3512003-03-12 10:41:04 +0000462 {
463 return (rc);
464 }
465 wp += 4;
466 }
wdenk8bde7f72003-06-27 21:31:46 +0000467
wdenk3bac3512003-03-12 10:41:04 +0000468 /*
469 * handle word aligned part
470 */
wdenk8bde7f72003-06-27 21:31:46 +0000471 while ( cnt >= 4 )
wdenk3bac3512003-03-12 10:41:04 +0000472 {
473 data = 0;
wdenk8bde7f72003-06-27 21:31:46 +0000474 for (i=0; i<4; ++i)
wdenk3bac3512003-03-12 10:41:04 +0000475 {
476 data = (data << 8) | *src++;
477 }
wdenk8bde7f72003-06-27 21:31:46 +0000478 if ( (rc = write_word(info, wp, data)) != 0 )
wdenk3bac3512003-03-12 10:41:04 +0000479 {
480 return (rc);
481 }
482 wp += 4;
483 cnt -= 4;
484 }
wdenk8bde7f72003-06-27 21:31:46 +0000485
486 if ( cnt == 0 )
wdenk3bac3512003-03-12 10:41:04 +0000487 {
488 return (0);
489 }
wdenk8bde7f72003-06-27 21:31:46 +0000490
wdenk3bac3512003-03-12 10:41:04 +0000491 /*
492 * handle unaligned tail bytes
493 */
494 data = 0;
wdenk8bde7f72003-06-27 21:31:46 +0000495 for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp)
wdenk3bac3512003-03-12 10:41:04 +0000496 {
497 data = (data << 8) | *src++;
498 --cnt;
499 }
wdenk8bde7f72003-06-27 21:31:46 +0000500 for (; i<4; ++i, ++cp)
wdenk3bac3512003-03-12 10:41:04 +0000501 {
502 data = (data << 8) | (*(uchar *)cp);
503 }
wdenk8bde7f72003-06-27 21:31:46 +0000504
wdenk3bac3512003-03-12 10:41:04 +0000505 return (write_word(info, wp, data));
506 }
507}
508
509/*-----------------------------------------------------------------------
510 * Write a word to Flash, returns:
511 * 0 - OK
512 * 1 - write timeout
513 * 2 - Flash not erased
514 */
wdenk8bde7f72003-06-27 21:31:46 +0000515static int
516write_word (flash_info_t *info,
517 ulong dest,
wdenk3bac3512003-03-12 10:41:04 +0000518 ulong data)
519{
520 vu_long *addr = (vu_long*)(info->start[0]);
521 ulong start;
522 int flag;
wdenk8bde7f72003-06-27 21:31:46 +0000523
wdenk3bac3512003-03-12 10:41:04 +0000524 /* Check if Flash is (sufficiently) erased */
wdenk8bde7f72003-06-27 21:31:46 +0000525 if ( (*((vu_long *)dest) & data) != data )
wdenk3bac3512003-03-12 10:41:04 +0000526 {
527 return (2);
528 }
529 /* Disable interrupts which might cause a timeout here */
530 flag = disable_interrupts();
wdenk8bde7f72003-06-27 21:31:46 +0000531
wdenk3bac3512003-03-12 10:41:04 +0000532 addr[0x0555] = 0x00AA00AA;
533 addr[0x02AA] = 0x00550055;
534 addr[0x0555] = 0x00A000A0;
wdenk8bde7f72003-06-27 21:31:46 +0000535
wdenk3bac3512003-03-12 10:41:04 +0000536 *((vu_long *)dest) = data;
wdenk8bde7f72003-06-27 21:31:46 +0000537
wdenk3bac3512003-03-12 10:41:04 +0000538 /* re-enable interrupts if necessary */
539 if ( flag )
540 enable_interrupts();
541
542 /* data polling for D7 */
543 start = get_timer (0);
wdenk8bde7f72003-06-27 21:31:46 +0000544 while ( (*((vu_long *)dest) & 0x00800080) != (data & 0x00800080) )
wdenk3bac3512003-03-12 10:41:04 +0000545 {
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200546 if ( get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT )
wdenk3bac3512003-03-12 10:41:04 +0000547 {
548 return (1);
549 }
550 }
551
552 return (0);
553}
554
555/*-----------------------------------------------------------------------
556 * Write a byte to Flash, returns:
557 * 0 - OK
558 * 1 - write timeout
559 * 2 - Flash not erased
560 */
wdenk8bde7f72003-06-27 21:31:46 +0000561static int
562write_byte (flash_info_t *info,
563 ulong dest,
wdenk3bac3512003-03-12 10:41:04 +0000564 uchar data)
565{
566 volatile unsigned char *addr = (volatile unsigned char *)(info->start[0]);
567 ulong start;
568 int flag;
wdenk8bde7f72003-06-27 21:31:46 +0000569
wdenk3bac3512003-03-12 10:41:04 +0000570 /* Check if Flash is (sufficiently) erased */
wdenk8bde7f72003-06-27 21:31:46 +0000571 if ( (*((volatile unsigned char *)dest) & data) != data )
wdenk3bac3512003-03-12 10:41:04 +0000572 {
573 return (2);
574 }
575 /* Disable interrupts which might cause a timeout here */
576 flag = disable_interrupts();
wdenk8bde7f72003-06-27 21:31:46 +0000577
wdenk3bac3512003-03-12 10:41:04 +0000578 addr[0x0555] = 0xAA;
579 addr[0x02AA] = 0x55;
580 addr[0x0555] = 0xA0;
wdenk8bde7f72003-06-27 21:31:46 +0000581
wdenk3bac3512003-03-12 10:41:04 +0000582 *((volatile unsigned char *)dest) = data;
wdenk8bde7f72003-06-27 21:31:46 +0000583
wdenk3bac3512003-03-12 10:41:04 +0000584 /* re-enable interrupts if necessary */
585 if ( flag )
586 enable_interrupts();
587
588 /* data polling for D7 */
589 start = get_timer (0);
wdenk8bde7f72003-06-27 21:31:46 +0000590 while ( (*((volatile unsigned char *)dest) & 0x80) != (data & 0x80) )
wdenk3bac3512003-03-12 10:41:04 +0000591 {
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200592 if ( get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT )
wdenk3bac3512003-03-12 10:41:04 +0000593 {
594 return (1);
595 }
596 }
597
598 return (0);
599}
600
601/*-----------------------------------------------------------------------
602 */