diff options
author | Stefan Roese <sr@denx.de> | 2007-06-01 16:15:34 +0200 |
---|---|---|
committer | Stefan Roese <sr@denx.de> | 2007-06-01 16:15:34 +0200 |
commit | f3679aa13d9f483adb38245a87ecd5c84f57a5d3 (patch) | |
tree | 56099e57611527ba2460cd57f1f8af5c0b686a6e /cpu/ppc4xx | |
parent | 155a96478a0881e6da96cbbbcf34952d6a3b1b4b (diff) | |
parent | 9d9096043e8f713d4bf1743d32e1459e6a11644b (diff) | |
download | u-boot-imx-f3679aa13d9f483adb38245a87ecd5c84f57a5d3.zip u-boot-imx-f3679aa13d9f483adb38245a87ecd5c84f57a5d3.tar.gz u-boot-imx-f3679aa13d9f483adb38245a87ecd5c84f57a5d3.tar.bz2 |
Merge with /home/stefan/git/u-boot/bamboo-nand
Diffstat (limited to 'cpu/ppc4xx')
-rw-r--r-- | cpu/ppc4xx/44x_spd_ddr.c | 341 | ||||
-rw-r--r-- | cpu/ppc4xx/ndfc.c | 74 | ||||
-rw-r--r-- | cpu/ppc4xx/start.S | 221 |
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 */ |