diff -urN u-boot-2009.01-0rig//common/cmd_mem.c u-boot-2009.01/common/cmd_mem.c --- u-boot-2009.01-0rig//common/cmd_mem.c 2008-12-16 23:48:27.000000000 +0100 +++ u-boot-2009.01/common/cmd_mem.c 2009-01-04 13:27:03.000000000 +0100 @@ -37,11 +37,120 @@ #endif #include +#include +#ifdef CONFIG_SYS_NO_FLASH +#define in_flash(x) 0 +#else +#define in_flash(x) (addr2info(x)!=NULL) +#endif + +#ifdef CONFIG_HAS_DATAFLASH +#define in_dataflash(x) addr_dataflash(x) +#else +#define in_dataflash(x) 0 +#endif + +#ifdef CONFIG_CMD_MMC +#define in_SD_card(x) (mmc2info(x) != 0) +#else +#define in_SD_card(x) 0 +#endif + + #ifdef CMD_MEM_DEBUG #define PRINTF(fmt,args...) printf (fmt ,##args) #else #define PRINTF(fmt,args...) #endif +#if defined(CONFIG_HAS_DATAFLASH) +#define DF_PAGE_VALID 0x01 +#define CONFIG_SYS_DATAFLASH_PAGE_SIZE 1056 +typedef char dfpagebuf[CONFIG_SYS_DATAFLASH_PAGE_SIZE]; +dfpagebuf dfcache[3]; // Cache buffers for dataflash +unsigned char dfvalid[3]; // if DF_PAGE_VALID is set, then the, cache buffer contents are valid +unsigned char dflru[3]; // Least recently used algorithm to determine which buffer to reuse +unsigned int dfpage[3]; // TLB for cache, tells which page is loaded into dfcache + + +void flush_mem_cache(void) +{ + dfvalid[0] = dfvalid[1] = dfvalid[2] = 0; + dflru[0] = 0; + dflru[1] = 1; + dflru[2] = 2; +} + +typedef union { + uchar byte[4]; + ulong word; +} reg; + +unsigned int replace(char *p, unsigned int data) +{ + ulong i; + reg in; + reg out; + + in.word = data; + for(i = 0; i <= 3; i++) { + out.byte[0] = *p; + *p++ = in.byte[0]; + } + return out.word; +} + +ulong translate(unsigned int addr) +{ + unsigned int page = (addr) / CONFIG_SYS_DATAFLASH_PAGE_SIZE; + unsigned int index = (addr) - (page * CONFIG_SYS_DATAFLASH_PAGE_SIZE); + unsigned int i,rc; + for(i = 0; i < 2; i++) { + if((page == dfpage[i]) && (dfvalid[i] & DF_PAGE_VALID)) { + if(dflru[0] == i) { + // nothing + } else if(dflru[1] == i) { + // swap with 0 + dflru[1] = dflru[0]; + dflru[0] = i; + } else { + // shift down + dflru[2] = dflru[1]; + dflru[1] = dflru[0]; + dflru[0] = i; + } + return (unsigned int) &dfcache[i][index]; + } + } + // not found + // use buffer found in dflru[2] + i = dflru[2]; + if ((rc = read_dataflash(addr, CONFIG_SYS_DATAFLASH_PAGE_SIZE, dfcache[i])) == DATAFLASH_OK){ + dflru[2] = dflru[1]; + dflru[1] = dflru[0]; + dflru[0] = i; + dfvalid[i] |= DF_PAGE_VALID; + return (unsigned int) &dfcache[i][index]; + } + return 0; +} + + + +void df_writed(unsigned char *ldest, ulong laddr) +{ + +} +void df_writew(unsigned char *ldest,ushort laddr) {} +void df_writeb(unsigned char *ldest, u_char laddr) {} +#endif + +#if defined(CONFIG_HAS_DATAFLASH) +void flush_mem_cache(void); +ulong translate(unsigned int addr); +#else +#define flush_mem_cache(x) +#define translate(x) x +#endif static int mod_mem(cmd_tbl_t *, int, int, int, char *[]); @@ -67,7 +176,8 @@ ulong nbytes, linebytes; #endif int size; - int rc = 0; + int rc = 0; + int done = 0; /* We use the last specified parameters, unless new ones are * entered. @@ -106,26 +216,29 @@ * We buffer all read data, so we can make sure data is read only * once, and all accesses are with the specified bus width. */ - nbytes = length * size; - do { - char linebuf[DISP_LINE_LEN]; - void* p; - linebytes = (nbytes>DISP_LINE_LEN)?DISP_LINE_LEN:nbytes; - - rc = read_dataflash(addr, (linebytes/size)*size, linebuf); - p = (rc == DATAFLASH_OK) ? linebuf : (void*)addr; - print_buffer(addr, p, size, linebytes/size, DISP_LINE_LEN/size); - - nbytes -= linebytes; - addr += linebytes; - if (ctrlc()) { - rc = 1; - break; - } - } while (nbytes > 0); -#else + if(in_dataflash(addr)) { + nbytes = length * size; + do { + char linebuf[DISP_LINE_LEN]; + void* p; + linebytes = (nbytes>DISP_LINE_LEN)?DISP_LINE_LEN:nbytes; + + rc = read_dataflash(addr, (linebytes/size)*size, linebuf); + p = (rc == DATAFLASH_OK) ? linebuf : (void*)addr; + print_buffer(addr, p, size, linebytes/size, DISP_LINE_LEN/size); + + nbytes -= linebytes; + addr += linebytes; + if (ctrlc()) { + rc = 1; + break; + } + } while (nbytes > 0); + done = 1; + } +#endif -# if defined(CONFIG_BLACKFIN) +#if defined(CONFIG_BLACKFIN) /* See if we're trying to display L1 inst */ if (addr_bfin_on_chip_mem(addr)) { char linebuf[DISP_LINE_LEN]; @@ -142,15 +255,15 @@ break; } } while (nbytes > 0); - } else -# endif + done = 1; + } +#endif - { + if (!done) { /* Print the lines. */ print_buffer(addr, (void*)addr, size, length, DISP_LINE_LEN/size); addr += size*length; } -#endif dp_last_addr = addr; dp_last_length = length; @@ -273,6 +386,8 @@ int do_mem_cmp (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) { ulong addr1, addr2, count, ngood; + ulong laddr1, laddr2; + int size; int rcode = 0; @@ -294,12 +409,6 @@ count = simple_strtoul(argv[3], NULL, 16); -#ifdef CONFIG_HAS_DATAFLASH - if (addr_dataflash(addr1) | addr_dataflash(addr2)){ - puts ("Comparison with DataFlash space not supported.\n\r"); - return 0; - } -#endif #ifdef CONFIG_BLACKFIN if (addr_bfin_on_chip_mem(addr1) || addr_bfin_on_chip_mem(addr2)) { @@ -308,9 +417,12 @@ } #endif + flush_mem_cache(); ngood = 0; while (count-- > 0) { + laddr1 = translate((ulong) addr1); + laddr2 = translate((ulong) addr2); if (size == 4) { ulong word1 = *(ulong *)addr1; ulong word2 = *(ulong *)addr2; @@ -359,6 +471,14 @@ { ulong addr, dest, count; int size; +#ifdef CONFIG_HAS_DATAFLASH + int rc; + unsigned int crc,oldcrc,use_crc; + unsigned int olddata; + char *p; + char *env_crc_check; + +#endif if (argc != 4) { printf ("Usage:\n%s\n", cmdtp->usage); @@ -385,13 +505,14 @@ #ifndef CONFIG_SYS_NO_FLASH /* check if we are copying to Flash */ - if ( (addr2info(dest) != NULL) -#ifdef CONFIG_HAS_DATAFLASH - && (!addr_dataflash(dest)) -#endif - ) { + if (in_flash(dest)) { int rc; - +#if defined(CONFIG_HAS_DATAFLASH) || defined(CONFIG_CMD_MMC) + if(in_dataflash(addr) || in_SD_card(addr)) { + puts ("Cannot copy to flash from storage...\n"); + return 1; + } +#endif puts ("Copy to Flash... "); rc = flash_write ((char *)addr, dest, count*size); @@ -405,9 +526,15 @@ #endif #if defined(CONFIG_CMD_MMC) - if (mmc2info(dest)) { + if (in_SD_card(dest)) { int rc; +#if defined(CONFIG_HAS_DATAFLASH) + if(in_dataflash(addr) || in_SD_card(addr)) { + puts ("Cannot copy to flash-card from another storage location...\n"); + return 1; + } +#endif puts ("Copy to MMC... "); switch (rc = mmc_write ((uchar *)addr, dest, count*size)) { case 0: @@ -424,9 +551,12 @@ return 0; } - if (mmc2info(addr)) { + if (in_SD_card(addr)) { int rc; - + if(in_flash(dest) || in_dataflash(dest) || in_SD_card(dest)) { + puts ("Cannot copy from flash-card from another storage location...\n"); + return 1; + } puts ("Copy from MMC... "); switch (rc = mmc_read (addr, (uchar *)dest, count*size)) { case 0: @@ -445,39 +575,64 @@ #endif #ifdef CONFIG_HAS_DATAFLASH - /* Check if we are copying from RAM or Flash to DataFlash */ - if (addr_dataflash(dest) && !addr_dataflash(addr)){ - int rc; - - puts ("Copy to DataFlash... "); - - rc = write_dataflash (dest, addr, count*size); - + /* Check if we are copying from Dataflash to RAM */ + /* Note: Cannot copy from Dataflash to Flash directly */ + env_crc_check = getenv("crc-check"); + use_crc = (strcmp(env_crc_check, "on") == 0); + if (in_dataflash(addr)) { + if(in_dataflash(dest) || in_flash(dest) || in_SD_card(dest)) { + puts ("Cannot copy to dataflash from another storage location...\n"); + return 1; + } + puts ("Copy from DataFlash..."); + rc = read_dataflash(addr, count * size, (char *) dest); if (rc != 1) { dataflash_perror (rc); return (1); } - puts ("done\n"); - return 0; - } - /* Check if we are copying from DataFlash to RAM */ - if (addr_dataflash(addr) && !addr_dataflash(dest) -#ifndef CONFIG_SYS_NO_FLASH - && (addr2info(dest) == NULL) -#endif - ){ - int rc; - rc = read_dataflash(addr, count * size, (char *) dest); + if (use_crc) { + puts ("(Calculating CRC) ... "); + p = (char *) dest + (count * size) + 3; + olddata = replace(p,0); + rc = read_dataflash(addr, (count * size)+4, (char *) dest); + oldcrc = replace(p,olddata); + crc = crc32 (0, (const uchar *) dest, count*size); + if(crc != oldcrc) { + printf("\n\rBad CRC, %x expected, found %x... \n\r",oldcrc,crc); + return 1; + } else { + printf("[0x%x]",crc); + } + } + puts ("done\n\r"); + return 0; + } else if (!in_dataflash(addr) && in_dataflash(dest)) { + if(in_dataflash(addr) || in_SD_card(addr)) { + puts ("Cannot copy to dataflash from another storage location...\n"); + return 1; + } + puts ("Copy to DataFlash... "); + if (use_crc) { + puts ("(Calulating CRC) ... "); + crc = crc32 (0, (const uchar *) addr, count*size); + // Save CRC in small endian format + printf("= 0x%08x written to [%08x] ... ",crc,(unsigned int) (dest + count * size)); + p = (char *) addr+(count*size); + olddata = replace(p,crc); + rc = write_dataflash (dest, addr, count*size+4); + crc = replace((char *) addr+(count*size),olddata); + } else { + rc = write_dataflash (dest, addr, count*size); + } if (rc != 1) { dataflash_perror (rc); return (1); } + puts ("done\n"); return 0; - } - - if (addr_dataflash(addr) && addr_dataflash(dest)){ - puts ("Unsupported combination of source/destination.\n\r"); + } else if (in_dataflash(addr) && in_dataflash(dest)){ + puts ("Cannot copy between two dataflash areas\n\r"); return 1; } #endif @@ -490,6 +645,7 @@ } #endif + /* Copy between RAM locations, or parallell flash to RAM */ while (count-- > 0) { if (size == 4) *((ulong *)dest) = *((ulong *)addr); @@ -1011,7 +1167,7 @@ } #ifdef CONFIG_HAS_DATAFLASH - if (addr_dataflash(addr)){ + if (in_dataflash(addr)){ puts ("Can't modify DataFlash in place. Use cp instead.\n\r"); return 0; }