Merge branch 'master' of git://git.denx.de/u-boot-ppc4xx

This commit is contained in:
Wolfgang Denk
2009-10-03 23:40:35 +02:00
8 changed files with 347 additions and 357 deletions

View File

@@ -23,7 +23,7 @@
#include <asm-ppc/mmu.h> #include <asm-ppc/mmu.h>
#include <config.h> #include <config.h>
/************************************************************************** /*
* TLB TABLE * TLB TABLE
* *
* This table is used by the cpu boot code to setup the initial tlb * 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 * Pointer to the table is returned in r1
* *
*************************************************************************/ */
.section .bootpg,"ax" .section .bootpg,"ax"
.globl tlbtab .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 ) 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 #endif
/* TLB-entry for DDR SDRAM (Up to 2GB) */ /* TLB entries for DDR2 SDRAM are generated dynamically */
#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
#ifdef CONFIG_SYS_INIT_RAM_DCACHE #ifdef CONFIG_SYS_INIT_RAM_DCACHE
/* TLB-entry for init-ram in dcache (SA_I must be turned off!) */ /* TLB-entry for init-ram in dcache (SA_I must be turned off!) */

View File

@@ -1,4 +1,7 @@
/* /*
* (C) Copyright 2009
* Matthias Fuchs, esd gmbh, matthias.fuchs@esd.eu
*
* (C) Copyright 2006 * (C) Copyright 2006
* Sylvie Gohl, AMCC/IBM, gohl.sylvie@fr.ibm.com * Sylvie Gohl, AMCC/IBM, gohl.sylvie@fr.ibm.com
* Jacqueline Pira-Ferriol, AMCC/IBM, jpira-ferriol@fr.ibm.com * Jacqueline Pira-Ferriol, AMCC/IBM, jpira-ferriol@fr.ibm.com
@@ -31,33 +34,30 @@
#include <common.h> #include <common.h>
#include <asm/processor.h> #include <asm/processor.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/mmu.h>
#include <ppc440.h> #include <ppc440.h>
extern int denali_wait_for_dlllock(void); extern int denali_wait_for_dlllock(void);
extern void denali_core_search_data_eye(void); extern void denali_core_search_data_eye(void);
struct sdram_conf_s {
ulong size;
int rows;
int banks;
};
#if defined(CONFIG_NAND_SPL) struct sdram_conf_s sdram_conf[] = {
/* Using cpu/ppc4xx/speed.c to calculate the bus frequency is too big {(1024 << 20), 14, 8}, /* 1GByte: 4x2GBit, 14x10, 8 banks */
* for the 4k NAND boot image so define bus_frequency to 133MHz here {(512 << 20), 13, 8}, /* 512MByte: 4x1GBit, 13x10, 8 banks */
* which is save for the refresh counter setup. {(256 << 20), 13, 4}, /* 256MByte: 4x512MBit, 13x10, 4 banks */
*/ };
#define get_bus_freq(val) 133000000
#endif
/************************************************************************* /*
*
* initdram -- 440EPx's DDR controller is a DENALI Core * initdram -- 440EPx's DDR controller is a DENALI Core
* */
************************************************************************/ int initdram_by_rb(int rows, int banks)
phys_size_t initdram (int board_type)
{ {
#if !defined(CONFIG_NAND_U_BOOT) || defined(CONFIG_NAND_SPL)
#if !defined(CONFIG_NAND_SPL)
ulong speed = get_bus_freq(0); ulong speed = get_bus_freq(0);
#else
ulong speed = 133333333; /* 133MHz is on the safe side */
#endif
mtsdram(DDR0_02, 0x00000000); mtsdram(DDR0_02, 0x00000000);
@@ -89,21 +89,25 @@ phys_size_t initdram (int board_type)
mtsdram(DDR0_27, 0x0000682B); mtsdram(DDR0_27, 0x0000682B);
mtsdram(DDR0_28, 0x00000000); mtsdram(DDR0_28, 0x00000000);
mtsdram(DDR0_31, 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_44, 0x00000003);
mtsdram(DDR0_02, 0x00000001); mtsdram(DDR0_02, 0x00000001);
denali_wait_for_dlllock(); denali_wait_for_dlllock();
#endif /* #ifndef CONFIG_NAND_U_BOOT */
#ifdef CONFIG_DDR_DATA_EYE #ifdef CONFIG_DDR_DATA_EYE
/* -----------------------------------------------------------+ /*
* Perform data eye search if requested. * Perform data eye search if requested.
* ----------------------------------------------------------*/ */
denali_core_search_data_eye(); denali_core_search_data_eye();
#endif #endif
/* /*
* Clear possible errors resulting from data-eye-search. * Clear possible errors resulting from data-eye-search.
* If not done, then we could get an interrupt later on when * 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()); 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;
} }

View File

@@ -9,7 +9,7 @@
* Copyright (c) 2008 Nuovation System Designs, LLC * Copyright (c) 2008 Nuovation System Designs, LLC
* Grant Erickson <gerickson@nuovations.com> * Grant Erickson <gerickson@nuovations.com>
* (C) Copyright 2007-2008 * (C) Copyright 2007-2009
* Stefan Roese, DENX Software Engineering, sr@denx.de. * Stefan Roese, DENX Software Engineering, sr@denx.de.
* *
* COPYRIGHT AMCC CORPORATION 2004 * COPYRIGHT AMCC CORPORATION 2004
@@ -86,8 +86,133 @@
/* disable caching on SDRAM */ /* disable caching on SDRAM */
#define MY_TLB_WORD2_I_ENABLE TLB_WORD2_I_ENABLE #define MY_TLB_WORD2_I_ENABLE TLB_WORD2_I_ENABLE
#endif /* CONFIG_4xx_DCACHE */ #endif /* CONFIG_4xx_DCACHE */
void dcbz_area(u32 start_address, u32 num_bytes);
#endif /* CONFIG_440 */ #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) #if defined(CONFIG_SPD_EEPROM)
/*-----------------------------------------------------------------------------+ /*-----------------------------------------------------------------------------+
@@ -105,14 +230,10 @@
#define SDRAM_NONE 0 #define SDRAM_NONE 0
#define MAXDIMMS 2 #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 MAX_SPD_BYTES 256 /* Max number of bytes on the DIMM's SPD EEPROM */
#define ONE_BILLION 1000000000 #define ONE_BILLION 1000000000
#define MULDIV64(m1, m2, d) (u32)(((u64)(m1) * (u64)(m2)) / (u64)(d))
#define CMD_NOP (7 << 19) #define CMD_NOP (7 << 19)
#define CMD_PRECHARGE (2 << 19) #define CMD_PRECHARGE (2 << 19)
#define CMD_REFRESH (1 << 19) #define CMD_REFRESH (1 << 19)
@@ -213,7 +334,6 @@ typedef enum ddr_cas_id {
/*-----------------------------------------------------------------------------+ /*-----------------------------------------------------------------------------+
* Prototypes * Prototypes
*-----------------------------------------------------------------------------*/ *-----------------------------------------------------------------------------*/
static phys_size_t sdram_memsize(void);
static void get_spd_info(unsigned long *dimm_populated, static void get_spd_info(unsigned long *dimm_populated,
unsigned char *iic0_dimm_addr, unsigned char *iic0_dimm_addr,
unsigned long num_dimm_banks); unsigned long num_dimm_banks);
@@ -257,15 +377,11 @@ static void program_initplr(unsigned long *dimm_populated,
unsigned long num_dimm_banks, unsigned long num_dimm_banks,
ddr_cas_id_t selected_cas, ddr_cas_id_t selected_cas,
int write_recovery); int write_recovery);
static unsigned long is_ecc_enabled(void);
#ifdef CONFIG_DDR_ECC #ifdef CONFIG_DDR_ECC
static void program_ecc(unsigned long *dimm_populated, static void program_ecc(unsigned long *dimm_populated,
unsigned char *iic0_dimm_addr, unsigned char *iic0_dimm_addr,
unsigned long num_dimm_banks, unsigned long num_dimm_banks,
unsigned long tlb_word2_i_value); 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 #endif
#if !defined(CONFIG_PPC4xx_DDR_AUTOCALIBRATION) #if !defined(CONFIG_PPC4xx_DDR_AUTOCALIBRATION)
static void program_DQS_calibration(unsigned long *dimm_populated, static void program_DQS_calibration(unsigned long *dimm_populated,
@@ -278,7 +394,6 @@ static void DQS_calibration_process(void);
#endif #endif
#endif #endif
int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); 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) static unsigned char spd_read(uchar chip, uint addr)
{ {
@@ -291,79 +406,6 @@ static unsigned char spd_read(uchar chip, uint addr)
return 0; 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. * 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 * 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 * For the memory DIMMs installed, this routine verifies that they
@@ -2277,25 +2299,6 @@ static void program_memory_queue(unsigned long *dimm_populated,
#endif #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 #ifdef CONFIG_DDR_ECC
/*-----------------------------------------------------------------------------+ /*-----------------------------------------------------------------------------+
* program_ecc. * program_ecc.
@@ -2305,9 +2308,6 @@ static void program_ecc(unsigned long *dimm_populated,
unsigned long num_dimm_banks, unsigned long num_dimm_banks,
unsigned long tlb_word2_i_value) unsigned long tlb_word2_i_value)
{ {
unsigned long mcopt1;
unsigned long mcopt2;
unsigned long mcstat;
unsigned long dimm_num; unsigned long dimm_num;
unsigned long ecc; unsigned long ecc;
@@ -2321,105 +2321,7 @@ static void program_ecc(unsigned long *dimm_populated,
if (ecc == 0) if (ecc == 0)
return; return;
if (sdram_memsize() > CONFIG_MAX_MEM_MAPPED) { do_program_ecc(tlb_word2_i_value);
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();
}
} }
#endif #endif
@@ -3106,7 +3008,7 @@ phys_size_t initdram(int board_type)
#endif /* CONFIG_PPC4xx_DDR_AUTOCALIBRATION */ #endif /* CONFIG_PPC4xx_DDR_AUTOCALIBRATION */
#if defined(CONFIG_DDR_ECC) #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) */ #endif /* defined(CONFIG_DDR_ECC) */
#if defined(CONFIG_440) #if defined(CONFIG_440)
@@ -3183,18 +3085,6 @@ void mtdcr_any(u32 dcr, u32 val)
} }
} }
#endif /* defined(CONFIG_440) */ #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) */ #endif /* !defined(CONFIG_NAND_U_BOOT) && !defined(CONFIG_NAND_SPL) */
inline void ppc4xx_ibm_ddr2_register_dump(void) inline void ppc4xx_ibm_ddr2_register_dump(void)

View File

@@ -42,6 +42,8 @@
#include <asm/io.h> #include <asm/io.h>
#include <asm/processor.h> #include <asm/processor.h>
#include "ecc.h"
#if defined(CONFIG_PPC4xx_DDR_AUTOCALIBRATION) #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) static inline void ecc_clear_status_reg(void)
{ {
mtsdram(SDRAM_ECCCR, 0xffffffff); mtsdram(SDRAM_ECCES, 0xffffffff);
#if defined(SDRAM_R0BAS) #if defined(SDRAM_R0BAS)
mtdcr(SDRAM_ERRSTATLL, 0xffffffff); mtdcr(SDRAM_ERRSTATLL, 0xffffffff);
#endif #endif
@@ -210,7 +212,7 @@ static int ecc_check_status_reg(void)
* ecc error, then don't count * ecc error, then don't count
* this as a passing value * this as a passing value
*/ */
mfsdram(SDRAM_ECCCR, ecc_status); mfsdram(SDRAM_ECCES, ecc_status);
if (ecc_status != 0x00000000) { if (ecc_status != 0x00000000) {
/* clear on error */ /* clear on error */
ecc_clear_status_reg(); ecc_clear_status_reg();

View File

@@ -2,7 +2,7 @@
* Copyright (c) 2008 Nuovation System Designs, LLC * Copyright (c) 2008 Nuovation System Designs, LLC
* Grant Erickson <gerickson@nuovations.com> * Grant Erickson <gerickson@nuovations.com>
* *
* (C) Copyright 2005-2007 * (C) Copyright 2005-2009
* Stefan Roese, DENX Software Engineering, sr@denx.de. * Stefan Roese, DENX Software Engineering, sr@denx.de.
* *
* (C) Copyright 2002 * (C) Copyright 2002
@@ -42,81 +42,144 @@
#include <ppc_defs.h> #include <ppc_defs.h>
#include <asm/processor.h> #include <asm/processor.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/mmu.h>
#include <asm/cache.h>
#include "ecc.h" #include "ecc.h"
#if defined(CONFIG_SDRAM_PPC4xx_IBM_DDR) || \ #if defined(CONFIG_SDRAM_PPC4xx_IBM_DDR) || \
defined(CONFIG_SDRAM_PPC4xx_IBM_DDR2) defined(CONFIG_SDRAM_PPC4xx_IBM_DDR2)
#if defined(CONFIG_DDR_ECC) || defined(CONFIG_SDRAM_ECC) #if defined(CONFIG_DDR_ECC) || defined(CONFIG_SDRAM_ECC)
#if defined(CONFIG_405EX)
/* /*
* void ecc_init() * Currently only 405EX uses 16bit data bus width as an alternative
* * option to 32bit data width (SDRAM0_MCOPT1_WDTH)
* 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
*/ */
#define SDRAM_DATA_ALT_WIDTH 2
#else
#define SDRAM_DATA_ALT_WIDTH 8
#endif
static void wait_ddr_idle(void)
{
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;
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 = SDRAM_DATA_ALT_WIDTH;
end_address = current_address + num_bytes;
while (current_address < end_address) {
*((unsigned long *)current_address) = 0;
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_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) void ecc_init(unsigned long * const start, unsigned long size)
{ {
const unsigned long pattern = CONFIG_SYS_ECC_PATTERN;
unsigned long * const end = (unsigned long * const)((long)start + size);
unsigned long * current = start;
unsigned long mcopt1;
long increment;
if (start >= end)
return;
mfsdram(SDRAM_ECC_CFG, mcopt1);
/* Enable ECC generation without checking or reporting */
mtsdram(SDRAM_ECC_CFG, ((mcopt1 & ~SDRAM_ECC_CFG_MCHK_MASK) |
SDRAM_ECC_CFG_MCHK_GEN));
increment = sizeof(u32);
#if defined(CONFIG_440)
/* /*
* Look at the geometry of SDRAM (data width) to determine whether we * Init ECC with cache disabled (on PPC's with IBM DDR
* can skip words when writing. * 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) #if defined(CONFIG_SDRAM_PPC4xx_IBM_DDR2)
increment = sizeof(u64); void do_program_ecc(unsigned long tlb_word2_i_value)
#endif /* defined(CONFIG_440) */ {
unsigned long mcopt1;
unsigned long mcopt2;
unsigned long mcstat;
phys_size_t memsize = sdram_memsize();
while (current < end) { if (memsize > CONFIG_MAX_MEM_MAPPED) {
*current = pattern; printf("\nWarning: Can't enable ECC on systems with more than 2GB of SDRAM!\n");
current = (unsigned long *)((long)current + increment); 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 */ program_ecc_addr(0, memsize, tlb_word2_i_value);
}
mtsdram(SDRAM_ECC_CFG, ((mcopt1 & ~SDRAM_ECC_CFG_MCHK_MASK) | }
SDRAM_ECC_CFG_MCHK_CHK));
} }
#endif
#endif /* defined(CONFIG_DDR_ECC) || defined(CONFIG_SDRAM_ECC) */ #endif /* defined(CONFIG_DDR_ECC) || defined(CONFIG_SDRAM_ECC) */
#endif /* defined(CONFIG_SDRAM_PPC4xx_IBM_DDR)... */ #endif /* defined(CONFIG_SDRAM_PPC4xx_IBM_DDR)... */

View File

@@ -2,7 +2,7 @@
* Copyright (c) 2008 Nuovation System Designs, LLC * Copyright (c) 2008 Nuovation System Designs, LLC
* Grant Erickson <gerickson@nuovations.com> * 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> * Stefan Roese <sr@denx.de>
* *
* See file CREDITS for list of people who contributed to this * See file CREDITS for list of people who contributed to this
@@ -25,18 +25,13 @@
* *
* Description: * Description:
* This file implements ECC initialization for PowerPC processors * This file implements ECC initialization for PowerPC processors
* using the SDRAM DDR2 controller, including the 405EX(r), * using the IBM SDRAM DDR1 & DDR2 controller.
* 440SP(E), 460EX and 460GT.
* *
*/ */
#ifndef _ECC_H_ #ifndef _ECC_H_
#define _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 * 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 * compatible to the IBM DDR/2 controller used on 405EX/440SP/SPe/460EX/GT
@@ -46,24 +41,35 @@
/* For 440GP/GX/EP/GR */ /* For 440GP/GX/EP/GR */
#if defined(CONFIG_SDRAM_PPC4xx_IBM_DDR) #if defined(CONFIG_SDRAM_PPC4xx_IBM_DDR)
#define SDRAM_ECC_CFG SDRAM_CFG0 #define SDRAM_MCOPT1 SDRAM_CFG0
#define SDRAM_ECC_CFG_MCHK_MASK SDRAM_CFG0_MCHK_MASK #define SDRAM_MCOPT1_MCHK_MASK SDRAM_CFG0_MCHK_MASK
#define SDRAM_ECC_CFG_MCHK_GEN SDRAM_CFG0_MCHK_GEN #define SDRAM_MCOPT1_MCHK_NON SDRAM_CFG0_MCHK_NON
#define SDRAM_ECC_CFG_MCHK_CHK SDRAM_CFG0_MCHK_CHK #define SDRAM_MCOPT1_MCHK_GEN SDRAM_CFG0_MCHK_GEN
#define SDRAM_ECC_CFG_DMWD_MASK SDRAM_CFG0_DMWD_MASK #define SDRAM_MCOPT1_MCHK_CHK SDRAM_CFG0_MCHK_CHK
#define SDRAM_ECC_CFG_DMWD_32 SDRAM_CFG0_DMWD_32 #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
#define SDRAM_ECCES SDRAM0_ECCESR
#endif #endif
/* For 405EX/440SP/SPe/460EX/GT */ void ecc_init(unsigned long * const start, unsigned long size);
#if defined(CONFIG_SDRAM_PPC4xx_IBM_DDR2) void do_program_ecc(unsigned long tlb_word2_i_value);
#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
#endif
extern void ecc_init(unsigned long * const start, unsigned long size); 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_ */ #endif /* _ECC_H_ */

View File

@@ -117,6 +117,7 @@
#define SDRAM_MCSTS_MRSC 0x80000000 #define SDRAM_MCSTS_MRSC 0x80000000
#define SDRAM_MCSTS_SRMS 0x40000000 #define SDRAM_MCSTS_SRMS 0x40000000
#define SDRAM_MCSTS_CIS 0x20000000 #define SDRAM_MCSTS_CIS 0x20000000
#define SDRAM_MCSTS_IDLE_NOT 0x00000000 /* Mem contr not idle */
/* /*
* SDRAM Refresh Timer Register * SDRAM Refresh Timer Register
@@ -416,8 +417,7 @@
#define SDRAM_SDTR3 0x87 /* DDR SDRAM timing 3 */ #define SDRAM_SDTR3 0x87 /* DDR SDRAM timing 3 */
#define SDRAM_MMODE 0x88 /* memory mode */ #define SDRAM_MMODE 0x88 /* memory mode */
#define SDRAM_MEMODE 0x89 /* memory extended mode */ #define SDRAM_MEMODE 0x89 /* memory extended mode */
#define SDRAM_ECCCR 0x98 /* ECC error status */ #define SDRAM_ECCES 0x98 /* ECC error status */
#define SDRAM_ECCES SDRAM_ECCCR
#define SDRAM_CID 0xA4 /* core ID */ #define SDRAM_CID 0xA4 /* core ID */
#ifndef CONFIG_405EX #ifndef CONFIG_405EX
#define SDRAM_RID 0xA8 /* revision ID */ #define SDRAM_RID 0xA8 /* revision ID */
@@ -1397,7 +1397,6 @@
/* /*
* Prototypes * Prototypes
*/ */
void inline blank_string(int size);
inline void ppc4xx_ibm_ddr2_register_dump(void); inline void ppc4xx_ibm_ddr2_register_dump(void);
u32 mfdcr_any(u32); u32 mfdcr_any(u32);
void mtdcr_any(u32, u32); void mtdcr_any(u32, u32);
@@ -1405,6 +1404,8 @@ u32 ddr_wrdtr(u32);
u32 ddr_clktr(u32); u32 ddr_clktr(u32);
void spd_ddr_init_hang(void); void spd_ddr_init_hang(void);
u32 DQS_autocalibration(void); u32 DQS_autocalibration(void);
phys_size_t sdram_memsize(void);
void dcbz_area(u32 start_address, u32 num_bytes);
#endif /* __ASSEMBLY__ */ #endif /* __ASSEMBLY__ */
#endif /* _PPC4xx_SDRAM_H_ */ #endif /* _PPC4xx_SDRAM_H_ */

View File

@@ -215,7 +215,6 @@
/*----------------------------------------------------------------------- /*-----------------------------------------------------------------------
* DDR SDRAM * DDR SDRAM
*----------------------------------------------------------------------*/ *----------------------------------------------------------------------*/
#define CONFIG_SYS_MBYTES_SDRAM (256) /* 256MB */
#if !defined(CONFIG_NAND_U_BOOT) && !defined(CONFIG_NAND_SPL) #if !defined(CONFIG_NAND_U_BOOT) && !defined(CONFIG_NAND_SPL)
#define CONFIG_DDR_DATA_EYE /* use DDR2 optimization */ #define CONFIG_DDR_DATA_EYE /* use DDR2 optimization */
#endif #endif