* 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
#include <asm/mmu.h>
#include <asm/cache.h>
+#include "ecc.h"
+
#if defined(CONFIG_SDRAM_PPC4xx_IBM_DDR2)
#define PPC4xx_IBM_DDR2_DUMP_REGISTER(mnemonic) \
#define MULDIV64(m1, m2, d) (u32)(((u64)(m1) * (u64)(m2)) / (u64)(d))
-static unsigned long is_ecc_enabled(void);
-
-/*-----------------------------------------------------------------------------+
- * wait_ddr_idle
- *-----------------------------------------------------------------------------*/
-static void wait_ddr_idle(void)
-{
- u32 val;
-
- do {
- mfsdram(SDRAM_MCSTAT, val);
- } while ((val & SDRAM_MCSTAT_IDLE_MASK) == SDRAM_MCSTAT_IDLE_NOT);
-}
-
+#if !defined(CONFIG_NAND_SPL)
/*-----------------------------------------------------------------------------+
* sdram_memsize
*-----------------------------------------------------------------------------*/
-static phys_size_t sdram_memsize(void)
+phys_size_t sdram_memsize(void)
{
phys_size_t mem_size;
unsigned long mcopt2;
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
*-----------------------------------------------------------------------------*/
get_sys_info(&board_cfg);
-#if defined(CONFIG_440)
+#if defined(CONFIG_405EX)
+ val = board_cfg.freqPLB;
+#else
mfsdr(SDR0_DDR0, val);
val = MULDIV64((board_cfg.freqPLB), SDR0_DDR0_DDRM_DECODE(val), 1);
-#else
- mfsdr(SDR0_SDSTP0, val);
- val = MULDIV64((board_cfg.freqPLB), SDR0_SDSTP0_PLB2xDV0_DECODE(val), 1);
#endif
printf(" enabled, %d MHz", (val * 2) / 1000000);
val = (val & SDRAM_MMODE_DCL_MASK) >> 4;
printf(", CL%d)", val);
}
-
-#ifdef CONFIG_DDR_ECC
-/*-----------------------------------------------------------------------------+
- * 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);
-
-#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 = 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]);
- }
- }
-#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 */
-
- 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.
- *-----------------------------------------------------------------------------*/
-static 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();
-
- if (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, memsize, tlb_word2_i_value);
- }
- }
-}
-#endif /* CONFIG_DDR_ECC */
+#endif /* !CONFIG_NAND_SPL */
#if defined(CONFIG_SPD_EEPROM)
/*-----------------------------------------------------------------------------+
* 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);
#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.
#else /* CONFIG_SPD_EEPROM */
-/*-----------------------------------------------------------------------------+
- * is_ecc_enabled
- *-----------------------------------------------------------------------------*/
-static unsigned long is_ecc_enabled(void)
-{
- unsigned long ecc;
- unsigned long val;
-
- ecc = 0;
- mfsdram(SDRAM_MCOPT1, val);
- ecc = max(ecc, SDRAM_MCOPT1_MCHK_CHK_DECODE(val));
-
- return ecc;
-}
-
/*-----------------------------------------------------------------------------
* Function: initdram
* Description: Configures the PPC4xx IBM DDR1/DDR2 SDRAM memory controller.
}
}
#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)
#include <asm/io.h>
#include <asm/processor.h>
+#include "ecc.h"
+
#if defined(CONFIG_PPC4xx_DDR_AUTOCALIBRATION)
/*
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
* 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();
* 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
#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)... */
* 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
*
* 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
/* 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_ */
#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
#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 */
/*
* Prototypes
*/
-void inline blank_string(int size);
inline void ppc4xx_ibm_ddr2_register_dump(void);
u32 mfdcr_any(u32);
void mtdcr_any(u32, 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_ */
#define SDR0_SDCS_SDD (0x80000000 >> 31)
-/* SDR0_SDSTP0 Serial Device Strap Register0 */
-#define SDR0_SDSTP0 0x0020
-#define SDR0_SDSTP0_PLB2xDV0_DECODE(n) ((((unsigned long)(n)) & 0x07))
-
/* CUST0 Customer Configuration Register0 */
#define SDR0_CUST0 0x4000
#define SDR0_CUST0_MUX_E_N_G_MASK 0xC0000000 /* Mux_Emac_NDFC_GPIO */