Commit ce5971ec authored by Ulf Samuelsson's avatar Ulf Samuelsson
Browse files

Add 'mux' command to control ext mux on at91rm9200dk/ek

parent d6afbb99
Loading
Loading
Loading
Loading
+93 −0
Original line number Diff line number Diff line
diff -urN u-boot-2009.01-0rig//common/cmd_mux.c u-boot-2009.01/common/cmd_mux.c
--- u-boot-2009.01-0rig//common/cmd_mux.c	1970-01-01 01:00:00.000000000 +0100
+++ u-boot-2009.01/common/cmd_mux.c	2009-01-04 00:17:19.000000000 +0100
@@ -0,0 +1,78 @@
+/*
+ * (C) Copyright 2008
+ * Ulf Samuelsson <ulf.samuelsson@atmel.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <command.h>
+#if (defined(CONFIG_AT91RM9200DK) || defined(CONFIG_AT91RM9200EK) || defined(CONFIG_AT91RM9200DF))
+
+#include <asm/arch/AT91RM9200.h>
+#include <dataflash.h>
+#include <at45.h>
+
+
+static int mmc_nspi (const char *s)
+{
+	if (strcmp(s, "mmc") == 0) {
+		return (1);
+	} else if (strcmp(s, "spi") == 0) {
+		return (0);
+	}
+	return (-1);
+}
+
+int do_mux ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+	switch (argc) {
+	case 2:			/* on / off	*/
+		switch (mmc_nspi(argv[1])) {
+#if 0	/* prevented by varargs handling; FALLTROUGH is harmless, too */
+		default: printf ("Usage:\n%s\n", cmdtp->usage);
+			return;
+#endif
+		case 0:	AT91F_SelectSPI ();
+			break;
+		case 1:	AT91F_SelectMMC ();
+			break;
+		}
+		/* FALL TROUGH */
+	case 1:			/* get status */
+		printf ("Mux is configured to be %s\n",
+			AT91F_GetMuxStatus() ? "MMC" : "SPI");
+		return 0;
+	default:
+		printf ("Usage:\n%s\n", cmdtp->usage);
+		return 1;
+	}
+	return 0;
+}
+
+
+U_BOOT_CMD(
+	mux,   2,   1,     do_mux,
+	"mux\t- enable or disable MMC or SPI\n",
+	"[mmc, spi]\n"
+	"    - enable or disable MMC or SPI\n"
+);
+
+#endif	/* CONFIG_CMD_MUX */
+
diff -urN u-boot-2009.01-0rig//common/Makefile u-boot-2009.01/common/Makefile
--- u-boot-2009.01-0rig//common/Makefile	2009-01-04 00:10:28.000000000 +0100
+++ u-boot-2009.01/common/Makefile	2009-01-04 00:20:39.000000000 +0100
@@ -112,6 +112,7 @@
 COBJS-$(CONFIG_CMD_MISC) += cmd_misc.o
 COBJS-$(CONFIG_CMD_MMC) += cmd_mmc.o
 COBJS-$(CONFIG_MP) += cmd_mp.o
+COBJS-$(CONFIG_CMD_AT91_SPIMUX) += cmd_mux.o
 COBJS-y += cmd_nand.o
 COBJS-$(CONFIG_CMD_NET) += cmd_net.o
 COBJS-$(CONFIG_CMD_ONENAND) += cmd_onenand.o
+77 −0
Original line number Diff line number Diff line
diff -urN u-boot-2009.01-0rig//common/cmd_ethinit.c u-boot-2009.01/common/cmd_ethinit.c
--- u-boot-2009.01-0rig//common/cmd_ethinit.c	1970-01-01 01:00:00.000000000 +0100
+++ u-boot-2009.01/common/cmd_ethinit.c	2009-01-04 00:28:39.000000000 +0100
@@ -0,0 +1,62 @@
+/*
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * Boot support
+ */
+#include <common.h>
+#include <command.h>
+#include <net.h>
+#ifdef CONFIG_CMD_ETHINIT
+extern int eth_init (bd_t * bd);
+
+static void	delay(void)
+{
+}
+/* 
+ * This command allows you to delay booting until you have a 
+ * valid Ethernet connection.
+ * Neccessary if you want to NFS mount a rootfs etc.
+ * When both this target and the NFS server 
+ * are powered on at the same time, then the NFS
+ * server can take a long time to boot.
+ */
+int do_ethinit (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+	int	i;
+	DECLARE_GLOBAL_DATA_PTR;
+	while(eth_init (gd->bd) == 0) {
+		for(i = 0; i < 10000000; i ++) {
+			delay();
+		}
+	}
+	return 0;
+}
+
+U_BOOT_CMD(
+	ethinit,	1,	1,	do_ethinit,
+	"ethinit\t- Initialize Ethernet controller\n",
+	"\n"
+);
+
+#endif	/* CONFIG_CMD_ETHINIT */
diff -urN u-boot-2009.01-0rig//common/Makefile u-boot-2009.01/common/Makefile
--- u-boot-2009.01-0rig//common/Makefile	2009-01-04 00:22:06.000000000 +0100
+++ u-boot-2009.01/common/Makefile	2009-01-04 00:29:46.000000000 +0100
@@ -83,6 +83,7 @@
 COBJS-$(CONFIG_ENV_IS_IN_EEPROM) += cmd_eeprom.o
 COBJS-$(CONFIG_CMD_EEPROM) += cmd_eeprom.o
 COBJS-$(CONFIG_CMD_ELF) += cmd_elf.o
+COBJS-$(CONFIG_CMD_ETHINIT) += cmd_ethinit.o
 COBJS-$(CONFIG_CMD_EXT2) += cmd_ext2.o
 COBJS-$(CONFIG_CMD_FACTORY) += cmd_factory.o
 COBJS-$(CONFIG_CMD_FAT) += cmd_fat.o
+130 −0
Original line number Diff line number Diff line
diff -urN u-boot-2009.01-0rig//include/configs/at91cap9adk.h u-boot-2009.01/include/configs/at91cap9adk.h
--- u-boot-2009.01-0rig//include/configs/at91cap9adk.h	2008-12-16 23:48:27.000000000 +0100
+++ u-boot-2009.01/include/configs/at91cap9adk.h	2009-01-04 00:43:58.000000000 +0100
@@ -69,7 +69,9 @@
 #define CONFIG_ATMEL_LCD		1
 #define CONFIG_ATMEL_LCD_BGR555		1
 #define CONFIG_SYS_CONSOLE_IS_IN_ENV		1
-
+#define CONFIG_CMD_FACTORY
+#define CONFIG_CMD_LED
+#define CONFIG_COLOURED_LED
 #define CONFIG_BOOTDELAY	3
 
 /*
diff -urN u-boot-2009.01-0rig//include/configs/at91rm9200df.h u-boot-2009.01/include/configs/at91rm9200df.h
--- u-boot-2009.01-0rig//include/configs/at91rm9200df.h	2009-01-02 17:37:43.000000000 +0100
+++ u-boot-2009.01/include/configs/at91rm9200df.h	2009-01-04 00:43:33.000000000 +0100
@@ -123,6 +123,9 @@
 #define CONFIG_CMD_DHCP
 #define CONFIG_CMD_MII
 #define CONFIG_CMD_NAND
+#define CONFIG_CMD_FACTORY
+#define CONFIG_CMD_LED
+#define CONFIG_COLOURED_LED
 #define CONFIG_CMD_AT91_SPIMUX
 #define CONFIG_CMD_ETHINIT
 
diff -urN u-boot-2009.01-0rig//include/configs/at91rm9200dk_df.h u-boot-2009.01/include/configs/at91rm9200dk_df.h
--- u-boot-2009.01-0rig//include/configs/at91rm9200dk_df.h	2009-01-02 10:03:11.000000000 +0100
+++ u-boot-2009.01/include/configs/at91rm9200dk_df.h	2009-01-04 00:42:52.000000000 +0100
@@ -122,7 +122,11 @@
 #define CONFIG_CMD_DHCP
 #define CONFIG_CMD_MII
 #define CONFIG_CMD_NAND
+#define CONFIG_CMD_FACTORY
+#define CONFIG_CMD_LED
+#define CONFIG_COLOURED_LED
 #define CONFIG_CMD_AT91_SPIMUX
+#define CONFIG_CMD_ETHINIT
 
 #define CONFIG_NAND_LEGACY
 
diff -urN u-boot-2009.01-0rig//include/configs/at91rm9200dk.h u-boot-2009.01/include/configs/at91rm9200dk.h
--- u-boot-2009.01-0rig//include/configs/at91rm9200dk.h	2009-01-02 10:03:11.000000000 +0100
+++ u-boot-2009.01/include/configs/at91rm9200dk.h	2009-01-04 00:43:15.000000000 +0100
@@ -120,7 +120,11 @@
 #define CONFIG_CMD_DHCP
 #define CONFIG_CMD_MII
 #define CONFIG_CMD_NAND
+#define CONFIG_CMD_FACTORY
+#define CONFIG_CMD_LED
+#define CONFIG_COLOURED_LED
 #define CONFIG_CMD_AT91_SPIMUX
+#define CONFIG_CMD_ETHINIT
 
 #define CONFIG_NAND_LEGACY
 
diff -urN u-boot-2009.01-0rig//include/configs/at91rm9200ek.h u-boot-2009.01/include/configs/at91rm9200ek.h
--- u-boot-2009.01-0rig//include/configs/at91rm9200ek.h	2009-01-02 17:37:43.000000000 +0100
+++ u-boot-2009.01/include/configs/at91rm9200ek.h	2009-01-04 00:42:35.000000000 +0100
@@ -121,9 +121,11 @@
 #define CONFIG_CMD_DHCP
 #define CONFIG_CMD_MII
 #define CONFIG_CMD_NAND
+#define CONFIG_CMD_FACTORY
+#define CONFIG_CMD_LED
+#define CONFIG_COLOURED_LED
 #define CONFIG_CMD_AT91_SPIMUX
 #define CONFIG_CMD_ETHINIT
-
 #define CONFIG_NAND_LEGACY
 
 #define CONFIG_SYS_MAX_NAND_DEVICE	1	/* Max number of NAND devices		*/
diff -urN u-boot-2009.01-0rig//include/configs/at91sam9260ek.h u-boot-2009.01/include/configs/at91sam9260ek.h
--- u-boot-2009.01-0rig//include/configs/at91sam9260ek.h	2008-12-16 23:48:27.000000000 +0100
+++ u-boot-2009.01/include/configs/at91sam9260ek.h	2009-01-04 00:41:56.000000000 +0100
@@ -74,10 +74,13 @@
 #include <config_cmd_default.h>
 #undef CONFIG_CMD_BDI
 #undef CONFIG_CMD_IMI
-#undef CONFIG_CMD_AUTOSCRIPT
+#define CONFIG_CMD_AUTOSCRIPT
 #undef CONFIG_CMD_FPGA
 #undef CONFIG_CMD_LOADS
 #undef CONFIG_CMD_IMLS
+#define CONFIG_CMD_FACTORY
+#define CONFIG_CMD_LED
+#define CONFIG_COLOURED_LED
 
 #define CONFIG_CMD_PING		1
 #define CONFIG_CMD_DHCP		1
diff -urN u-boot-2009.01-0rig//include/configs/at91sam9261ek.h u-boot-2009.01/include/configs/at91sam9261ek.h
--- u-boot-2009.01-0rig//include/configs/at91sam9261ek.h	2008-12-16 23:48:27.000000000 +0100
+++ u-boot-2009.01/include/configs/at91sam9261ek.h	2009-01-04 00:44:11.000000000 +0100
@@ -68,6 +68,9 @@
 #define CONFIG_ATMEL_LCD		1
 #define CONFIG_ATMEL_LCD_BGR555		1
 #define CONFIG_SYS_CONSOLE_IS_IN_ENV		1
+#define CONFIG_CMD_FACTORY
+#define CONFIG_CMD_LED
+#define CONFIG_COLOURED_LED
 
 #define CONFIG_BOOTDELAY	3
 
diff -urN u-boot-2009.01-0rig//include/configs/at91sam9263ek.h u-boot-2009.01/include/configs/at91sam9263ek.h
--- u-boot-2009.01-0rig//include/configs/at91sam9263ek.h	2008-12-16 23:48:27.000000000 +0100
+++ u-boot-2009.01/include/configs/at91sam9263ek.h	2009-01-04 00:44:34.000000000 +0100
@@ -69,6 +69,9 @@
 #define CONFIG_ATMEL_LCD		1
 #define CONFIG_ATMEL_LCD_BGR555		1
 #define CONFIG_SYS_CONSOLE_IS_IN_ENV		1
+#define CONFIG_CMD_FACTORY
+#define CONFIG_CMD_LED
+#define CONFIG_COLOURED_LED
 
 #define CONFIG_BOOTDELAY	3
 
diff -urN u-boot-2009.01-0rig//include/configs/at91sam9rlek.h u-boot-2009.01/include/configs/at91sam9rlek.h
--- u-boot-2009.01-0rig//include/configs/at91sam9rlek.h	2008-12-16 23:48:27.000000000 +0100
+++ u-boot-2009.01/include/configs/at91sam9rlek.h	2009-01-04 00:44:54.000000000 +0100
@@ -68,6 +68,9 @@
 #define CONFIG_ATMEL_LCD		1
 #define CONFIG_ATMEL_LCD_RGB565		1
 #define CONFIG_SYS_CONSOLE_IS_IN_ENV		1
+#define CONFIG_CMD_FACTORY
+#define CONFIG_CMD_LED
+#define CONFIG_COLOURED_LED
 
 #define CONFIG_BOOTDELAY	3
 
+3866 −0

File added.

Preview size limit exceeded, changes collapsed.

+412 −0
Original line number Diff line number Diff line
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 <watchdog.h>
 
+#include <flash.h>
+#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;
 	}