summaryrefslogtreecommitdiff
path: root/cpu
diff options
context:
space:
mode:
Diffstat (limited to 'cpu')
-rw-r--r--cpu/ppc4xx/44x_spd_ddr.c341
-rw-r--r--cpu/ppc4xx/ndfc.c74
-rw-r--r--cpu/ppc4xx/start.S221
3 files changed, 349 insertions, 287 deletions
diff --git a/cpu/ppc4xx/44x_spd_ddr.c b/cpu/ppc4xx/44x_spd_ddr.c
index 10b4c18..c500d3f 100644
--- a/cpu/ppc4xx/44x_spd_ddr.c
+++ b/cpu/ppc4xx/44x_spd_ddr.c
@@ -20,7 +20,7 @@
* Jun Gu, Artesyn Technology, jung@artesyncp.com
* Support for AMCC 440 based on OpenBIOS draminit.c from IBM.
*
- * (C) Copyright 2005
+ * (C) Copyright 2005-2007
* Stefan Roese, DENX Software Engineering, sr@denx.de.
*
* See file CREDITS for list of people who contributed to this
@@ -42,6 +42,11 @@
* MA 02111-1307 USA
*/
+/* define DEBUG for debugging output (obviously ;-)) */
+#if 0
+#define DEBUG
+#endif
+
#include <common.h>
#include <asm/processor.h>
#include <i2c.h>
@@ -246,25 +251,6 @@
#define MY_TLB_WORD2_I_ENABLE TLB_WORD2_I_ENABLE /* disable caching on SDRAM */
#endif
-const unsigned long test[NUMMEMTESTS][NUMMEMWORDS] = {
- {0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
- 0xFFFFFFFF, 0xFFFFFFFF},
- {0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
- 0x00000000, 0x00000000},
- {0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA,
- 0x55555555, 0x55555555},
- {0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555,
- 0xAAAAAAAA, 0xAAAAAAAA},
- {0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5,
- 0x5A5A5A5A, 0x5A5A5A5A},
- {0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A,
- 0xA5A5A5A5, 0xA5A5A5A5},
- {0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55,
- 0x55AA55AA, 0x55AA55AA},
- {0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA,
- 0xAA55AA55, 0xAA55AA55}
-};
-
/* bank_parms is used to sort the bank sizes by descending order */
struct bank_param {
unsigned long cr;
@@ -278,46 +264,37 @@ extern unsigned char cfg_simulate_spd_eeprom[128];
#endif
void program_tlb(u32 start, u32 size, u32 tlb_word2_i_value);
-unsigned char spd_read(uchar chip, uint addr);
-
-void get_spd_info(unsigned long* dimm_populated,
- unsigned char* iic0_dimm_addr,
- unsigned long num_dimm_banks);
-
-void check_mem_type
-(unsigned long* dimm_populated,
- unsigned char* iic0_dimm_addr,
- unsigned long num_dimm_banks);
-
-void check_volt_type
-(unsigned long* dimm_populated,
- unsigned char* iic0_dimm_addr,
- unsigned long num_dimm_banks);
-
-void program_cfg0(unsigned long* dimm_populated,
- unsigned char* iic0_dimm_addr,
- unsigned long num_dimm_banks);
-
-void program_cfg1(unsigned long* dimm_populated,
- unsigned char* iic0_dimm_addr,
- unsigned long num_dimm_banks);
-
-void program_rtr (unsigned long* dimm_populated,
- unsigned char* iic0_dimm_addr,
- unsigned long num_dimm_banks);
-
-void program_tr0 (unsigned long* dimm_populated,
- unsigned char* iic0_dimm_addr,
- unsigned long num_dimm_banks);
-
-void program_tr1 (void);
-
-void program_ecc (unsigned long num_bytes);
+static unsigned char spd_read(uchar chip, uint addr);
+static void get_spd_info(unsigned long *dimm_populated,
+ unsigned char *iic0_dimm_addr,
+ unsigned long num_dimm_banks);
+static void check_mem_type(unsigned long *dimm_populated,
+ unsigned char *iic0_dimm_addr,
+ unsigned long num_dimm_banks);
+static void check_volt_type(unsigned long *dimm_populated,
+ unsigned char *iic0_dimm_addr,
+ unsigned long num_dimm_banks);
+static void program_cfg0(unsigned long *dimm_populated,
+ unsigned char *iic0_dimm_addr,
+ unsigned long num_dimm_banks);
+static void program_cfg1(unsigned long *dimm_populated,
+ unsigned char *iic0_dimm_addr,
+ unsigned long num_dimm_banks);
+static void program_rtr(unsigned long *dimm_populated,
+ unsigned char *iic0_dimm_addr,
+ unsigned long num_dimm_banks);
+static void program_tr0(unsigned long *dimm_populated,
+ unsigned char *iic0_dimm_addr,
+ unsigned long num_dimm_banks);
+static void program_tr1(void);
+
+#ifdef CONFIG_DDR_ECC
+static void program_ecc(unsigned long num_bytes);
+#endif
-unsigned
-long program_bxcr(unsigned long* dimm_populated,
- unsigned char* iic0_dimm_addr,
- unsigned long num_dimm_banks);
+static unsigned long program_bxcr(unsigned long *dimm_populated,
+ unsigned char *iic0_dimm_addr,
+ unsigned long num_dimm_banks);
/*
* This function is reading data from the DIMM module EEPROM over the SPD bus
@@ -328,7 +305,6 @@ long program_bxcr(unsigned long* dimm_populated,
* BUG: Don't handle ECC memory
* BUG: A few values in the TR register is currently hardcoded
*/
-
long int spd_sdram(void) {
unsigned char iic0_dimm_addr[] = SPD_EEPROM_ADDRESS;
unsigned long dimm_populated[sizeof(iic0_dimm_addr)];
@@ -421,9 +397,8 @@ long int spd_sdram(void) {
*/
while (1) {
mfsdram(mem_mcsts, mcsts);
- if ((mcsts & SDRAM_MCSTS_MRSC) != 0) {
+ if ((mcsts & SDRAM_MCSTS_MRSC) != 0)
break;
- }
}
/*
@@ -431,14 +406,17 @@ long int spd_sdram(void) {
*/
program_tr1();
+#ifdef CONFIG_DDR_ECC
/*
- * if ECC is enabled, initialize parity bits
+ * If ecc is enabled, initialize the parity bits.
*/
+ program_ecc(total_size);
+#endif
return total_size;
}
-unsigned char spd_read(uchar chip, uint addr)
+static unsigned char spd_read(uchar chip, uint addr)
{
unsigned char data[2];
@@ -460,9 +438,9 @@ unsigned char spd_read(uchar chip, uint addr)
return 0;
}
-void get_spd_info(unsigned long* dimm_populated,
- unsigned char* iic0_dimm_addr,
- unsigned long num_dimm_banks)
+static void get_spd_info(unsigned long *dimm_populated,
+ unsigned char *iic0_dimm_addr,
+ unsigned long num_dimm_banks)
{
unsigned long dimm_num;
unsigned long dimm_found;
@@ -480,14 +458,10 @@ void get_spd_info(unsigned long* dimm_populated,
if ((num_of_bytes != 0) && (total_size != 0)) {
dimm_populated[dimm_num] = TRUE;
dimm_found = TRUE;
-#if 0
- printf("DIMM slot %lu: populated\n", dimm_num);
-#endif
+ debug("DIMM slot %lu: populated\n", dimm_num);
} else {
dimm_populated[dimm_num] = FALSE;
-#if 0
- printf("DIMM slot %lu: Not populated\n", dimm_num);
-#endif
+ debug("DIMM slot %lu: Not populated\n", dimm_num);
}
}
@@ -497,9 +471,9 @@ void get_spd_info(unsigned long* dimm_populated,
}
}
-void check_mem_type(unsigned long* dimm_populated,
- unsigned char* iic0_dimm_addr,
- unsigned long num_dimm_banks)
+static void check_mem_type(unsigned long *dimm_populated,
+ unsigned char *iic0_dimm_addr,
+ unsigned long num_dimm_banks)
{
unsigned long dimm_num;
unsigned char dimm_type;
@@ -509,9 +483,7 @@ void check_mem_type(unsigned long* dimm_populated,
dimm_type = spd_read(iic0_dimm_addr[dimm_num], 2);
switch (dimm_type) {
case 7:
-#if 0
- printf("DIMM slot %lu: DDR SDRAM detected\n", dimm_num);
-#endif
+ debug("DIMM slot %lu: DDR SDRAM detected\n", dimm_num);
break;
default:
printf("ERROR: Unsupported DIMM detected in slot %lu.\n",
@@ -525,10 +497,9 @@ void check_mem_type(unsigned long* dimm_populated,
}
}
-
-void check_volt_type(unsigned long* dimm_populated,
- unsigned char* iic0_dimm_addr,
- unsigned long num_dimm_banks)
+static void check_volt_type(unsigned long *dimm_populated,
+ unsigned char *iic0_dimm_addr,
+ unsigned long num_dimm_banks)
{
unsigned long dimm_num;
unsigned long voltage_type;
@@ -541,18 +512,16 @@ void check_volt_type(unsigned long* dimm_populated,
dimm_num);
hang();
} else {
-#if 0
- printf("DIMM %lu voltage level supported.\n", dimm_num);
-#endif
+ debug("DIMM %lu voltage level supported.\n", dimm_num);
}
break;
}
}
}
-void program_cfg0(unsigned long* dimm_populated,
- unsigned char* iic0_dimm_addr,
- unsigned long num_dimm_banks)
+static void program_cfg0(unsigned long *dimm_populated,
+ unsigned char *iic0_dimm_addr,
+ unsigned long num_dimm_banks)
{
unsigned long dimm_num;
unsigned long cfg0;
@@ -640,9 +609,9 @@ void program_cfg0(unsigned long* dimm_populated,
mtsdram(mem_cfg0, cfg0);
}
-void program_cfg1(unsigned long* dimm_populated,
- unsigned char* iic0_dimm_addr,
- unsigned long num_dimm_banks)
+static void program_cfg1(unsigned long *dimm_populated,
+ unsigned char *iic0_dimm_addr,
+ unsigned long num_dimm_banks)
{
unsigned long cfg1;
mfsdram(mem_cfg1, cfg1);
@@ -658,9 +627,9 @@ void program_cfg1(unsigned long* dimm_populated,
mtsdram(mem_cfg1, cfg1);
}
-void program_rtr (unsigned long* dimm_populated,
- unsigned char* iic0_dimm_addr,
- unsigned long num_dimm_banks)
+static void program_rtr(unsigned long *dimm_populated,
+ unsigned char *iic0_dimm_addr,
+ unsigned long num_dimm_banks)
{
unsigned long dimm_num;
unsigned long bus_period_x_10;
@@ -676,7 +645,6 @@ void program_rtr (unsigned long* dimm_populated,
get_sys_info(&sys_info);
bus_period_x_10 = ONE_BILLION / (sys_info.freqPLB / 10);
-
for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) {
if (dimm_populated[dimm_num] == TRUE) {
refresh_rate_type = 0x7F & spd_read(iic0_dimm_addr[dimm_num], 12);
@@ -719,9 +687,9 @@ void program_rtr (unsigned long* dimm_populated,
mtsdram(mem_rtr, sdram_rtr);
}
-void program_tr0 (unsigned long* dimm_populated,
- unsigned char* iic0_dimm_addr,
- unsigned long num_dimm_banks)
+static void program_tr0(unsigned long *dimm_populated,
+ unsigned char *iic0_dimm_addr,
+ unsigned long num_dimm_banks)
{
unsigned long dimm_num;
unsigned long tr0;
@@ -1001,13 +969,73 @@ void program_tr0 (unsigned long* dimm_populated,
break;
}
-#if 0
- printf("tr0: %x\n", tr0);
-#endif
+ debug("tr0: %x\n", tr0);
mtsdram(mem_tr0, tr0);
}
-void program_tr1 (void)
+static int short_mem_test(void)
+{
+ unsigned long i, j;
+ unsigned long bxcr_num;
+ unsigned long *membase;
+ const unsigned long test[NUMMEMTESTS][NUMMEMWORDS] = {
+ {0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF},
+ {0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+ 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000},
+ {0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555,
+ 0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555},
+ {0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA,
+ 0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA},
+ {0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A,
+ 0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A},
+ {0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5,
+ 0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5},
+ {0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA,
+ 0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA},
+ {0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55,
+ 0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55}};
+
+ for (bxcr_num = 0; bxcr_num < MAXBXCR; bxcr_num++) {
+ mtdcr(memcfga, mem_b0cr + (bxcr_num << 2));
+ if ((mfdcr(memcfgd) & SDRAM_BXCR_SDBE) == SDRAM_BXCR_SDBE) {
+ /* Bank is enabled */
+ membase = (unsigned long*)
+ (mfdcr(memcfgd) & SDRAM_BXCR_SDBA_MASK);
+
+ /*
+ * Run the short memory test
+ */
+ for (i = 0; i < NUMMEMTESTS; i++) {
+ for (j = 0; j < NUMMEMWORDS; j++) {
+ membase[j] = test[i][j];
+ ppcDcbf((unsigned long)&(membase[j]));
+ }
+
+ for (j = 0; j < NUMMEMWORDS; j++) {
+ if (membase[j] != test[i][j]) {
+ ppcDcbf((unsigned long)&(membase[j]));
+ return 0;
+ }
+ ppcDcbf((unsigned long)&(membase[j]));
+ }
+
+ if (j < NUMMEMWORDS)
+ return 0;
+ }
+
+ /*
+ * see if the rdclt value passed
+ */
+ if (i < NUMMEMTESTS)
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+static void program_tr1(void)
{
unsigned long tr0;
unsigned long tr1;
@@ -1015,8 +1043,7 @@ void program_tr1 (void)
unsigned long ecc_temp;
unsigned long dlycal;
unsigned long dly_val;
- unsigned long i, j, k;
- unsigned long bxcr_num;
+ unsigned long k;
unsigned long max_pass_length;
unsigned long current_pass_length;
unsigned long current_fail_length;
@@ -1029,7 +1056,6 @@ void program_tr1 (void)
unsigned char window_found;
unsigned char fail_found;
unsigned char pass_found;
- unsigned long * membase;
PPC440_SYS_INFO sys_info;
/*
@@ -1079,55 +1105,16 @@ void program_tr1 (void)
window_found = FALSE;
fail_found = FALSE;
pass_found = FALSE;
-#ifdef DEBUG
- printf("Starting memory test ");
-#endif
+ debug("Starting memory test ");
+
for (k = 0; k < NUMHALFCYCLES; k++) {
- for (rdclt = 0; rdclt < dly_val; rdclt++) {
+ for (rdclt = 0; rdclt < dly_val; rdclt++) {
/*
* Set the timing reg for the test.
*/
mtsdram(mem_tr1, (tr1 | SDRAM_TR1_RDCT_ENCODE(rdclt)));
- for (bxcr_num = 0; bxcr_num < MAXBXCR; bxcr_num++) {
- mtdcr(memcfga, mem_b0cr + (bxcr_num<<2));
- if ((mfdcr(memcfgd) & SDRAM_BXCR_SDBE) == SDRAM_BXCR_SDBE) {
- /* Bank is enabled */
- membase = (unsigned long*)
- (mfdcr(memcfgd) & SDRAM_BXCR_SDBA_MASK);
-
- /*
- * Run the short memory test
- */
- for (i = 0; i < NUMMEMTESTS; i++) {
- for (j = 0; j < NUMMEMWORDS; j++) {
- membase[j] = test[i][j];
- ppcDcbf((unsigned long)&(membase[j]));
- }
-
- for (j = 0; j < NUMMEMWORDS; j++) {
- if (membase[j] != test[i][j]) {
- ppcDcbf((unsigned long)&(membase[j]));
- break;
- }
- ppcDcbf((unsigned long)&(membase[j]));
- }
-
- if (j < NUMMEMWORDS) {
- break;
- }
- }
-
- /*
- * see if the rdclt value passed
- */
- if (i < NUMMEMTESTS) {
- break;
- }
- }
- }
-
- if (bxcr_num == MAXBXCR) {
+ if (short_mem_test()) {
if (fail_found == TRUE) {
pass_found = TRUE;
if (current_pass_length == 0) {
@@ -1157,9 +1144,8 @@ void program_tr1 (void)
}
}
}
-#ifdef DEBUG
- printf(".");
-#endif
+ debug(".");
+
if (window_found == TRUE) {
break;
}
@@ -1167,9 +1153,7 @@ void program_tr1 (void)
tr1 = tr1 ^ SDRAM_TR1_RDCD_MASK;
rdclt_offset += dly_val;
}
-#ifdef DEBUG
- printf("\n");
-#endif
+ debug("\n");
/*
* make sure we find the window
@@ -1218,18 +1202,17 @@ void program_tr1 (void)
}
tr1 |= SDRAM_TR1_RDCT_ENCODE(rdclt_average);
-#if 0
- printf("tr1: %x\n", tr1);
-#endif
+ debug("tr1: %x\n", tr1);
+
/*
* program SDRAM Timing Register 1 TR1
*/
mtsdram(mem_tr1, tr1);
}
-unsigned long program_bxcr(unsigned long* dimm_populated,
- unsigned char* iic0_dimm_addr,
- unsigned long num_dimm_banks)
+static unsigned long program_bxcr(unsigned long *dimm_populated,
+ unsigned char *iic0_dimm_addr,
+ unsigned long num_dimm_banks)
{
unsigned long dimm_num;
unsigned long bank_base_addr;
@@ -1262,8 +1245,8 @@ unsigned long program_bxcr(unsigned long* dimm_populated,
#ifdef CONFIG_BAMBOO
/*
* This next section is hardware dependent and must be programmed
- * to match the hardware. For bammboo, the following holds...
- * 1. SDRAM0_B0CR: Bank 0 of dimm 0 ctrl_bank_num : 0
+ * to match the hardware. For bamboo, the following holds...
+ * 1. SDRAM0_B0CR: Bank 0 of dimm 0 ctrl_bank_num : 0 (soldered onboard)
* 2. SDRAM0_B1CR: Bank 0 of dimm 1 ctrl_bank_num : 1
* 3. SDRAM0_B2CR: Bank 1 of dimm 1 ctrl_bank_num : 1
* 4. SDRAM0_B3CR: Bank 0 of dimm 2 ctrl_bank_num : 3
@@ -1273,10 +1256,12 @@ unsigned long program_bxcr(unsigned long* dimm_populated,
ctrl_bank_num[1] = 1;
ctrl_bank_num[2] = 3;
#else
+ /*
+ * Ocotea, Ebony and the other IBM/AMCC eval boards have
+ * 2 DIMM slots with each max 2 banks
+ */
ctrl_bank_num[0] = 0;
- ctrl_bank_num[1] = 1;
- ctrl_bank_num[2] = 2;
- ctrl_bank_num[3] = 3;
+ ctrl_bank_num[1] = 2;
#endif
/*
@@ -1290,6 +1275,8 @@ unsigned long program_bxcr(unsigned long* dimm_populated,
num_col_addr = spd_read(iic0_dimm_addr[dimm_num], 4);
num_banks = spd_read(iic0_dimm_addr[dimm_num], 5);
bank_size_id = spd_read(iic0_dimm_addr[dimm_num], 31);
+ debug("DIMM%d: row=%d col=%d banks=%d\n", dimm_num,
+ num_row_addr, num_col_addr, num_banks);
/*
* Set the SDRAM0_BxCR regs
@@ -1354,9 +1341,12 @@ unsigned long program_bxcr(unsigned long* dimm_populated,
cr |= SDRAM_BXCR_SDBE;
for (i = 0; i < num_banks; i++) {
- bank_parms[ctrl_bank_num[dimm_num]+i+dimm_num].bank_size_bytes =
- (4 * 1024 * 1024) * bank_size_id;
- bank_parms[ctrl_bank_num[dimm_num]+i+dimm_num].cr = cr;
+ bank_parms[ctrl_bank_num[dimm_num]+i].bank_size_bytes =
+ (4 << 20) * bank_size_id;
+ bank_parms[ctrl_bank_num[dimm_num]+i].cr = cr;
+ debug("DIMM%d-bank %d (SDRAM0_B%dCR): bank_size_bytes=%d\n",
+ dimm_num, i, ctrl_bank_num[dimm_num]+i,
+ bank_parms[ctrl_bank_num[dimm_num]+i].bank_size_bytes);
}
}
}
@@ -1400,13 +1390,15 @@ unsigned long program_bxcr(unsigned long* dimm_populated,
bank_parms[sorted_bank_num[bx_cr_num]].cr;
mtdcr(memcfgd, temp);
bank_base_addr += bank_parms[sorted_bank_num[bx_cr_num]].bank_size_bytes;
+ debug("SDRAM0_B%dCR=0x%08lx\n", sorted_bank_num[bx_cr_num], temp);
}
}
return(bank_base_addr);
}
-void program_ecc (unsigned long num_bytes)
+#ifdef CONFIG_DDR_ECC
+static void program_ecc(unsigned long num_bytes)
{
unsigned long bank_base_addr;
unsigned long current_address;
@@ -1425,14 +1417,12 @@ void program_ecc (unsigned long num_bytes)
bank_base_addr = CFG_SDRAM_BASE;
if ((cfg0 & SDRAM_CFG0_MCHK_MASK) != SDRAM_CFG0_MCHK_NON) {
- mtsdram(mem_cfg0, (cfg0 & ~SDRAM_CFG0_MCHK_MASK) |
- SDRAM_CFG0_MCHK_GEN);
+ mtsdram(mem_cfg0, (cfg0 & ~SDRAM_CFG0_MCHK_MASK) | SDRAM_CFG0_MCHK_GEN);
- if ((cfg0 & SDRAM_CFG0_DMWD_MASK) == SDRAM_CFG0_DMWD_32) {
+ if ((cfg0 & SDRAM_CFG0_DMWD_MASK) == SDRAM_CFG0_DMWD_32)
address_increment = 4;
- } else {
+ else
address_increment = 8;
- }
current_address = (unsigned long)(bank_base_addr);
end_address = (unsigned long)(bank_base_addr) + num_bytes;
@@ -1446,4 +1436,5 @@ void program_ecc (unsigned long num_bytes)
SDRAM_CFG0_MCHK_CHK);
}
}
+#endif /* CONFIG_DDR_ECC */
#endif /* CONFIG_SPD_EEPROM */
diff --git a/cpu/ppc4xx/ndfc.c b/cpu/ppc4xx/ndfc.c
index 08dfc32..f63fc79 100644
--- a/cpu/ppc4xx/ndfc.c
+++ b/cpu/ppc4xx/ndfc.c
@@ -3,7 +3,7 @@
* Platform independend driver for NDFC (NanD Flash Controller)
* integrated into EP440 cores
*
- * (C) Copyright 2006
+ * (C) Copyright 2006-2007
* Stefan Roese, DENX Software Engineering, sr@denx.de.
*
* Based on original work by
@@ -38,7 +38,9 @@
#include <nand.h>
#include <linux/mtd/ndfc.h>
+#include <linux/mtd/nand_ecc.h>
#include <asm/processor.h>
+#include <asm/io.h>
#include <ppc4xx.h>
static u8 hwctl = 0;
@@ -70,11 +72,11 @@ static void ndfc_write_byte(struct mtd_info *mtdinfo, u_char byte)
ulong base = (ulong) this->IO_ADDR_W & 0xfffffffc;
if (hwctl & 0x1)
- out8(base + NDFC_CMD, byte);
+ out_8((u8 *)(base + NDFC_CMD), byte);
else if (hwctl & 0x2)
- out8(base + NDFC_ALE, byte);
+ out_8((u8 *)(base + NDFC_ALE), byte);
else
- out8(base + NDFC_DATA, byte);
+ out_8((u8 *)(base + NDFC_DATA), byte);
}
static u_char ndfc_read_byte(struct mtd_info *mtdinfo)
@@ -82,7 +84,7 @@ static u_char ndfc_read_byte(struct mtd_info *mtdinfo)
struct nand_chip *this = mtdinfo->priv;
ulong base = (ulong) this->IO_ADDR_W & 0xfffffffc;
- return (in8(base + NDFC_DATA));
+ return (in_8((u8 *)(base + NDFC_DATA)));
}
static int ndfc_dev_ready(struct mtd_info *mtdinfo)
@@ -90,17 +92,41 @@ static int ndfc_dev_ready(struct mtd_info *mtdinfo)
struct nand_chip *this = mtdinfo->priv;
ulong base = (ulong) this->IO_ADDR_W & 0xfffffffc;
- while (!(in32(base + NDFC_STAT) & NDFC_STAT_IS_READY))
+ while (!(in_be32((u32 *)(base + NDFC_STAT)) & NDFC_STAT_IS_READY))
;
return 1;
}
-#ifndef CONFIG_NAND_SPL
-/*
- * Don't use these speedup functions in NAND boot image, since the image
- * has to fit into 4kByte.
- */
+static void ndfc_enable_hwecc(struct mtd_info *mtdinfo, int mode)
+{
+ struct nand_chip *this = mtdinfo->priv;
+ ulong base = (ulong) this->IO_ADDR_W & 0xfffffffc;
+ u32 ccr;
+
+ ccr = in_be32((u32 *)(base + NDFC_CCR));
+ ccr |= NDFC_CCR_RESET_ECC;
+ out_be32((u32 *)(base + NDFC_CCR), ccr);
+}
+
+static int ndfc_calculate_ecc(struct mtd_info *mtdinfo,
+ const u_char *dat, u_char *ecc_code)
+{
+ struct nand_chip *this = mtdinfo->priv;
+ ulong base = (ulong) this->IO_ADDR_W & 0xfffffffc;
+ u32 ecc;
+ u8 *p = (u8 *)&ecc;
+
+ ecc = in_be32((u32 *)(base + NDFC_ECC));
+
+ /* The NDFC uses Smart Media (SMC) bytes order
+ */
+ ecc_code[0] = p[2];
+ ecc_code[1] = p[1];
+ ecc_code[2] = p[3];
+
+ return 0;
+}
/*
* Speedups for buffer read/write/verify
@@ -116,9 +142,14 @@ static void ndfc_read_buf(struct mtd_info *mtdinfo, uint8_t *buf, int len)
uint32_t *p = (uint32_t *) buf;
for (;len > 0; len -= 4)
- *p++ = in32(base + NDFC_DATA);
+ *p++ = in_be32((u32 *)(base + NDFC_DATA));
}
+#ifndef CONFIG_NAND_SPL
+/*
+ * Don't use these speedup functions in NAND boot image, since the image
+ * has to fit into 4kByte.
+ */
static void ndfc_write_buf(struct mtd_info *mtdinfo, const uint8_t *buf, int len)
{
struct nand_chip *this = mtdinfo->priv;
@@ -126,7 +157,7 @@ static void ndfc_write_buf(struct mtd_info *mtdinfo, const uint8_t *buf, int len
uint32_t *p = (uint32_t *) buf;
for (; len > 0; len -= 4)
- out32(base + NDFC_DATA, *p++);
+ out_be32((u32 *)(base + NDFC_DATA), *p++);
}
static int ndfc_verify_buf(struct mtd_info *mtdinfo, const uint8_t *buf, int len)
@@ -136,7 +167,7 @@ static int ndfc_verify_buf(struct mtd_info *mtdinfo, const uint8_t *buf, int len
uint32_t *p = (uint32_t *) buf;
for (; len > 0; len -= 4)
- if (*p++ != in32(base + NDFC_DATA))
+ if (*p++ != in_be32((u32 *)(base + NDFC_DATA)))
return -1;
return 0;
@@ -153,8 +184,8 @@ void board_nand_select_device(struct nand_chip *nand, int chip)
ulong base = (ulong)nand->IO_ADDR_W & 0xfffffffc;
/* Set NandFlash Core Configuration Register */
- /* 1col x 2 rows */
- out32(base + NDFC_CCR, 0x00000000 | (cs << 24));
+ /* 1 col x 2 rows */
+ out_be32((u32 *)(base + NDFC_CCR), 0x00000000 | (cs << 24));
}
int board_nand_init(struct nand_chip *nand)
@@ -162,16 +193,19 @@ int board_nand_init(struct nand_chip *nand)
int cs = (ulong)nand->IO_ADDR_W & 0x00000003;
ulong base = (ulong)nand->IO_ADDR_W & 0xfffffffc;
- nand->eccmode = NAND_ECC_SOFT;
-
nand->hwcontrol = ndfc_hwcontrol;
nand->read_byte = ndfc_read_byte;
+ nand->read_buf = ndfc_read_buf;
nand->write_byte = ndfc_write_byte;
nand->dev_ready = ndfc_dev_ready;
+ nand->eccmode = NAND_ECC_HW3_256;
+ nand->enable_hwecc = ndfc_enable_hwecc;
+ nand->calculate_ecc = ndfc_calculate_ecc;
+ nand->correct_data = nand_correct_data;
+
#ifndef CONFIG_NAND_SPL
nand->write_buf = ndfc_write_buf;
- nand->read_buf = ndfc_read_buf;
nand->verify_buf = ndfc_verify_buf;
#else
/*
@@ -187,7 +221,7 @@ int board_nand_init(struct nand_chip *nand)
* Select required NAND chip in NDFC
*/
board_nand_select_device(nand, cs);
- out32(base + NDFC_BCFG0 + (cs << 2), 0x80002222);
+ out_be32((u32 *)(base + NDFC_BCFG0 + (cs << 2)), 0x80002222);
return 0;
}
diff --git a/cpu/ppc4xx/start.S b/cpu/ppc4xx/start.S
index 85660b4..78de300 100644
--- a/cpu/ppc4xx/start.S
+++ b/cpu/ppc4xx/start.S
@@ -110,6 +110,13 @@
# endif
#endif /* CFG_INIT_DCACHE_CS */
+#define function_prolog(func_name) .text; \
+ .align 2; \
+ .globl func_name; \
+ func_name:
+#define function_epilog(func_name) .type func_name,@function; \
+ .size func_name,.-func_name
+
/* We don't want the MMU yet.
*/
#undef MSR_KERNEL
@@ -388,8 +395,9 @@ rsttlb: tlbwe r0,r1,0x0000 /* Invalidate all entries (V=0)*/
2:
#if defined(CONFIG_NAND_SPL)
+#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
/*
- * Enable internal SRAM
+ * Enable internal SRAM (only on 440EPx/GRx, 440EP/GR have no OCM)
*/
lis r2,0x7fff
ori r2,r2,0xffff
@@ -399,6 +407,45 @@ rsttlb: tlbwe r0,r1,0x0000 /* Invalidate all entries (V=0)*/
mfdcr r1,isram0_pmeg
and r1,r1,r2 /* Disable pwr mgmt */
mtdcr isram0_pmeg,r1
+#endif
+#if defined(CONFIG_440EP)
+ /*
+ * On 440EP with no internal SRAM, we setup SDRAM very early
+ * and copy the NAND_SPL to SDRAM and jump to it
+ */
+ /* Clear Dcache to use as RAM */
+ addis r3,r0,CFG_INIT_RAM_ADDR@h
+ ori r3,r3,CFG_INIT_RAM_ADDR@l
+ addis r4,r0,CFG_INIT_RAM_END@h
+ ori r4,r4,CFG_INIT_RAM_END@l
+ rlwinm. r5,r4,0,27,31
+ rlwinm r5,r4,27,5,31
+ beq ..d_ran3
+ addi r5,r5,0x0001
+..d_ran3:
+ mtctr r5
+..d_ag3:
+ dcbz r0,r3
+ addi r3,r3,32
+ bdnz ..d_ag3
+ /*----------------------------------------------------------------*/
+ /* Setup the stack in internal SRAM */
+ /*----------------------------------------------------------------*/
+ lis r1,CFG_INIT_RAM_ADDR@h
+ ori r1,r1,CFG_INIT_SP_OFFSET@l
+ li r0,0
+ stwu r0,-4(r1)
+ stwu r0,-4(r1) /* Terminate call chain */
+
+ stwu r1,-8(r1) /* Save back chain and move SP */
+ lis r0,RESET_VECTOR@h /* Address of reset vector */
+ ori r0,r0, RESET_VECTOR@l
+ stwu r1,-8(r1) /* Save back chain and move SP */
+ stw r0,+12(r1) /* Save return addr (underflow vect) */
+ sync
+ bl early_sdram_init
+ sync
+#endif /* CONFIG_440EP */
/*
* Copy SPL from cache into internal SRAM
@@ -429,7 +476,7 @@ spl_loop:
start_ram:
sync
isync
-#endif
+#endif /* CONFIG_NAND_SPL */
bl 3f
b _start
@@ -1137,7 +1184,6 @@ crit_return:
lwz r1,GPR1(r1)
SYNC
rfci
-#endif /* CONFIG_NAND_SPL */
/* Cache functions.
*/
@@ -1255,24 +1301,6 @@ wr_tcr:
blr
/*------------------------------------------------------------------------------- */
-/* Function: in8 */
-/* Description: Input 8 bits */
-/*------------------------------------------------------------------------------- */
- .globl in8
-in8:
- lbz r3,0x0000(r3)
- blr
-
-/*------------------------------------------------------------------------------- */
-/* Function: out8 */
-/* Description: Output 8 bits */
-/*------------------------------------------------------------------------------- */
- .globl out8
-out8:
- stb r4,0x0000(r3)
- blr
-
-/*------------------------------------------------------------------------------- */
/* Function: out16 */
/* Description: Output 16 bits */
/*------------------------------------------------------------------------------- */
@@ -1291,15 +1319,6 @@ out16r:
blr
/*------------------------------------------------------------------------------- */
-/* Function: out32 */
-/* Description: Output 32 bits */
-/*------------------------------------------------------------------------------- */
- .globl out32
-out32:
- stw r4,0x0000(r3)
- blr
-
-/*------------------------------------------------------------------------------- */
/* Function: out32r */
/* Description: Byte reverse and output 32 bits */
/*------------------------------------------------------------------------------- */
@@ -1327,15 +1346,6 @@ in16r:
blr
/*------------------------------------------------------------------------------- */
-/* Function: in32 */
-/* Description: Input 32 bits */
-/*------------------------------------------------------------------------------- */
- .globl in32
-in32:
- lwz 3,0x0000(3)
- blr
-
-/*------------------------------------------------------------------------------- */
/* Function: in32r */
/* Description: Input 32 bits and byte reverse */
/*------------------------------------------------------------------------------- */
@@ -1377,9 +1387,6 @@ ppcSync:
sync
blr
-/*------------------------------------------------------------------------------*/
-
-#ifndef CONFIG_NAND_SPL
/*
* void relocate_code (addr_sp, gd, addr_moni)
*
@@ -1644,8 +1651,88 @@ trap_reloc:
stw r0, 4(r7)
blr
+
+#if defined(CONFIG_440)
+/*----------------------------------------------------------------------------+
+| dcbz_area.
++----------------------------------------------------------------------------*/
+ function_prolog(dcbz_area)
+ rlwinm. r5,r4,0,27,31
+ rlwinm r5,r4,27,5,31
+ beq ..d_ra2
+ addi r5,r5,0x0001
+..d_ra2:mtctr r5
+..d_ag2:dcbz r0,r3
+ addi r3,r3,32
+ bdnz ..d_ag2
+ sync
+ blr
+ function_epilog(dcbz_area)
+
+/*----------------------------------------------------------------------------+
+| dflush. Assume 32K at vector address is cachable.
++----------------------------------------------------------------------------*/
+ function_prolog(dflush)
+ mfmsr r9
+ rlwinm r8,r9,0,15,13
+ rlwinm r8,r8,0,17,15
+ mtmsr r8
+ addi r3,r0,0x0000
+ mtspr dvlim,r3
+ mfspr r3,ivpr
+ addi r4,r0,1024
+ mtctr r4
+..dflush_loop:
+ lwz r6,0x0(r3)
+ addi r3,r3,32
+ bdnz ..dflush_loop
+ addi r3,r3,-32
+ mtctr r4
+..ag: dcbf r0,r3
+ addi r3,r3,-32
+ bdnz ..ag
+ sync
+ mtmsr r9
+ blr
+ function_epilog(dflush)
+#endif /* CONFIG_440 */
#endif /* CONFIG_NAND_SPL */
+/*------------------------------------------------------------------------------- */
+/* Function: in8 */
+/* Description: Input 8 bits */
+/*------------------------------------------------------------------------------- */
+ .globl in8
+in8:
+ lbz r3,0x0000(r3)
+ blr
+
+/*------------------------------------------------------------------------------- */
+/* Function: out8 */
+/* Description: Output 8 bits */
+/*------------------------------------------------------------------------------- */
+ .globl out8
+out8:
+ stb r4,0x0000(r3)
+ blr
+
+/*------------------------------------------------------------------------------- */
+/* Function: out32 */
+/* Description: Output 32 bits */
+/*------------------------------------------------------------------------------- */
+ .globl out32
+out32:
+ stw r4,0x0000(r3)
+ blr
+
+/*------------------------------------------------------------------------------- */
+/* Function: in32 */
+/* Description: Input 32 bits */
+/*------------------------------------------------------------------------------- */
+ .globl in32
+in32:
+ lwz 3,0x0000(3)
+ blr
/**************************************************************************/
/* PPC405EP specific stuff */
@@ -1892,13 +1979,6 @@ pll_wait:
#endif /* CONFIG_405EP */
#if defined(CONFIG_440)
-#define function_prolog(func_name) .text; \
- .align 2; \
- .globl func_name; \
- func_name:
-#define function_epilog(func_name) .type func_name,@function; \
- .size func_name,.-func_name
-
/*----------------------------------------------------------------------------+
| mttlb3.
+----------------------------------------------------------------------------*/
@@ -1946,47 +2026,4 @@ pll_wait:
TLBRE(3,3,0)
blr
function_epilog(mftlb1)
-
-/*----------------------------------------------------------------------------+
-| dcbz_area.
-+----------------------------------------------------------------------------*/
- function_prolog(dcbz_area)
- rlwinm. r5,r4,0,27,31
- rlwinm r5,r4,27,5,31
- beq ..d_ra2
- addi r5,r5,0x0001
-..d_ra2:mtctr r5
-..d_ag2:dcbz r0,r3
- addi r3,r3,32
- bdnz ..d_ag2
- sync
- blr
- function_epilog(dcbz_area)
-
-/*----------------------------------------------------------------------------+
-| dflush. Assume 32K at vector address is cachable.
-+----------------------------------------------------------------------------*/
- function_prolog(dflush)
- mfmsr r9
- rlwinm r8,r9,0,15,13
- rlwinm r8,r8,0,17,15
- mtmsr r8
- addi r3,r0,0x0000
- mtspr dvlim,r3
- mfspr r3,ivpr
- addi r4,r0,1024
- mtctr r4
-..dflush_loop:
- lwz r6,0x0(r3)
- addi r3,r3,32
- bdnz ..dflush_loop
- addi r3,r3,-32
- mtctr r4
-..ag: dcbf r0,r3
- addi r3,r3,-32
- bdnz ..ag
- sync
- mtmsr r9
- blr
- function_epilog(dflush)
#endif /* CONFIG_440 */