diff options
Diffstat (limited to 'board/lwmon/flash.c')
-rw-r--r-- | board/lwmon/flash.c | 89 |
1 files changed, 80 insertions, 9 deletions
diff --git a/board/lwmon/flash.c b/board/lwmon/flash.c index 127738a4bb5..4004865c315 100644 --- a/board/lwmon/flash.c +++ b/board/lwmon/flash.c @@ -47,6 +47,9 @@ flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips */ */ static ulong flash_get_size (vu_long *addr, flash_info_t *info); static int write_data (flash_info_t *info, ulong dest, ulong data); +#ifdef CFG_FLASH_USE_BUFFER_WRITE +static int write_data_buf (flash_info_t * info, ulong dest, uchar * cp, int len); +#endif static void flash_get_offsets (ulong base, flash_info_t *info); /*----------------------------------------------------------------------- @@ -480,6 +483,17 @@ int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt) /* * handle FLASH_WIDTH aligned part */ +#ifdef CFG_FLASH_USE_BUFFER_WRITE + while(cnt >= FLASH_WIDTH) { + i = CFG_FLASH_BUFFER_SIZE > cnt ? + (cnt & ~(FLASH_WIDTH - 1)) : CFG_FLASH_BUFFER_SIZE; + if((rc = write_data_buf(info, wp, src,i)) != 0) + return rc; + wp += i; + src += i; + cnt -=i; + } +#else while (cnt >= FLASH_WIDTH) { data = 0; for (i=0; i<FLASH_WIDTH; ++i) { @@ -491,6 +505,7 @@ int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt) wp += FLASH_WIDTH; cnt -= FLASH_WIDTH; } +#endif /* CFG_FLASH_USE_BUFFER_WRITE */ if (cnt == 0) { return (0); @@ -512,6 +527,28 @@ int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt) } /*----------------------------------------------------------------------- + * Check flash status, returns: + * 0 - OK + * 1 - timeout + */ +static int flash_status_check(vu_long *addr, ulong tout, char * prompt) +{ + ulong status; + ulong start; + + /* Wait for command completion */ + start = get_timer (0); + while(((status = *addr) & 0x00800080) != 0x00800080) { + if (get_timer(start) > tout) { + printf("Flash %s timeout at address %p\n", prompt, addr); + *addr = 0x00FF00FF; /* restore read mode */ + return (1); + } + } + return 0; +} + +/*----------------------------------------------------------------------- * Write a word to Flash, returns: * 0 - OK * 1 - write timeout @@ -520,8 +557,6 @@ int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt) static int write_data (flash_info_t *info, ulong dest, ulong data) { vu_long *addr = (vu_long *)dest; - ulong status; - ulong start; int flag; /* Check if Flash is (sufficiently) erased */ @@ -538,13 +573,8 @@ static int write_data (flash_info_t *info, ulong dest, ulong data) if (flag) enable_interrupts(); - start = get_timer (0); - - while (((status = *addr) & 0x00800080) != 0x00800080) { - if (get_timer(start) > CFG_FLASH_WRITE_TOUT) { - *addr = 0x00FF00FF; /* restore read mode */ - return (1); - } + if (flash_status_check(addr, CFG_FLASH_WRITE_TOUT, "write") != 0) { + return (1); } *addr = 0x00FF00FF; /* restore read mode */ @@ -552,5 +582,46 @@ static int write_data (flash_info_t *info, ulong dest, ulong data) return (0); } +#ifdef CFG_FLASH_USE_BUFFER_WRITE +/*----------------------------------------------------------------------- + * Write a buffer to Flash, returns: + * 0 - OK + * 1 - write timeout + */ +static int write_data_buf(flash_info_t * info, ulong dest, uchar * cp, int len) +{ + vu_long *addr = (vu_long *)dest; + int sector; + int cnt; + int retcode; + vu_long * src = (vu_long *)cp; + vu_long * dst = (vu_long *)dest; + + /* find sector */ + for(sector = info->sector_count - 1; sector >= 0; sector--) { + if(dest >= info->start[sector]) + break; + } + + *addr = 0x00500050; /* clear status */ + *addr = 0x00e800e8; /* write buffer */ + + if((retcode = flash_status_check(addr, CFG_FLASH_BUFFER_WRITE_TOUT, + "write to buffer")) == 0) { + cnt = len / FLASH_WIDTH; + *addr = (cnt-1) | ((cnt-1) << 16); + while(cnt-- > 0) { + *dst++ = *src++; + } + *addr = 0x00d000d0; /* write buffer confirm */ + retcode = flash_status_check(addr, CFG_FLASH_BUFFER_WRITE_TOUT, + "buffer write"); + } + *addr = 0x00FF00FF; /* restore read mode */ + *addr = 0x00500050; /* clear status */ + return retcode; +} +#endif /* CFG_USE_FLASH_BUFFER_WRITE */ + /*----------------------------------------------------------------------- */ |