summaryrefslogtreecommitdiff
path: root/board/lwmon5/sdram.c
diff options
context:
space:
mode:
Diffstat (limited to 'board/lwmon5/sdram.c')
-rw-r--r--board/lwmon5/sdram.c90
1 files changed, 20 insertions, 70 deletions
diff --git a/board/lwmon5/sdram.c b/board/lwmon5/sdram.c
index affaeff..7c3cf49 100644
--- a/board/lwmon5/sdram.c
+++ b/board/lwmon5/sdram.c
@@ -6,7 +6,7 @@
* Alain Saurel, AMCC/IBM, alain.saurel@fr.ibm.com
* Robert Snyder, AMCC/IBM, rob.snyder@fr.ibm.com
*
- * (C) Copyright 2007
+ * (C) Copyright 2007-2008
* Stefan Roese, DENX Software Engineering, sr@denx.de.
*
* This program is free software; you can redistribute it and/or
@@ -35,6 +35,7 @@
#include <asm/mmu.h>
#include <asm/io.h>
#include <ppc440.h>
+#include <watchdog.h>
/*
* This DDR2 setup code can dynamically setup the TLB entries for the DDR2 memory
@@ -99,87 +100,37 @@ static void wait_ddr_idle(void)
*/
}
-static 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');
-}
-
static void program_ecc(u32 start_address,
u32 num_bytes,
u32 tlb_word2_i_value)
{
- u32 current_address;
- u32 end_address;
- u32 address_increment;
u32 val;
- char str[] = "ECC generation -";
- char slash[] = "\\|/-\\|/-";
- int loop = 0;
- int loopi = 0;
-
- current_address = start_address;
+ u32 current_addr = start_address;
+ int bytes_remaining;
sync();
- eieio();
wait_ddr_idle();
- if (tlb_word2_i_value == TLB_WORD2_I_ENABLE) {
- /* ECC bit set method for non-cached memory */
- address_increment = 4;
- end_address = current_address + num_bytes;
-
- puts(str);
-
- while (current_address < end_address) {
- *((u32 *)current_address) = 0x00000000;
- current_address += address_increment;
-
- if ((loop++ % (2 << 20)) == 0) {
- putc('\b');
- putc(slash[loopi++ % 8]);
- }
- }
+ /*
+ * Because of 440EPx errata CHIP 11, we don't touch the last 256
+ * bytes of SDRAM.
+ */
+ bytes_remaining = num_bytes - CFG_MEM_TOP_HIDE;
- blank_string(strlen(str));
- } else {
- /* ECC bit set method for cached memory */
-#if 0 /* test-only: will remove this define later, when ECC problems are solved! */
- /*
- * Some boards (like lwmon5) need to preserve the memory
- * content upon ECC generation (for the log-buffer).
- * Therefore we don't fill the memory with a pattern or
- * just zero it, but write the same values back that are
- * already in the memory cells.
- */
- address_increment = CFG_CACHELINE_SIZE;
- end_address = current_address + num_bytes;
-
- current_address = start_address;
- while (current_address < end_address) {
- /*
- * TODO: Th following sequence doesn't work correctly.
- * Just invalidating and flushing the cache doesn't
- * seem to trigger the re-write of the memory.
- */
- ppcDcbi(current_address);
- ppcDcbf(current_address);
- current_address += CFG_CACHELINE_SIZE;
- }
-#else
- dcbz_area(start_address, num_bytes);
- dflush();
-#endif
+ /*
+ * We have to write the ECC bytes by zeroing and flushing in smaller
+ * steps, since the whole 256MByte takes too long for the external
+ * watchdog.
+ */
+ while (bytes_remaining > 0) {
+ dcbz_area(current_addr, min((64 << 20), bytes_remaining));
+ current_addr += 64 << 20;
+ bytes_remaining -= 64 << 20;
+ WATCHDOG_RESET();
}
+ dflush();
sync();
- eieio();
wait_ddr_idle();
/* Clear error status */
@@ -191,7 +142,6 @@ static void program_ecc(u32 start_address,
mtsdram(DDR0_01, ((val &~ DDR0_01_INT_MASK_MASK) | DDR0_01_INT_MASK_ALL_OFF));
sync();
- eieio();
wait_ddr_idle();
}
#endif