* Patch by Nicolas Lacressonniere, 11 Jun 2003:
  Modifications for Atmel AT91RM9200DK ARM920T based development kit
  - Add Atmel DataFlash support for reading and writing.
  - Add possibility to boot a Linux from DataFlash with BOOTM command.
  - Add Flash detection on Atmel AT91RM9200DK
    (between Atmel AT49BV1614 and AT49BV1614A flashes)
  - Replace old Ethernet PHY layer functions
  - Change link address

* Patch by Frank Smith, 9 Jun 2003:
  use CRIT_EXCEPTION for machine check on 4xx

* Patch by Detlev Zundel, 13 Jun 2003:
  added implementation of the "carinfo" command in cmd_immap.c
diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c
index af62bec..8af7c7c 100644
--- a/common/cmd_bootm.c
+++ b/common/cmd_bootm.c
@@ -56,6 +56,10 @@
 #include <logbuff.h>
 #endif
 
+#ifdef CONFIG_HAS_DATAFLASH
+#include <dataflash.h>
+#endif
+
 /*
  * Some systems (for example LWMON) have very short watchdog periods;
  * we must make sure to split long operations like memmove() or
@@ -138,6 +142,11 @@
 	printf ("## Booting image at %08lx ...\n", addr);
 
 	/* Copy header so we can blank CRC field for re-calculation */
+#ifdef CONFIG_HAS_DATAFLASH
+	if (addr_dataflash(addr)){
+		read_dataflash(addr, sizeof(image_header_t), (char *)&header);
+	} else
+#endif
 	memmove (&header, (char *)addr, sizeof(image_header_t));
 
 	if (ntohl(hdr->ih_magic) != IH_MAGIC) {
@@ -178,6 +187,13 @@
 	data = addr + sizeof(image_header_t);
 	len  = ntohl(hdr->ih_size);
 
+#ifdef CONFIG_HAS_DATAFLASH
+	if (addr_dataflash(addr)){
+		read_dataflash(data, len, (char *)CFG_LOAD_ADDR);
+		data = CFG_LOAD_ADDR;
+	}
+#endif	
+
 	if (verify) {
 		printf ("   Verifying Checksum ... ");
 		if (crc32 (0, (char *)data, len) != ntohl(hdr->ih_dcrc)) {
diff --git a/common/cmd_flash.c b/common/cmd_flash.c
index 92faf62..efc89dc 100644
--- a/common/cmd_flash.c
+++ b/common/cmd_flash.c
@@ -29,6 +29,10 @@
 #include <cmd_boot.h>
 #include <flash.h>
 
+#ifdef CONFIG_HAS_DATAFLASH
+#include <dataflash.h>
+#endif
+
 #if (CONFIG_COMMANDS & CFG_CMD_FLASH)
 
 extern flash_info_t flash_info[];	/* info for FLASH chips */
@@ -96,6 +100,10 @@
 {
 	ulong bank;
 
+#ifdef CONFIG_HAS_DATAFLASH
+	dataflash_print_info();
+#endif
+
 	if (argc == 1) {	/* print info for all FLASH banks */
 		for (bank=0; bank <CFG_MAX_FLASH_BANKS; ++bank) {
 			printf ("\nBank # %ld: ", bank+1);
diff --git a/common/cmd_immap.c b/common/cmd_immap.c
index 443335b..3eb5895 100644
--- a/common/cmd_immap.c
+++ b/common/cmd_immap.c
@@ -1,5 +1,5 @@
 /*
- * (C) Copyright 2000
+ * (C) Copyright 2000-2003
  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
  *
  * See file CREDITS for list of people who contributed to this
@@ -150,7 +150,24 @@
 int
 do_carinfo (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
 {
-	unimplemented (cmdtp, flag, argc, argv);
+	volatile immap_t *immap = (immap_t *) CFG_IMMR;
+
+#if defined(CONFIG_8xx)
+	volatile car8xx_t *car = &immap->im_clkrst;
+#elif defined(CONFIG_8260)
+	volatile car8260_t *car = &immap->im_clkrst;
+#endif
+
+#if defined(CONFIG_8xx)
+	printf ("SCCR  = %08x\n", car->car_sccr);
+	printf ("PLPRCR= %08x\n", car->car_plprcr);
+	printf ("RSR   = %08x\n", car->car_rsr);
+#elif defined(CONFIG_8260)
+	printf ("SCCR  = %08x\n", car->car_sccr);
+	printf ("SCMR  = %08x\n", car->car_scmr);
+	printf ("RSR   = %08x\n", car->car_rsr);
+	printf ("RMR   = %08x\n", car->car_rmr);
+#endif
 	return 0;
 }
 
@@ -168,7 +185,7 @@
 	int i;
 
 	if (counter % 2)
-	putc('\n');
+		putc('\n');
 	counter = 0;
 
 	for (i = 0; i < 4; i++, data += 79)
diff --git a/common/cmd_mem.c b/common/cmd_mem.c
index bbfe958..aca6926 100644
--- a/common/cmd_mem.c
+++ b/common/cmd_mem.c
@@ -33,6 +33,9 @@
 #if (CONFIG_COMMANDS & CFG_CMD_MMC)
 #include <mmc.h>
 #endif
+#ifdef CONFIG_HAS_DATAFLASH
+#include <dataflash.h>
+#endif
 
 #if (CONFIG_COMMANDS & (CFG_CMD_MEMORY | CFG_CMD_PCI | CFG_CMD_I2C\
 			| CMD_CMD_PORTIO))
@@ -131,6 +134,23 @@
 
 		printf("%08lx:", addr);
 		linebytes = (nbytes>DISP_LINE_LEN)?DISP_LINE_LEN:nbytes;
+
+#ifdef CONFIG_HAS_DATAFLASH
+		if (read_dataflash(addr, (linebytes/size)*size, linebuf) != -1){
+
+			for (i=0; i<linebytes; i+= size) {
+				if (size == 4) {
+					printf(" %08x", *uip++);
+				} else if (size == 2) {
+					printf(" %04x", *usp++);
+				} else {
+					printf(" %02x", *ucp++);
+				}
+				addr += size;
+			}
+			
+		} else {	/* addr does not correspond to DataFlash */
+#endif
 		for (i=0; i<linebytes; i+= size) {
 			if (size == 4) {
 				printf(" %08x", (*uip++ = *((uint *)addr)));
@@ -141,6 +161,9 @@
 			}
 			addr += size;
 		}
+#ifdef CONFIG_HAS_DATAFLASH
+		}
+#endif
 		printf("    ");
 		cp = linebuf;
 		for (i=0; i<linebytes; i++) {
@@ -236,6 +259,13 @@
 
 	count = simple_strtoul(argv[3], NULL, 16);
 
+#ifdef CONFIG_HAS_DATAFLASH
+	if (addr_dataflash(addr1) | addr_dataflash(addr2)){
+		printf("Comparison with DataFlash space not supported.\n\r");
+		return 0;
+	}
+#endif
+
 	ngood = 0;
 
 	while (count-- > 0) {
@@ -311,7 +341,11 @@
 
 #ifndef CFG_NO_FLASH
 	/* check if we are copying to Flash */
-	if (addr2info(dest) != NULL) {
+	if ( (addr2info(dest) != NULL)
+#ifdef CONFIG_HAS_DATAFLASH
+	   && (!addr_dataflash(addr))
+#endif
+	   ) {
 		int rc;
 
 		printf ("Copy to Flash... ");
@@ -366,6 +400,35 @@
 	}
 #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;
+
+		printf ("Copy to DataFlash... ");
+
+		rc = write_dataflash (dest, addr, count*size);
+
+		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) && (addr2info(dest)==NULL) ){
+		read_dataflash(addr, count * size, (char *) dest);
+		return 0;
+	}
+
+	if (addr_dataflash(addr) && addr_dataflash(dest)){
+		printf("Unsupported combination of source/destination.\n\r");
+		return 1;
+	}
+#endif
+
 	while (count-- > 0) {
 		if (size == 4)
 			*((ulong  *)dest) = *((ulong  *)addr);
@@ -805,6 +868,13 @@
 		addr += base_address;
 	}
 
+#ifdef CONFIG_HAS_DATAFLASH
+	if (addr_dataflash(addr)){
+		printf("Can't modify DataFlash in place. Use cp instead.\n\r");
+		return 0;
+	}
+#endif
+
 	/* Print the address, followed by value.  Then accept input for
 	 * the next value.  A non-converted value exits.
 	 */