diff --git a/board/esd/pmc440/init.S b/board/esd/pmc440/init.S
index 26a8282cec021e35cb07731887f613746701de11..6585fed664746243d67e43501fa850f9511d1b49 100644
--- a/board/esd/pmc440/init.S
+++ b/board/esd/pmc440/init.S
@@ -23,7 +23,7 @@
 #include <asm-ppc/mmu.h>
 #include <config.h>
 
-/**************************************************************************
+/*
  * TLB TABLE
  *
  * This table is used by the cpu boot code to setup the initial tlb
@@ -32,7 +32,7 @@
  *
  *  Pointer to the table is returned in r1
  *
- *************************************************************************/
+ */
     .section .bootpg,"ax"
     .globl tlbtab
 
@@ -49,12 +49,7 @@ tlbtab:
 	tlbentry( CONFIG_SYS_NAND_BOOT_SPL_SRC, SZ_4K, CONFIG_SYS_NAND_BOOT_SPL_SRC, 1, AC_R|AC_W|AC_X|SA_G )
 #endif
 
-	/* TLB-entry for DDR SDRAM (Up to 2GB) */
-#ifdef CONFIG_4xx_DCACHE
-	tlbentry( CONFIG_SYS_SDRAM_BASE, SZ_256M, CONFIG_SYS_SDRAM_BASE, 0, AC_R|AC_W|AC_X|SA_G)
-#else
-	tlbentry( CONFIG_SYS_SDRAM_BASE, SZ_256M, CONFIG_SYS_SDRAM_BASE, 0, AC_R|AC_W|AC_X|SA_G|SA_I )
-#endif
+	/* TLB entries for DDR2 SDRAM are generated dynamically */
 
 #ifdef CONFIG_SYS_INIT_RAM_DCACHE
 	/* TLB-entry for init-ram in dcache (SA_I must be turned off!) */
diff --git a/board/esd/pmc440/sdram.c b/board/esd/pmc440/sdram.c
index bb46ecce2e6d6ee43a92c8bcf3890a0afcd7814b..c3528bca4bd6d698ca142f309957f398d75b27c6 100644
--- a/board/esd/pmc440/sdram.c
+++ b/board/esd/pmc440/sdram.c
@@ -1,4 +1,7 @@
 /*
+ * (C) Copyright 2009
+ * Matthias Fuchs, esd gmbh, matthias.fuchs@esd.eu
+ *
  * (C) Copyright 2006
  * Sylvie Gohl,             AMCC/IBM, gohl.sylvie@fr.ibm.com
  * Jacqueline Pira-Ferriol, AMCC/IBM, jpira-ferriol@fr.ibm.com
@@ -31,33 +34,30 @@
 #include <common.h>
 #include <asm/processor.h>
 #include <asm/io.h>
+#include <asm/mmu.h>
 #include <ppc440.h>
 
 extern int denali_wait_for_dlllock(void);
 extern void denali_core_search_data_eye(void);
 
+struct sdram_conf_s {
+	ulong size;
+	int rows;
+	int banks;
+};
 
-#if defined(CONFIG_NAND_SPL)
-/* Using cpu/ppc4xx/speed.c to calculate the bus frequency is too big
- * for the 4k NAND boot image so define bus_frequency to 133MHz here
- * which is save for the refresh counter setup.
- */
-#define get_bus_freq(val)	133000000
-#endif
+struct sdram_conf_s sdram_conf[] = {
+	{(1024 << 20), 14, 8}, /* 1GByte: 4x2GBit, 14x10, 8 banks */
+	{(512 << 20),  13, 8}, /* 512MByte: 4x1GBit, 13x10, 8 banks */
+	{(256 << 20),  13, 4}, /* 256MByte: 4x512MBit, 13x10, 4 banks */
+};
 
-/*************************************************************************
- *
+/*
  * initdram -- 440EPx's DDR controller is a DENALI Core
- *
- ************************************************************************/
-phys_size_t initdram (int board_type)
+ */
+int initdram_by_rb(int rows, int banks)
 {
-#if !defined(CONFIG_NAND_U_BOOT) || defined(CONFIG_NAND_SPL)
-#if !defined(CONFIG_NAND_SPL)
 	ulong speed = get_bus_freq(0);
-#else
-	ulong speed = 133333333;	/* 133MHz is on the safe side	*/
-#endif
 
 	mtsdram(DDR0_02, 0x00000000);
 
@@ -89,21 +89,25 @@ phys_size_t initdram (int board_type)
 	mtsdram(DDR0_27, 0x0000682B);
 	mtsdram(DDR0_28, 0x00000000);
 	mtsdram(DDR0_31, 0x00000000);
-	mtsdram(DDR0_42, 0x01000006);
-	mtsdram(DDR0_43, 0x030A0200);
+
+	mtsdram(DDR0_42,
+		DDR0_42_ADDR_PINS_DECODE(14 - rows) |
+		0x00000006);
+	mtsdram(DDR0_43,
+		DDR0_43_EIGHT_BANK_MODE_ENCODE(8 == banks ? 1 : 0) |
+		0x030A0200);
+
 	mtsdram(DDR0_44, 0x00000003);
 	mtsdram(DDR0_02, 0x00000001);
 
 	denali_wait_for_dlllock();
-#endif /* #ifndef CONFIG_NAND_U_BOOT */
 
 #ifdef CONFIG_DDR_DATA_EYE
-	/* -----------------------------------------------------------+
+	/*
 	 * Perform data eye search if requested.
-	 * ----------------------------------------------------------*/
+	 */
 	denali_core_search_data_eye();
 #endif
-
 	/*
 	 * Clear possible errors resulting from data-eye-search.
 	 * If not done, then we could get an interrupt later on when
@@ -111,5 +115,35 @@ phys_size_t initdram (int board_type)
 	 */
 	set_mcsr(get_mcsr());
 
-	return (CONFIG_SYS_MBYTES_SDRAM << 20);
+	return 0;
+}
+
+phys_size_t initdram(int board_type)
+{
+	phys_size_t size;
+	int n;
+
+	/* go through supported memory configurations */
+	for (n = 0; n < ARRAY_SIZE(sdram_conf); n++) {
+		size = sdram_conf[n].size;
+
+		/* program TLB entries */
+		program_tlb(0, CONFIG_SYS_SDRAM_BASE, size,
+			    TLB_WORD2_I_ENABLE);
+
+		/*
+		 * setup denali core
+		 */
+		initdram_by_rb(sdram_conf[n].rows,
+			       sdram_conf[n].banks);
+
+		/* check for suitable configuration */
+		if (get_ram_size(CONFIG_SYS_SDRAM_BASE, size) == size)
+			return size;
+
+		/* delete TLB entries */
+		remove_tlb(CONFIG_SYS_SDRAM_BASE, size);
+	}
+
+	return 0;
 }
diff --git a/cpu/ppc4xx/44x_spd_ddr2.c b/cpu/ppc4xx/44x_spd_ddr2.c
index 2ab23365a537e8c53702313fcd43eca6322613f2..39753064006229fda38e2a540ffaada47752c9c2 100644
--- a/cpu/ppc4xx/44x_spd_ddr2.c
+++ b/cpu/ppc4xx/44x_spd_ddr2.c
@@ -9,7 +9,7 @@
  * Copyright (c) 2008 Nuovation System Designs, LLC
  *   Grant Erickson <gerickson@nuovations.com>
 
- * (C) Copyright 2007-2008
+ * (C) Copyright 2007-2009
  * Stefan Roese, DENX Software Engineering, sr@denx.de.
  *
  * COPYRIGHT   AMCC   CORPORATION 2004
@@ -86,8 +86,133 @@
 /* disable caching on SDRAM */
 #define MY_TLB_WORD2_I_ENABLE		TLB_WORD2_I_ENABLE
 #endif /* CONFIG_4xx_DCACHE */
+
+void dcbz_area(u32 start_address, u32 num_bytes);
 #endif /* CONFIG_440 */
 
+#define MAXRANKS	4
+#define MAXBXCF		4
+
+#define MULDIV64(m1, m2, d)	(u32)(((u64)(m1) * (u64)(m2)) / (u64)(d))
+
+#if !defined(CONFIG_NAND_SPL)
+/*-----------------------------------------------------------------------------+
+ * sdram_memsize
+ *-----------------------------------------------------------------------------*/
+phys_size_t sdram_memsize(void)
+{
+	phys_size_t mem_size;
+	unsigned long mcopt2;
+	unsigned long mcstat;
+	unsigned long mb0cf;
+	unsigned long sdsz;
+	unsigned long i;
+
+	mem_size = 0;
+
+	mfsdram(SDRAM_MCOPT2, mcopt2);
+	mfsdram(SDRAM_MCSTAT, mcstat);
+
+	/* DDR controller must be enabled and not in self-refresh. */
+	/* Otherwise memsize is zero. */
+	if (((mcopt2 & SDRAM_MCOPT2_DCEN_MASK) == SDRAM_MCOPT2_DCEN_ENABLE)
+	    && ((mcopt2 & SDRAM_MCOPT2_SREN_MASK) == SDRAM_MCOPT2_SREN_EXIT)
+	    && ((mcstat & (SDRAM_MCSTAT_MIC_MASK | SDRAM_MCSTAT_SRMS_MASK))
+		== (SDRAM_MCSTAT_MIC_COMP | SDRAM_MCSTAT_SRMS_NOT_SF))) {
+		for (i = 0; i < MAXBXCF; i++) {
+			mfsdram(SDRAM_MB0CF + (i << 2), mb0cf);
+			/* Banks enabled */
+			if ((mb0cf & SDRAM_BXCF_M_BE_MASK) == SDRAM_BXCF_M_BE_ENABLE) {
+#if defined(CONFIG_440)
+				sdsz = mfdcr_any(SDRAM_R0BAS + i) & SDRAM_RXBAS_SDSZ_MASK;
+#else
+				sdsz = mb0cf & SDRAM_RXBAS_SDSZ_MASK;
+#endif
+				switch(sdsz) {
+				case SDRAM_RXBAS_SDSZ_8:
+					mem_size+=8;
+					break;
+				case SDRAM_RXBAS_SDSZ_16:
+					mem_size+=16;
+					break;
+				case SDRAM_RXBAS_SDSZ_32:
+					mem_size+=32;
+					break;
+				case SDRAM_RXBAS_SDSZ_64:
+					mem_size+=64;
+					break;
+				case SDRAM_RXBAS_SDSZ_128:
+					mem_size+=128;
+					break;
+				case SDRAM_RXBAS_SDSZ_256:
+					mem_size+=256;
+					break;
+				case SDRAM_RXBAS_SDSZ_512:
+					mem_size+=512;
+					break;
+				case SDRAM_RXBAS_SDSZ_1024:
+					mem_size+=1024;
+					break;
+				case SDRAM_RXBAS_SDSZ_2048:
+					mem_size+=2048;
+					break;
+				case SDRAM_RXBAS_SDSZ_4096:
+					mem_size+=4096;
+					break;
+				default:
+					printf("WARNING: Unsupported bank size (SDSZ=0x%lx)!\n"
+					       , sdsz);
+					mem_size=0;
+					break;
+				}
+			}
+		}
+	}
+
+	return mem_size << 20;
+}
+
+/*-----------------------------------------------------------------------------+
+ * is_ecc_enabled
+ *-----------------------------------------------------------------------------*/
+static unsigned long is_ecc_enabled(void)
+{
+	unsigned long val;
+
+	mfsdram(SDRAM_MCOPT1, val);
+
+	return SDRAM_MCOPT1_MCHK_CHK_DECODE(val);
+}
+
+/*-----------------------------------------------------------------------------+
+ * board_add_ram_info
+ *-----------------------------------------------------------------------------*/
+void board_add_ram_info(int use_default)
+{
+	PPC4xx_SYS_INFO board_cfg;
+	u32 val;
+
+	if (is_ecc_enabled())
+		puts(" (ECC");
+	else
+		puts(" (ECC not");
+
+	get_sys_info(&board_cfg);
+
+#if defined(CONFIG_405EX)
+	val = board_cfg.freqPLB;
+#else
+	mfsdr(SDR0_DDR0, val);
+	val = MULDIV64((board_cfg.freqPLB), SDR0_DDR0_DDRM_DECODE(val), 1);
+#endif
+	printf(" enabled, %d MHz", (val * 2) / 1000000);
+
+	mfsdram(SDRAM_MMODE, val);
+	val = (val & SDRAM_MMODE_DCL_MASK) >> 4;
+	printf(", CL%d)", val);
+}
+#endif /* !CONFIG_NAND_SPL */
+
 #if defined(CONFIG_SPD_EEPROM)
 
 /*-----------------------------------------------------------------------------+
@@ -105,14 +230,10 @@
 #define SDRAM_NONE	0
 
 #define MAXDIMMS	2
-#define MAXRANKS	4
-#define MAXBXCF		4
 #define MAX_SPD_BYTES	256   /* Max number of bytes on the DIMM's SPD EEPROM */
 
 #define ONE_BILLION	1000000000
 
-#define MULDIV64(m1, m2, d)	(u32)(((u64)(m1) * (u64)(m2)) / (u64)(d))
-
 #define CMD_NOP		(7 << 19)
 #define CMD_PRECHARGE	(2 << 19)
 #define CMD_REFRESH	(1 << 19)
@@ -213,7 +334,6 @@ typedef enum ddr_cas_id {
 /*-----------------------------------------------------------------------------+
  * Prototypes
  *-----------------------------------------------------------------------------*/
-static phys_size_t sdram_memsize(void);
 static void get_spd_info(unsigned long *dimm_populated,
 			 unsigned char *iic0_dimm_addr,
 			 unsigned long num_dimm_banks);
@@ -257,15 +377,11 @@ static void program_initplr(unsigned long *dimm_populated,
 			    unsigned long num_dimm_banks,
 			    ddr_cas_id_t selected_cas,
 			    int write_recovery);
-static unsigned long is_ecc_enabled(void);
 #ifdef CONFIG_DDR_ECC
 static void program_ecc(unsigned long *dimm_populated,
 			unsigned char *iic0_dimm_addr,
 			unsigned long num_dimm_banks,
 			unsigned long tlb_word2_i_value);
-static void program_ecc_addr(unsigned long start_address,
-			     unsigned long num_bytes,
-			     unsigned long tlb_word2_i_value);
 #endif
 #if !defined(CONFIG_PPC4xx_DDR_AUTOCALIBRATION)
 static void program_DQS_calibration(unsigned long *dimm_populated,
@@ -278,7 +394,6 @@ static void	DQS_calibration_process(void);
 #endif
 #endif
 int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
-void dcbz_area(u32 start_address, u32 num_bytes);
 
 static unsigned char spd_read(uchar chip, uint addr)
 {
@@ -291,79 +406,6 @@ static unsigned char spd_read(uchar chip, uint addr)
 	return 0;
 }
 
-/*-----------------------------------------------------------------------------+
- * sdram_memsize
- *-----------------------------------------------------------------------------*/
-static phys_size_t sdram_memsize(void)
-{
-	phys_size_t mem_size;
-	unsigned long mcopt2;
-	unsigned long mcstat;
-	unsigned long mb0cf;
-	unsigned long sdsz;
-	unsigned long i;
-
-	mem_size = 0;
-
-	mfsdram(SDRAM_MCOPT2, mcopt2);
-	mfsdram(SDRAM_MCSTAT, mcstat);
-
-	/* DDR controller must be enabled and not in self-refresh. */
-	/* Otherwise memsize is zero. */
-	if (((mcopt2 & SDRAM_MCOPT2_DCEN_MASK) == SDRAM_MCOPT2_DCEN_ENABLE)
-	    && ((mcopt2 & SDRAM_MCOPT2_SREN_MASK) == SDRAM_MCOPT2_SREN_EXIT)
-	    && ((mcstat & (SDRAM_MCSTAT_MIC_MASK | SDRAM_MCSTAT_SRMS_MASK))
-		== (SDRAM_MCSTAT_MIC_COMP | SDRAM_MCSTAT_SRMS_NOT_SF))) {
-		for (i = 0; i < MAXBXCF; i++) {
-			mfsdram(SDRAM_MB0CF + (i << 2), mb0cf);
-			/* Banks enabled */
-			if ((mb0cf & SDRAM_BXCF_M_BE_MASK) == SDRAM_BXCF_M_BE_ENABLE) {
-				sdsz = mfdcr_any(SDRAM_R0BAS + i) & SDRAM_RXBAS_SDSZ_MASK;
-
-				switch(sdsz) {
-				case SDRAM_RXBAS_SDSZ_8:
-					mem_size+=8;
-					break;
-				case SDRAM_RXBAS_SDSZ_16:
-					mem_size+=16;
-					break;
-				case SDRAM_RXBAS_SDSZ_32:
-					mem_size+=32;
-					break;
-				case SDRAM_RXBAS_SDSZ_64:
-					mem_size+=64;
-					break;
-				case SDRAM_RXBAS_SDSZ_128:
-					mem_size+=128;
-					break;
-				case SDRAM_RXBAS_SDSZ_256:
-					mem_size+=256;
-					break;
-				case SDRAM_RXBAS_SDSZ_512:
-					mem_size+=512;
-					break;
-				case SDRAM_RXBAS_SDSZ_1024:
-					mem_size+=1024;
-					break;
-				case SDRAM_RXBAS_SDSZ_2048:
-					mem_size+=2048;
-					break;
-				case SDRAM_RXBAS_SDSZ_4096:
-					mem_size+=4096;
-					break;
-				default:
-					printf("WARNING: Unsupported bank size (SDSZ=0x%lx)!\n"
-					       , sdsz);
-					mem_size=0;
-					break;
-				}
-			}
-		}
-	}
-
-	return mem_size << 20;
-}
-
 /*-----------------------------------------------------------------------------+
  * initdram.  Initializes the 440SP Memory Queue and DDR SDRAM controller.
  * Note: This routine runs from flash with a stack set up in the chip's
@@ -643,26 +685,6 @@ static void get_spd_info(unsigned long *dimm_populated,
 	}
 }
 
-void board_add_ram_info(int use_default)
-{
-	PPC4xx_SYS_INFO board_cfg;
-	u32 val;
-
-	if (is_ecc_enabled())
-		puts(" (ECC");
-	else
-		puts(" (ECC not");
-
-	get_sys_info(&board_cfg);
-
-	mfsdr(SDR0_DDR0, val);
-	val = MULDIV64((board_cfg.freqPLB), SDR0_DDR0_DDRM_DECODE(val), 1);
-	printf(" enabled, %d MHz", (val * 2) / 1000000);
-
-	mfsdram(SDRAM_MMODE, val);
-	val = (val & SDRAM_MMODE_DCL_MASK) >> 4;
-	printf(", CL%d)", val);
-}
 
 /*------------------------------------------------------------------
  * For the memory DIMMs installed, this routine verifies that they
@@ -2277,25 +2299,6 @@ static void program_memory_queue(unsigned long *dimm_populated,
 #endif
 }
 
-/*-----------------------------------------------------------------------------+
- * is_ecc_enabled.
- *-----------------------------------------------------------------------------*/
-static unsigned long is_ecc_enabled(void)
-{
-	unsigned long dimm_num;
-	unsigned long ecc;
-	unsigned long val;
-
-	ecc = 0;
-	/* loop through all the DIMM slots on the board */
-	for (dimm_num = 0; dimm_num < MAXDIMMS; dimm_num++) {
-		mfsdram(SDRAM_MCOPT1, val);
-		ecc = max(ecc, SDRAM_MCOPT1_MCHK_CHK_DECODE(val));
-	}
-
-	return ecc;
-}
-
 #ifdef CONFIG_DDR_ECC
 /*-----------------------------------------------------------------------------+
  * program_ecc.
@@ -2305,9 +2308,6 @@ static void program_ecc(unsigned long *dimm_populated,
 			unsigned long num_dimm_banks,
 			unsigned long tlb_word2_i_value)
 {
-	unsigned long mcopt1;
-	unsigned long mcopt2;
-	unsigned long mcstat;
 	unsigned long dimm_num;
 	unsigned long ecc;
 
@@ -2321,105 +2321,7 @@ static void program_ecc(unsigned long *dimm_populated,
 	if (ecc == 0)
 		return;
 
-	if (sdram_memsize() > CONFIG_MAX_MEM_MAPPED) {
-		printf("\nWarning: Can't enable ECC on systems with more than 2GB of SDRAM!\n");
-		return;
-	}
-
-	mfsdram(SDRAM_MCOPT1, mcopt1);
-	mfsdram(SDRAM_MCOPT2, mcopt2);
-
-	if ((mcopt1 & SDRAM_MCOPT1_MCHK_MASK) != SDRAM_MCOPT1_MCHK_NON) {
-		/* DDR controller must be enabled and not in self-refresh. */
-		mfsdram(SDRAM_MCSTAT, mcstat);
-		if (((mcopt2 & SDRAM_MCOPT2_DCEN_MASK) == SDRAM_MCOPT2_DCEN_ENABLE)
-		    && ((mcopt2 & SDRAM_MCOPT2_SREN_MASK) == SDRAM_MCOPT2_SREN_EXIT)
-		    && ((mcstat & (SDRAM_MCSTAT_MIC_MASK | SDRAM_MCSTAT_SRMS_MASK))
-			== (SDRAM_MCSTAT_MIC_COMP | SDRAM_MCSTAT_SRMS_NOT_SF))) {
-
-			program_ecc_addr(0, sdram_memsize(), tlb_word2_i_value);
-		}
-	}
-
-	return;
-}
-
-static void wait_ddr_idle(void)
-{
-	u32 val;
-
-	do {
-		mfsdram(SDRAM_MCSTAT, val);
-	} while ((val & SDRAM_MCSTAT_IDLE_MASK) == SDRAM_MCSTAT_IDLE_NOT);
-}
-
-/*-----------------------------------------------------------------------------+
- * program_ecc_addr.
- *-----------------------------------------------------------------------------*/
-static void program_ecc_addr(unsigned long start_address,
-			     unsigned long num_bytes,
-			     unsigned long tlb_word2_i_value)
-{
-	unsigned long current_address;
-	unsigned long end_address;
-	unsigned long address_increment;
-	unsigned long mcopt1;
-	char str[] = "ECC generation -";
-	char slash[] = "\\|/-\\|/-";
-	int loop = 0;
-	int loopi = 0;
-
-	current_address = start_address;
-	mfsdram(SDRAM_MCOPT1, mcopt1);
-	if ((mcopt1 & SDRAM_MCOPT1_MCHK_MASK) != SDRAM_MCOPT1_MCHK_NON) {
-		mtsdram(SDRAM_MCOPT1,
-			(mcopt1 & ~SDRAM_MCOPT1_MCHK_MASK) | SDRAM_MCOPT1_MCHK_GEN);
-		sync();
-		eieio();
-		wait_ddr_idle();
-
-		puts(str);
-		if (tlb_word2_i_value == TLB_WORD2_I_ENABLE) {
-			/* ECC bit set method for non-cached memory */
-			if ((mcopt1 & SDRAM_MCOPT1_DMWD_MASK) == SDRAM_MCOPT1_DMWD_32)
-				address_increment = 4;
-			else
-				address_increment = 8;
-			end_address = current_address + num_bytes;
-
-			while (current_address < end_address) {
-				*((unsigned long *)current_address) = 0x00000000;
-				current_address += address_increment;
-
-				if ((loop++ % (2 << 20)) == 0) {
-					putc('\b');
-					putc(slash[loopi++ % 8]);
-				}
-			}
-
-		} else {
-			/* ECC bit set method for cached memory */
-			dcbz_area(start_address, num_bytes);
-			/* Write modified dcache lines back to memory */
-			clean_dcache_range(start_address, start_address + num_bytes);
-		}
-
-		blank_string(strlen(str));
-
-		sync();
-		eieio();
-		wait_ddr_idle();
-
-		/* clear ECC error repoting registers */
-		mtsdram(SDRAM_ECCCR, 0xffffffff);
-		mtdcr(0x4c, 0xffffffff);
-
-		mtsdram(SDRAM_MCOPT1,
-			(mcopt1 & ~SDRAM_MCOPT1_MCHK_MASK) | SDRAM_MCOPT1_MCHK_CHK_REP);
-		sync();
-		eieio();
-		wait_ddr_idle();
-	}
+	do_program_ecc(tlb_word2_i_value);
 }
 #endif
 
@@ -3106,7 +3008,7 @@ phys_size_t initdram(int board_type)
 #endif /* CONFIG_PPC4xx_DDR_AUTOCALIBRATION */
 
 #if defined(CONFIG_DDR_ECC)
-	ecc_init(CONFIG_SYS_SDRAM_BASE, CONFIG_SYS_MBYTES_SDRAM << 20);
+	do_program_ecc(0);
 #endif /* defined(CONFIG_DDR_ECC) */
 
 #if defined(CONFIG_440)
@@ -3183,18 +3085,6 @@ void mtdcr_any(u32 dcr, u32 val)
 	}
 }
 #endif /* defined(CONFIG_440) */
-
-void blank_string(int size)
-{
-	int i;
-
-	for (i = 0; i < size; i++)
-		putc('\b');
-	for (i = 0; i < size; i++)
-		putc(' ');
-	for (i = 0; i < size; i++)
-		putc('\b');
-}
 #endif /* !defined(CONFIG_NAND_U_BOOT) &&  !defined(CONFIG_NAND_SPL) */
 
 inline void ppc4xx_ibm_ddr2_register_dump(void)
diff --git a/cpu/ppc4xx/4xx_ibm_ddr2_autocalib.c b/cpu/ppc4xx/4xx_ibm_ddr2_autocalib.c
index 91bf582d6e800409671894640f2e25d35f990d5a..0283c91d84109a3533d8aa8a40a23201dea2f21d 100644
--- a/cpu/ppc4xx/4xx_ibm_ddr2_autocalib.c
+++ b/cpu/ppc4xx/4xx_ibm_ddr2_autocalib.c
@@ -42,6 +42,8 @@
 #include <asm/io.h>
 #include <asm/processor.h>
 
+#include "ecc.h"
+
 #if defined(CONFIG_PPC4xx_DDR_AUTOCALIBRATION)
 
 /*
@@ -177,7 +179,7 @@ static u32 *get_membase(int bxcr_num)
 
 static inline void ecc_clear_status_reg(void)
 {
-	mtsdram(SDRAM_ECCCR, 0xffffffff);
+	mtsdram(SDRAM_ECCES, 0xffffffff);
 #if defined(SDRAM_R0BAS)
 	mtdcr(SDRAM_ERRSTATLL, 0xffffffff);
 #endif
@@ -210,7 +212,7 @@ static int ecc_check_status_reg(void)
 	 * ecc error, then don't count
 	 * this as a passing value
 	 */
-	mfsdram(SDRAM_ECCCR, ecc_status);
+	mfsdram(SDRAM_ECCES, ecc_status);
 	if (ecc_status != 0x00000000) {
 		/* clear on error */
 		ecc_clear_status_reg();
diff --git a/cpu/ppc4xx/ecc.c b/cpu/ppc4xx/ecc.c
index 3f989e7f59b16083154adc5503636a29ef3eee8a..f105605459d5aec6490d70dccc111e8633e23968 100644
--- a/cpu/ppc4xx/ecc.c
+++ b/cpu/ppc4xx/ecc.c
@@ -2,7 +2,7 @@
  *    Copyright (c) 2008 Nuovation System Designs, LLC
  *      Grant Erickson <gerickson@nuovations.com>
  *
- *    (C) Copyright 2005-2007
+ *    (C) Copyright 2005-2009
  *    Stefan Roese, DENX Software Engineering, sr@denx.de.
  *
  *    (C) Copyright 2002
@@ -42,81 +42,144 @@
 #include <ppc_defs.h>
 #include <asm/processor.h>
 #include <asm/io.h>
+#include <asm/mmu.h>
+#include <asm/cache.h>
 
 #include "ecc.h"
 
 #if defined(CONFIG_SDRAM_PPC4xx_IBM_DDR) || \
     defined(CONFIG_SDRAM_PPC4xx_IBM_DDR2)
 #if defined(CONFIG_DDR_ECC) || defined(CONFIG_SDRAM_ECC)
+
+#if defined(CONFIG_405EX)
 /*
- *  void ecc_init()
- *
- *  Description:
- *    This routine initializes a range of DRAM ECC memory with known
- *    data and enables ECC checking.
- *
- *  TO DO:
- *    - Improve performance by utilizing cache.
- *    - Further generalize to make usable by other 4xx variants (e.g.
- *      440EPx, et al).
- *
- *  Input(s):
- *    start - A pointer to the start of memory covered by ECC requiring
- *	      initialization.
- *    size  - The size, in bytes, of the memory covered by ECC requiring
- *	      initialization.
- *
- *  Output(s):
- *    start - A pointer to the start of memory covered by ECC with
- *	      CONFIG_SYS_ECC_PATTERN written to all locations and ECC data
- *	      primed.
- *
- *  Returns:
- *    N/A
+ * Currently only 405EX uses 16bit data bus width as an alternative
+ * option to 32bit data width (SDRAM0_MCOPT1_WDTH)
  */
-void ecc_init(unsigned long * const start, unsigned long size)
+#define SDRAM_DATA_ALT_WIDTH	2
+#else
+#define SDRAM_DATA_ALT_WIDTH	8
+#endif
+
+static void wait_ddr_idle(void)
 {
-	const unsigned long pattern = CONFIG_SYS_ECC_PATTERN;
-	unsigned long * const end = (unsigned long * const)((long)start + size);
-	unsigned long * current = start;
+	u32 val;
+
+	do {
+		mfsdram(SDRAM_MCSTAT, val);
+	} while ((val & SDRAM_MCSTAT_IDLE_MASK) == SDRAM_MCSTAT_IDLE_NOT);
+}
+
+static void program_ecc_addr(unsigned long start_address,
+			     unsigned long num_bytes,
+			     unsigned long tlb_word2_i_value)
+{
+	unsigned long current_address;
+	unsigned long end_address;
+	unsigned long address_increment;
 	unsigned long mcopt1;
-	long increment;
+	char str[] = "ECC generation -";
+	char slash[] = "\\|/-\\|/-";
+	int loop = 0;
+	int loopi = 0;
 
-	if (start >= end)
-		return;
+	current_address = start_address;
+	mfsdram(SDRAM_MCOPT1, mcopt1);
+	if ((mcopt1 & SDRAM_MCOPT1_MCHK_MASK) != SDRAM_MCOPT1_MCHK_NON) {
+		mtsdram(SDRAM_MCOPT1,
+			(mcopt1 & ~SDRAM_MCOPT1_MCHK_MASK) | SDRAM_MCOPT1_MCHK_GEN);
+		sync();
+		eieio();
+		wait_ddr_idle();
+
+		puts(str);
 
-	mfsdram(SDRAM_ECC_CFG, mcopt1);
+#ifdef CONFIG_440
+		if (tlb_word2_i_value == TLB_WORD2_I_ENABLE) {
+#endif
+			/* ECC bit set method for non-cached memory */
+			if ((mcopt1 & SDRAM_MCOPT1_DMWD_MASK) == SDRAM_MCOPT1_DMWD_32)
+				address_increment = 4;
+			else
+				address_increment = SDRAM_DATA_ALT_WIDTH;
+			end_address = current_address + num_bytes;
 
-	/* Enable ECC generation without checking or reporting */
+			while (current_address < end_address) {
+				*((unsigned long *)current_address) = 0;
+				current_address += address_increment;
 
-	mtsdram(SDRAM_ECC_CFG, ((mcopt1 & ~SDRAM_ECC_CFG_MCHK_MASK) |
-				SDRAM_ECC_CFG_MCHK_GEN));
+				if ((loop++ % (2 << 20)) == 0) {
+					putc('\b');
+					putc(slash[loopi++ % 8]);
+				}
+			}
+#ifdef CONFIG_440
+		} else {
+			/* ECC bit set method for cached memory */
+			dcbz_area(start_address, num_bytes);
+			/* Write modified dcache lines back to memory */
+			clean_dcache_range(start_address, start_address + num_bytes);
+		}
+#endif /* CONFIG_440 */
 
-	increment = sizeof(u32);
+		blank_string(strlen(str));
 
-#if defined(CONFIG_440)
+		sync();
+		eieio();
+		wait_ddr_idle();
+
+		/* clear ECC error repoting registers */
+		mtsdram(SDRAM_ECCES, 0xffffffff);
+		mtdcr(0x4c, 0xffffffff);
+
+		mtsdram(SDRAM_MCOPT1,
+			(mcopt1 & ~SDRAM_MCOPT1_MCHK_MASK) | SDRAM_MCOPT1_MCHK_CHK_REP);
+		sync();
+		eieio();
+		wait_ddr_idle();
+	}
+}
+
+#if defined(CONFIG_SDRAM_PPC4xx_IBM_DDR)
+void ecc_init(unsigned long * const start, unsigned long size)
+{
 	/*
-	 * Look at the geometry of SDRAM (data width) to determine whether we
-	 * can skip words when writing.
+	 * Init ECC with cache disabled (on PPC's with IBM DDR
+	 * controller (non DDR2), not tested with cache enabled yet
 	 */
+	program_ecc_addr((u32)start, size, TLB_WORD2_I_ENABLE);
+}
+#endif
 
-	if ((mcopt1 & SDRAM_ECC_CFG_DMWD_MASK) != SDRAM_ECC_CFG_DMWD_32)
-		increment = sizeof(u64);
-#endif /* defined(CONFIG_440) */
+#if defined(CONFIG_SDRAM_PPC4xx_IBM_DDR2)
+void do_program_ecc(unsigned long tlb_word2_i_value)
+{
+	unsigned long mcopt1;
+	unsigned long mcopt2;
+	unsigned long mcstat;
+	phys_size_t memsize = sdram_memsize();
 
-	while (current < end) {
-		*current = pattern;
-		 current = (unsigned long *)((long)current + increment);
+	if (memsize > CONFIG_MAX_MEM_MAPPED) {
+		printf("\nWarning: Can't enable ECC on systems with more than 2GB of SDRAM!\n");
+		return;
 	}
 
-	/* Wait until the writes are finished. */
+	mfsdram(SDRAM_MCOPT1, mcopt1);
+	mfsdram(SDRAM_MCOPT2, mcopt2);
 
-	sync();
+	if ((mcopt1 & SDRAM_MCOPT1_MCHK_MASK) != SDRAM_MCOPT1_MCHK_NON) {
+		/* DDR controller must be enabled and not in self-refresh. */
+		mfsdram(SDRAM_MCSTAT, mcstat);
+		if (((mcopt2 & SDRAM_MCOPT2_DCEN_MASK) == SDRAM_MCOPT2_DCEN_ENABLE)
+		    && ((mcopt2 & SDRAM_MCOPT2_SREN_MASK) == SDRAM_MCOPT2_SREN_EXIT)
+		    && ((mcstat & (SDRAM_MCSTAT_MIC_MASK | SDRAM_MCSTAT_SRMS_MASK))
+			== (SDRAM_MCSTAT_MIC_COMP | SDRAM_MCSTAT_SRMS_NOT_SF))) {
 
-	/* Enable ECC generation with checking and no reporting */
-
-	mtsdram(SDRAM_ECC_CFG, ((mcopt1 & ~SDRAM_ECC_CFG_MCHK_MASK) |
-				SDRAM_ECC_CFG_MCHK_CHK));
+			program_ecc_addr(0, memsize, tlb_word2_i_value);
+		}
+	}
 }
+#endif
+
 #endif /* defined(CONFIG_DDR_ECC) || defined(CONFIG_SDRAM_ECC) */
 #endif /* defined(CONFIG_SDRAM_PPC4xx_IBM_DDR)... */
diff --git a/cpu/ppc4xx/ecc.h b/cpu/ppc4xx/ecc.h
index 67c3bff878ef3d0fb18338084bdc37d28d62c121..b2588919ebec0e6e9f8b7b78babe906dee76d18f 100644
--- a/cpu/ppc4xx/ecc.h
+++ b/cpu/ppc4xx/ecc.h
@@ -2,7 +2,7 @@
  *    Copyright (c) 2008 Nuovation System Designs, LLC
  *	Grant Erickson <gerickson@nuovations.com>
  *
- *    Copyright (c) 2007 DENX Software Engineering, GmbH
+ *    Copyright (c) 2007-2009 DENX Software Engineering, GmbH
  *	Stefan Roese <sr@denx.de>
  *
  *    See file CREDITS for list of people who contributed to this
@@ -25,18 +25,13 @@
  *
  *    Description:
  *	This file implements ECC initialization for PowerPC processors
- *	using the SDRAM DDR2 controller, including the 405EX(r),
- *	440SP(E), 460EX and 460GT.
+ *	using the IBM SDRAM DDR1 & DDR2 controller.
  *
  */
 
 #ifndef _ECC_H_
 #define _ECC_H_
 
-#if !defined(CONFIG_SYS_ECC_PATTERN)
-#define	CONFIG_SYS_ECC_PATTERN	0x00000000
-#endif /* !defined(CONFIG_SYS_ECC_PATTERN) */
-
 /*
  * Since the IBM DDR controller used on 440GP/GX/EP/GR is not register
  * compatible to the IBM DDR/2 controller used on 405EX/440SP/SPe/460EX/GT
@@ -46,24 +41,35 @@
 
 /* For 440GP/GX/EP/GR */
 #if defined(CONFIG_SDRAM_PPC4xx_IBM_DDR)
-#define SDRAM_ECC_CFG		SDRAM_CFG0
-#define SDRAM_ECC_CFG_MCHK_MASK	SDRAM_CFG0_MCHK_MASK
-#define SDRAM_ECC_CFG_MCHK_GEN	SDRAM_CFG0_MCHK_GEN
-#define SDRAM_ECC_CFG_MCHK_CHK	SDRAM_CFG0_MCHK_CHK
-#define SDRAM_ECC_CFG_DMWD_MASK	SDRAM_CFG0_DMWD_MASK
-#define SDRAM_ECC_CFG_DMWD_32	SDRAM_CFG0_DMWD_32
-#endif
+#define SDRAM_MCOPT1		SDRAM_CFG0
+#define SDRAM_MCOPT1_MCHK_MASK	SDRAM_CFG0_MCHK_MASK
+#define SDRAM_MCOPT1_MCHK_NON	SDRAM_CFG0_MCHK_NON
+#define SDRAM_MCOPT1_MCHK_GEN	SDRAM_CFG0_MCHK_GEN
+#define SDRAM_MCOPT1_MCHK_CHK	SDRAM_CFG0_MCHK_CHK
+#define SDRAM_MCOPT1_MCHK_CHK_REP SDRAM_CFG0_MCHK_CHK
+#define SDRAM_MCOPT1_DMWD_MASK	SDRAM_CFG0_DMWD_MASK
+#define SDRAM_MCOPT1_DMWD_32	SDRAM_CFG0_DMWD_32
+
+#define SDRAM_MCSTAT		SDRAM0_MCSTS
+#define SDRAM_MCSTAT_IDLE_MASK	SDRAM_MCSTS_CIS
+#define SDRAM_MCSTAT_IDLE_NOT	SDRAM_MCSTS_IDLE_NOT
 
-/* For 405EX/440SP/SPe/460EX/GT */
-#if defined(CONFIG_SDRAM_PPC4xx_IBM_DDR2)
-#define SDRAM_ECC_CFG		SDRAM_MCOPT1
-#define SDRAM_ECC_CFG_MCHK_MASK	SDRAM_MCOPT1_MCHK_MASK
-#define SDRAM_ECC_CFG_MCHK_GEN	SDRAM_MCOPT1_MCHK_GEN
-#define SDRAM_ECC_CFG_MCHK_CHK	SDRAM_MCOPT1_MCHK_CHK
-#define SDRAM_ECC_CFG_DMWD_MASK	SDRAM_MCOPT1_DMWD_MASK
-#define SDRAM_ECC_CFG_DMWD_32	SDRAM_MCOPT1_DMWD_32
+#define SDRAM_ECCES		SDRAM0_ECCESR
 #endif
 
-extern void ecc_init(unsigned long * const start, unsigned long size);
+void ecc_init(unsigned long * const start, unsigned long size);
+void do_program_ecc(unsigned long tlb_word2_i_value);
+
+static void inline blank_string(int size)
+{
+	int i;
+
+	for (i = 0; i < size; i++)
+		putc('\b');
+	for (i = 0; i < size; i++)
+		putc(' ');
+	for (i = 0; i < size; i++)
+		putc('\b');
+}
 
 #endif /* _ECC_H_ */
diff --git a/include/asm-ppc/ppc4xx-sdram.h b/include/asm-ppc/ppc4xx-sdram.h
index b6182d4f21ae07873d4f4af29bf3be2af7446388..92be514b40419573095b97ac6156982fe0a96ae9 100644
--- a/include/asm-ppc/ppc4xx-sdram.h
+++ b/include/asm-ppc/ppc4xx-sdram.h
@@ -117,6 +117,7 @@
 #define SDRAM_MCSTS_MRSC	0x80000000
 #define SDRAM_MCSTS_SRMS	0x40000000
 #define SDRAM_MCSTS_CIS		0x20000000
+#define SDRAM_MCSTS_IDLE_NOT	0x00000000	/* Mem contr not idle		*/
 
 /*
  * SDRAM Refresh Timer Register
@@ -416,8 +417,7 @@
 #define SDRAM_SDTR3	0x87	/* DDR SDRAM timing 3                        */
 #define SDRAM_MMODE	0x88	/* memory mode                               */
 #define SDRAM_MEMODE	0x89	/* memory extended mode                      */
-#define SDRAM_ECCCR	0x98	/* ECC error status                          */
-#define SDRAM_ECCES	SDRAM_ECCCR
+#define SDRAM_ECCES	0x98	/* ECC error status                          */
 #define SDRAM_CID	0xA4	/* core ID                                   */
 #ifndef CONFIG_405EX
 #define SDRAM_RID	0xA8	/* revision ID                               */
@@ -1397,7 +1397,6 @@
 /*
  * Prototypes
  */
-void inline blank_string(int size);
 inline void ppc4xx_ibm_ddr2_register_dump(void);
 u32 mfdcr_any(u32);
 void mtdcr_any(u32, u32);
@@ -1405,6 +1404,8 @@ u32 ddr_wrdtr(u32);
 u32 ddr_clktr(u32);
 void spd_ddr_init_hang(void);
 u32 DQS_autocalibration(void);
+phys_size_t sdram_memsize(void);
+void dcbz_area(u32 start_address, u32 num_bytes);
 #endif /* __ASSEMBLY__ */
 
 #endif /* _PPC4xx_SDRAM_H_ */
diff --git a/include/configs/PMC440.h b/include/configs/PMC440.h
index 012ae798d18aec1dc381b9ebf23a0e15b1f0554a..d6e2f6bc5e2be03e4610e676ca11264a9744f3e3 100644
--- a/include/configs/PMC440.h
+++ b/include/configs/PMC440.h
@@ -215,7 +215,6 @@
 /*-----------------------------------------------------------------------
  * DDR SDRAM
  *----------------------------------------------------------------------*/
-#define CONFIG_SYS_MBYTES_SDRAM	(256)	/* 256MB                        */
 #if !defined(CONFIG_NAND_U_BOOT) && !defined(CONFIG_NAND_SPL)
 #define CONFIG_DDR_DATA_EYE	/* use DDR2 optimization        */
 #endif