blob: ca1ed3d62da08753be2d984c929833572aa1ce70 [file] [log] [blame]
wdenkc6097192002-11-03 00:24:07 +00001/*
2 * (C) Copyright 2001
3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4 * Keith Outwater, keith_outwater@mvsi.com
5 *
Wolfgang Denk1a459662013-07-08 09:37:19 +02006 * SPDX-License-Identifier: GPL-2.0+
wdenkc6097192002-11-03 00:24:07 +00007 */
8
9#include <common.h>
10#include <mpc8xx.h>
11
Jean-Christophe PLAGNIOL-VILLARD5a1aceb2008-09-10 22:48:04 +020012#if defined(CONFIG_ENV_IS_IN_FLASH)
Jean-Christophe PLAGNIOL-VILLARD0e8d1582008-09-10 22:48:06 +020013# ifndef CONFIG_ENV_ADDR
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020014# define CONFIG_ENV_ADDR (CONFIG_SYS_FLASH_BASE + CONFIG_ENV_OFFSET)
wdenkc6097192002-11-03 00:24:07 +000015# endif
Jean-Christophe PLAGNIOL-VILLARD0e8d1582008-09-10 22:48:06 +020016# ifndef CONFIG_ENV_SIZE
17# define CONFIG_ENV_SIZE CONFIG_ENV_SECT_SIZE
wdenkc6097192002-11-03 00:24:07 +000018# endif
Jean-Christophe PLAGNIOL-VILLARD0e8d1582008-09-10 22:48:06 +020019# ifndef CONFIG_ENV_SECT_SIZE
20# define CONFIG_ENV_SECT_SIZE CONFIG_ENV_SIZE
wdenkc6097192002-11-03 00:24:07 +000021# endif
22#endif
23
24/*
25 * Use buffered writes to flash by default - they are about 32x faster than
26 * single byte writes.
27 */
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020028#ifndef CONFIG_SYS_GEN860T_FLASH_USE_WRITE_BUFFER
29#define CONFIG_SYS_GEN860T_FLASH_USE_WRITE_BUFFER
wdenkc6097192002-11-03 00:24:07 +000030#endif
31
32/*
33 * Max time to wait (in mS) for flash device to allocate a write buffer.
34 */
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020035#ifndef CONFIG_SYS_FLASH_ALLOC_BUFFER_TOUT
36#define CONFIG_SYS_FLASH_ALLOC_BUFFER_TOUT 100
wdenkc6097192002-11-03 00:24:07 +000037#endif
38
39/*
40 * These functions support a single Intel StrataFlash device (28F128J3A)
41 * in byte mode only!. The flash routines are very basic and simple
42 * since there isn't really any remapping necessary.
43 */
44
45/*
46 * Intel SCS (Scalable Command Set) command definitions
47 * (taken from 28F128J3A datasheet)
48 */
49#define SCS_READ_CMD 0xff
50#define SCS_READ_ID_CMD 0x90
51#define SCS_QUERY_CMD 0x98
52#define SCS_READ_STATUS_CMD 0x70
53#define SCS_CLEAR_STATUS_CMD 0x50
54#define SCS_WRITE_BUF_CMD 0xe8
55#define SCS_PROGRAM_CMD 0x40
56#define SCS_BLOCK_ERASE_CMD 0x20
57#define SCS_BLOCK_ERASE_RESUME_CMD 0xd0
58#define SCS_PROGRAM_RESUME_CMD 0xd0
59#define SCS_BLOCK_ERASE_SUSPEND_CMD 0xb0
60#define SCS_SET_BLOCK_LOCK_CMD 0x60
61#define SCS_CLR_BLOCK_LOCK_CMD 0x60
62
63/*
64 * SCS status/extended status register bit definitions
65 */
66#define SCS_SR7 0x80
67#define SCS_XSR7 0x80
68
69/*---------------------------------------------------------------------*/
70#if 0
71#define DEBUG_FLASH
72#endif
73
74#ifdef DEBUG_FLASH
75#define PRINTF(fmt,args...) printf(fmt ,##args)
76#else
77#define PRINTF(fmt,args...)
78#endif
79/*---------------------------------------------------------------------*/
80
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020081flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS];
wdenkc6097192002-11-03 00:24:07 +000082
83/*-----------------------------------------------------------------------
84 * Functions
85 */
86static ulong flash_get_size (vu_char *addr, flash_info_t *info);
87static int write_data8 (flash_info_t *info, ulong dest, uchar data);
88static void flash_get_offsets (ulong base, flash_info_t *info);
89
90/*-----------------------------------------------------------------------
91 * Initialize the flash memory.
92 */
93unsigned long
94flash_init (void)
95{
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020096 volatile immap_t *immap = (immap_t *)CONFIG_SYS_IMMR;
wdenkc6097192002-11-03 00:24:07 +000097 volatile memctl8xx_t *memctl = &immap->im_memctl;
98 unsigned long size_b0;
99 int i;
100
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200101 for (i= 0; i < CONFIG_SYS_MAX_FLASH_BANKS; ++i) {
wdenkc6097192002-11-03 00:24:07 +0000102 flash_info[i].flash_id = FLASH_UNKNOWN;
103 }
104
105 /*
106 * The gen860t board only has one FLASH memory device, so the
107 * FLASH Bank configuration is done statically.
108 */
109 PRINTF("\n## Get flash bank 1 size @ 0x%08x\n", FLASH_BASE0_PRELIM);
110 size_b0 = flash_get_size((vu_char *)FLASH_BASE0_PRELIM, &flash_info[0]);
111 if (flash_info[0].flash_id == FLASH_UNKNOWN) {
112 printf ("## Unknown FLASH on Bank 0: "
113 "ID 0x%lx, Size = 0x%08lx = %ld MB\n",
114 flash_info[0].flash_id,size_b0, size_b0 << 20);
115 }
116
117 PRINTF("## Before remap:\n"
118 " BR0: 0x%08x OR0: 0x%08x\n BR1: 0x%08x OR1: 0x%08x\n",
119 memctl->memc_br0, memctl->memc_or0,
120 memctl->memc_br1, memctl->memc_or1);
121
122 /*
123 * Remap FLASH according to real size
124 */
125 memctl->memc_or0 |= (-size_b0 & 0xFFFF8000);
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200126 memctl->memc_br0 |= (CONFIG_SYS_FLASH_BASE & BR_BA_MSK);
wdenkc6097192002-11-03 00:24:07 +0000127
128 PRINTF("## After remap:\n"
129 " BR0: 0x%08x OR0: 0x%08x\n", memctl->memc_br0, memctl->memc_or0);
130
131 /*
132 * Re-do sizing to get full correct info
133 */
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200134 size_b0 = flash_get_size ((vu_char *)CONFIG_SYS_FLASH_BASE, &flash_info[0]);
135 flash_get_offsets (CONFIG_SYS_FLASH_BASE, &flash_info[0]);
wdenkc6097192002-11-03 00:24:07 +0000136 flash_info[0].size = size_b0;
137
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200138#if CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE
wdenkc6097192002-11-03 00:24:07 +0000139 /*
140 * Monitor protection is ON by default
141 */
142 flash_protect(FLAG_PROTECT_SET,
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200143 CONFIG_SYS_MONITOR_BASE,
144 CONFIG_SYS_MONITOR_BASE + monitor_flash_len - 1,
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200145 &flash_info[0]);
wdenkc6097192002-11-03 00:24:07 +0000146#endif
147
Jean-Christophe PLAGNIOL-VILLARD5a1aceb2008-09-10 22:48:04 +0200148#ifdef CONFIG_ENV_IS_IN_FLASH
wdenkc6097192002-11-03 00:24:07 +0000149 /*
150 * Environment protection ON by default
151 */
152 flash_protect(FLAG_PROTECT_SET,
Jean-Christophe PLAGNIOL-VILLARD0e8d1582008-09-10 22:48:06 +0200153 CONFIG_ENV_ADDR,
154 CONFIG_ENV_ADDR + CONFIG_ENV_SECT_SIZE - 1,
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200155 &flash_info[0]);
wdenkc6097192002-11-03 00:24:07 +0000156#endif
157
158 PRINTF("## Final Flash bank size: 0x%08lx\n",size_b0);
159 return (size_b0);
160}
161
162
163/*-----------------------------------------------------------------------
164 * Fill in the FLASH offset table
165 */
166static void
167flash_get_offsets (ulong base, flash_info_t *info)
168{
169 int i;
170
171 if (info->flash_id == FLASH_UNKNOWN) {
172 return;
173 }
174
175 switch (info->flash_id & FLASH_VENDMASK) {
176 case FLASH_MAN_INTEL:
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200177 for (i = 0; i < info->sector_count; i++) {
wdenkc6097192002-11-03 00:24:07 +0000178 info->start[i] = base;
179 base += 1024 * 128;
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200180 }
181 return;
wdenkc6097192002-11-03 00:24:07 +0000182
183 default:
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200184 printf ("Don't know sector offsets for FLASH"
Wolfgang Denk93e14592013-10-04 17:43:24 +0200185 " type 0x%lx\n", info->flash_id);
wdenkc6097192002-11-03 00:24:07 +0000186 return;
187 }
188}
189
190
191/*-----------------------------------------------------------------------
192 * Display FLASH device info
193 */
194void
195flash_print_info (flash_info_t *info)
196{
197 int i;
198
199 if (info->flash_id == FLASH_UNKNOWN) {
200 printf ("Missing or unknown FLASH type\n");
201 return;
202 }
203
204 switch (info->flash_id & FLASH_VENDMASK) {
205 case FLASH_MAN_INTEL:
206 printf ("Intel ");
207 break;
208 default:
209 printf ("Unknown Vendor ");
210 break;
211 }
212
213 switch (info->flash_id & FLASH_TYPEMASK) {
214 case FLASH_28F128J3A:
215 printf ("28F128J3A (128Mbit = 128K x 128)\n");
216 break;
217 default:
218 printf ("Unknown Chip Type\n");
219 break;
220 }
221
222 if (info->size >= (1024 * 1024)) {
223 i = 20;
224 } else {
225 i = 10;
226 }
227 printf (" Size: %ld %cB in %d Sectors\n",
228 info->size >> i,
229 (i == 20) ? 'M' : 'k',
230 info->sector_count);
231
232 printf (" Sector Start Addresses:");
233 for (i=0; i<info->sector_count; ++i) {
234 if ((i % 5) == 0)
235 printf ("\n ");
236 printf (" %08lX%s",
237 info->start[i],
238 info->protect[i] ? " (RO)" : " "
239 );
240 }
241 printf ("\n");
242 return;
243}
244
245
246/*-----------------------------------------------------------------------
247 * Get size and other information for a FLASH device.
248 * NOTE: The following code cannot be run from FLASH!
249 */
250static
251ulong flash_get_size (vu_char *addr, flash_info_t *info)
252{
253#define NO_FLASH 0
254
255 vu_char value[2];
256
257 /*
258 * Try to read the manufacturer ID
259 */
260 addr[0] = SCS_READ_CMD;
261 addr[0] = SCS_READ_ID_CMD;
262 value[0] = addr[0];
263 value[1] = addr[2];
264 addr[0] = SCS_READ_CMD;
265
266 PRINTF("Manuf. ID @ 0x%08lx: 0x%02x\n", (ulong)addr, value[0]);
267 switch (value[0]) {
268 case (INTEL_MANUFACT & 0xff):
269 info->flash_id = FLASH_MAN_INTEL;
270 break;
271 default:
272 info->flash_id = FLASH_UNKNOWN;
273 info->sector_count = 0;
274 info->size = 0;
275 return (NO_FLASH);
276 }
277
278 /*
279 * Read the device ID
280 */
281 PRINTF("Device ID @ 0x%08lx: 0x%02x\n", (ulong)(&addr[2]), value[1]);
282 switch (value[1]) {
283 case (INTEL_ID_28F128J3A & 0xff):
284 info->flash_id += FLASH_28F128J3A;
285 info->sector_count = 128;
286 info->size = 16 * 1024 * 1024;
287 break;
288
289 default:
290 info->flash_id = FLASH_UNKNOWN;
291 return (NO_FLASH);
292 }
293
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200294 if (info->sector_count > CONFIG_SYS_MAX_FLASH_SECT) {
wdenkc6097192002-11-03 00:24:07 +0000295 printf ("** ERROR: sector count %d > max (%d) **\n",
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200296 info->sector_count, CONFIG_SYS_MAX_FLASH_SECT);
297 info->sector_count = CONFIG_SYS_MAX_FLASH_SECT;
wdenkc6097192002-11-03 00:24:07 +0000298 }
299 return (info->size);
300}
301
302
303/*-----------------------------------------------------------------------
304 * Erase the specified sectors in the specified FLASH device
305 */
306int
307flash_erase(flash_info_t *info, int s_first, int s_last)
308{
309 int flag, prot, sect;
310 ulong start, now, last;
311
312 if ((s_first < 0) || (s_first > s_last)) {
313 if (info->flash_id == FLASH_UNKNOWN) {
314 printf ("- missing\n");
315 } else {
316 printf ("- no sectors to erase\n");
317 }
318 return 1;
319 }
320
321 if ((info->flash_id & FLASH_VENDMASK) != FLASH_MAN_INTEL) {
322 printf ("Can erase only Intel flash types - aborted\n");
323 return 1;
324 }
325
326 prot = 0;
327 for (sect=s_first; sect<=s_last; ++sect) {
328 if (info->protect[sect]) {
329 prot++;
330 }
331 }
332
333 if (prot) {
334 printf ("- Warning: %d protected sectors will not be erased!\n",
335 prot);
336 } else {
337 printf ("\n");
338 }
339
340 start = get_timer (0);
341 last = start;
342
343 /*
344 * Start erase on unprotected sectors
345 */
346 for (sect = s_first; sect<=s_last; sect++) {
347 if (info->protect[sect] == 0) { /* not protected */
348 vu_char *addr = (uchar *)(info->start[sect]);
349 vu_char status;
350
351 /*
352 * Disable interrupts which might cause a timeout
353 */
354 flag = disable_interrupts();
355
356 *addr = SCS_CLEAR_STATUS_CMD;
357 *addr = SCS_BLOCK_ERASE_CMD;
358 *addr = SCS_BLOCK_ERASE_RESUME_CMD;
359
360 /*
361 * Re-enable interrupts if necessary
362 */
363 if (flag)
364 enable_interrupts();
365
366 /*
367 * Wait at least 80us - let's wait 1 ms
368 */
369 udelay (1000);
370
371 while (((status = *addr) & SCS_SR7) != SCS_SR7) {
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200372 if ((now=get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
wdenkc6097192002-11-03 00:24:07 +0000373 printf ("Timeout\n");
374 *addr = SCS_BLOCK_ERASE_SUSPEND_CMD;
375 *addr = SCS_READ_CMD;
376 return 1;
377 }
378
379 /*
380 * Show that we're waiting
381 */
382 if ((now - last) > 1000) { /* 1 second */
383 putc ('.');
384 last = now;
385 }
386 }
387 *addr = SCS_READ_CMD;
388 }
389 }
390 printf (" done\n");
391 return 0;
392}
393
394
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200395#ifdef CONFIG_SYS_GEN860T_FLASH_USE_WRITE_BUFFER
wdenkc6097192002-11-03 00:24:07 +0000396/*
397 * Allocate a flash buffer, fill it with data and write it to the flash.
398 * 0 - OK
399 * 1 - Timeout on buffer request
400 *
401 * NOTE: After the last call to this function, WSM status needs to be checked!
402 */
403static int
404write_flash_buffer8(flash_info_t *info_p, vu_char *src_p, vu_char *dest_p,
405 uint count)
406{
407 vu_char *block_addr_p = NULL;
408 vu_char *start_addr_p = NULL;
409 ulong blocksize = info_p->size / (ulong)info_p->sector_count;
410
411 int i;
412 uint time = get_timer(0);
413
414 PRINTF("%s:%d: src: 0x%p dest: 0x%p count: %d\n",
415 __FUNCTION__, __LINE__, src_p, dest_p, count);
416
417 /*
418 * What block are we in? We already know that the source address is
419 * in the flash address range, but we also can't cross a block boundary.
420 * We assume that the block does not cross a boundary (we'll check before
421 * calling this function).
422 */
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200423 for (i = 0; i < info_p->sector_count; ++i) {
wdenkc6097192002-11-03 00:24:07 +0000424 if ( ((ulong)dest_p >= info_p->start[i]) &&
425 ((ulong)dest_p < (info_p->start[i] + blocksize)) ) {
426 PRINTF("%s:%d: Dest addr 0x%p is in block %d @ 0x%.8lx\n",
427 __FUNCTION__, __LINE__, dest_p, i, info_p->start[i]);
428 block_addr_p = (vu_char *)info_p->start[i];
429 break;
430 }
431 }
432
433 /*
434 * Request a buffer
435 */
436 *block_addr_p = SCS_WRITE_BUF_CMD;
437 while ((*block_addr_p & SCS_XSR7) != SCS_XSR7) {
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200438 if (get_timer(time) > CONFIG_SYS_FLASH_ALLOC_BUFFER_TOUT) {
wdenkc6097192002-11-03 00:24:07 +0000439 PRINTF("%s:%d: Buffer allocation timeout @ 0x%p (waited %d mS)\n",
440 __FUNCTION__, __LINE__, block_addr_p,
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200441 CONFIG_SYS_FLASH_ALLOC_BUFFER_TOUT);
wdenkc6097192002-11-03 00:24:07 +0000442 return 1;
443 }
444 *block_addr_p = SCS_WRITE_BUF_CMD;
445 }
446
447 /*
448 * Fill the buffer with data
449 */
450 start_addr_p = dest_p;
451 *block_addr_p = count - 1; /* flash device wants count - 1 */
452 PRINTF("%s:%d: Fill buffer at block addr 0x%p\n",
453 __FUNCTION__, __LINE__, block_addr_p);
454 for (i = 0; i < count; i++) {
455 *start_addr_p++ = *src_p++;
456 }
457
458 /*
459 * Flush buffer to flash
460 */
461 *block_addr_p = SCS_PROGRAM_RESUME_CMD;
462#if 1
463 time = get_timer(0);
464 while ((*block_addr_p & SCS_SR7) != SCS_SR7) {
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200465 if (get_timer(time) > CONFIG_SYS_FLASH_WRITE_TOUT) {
wdenkc6097192002-11-03 00:24:07 +0000466 PRINTF("%s:%d: Write timeout @ 0x%p (waited %d mS)\n",
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200467 __FUNCTION__, __LINE__, block_addr_p, CONFIG_SYS_FLASH_WRITE_TOUT);
wdenkc6097192002-11-03 00:24:07 +0000468 return 1;
469 }
470 }
471
472#endif
473 return 0;
474}
475#endif
476
477
478/*-----------------------------------------------------------------------
479 * Copy memory to flash, returns:
480 * 0 - OK
481 * 1 - write timeout
482 * 2 - Flash not erased
483 * 4 - Flash not identified
484 */
485int
486write_buff(flash_info_t *info_p, uchar *src_p, ulong addr, ulong count)
487{
488 int rc = 0;
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200489#ifdef CONFIG_SYS_GEN860T_FLASH_USE_WRITE_BUFFER
wdenkc6097192002-11-03 00:24:07 +0000490#define FLASH_WRITE_BUF_SIZE 0x00000020 /* 32 bytes */
491 int i;
492 uint bufs;
493 ulong buf_count;
494 vu_char *sp;
495 vu_char *dp;
496#else
497 ulong wp;
498#endif
499
500 PRINTF("\n%s:%d: src: 0x%.8lx dest: 0x%.8lx size: %d (0x%.8lx)\n",
501 __FUNCTION__, __LINE__, (ulong)src_p, addr, (uint)count, count);
502
503 if (info_p->flash_id == FLASH_UNKNOWN) {
504 return 4;
505 }
506
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200507#ifdef CONFIG_SYS_GEN860T_FLASH_USE_WRITE_BUFFER
wdenkc6097192002-11-03 00:24:07 +0000508 sp = src_p;
509 dp = (uchar *)addr;
510
511 /*
512 * For maximum performance, we want to align the start address to
513 * the beginning of a write buffer boundary (i.e. A4-A0 of the
514 * start address = 0). See how many bytes are required to get to a
515 * write-buffer-aligned address. If that number is non-zero, do
516 * non buffered writes of the non-aligned data. By doing non-buffered
517 * writes, we avoid the problem of crossing a block (sector) boundary
518 * with buffered writes.
519 */
520 buf_count = FLASH_WRITE_BUF_SIZE - (addr & (FLASH_WRITE_BUF_SIZE - 1));
521 if (buf_count == FLASH_WRITE_BUF_SIZE) { /* already on a boundary */
522 buf_count = 0;
523 }
524 if (buf_count > count) { /* not a full buffers worth of data to write */
525 buf_count = count;
526 }
527 count -= buf_count;
528
529 PRINTF("%s:%d: Write buffer alignment count = %ld\n",
530 __FUNCTION__, __LINE__, buf_count);
531 while (buf_count-- >= 1) {
532 if ((rc = write_data8(info_p, (ulong)dp++, *sp++)) != 0) {
533 return (rc);
534 }
535 }
536
537 PRINTF("%s:%d: count = %ld\n", __FUNCTION__, __LINE__, count);
538 if (count == 0) { /* all done */
539 PRINTF("%s:%d: Less than 1 buffer (%d) worth of bytes\n",
540 __FUNCTION__, __LINE__, FLASH_WRITE_BUF_SIZE);
541 return (rc);
542 }
543
544 /*
545 * Now that we are write buffer aligned, write full or partial buffers.
546 * The fact that we are write buffer aligned automatically avoids
547 * crossing a block address during a write buffer operation.
548 */
549 bufs = count / FLASH_WRITE_BUF_SIZE;
550 PRINTF("%s:%d: %d (0x%x) buffers to write\n", __FUNCTION__, __LINE__,
551 bufs, bufs);
552 while (bufs >= 1) {
553 rc = write_flash_buffer8(info_p, sp, dp, FLASH_WRITE_BUF_SIZE);
554 if (rc != 0) {
555 PRINTF("%s:%d: ** Error writing buf %d\n",
556 __FUNCTION__, __LINE__, bufs);
557 return (rc);
558 }
559 bufs--;
560 sp += FLASH_WRITE_BUF_SIZE;
561 dp += FLASH_WRITE_BUF_SIZE;
562 }
563
564 /*
565 * Do the leftovers
566 */
567 i = count % FLASH_WRITE_BUF_SIZE;
568 PRINTF("%s:%d: %d (0x%x) leftover bytes\n", __FUNCTION__, __LINE__, i, i);
569 if (i > 0) {
570 rc = write_flash_buffer8(info_p, sp, dp, i);
571 }
572
573 sp = (vu_char*)info_p->start[0];
574 *sp = SCS_READ_CMD;
575 return (rc);
576
577#else
578 wp = addr;
579 while (count-- >= 1) {
580 if((rc = write_data8(info_p, wp++, *src_p++)) != 0)
581 return (rc);
582 }
583 return 0;
584#endif
585}
586
587
588/*-----------------------------------------------------------------------
589 * Write a byte to Flash, returns:
590 * 0 - OK
591 * 1 - write timeout
592 * 2 - Flash not erased
593 */
594static int
595write_data8 (flash_info_t *info, ulong dest, uchar data)
596{
597 vu_char *addr = (vu_char *)dest;
598 vu_char status;
599 ulong start;
600 int flag;
601
602 /* Check if Flash is (sufficiently) erased */
603 if ((*addr & data) != data) {
604 return (2);
605 }
606 /* Disable interrupts which might cause a timeout here */
607 flag = disable_interrupts();
608
609 *addr = SCS_PROGRAM_CMD;
610 *addr = data;
611
612 /* re-enable interrupts if necessary */
613 if (flag)
614 enable_interrupts();
615
616 start = get_timer (0);
617
618 while (((status = *addr) & SCS_SR7) != SCS_SR7) {
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200619 if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
wdenkc6097192002-11-03 00:24:07 +0000620 *addr = SCS_READ_CMD;
621 return (1);
622 }
623 }
624 *addr = SCS_READ_CMD;
625 return (0);
626}
627
628/* vim: set ts=4 sw=4 tw=78: */