summaryrefslogtreecommitdiff
path: root/cpu/ppc4xx
diff options
context:
space:
mode:
authorMarkus Klotzbuecher <mk@denx.de>2007-04-23 13:17:22 +0200
committerMarkus Klotzbuecher <mk@pollux.denx.de>2007-04-23 13:17:22 +0200
commit61ea75aa07838435ec570ac85a2e3fc038844596 (patch)
tree20135a513c4c9d0bddb2a8ceaf009a8ed5e8bbdf /cpu/ppc4xx
parente2fb36a57f364016b973b1db255531e07cfefd52 (diff)
parent14da5f7675bbb427c469e3f45006e027b6e21db9 (diff)
Merge with git://www.denx.de/git/u-boot.git
Diffstat (limited to 'cpu/ppc4xx')
-rw-r--r--cpu/ppc4xx/44x_spd_ddr2.c193
-rw-r--r--cpu/ppc4xx/Makefile2
-rw-r--r--cpu/ppc4xx/cpu.c30
-rw-r--r--cpu/ppc4xx/cpu_init.c115
-rw-r--r--cpu/ppc4xx/gpio.c214
-rw-r--r--cpu/ppc4xx/i2c.c4
-rw-r--r--cpu/ppc4xx/start.S105
7 files changed, 408 insertions, 255 deletions
diff --git a/cpu/ppc4xx/44x_spd_ddr2.c b/cpu/ppc4xx/44x_spd_ddr2.c
index 83c991116f..2ecd3e4b61 100644
--- a/cpu/ppc4xx/44x_spd_ddr2.c
+++ b/cpu/ppc4xx/44x_spd_ddr2.c
@@ -107,10 +107,11 @@
#define CALC_ODT_RW(n) (CALC_ODT_R(n) | CALC_ODT_W(n))
/* Defines for the Read Cycle Delay test */
-#define NUMMEMTESTS 8
-#define NUMMEMWORDS 8
+#define NUMMEMTESTS 8
+#define NUMMEMWORDS 8
+#define NUMLOOPS 256 /* memory test loops */
-#define CONFIG_ECC_ERROR_RESET /* test-only: see description below, at check_ecc() */
+#undef CONFIG_ECC_ERROR_RESET /* test-only: see description below, at check_ecc() */
/*
* This DDR2 setup code can dynamically setup the TLB entries for the DDR2 memory
@@ -584,10 +585,23 @@ static void get_spd_info(unsigned long *dimm_populated,
#ifdef CONFIG_ADD_RAM_INFO
void board_add_ram_info(int use_default)
{
+ PPC440_SYS_INFO board_cfg;
+ u32 val;
+
if (is_ecc_enabled())
- puts(" (ECC enabled)");
+ puts(" (ECC");
else
- puts(" (ECC not enabled)");
+ 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);
}
#endif
@@ -731,6 +745,7 @@ static void check_frequency(unsigned long *dimm_populated,
else
cycle_time = (((tcyc_reg & 0xF0) >> 4) * 100) +
((tcyc_reg & 0x0F)*10);
+ debug("cycle_time=%d [10 picoseconds]\n", cycle_time);
if (cycle_time > (calc_cycle_time + 10)) {
/*
@@ -1109,7 +1124,7 @@ static void program_codt(unsigned long *dimm_populated,
modt3 = 0x00000000;
}
}
- } else {
+ } else {
codt |= SDRAM_CODT_DQS_2_5_V_DDR1;
modt0 = 0x00000000;
modt1 = 0x00000000;
@@ -1315,6 +1330,7 @@ static void program_mode(unsigned long *dimm_populated,
mfsdr(SDR0_DDR0, sdr_ddrpll);
sdram_freq = MULDIV64((board_cfg.freqPLB), SDR0_DDR0_DDRM_DECODE(sdr_ddrpll), 1);
+ debug("sdram_freq=%d\n", sdram_freq);
/*------------------------------------------------------------------
* Handle the timing. We need to find the worst case timing of all
@@ -1344,6 +1360,7 @@ static void program_mode(unsigned long *dimm_populated,
/* t_wr_ns = max(t_wr_ns, (unsigned long)dimm_spd[dimm_num][36] >> 2); */ /* not used in this loop. */
cas_bit = spd_read(iic0_dimm_addr[dimm_num], 18);
+ debug("cas_bit[SPD byte 18]=%02x\n", cas_bit);
/* For a particular DIMM, grab the three CAS values it supports */
for (cas_index = 0; cas_index < 3; cas_index++) {
@@ -1362,7 +1379,8 @@ static void program_mode(unsigned long *dimm_populated,
if ((tcyc_reg & 0x0F) >= 10) {
if ((tcyc_reg & 0x0F) == 0x0D) {
/* Convert from hex to decimal */
- cycle_time_ns_x_100[cas_index] = (((tcyc_reg & 0xF0) >> 4) * 100) + 75;
+ cycle_time_ns_x_100[cas_index] =
+ (((tcyc_reg & 0xF0) >> 4) * 100) + 75;
} else {
printf("ERROR: SPD reported Tcyc is incorrect for DIMM "
"in slot %d\n", (unsigned int)dimm_num);
@@ -1370,9 +1388,12 @@ static void program_mode(unsigned long *dimm_populated,
}
} else {
/* Convert from hex to decimal */
- cycle_time_ns_x_100[cas_index] = (((tcyc_reg & 0xF0) >> 4) * 100) +
+ cycle_time_ns_x_100[cas_index] =
+ (((tcyc_reg & 0xF0) >> 4) * 100) +
((tcyc_reg & 0x0F)*10);
}
+ debug("cas_index=%d: cycle_time_ns_x_100=%d\n", cas_index,
+ cycle_time_ns_x_100[cas_index]);
}
/* The rest of this routine determines if CAS 2.0, 2.5, 3.0, 4.0 and 5.0 are */
@@ -1385,8 +1406,10 @@ static void program_mode(unsigned long *dimm_populated,
* Bit 7 6 5 4 3 2 1 0
* TBD 4.0 3.5 3.0 2.5 2.0 1.5 1.0
*/
- if (((cas_bit & 0x40) == 0x40) && (cas_index < 3) && (cycle_time_ns_x_100[cas_index] != 0)) {
- max_4_0_tcyc_ns_x_100 = max(max_4_0_tcyc_ns_x_100, cycle_time_ns_x_100[cas_index]);
+ if (((cas_bit & 0x40) == 0x40) && (cas_index < 3) &&
+ (cycle_time_ns_x_100[cas_index] != 0)) {
+ max_4_0_tcyc_ns_x_100 = max(max_4_0_tcyc_ns_x_100,
+ cycle_time_ns_x_100[cas_index]);
cas_index++;
} else {
if (cas_index != 0)
@@ -1394,8 +1417,10 @@ static void program_mode(unsigned long *dimm_populated,
cas_4_0_available = FALSE;
}
- if (((cas_bit & 0x10) == 0x10) && (cas_index < 3) && (cycle_time_ns_x_100[cas_index] != 0)) {
- max_3_0_tcyc_ns_x_100 = max(max_3_0_tcyc_ns_x_100, cycle_time_ns_x_100[cas_index]);
+ if (((cas_bit & 0x10) == 0x10) && (cas_index < 3) &&
+ (cycle_time_ns_x_100[cas_index] != 0)) {
+ max_3_0_tcyc_ns_x_100 = max(max_3_0_tcyc_ns_x_100,
+ cycle_time_ns_x_100[cas_index]);
cas_index++;
} else {
if (cas_index != 0)
@@ -1403,8 +1428,10 @@ static void program_mode(unsigned long *dimm_populated,
cas_3_0_available = FALSE;
}
- if (((cas_bit & 0x08) == 0x08) && (cas_index < 3) && (cycle_time_ns_x_100[cas_index] != 0)) {
- max_2_5_tcyc_ns_x_100 = max(max_2_5_tcyc_ns_x_100, cycle_time_ns_x_100[cas_index]);
+ if (((cas_bit & 0x08) == 0x08) && (cas_index < 3) &&
+ (cycle_time_ns_x_100[cas_index] != 0)) {
+ max_2_5_tcyc_ns_x_100 = max(max_2_5_tcyc_ns_x_100,
+ cycle_time_ns_x_100[cas_index]);
cas_index++;
} else {
if (cas_index != 0)
@@ -1412,8 +1439,10 @@ static void program_mode(unsigned long *dimm_populated,
cas_2_5_available = FALSE;
}
- if (((cas_bit & 0x04) == 0x04) && (cas_index < 3) && (cycle_time_ns_x_100[cas_index] != 0)) {
- max_2_0_tcyc_ns_x_100 = max(max_2_0_tcyc_ns_x_100, cycle_time_ns_x_100[cas_index]);
+ if (((cas_bit & 0x04) == 0x04) && (cas_index < 3) &&
+ (cycle_time_ns_x_100[cas_index] != 0)) {
+ max_2_0_tcyc_ns_x_100 = max(max_2_0_tcyc_ns_x_100,
+ cycle_time_ns_x_100[cas_index]);
cas_index++;
} else {
if (cas_index != 0)
@@ -1426,8 +1455,10 @@ static void program_mode(unsigned long *dimm_populated,
* Bit 7 6 5 4 3 2 1 0
* TBD 6.0 5.0 4.0 3.0 2.0 TBD TBD
*/
- if (((cas_bit & 0x20) == 0x20) && (cas_index < 3) && (cycle_time_ns_x_100[cas_index] != 0)) {
- max_5_0_tcyc_ns_x_100 = max(max_5_0_tcyc_ns_x_100, cycle_time_ns_x_100[cas_index]);
+ if (((cas_bit & 0x20) == 0x20) && (cas_index < 3) &&
+ (cycle_time_ns_x_100[cas_index] != 0)) {
+ max_5_0_tcyc_ns_x_100 = max(max_5_0_tcyc_ns_x_100,
+ cycle_time_ns_x_100[cas_index]);
cas_index++;
} else {
if (cas_index != 0)
@@ -1435,8 +1466,10 @@ static void program_mode(unsigned long *dimm_populated,
cas_5_0_available = FALSE;
}
- if (((cas_bit & 0x10) == 0x10) && (cas_index < 3) && (cycle_time_ns_x_100[cas_index] != 0)) {
- max_4_0_tcyc_ns_x_100 = max(max_4_0_tcyc_ns_x_100, cycle_time_ns_x_100[cas_index]);
+ if (((cas_bit & 0x10) == 0x10) && (cas_index < 3) &&
+ (cycle_time_ns_x_100[cas_index] != 0)) {
+ max_4_0_tcyc_ns_x_100 = max(max_4_0_tcyc_ns_x_100,
+ cycle_time_ns_x_100[cas_index]);
cas_index++;
} else {
if (cas_index != 0)
@@ -1444,8 +1477,10 @@ static void program_mode(unsigned long *dimm_populated,
cas_4_0_available = FALSE;
}
- if (((cas_bit & 0x08) == 0x08) && (cas_index < 3) && (cycle_time_ns_x_100[cas_index] != 0)) {
- max_3_0_tcyc_ns_x_100 = max(max_3_0_tcyc_ns_x_100, cycle_time_ns_x_100[cas_index]);
+ if (((cas_bit & 0x08) == 0x08) && (cas_index < 3) &&
+ (cycle_time_ns_x_100[cas_index] != 0)) {
+ max_3_0_tcyc_ns_x_100 = max(max_3_0_tcyc_ns_x_100,
+ cycle_time_ns_x_100[cas_index]);
cas_index++;
} else {
if (cas_index != 0)
@@ -1468,6 +1503,9 @@ static void program_mode(unsigned long *dimm_populated,
cycle_3_0_clk = MULDIV64(ONE_BILLION, 100, max_3_0_tcyc_ns_x_100) + 10;
cycle_4_0_clk = MULDIV64(ONE_BILLION, 100, max_4_0_tcyc_ns_x_100) + 10;
cycle_5_0_clk = MULDIV64(ONE_BILLION, 100, max_5_0_tcyc_ns_x_100) + 10;
+ debug("cycle_3_0_clk=%d\n", cycle_3_0_clk);
+ debug("cycle_4_0_clk=%d\n", cycle_4_0_clk);
+ debug("cycle_5_0_clk=%d\n", cycle_5_0_clk);
if (sdram_ddr1 == TRUE) { /* DDR1 */
if ((cas_2_0_available == TRUE) && (sdram_freq <= cycle_2_0_clk)) {
@@ -1486,6 +1524,9 @@ static void program_mode(unsigned long *dimm_populated,
hang();
}
} else { /* DDR2 */
+ debug("cas_3_0_available=%d\n", cas_3_0_available);
+ debug("cas_4_0_available=%d\n", cas_4_0_available);
+ debug("cas_5_0_available=%d\n", cas_5_0_available);
if ((cas_3_0_available == TRUE) && (sdram_freq <= cycle_3_0_clk)) {
mmode |= SDRAM_MMODE_DCL_DDR2_3_0_CLK;
*selected_cas = DDR_CAS_3;
@@ -2137,6 +2178,18 @@ static unsigned long is_ecc_enabled(void)
return ecc;
}
+static void blank_string(int size)
+{
+ int i;
+
+ for (i=0; i<size; i++)
+ putc('\b');
+ for (i=0; i<size; i++)
+ putc(' ');
+ for (i=0; i<size; i++)
+ putc('\b');
+}
+
#ifdef CONFIG_DDR_ECC
/*-----------------------------------------------------------------------------+
* program_ecc.
@@ -2233,8 +2286,10 @@ static void program_ecc_addr(unsigned long start_address,
unsigned long end_address;
unsigned long address_increment;
unsigned long mcopt1;
- char str[] = "ECC generation...";
- int i;
+ char str[] = "ECC generation -";
+ char slash[] = "\\|/-\\|/-";
+ int loop = 0;
+ int loopi = 0;
current_address = start_address;
mfsdram(SDRAM_MCOPT1, mcopt1);
@@ -2257,14 +2312,20 @@ static void program_ecc_addr(unsigned long start_address,
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);
dflush();
}
- for (i=0; i<strlen(str); i++)
- putc('\b');
+
+ blank_string(strlen(str));
sync();
eieio();
@@ -2347,7 +2408,7 @@ static void program_DQS_calibration(unsigned long *dimm_populated,
#endif
}
-static u32 short_mem_test(void)
+static int short_mem_test(void)
{
u32 *membase;
u32 bxcr_num;
@@ -2371,42 +2432,41 @@ static u32 short_mem_test(void)
0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA},
{0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55,
0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55} };
+ int l;
for (bxcr_num = 0; bxcr_num < MAXBXCF; bxcr_num++) {
mfsdram(SDRAM_MB0CF + (bxcr_num << 2), bxcf);
/* Banks enabled */
if ((bxcf & SDRAM_BXCF_M_BE_MASK) == SDRAM_BXCF_M_BE_ENABLE) {
-
/* Bank is enabled */
- membase = (u32 *)(SDRAM_RXBAS_SDBA_DECODE(mfdcr_any(SDRAM_R0BAS+bxcr_num)));
/*------------------------------------------------------------------
* Run the short memory test.
*-----------------------------------------------------------------*/
+ membase = (u32 *)(SDRAM_RXBAS_SDBA_DECODE(mfdcr_any(SDRAM_R0BAS+bxcr_num)));
+
for (i = 0; i < NUMMEMTESTS; i++) {
for (j = 0; j < NUMMEMWORDS; j++) {
membase[j] = test[i][j];
ppcDcbf((u32)&(membase[j]));
}
sync();
- for (j = 0; j < NUMMEMWORDS; j++) {
- if (membase[j] != test[i][j]) {
+ for (l=0; l<NUMLOOPS; l++) {
+ for (j = 0; j < NUMMEMWORDS; j++) {
+ if (membase[j] != test[i][j]) {
+ ppcDcbf((u32)&(membase[j]));
+ return 0;
+ }
ppcDcbf((u32)&(membase[j]));
- break;
}
- ppcDcbf((u32)&(membase[j]));
+ sync();
}
- sync();
- if (j < NUMMEMWORDS)
- break;
}
- if (i < NUMMEMTESTS)
- break;
} /* if bank enabled */
} /* for bxcf_num */
- return bxcr_num;
+ return 1;
}
#ifndef HARD_CODED_DQS
@@ -2415,12 +2475,10 @@ static u32 short_mem_test(void)
*-----------------------------------------------------------------------------*/
static void DQS_calibration_process(void)
{
- unsigned long ecc_temp;
unsigned long rfdc_reg;
unsigned long rffd;
unsigned long rqdc_reg;
unsigned long rqfd;
- unsigned long bxcr_num;
unsigned long val;
long rqfd_average;
long rffd_average;
@@ -2440,6 +2498,10 @@ static void DQS_calibration_process(void)
long max_end;
unsigned char fail_found;
unsigned char pass_found;
+ u32 rqfd_start;
+ char str[] = "Auto calibration -";
+ char slash[] = "\\|/-\\|/-";
+ int loopi = 0;
/*------------------------------------------------------------------
* Test to determine the best read clock delay tuning bits.
@@ -2464,11 +2526,16 @@ static void DQS_calibration_process(void)
* we can clock the DDR interface at is 200 MHz (2x 100 MHz PLB speed),
* from experimentation it is safe to say you will always have a failure.
*-----------------------------------------------------------------*/
- mfsdram(SDRAM_MCOPT1, ecc_temp);
- ecc_temp &= SDRAM_MCOPT1_MCHK_MASK;
- mfsdram(SDRAM_MCOPT1, val);
- mtsdram(SDRAM_MCOPT1, (val & ~SDRAM_MCOPT1_MCHK_MASK) |
- SDRAM_MCOPT1_MCHK_NON);
+
+ /* first fix RQDC[RQFD] to an average of 80 degre phase shift to find RFDC[RFFD] */
+ rqfd_start = 64; /* test-only: don't know if this is the _best_ start value */
+
+ puts(str);
+
+calibration_loop:
+ mfsdram(SDRAM_RQDC, rqdc_reg);
+ mtsdram(SDRAM_RQDC, (rqdc_reg & ~SDRAM_RQDC_RQFD_MASK) |
+ SDRAM_RQDC_RQFD_ENCODE(rqfd_start));
max_start = 0;
min_end = 0;
@@ -2492,9 +2559,6 @@ static void DQS_calibration_process(void)
fail_found = FALSE;
pass_found = FALSE;
- /* first fix RQDC[RQFD] to an average of 80 degre phase shift to find RFDC[RFFD] */
- /* rqdc_reg = mfsdram(SDRAM_RQDC) & ~(SDRAM_RQDC_RQFD_MASK); */
-
/*
* get the delay line calibration register value
*/
@@ -2510,13 +2574,10 @@ static void DQS_calibration_process(void)
*-----------------------------------------------------------------*/
mtsdram(SDRAM_RFDC, rfdc_reg | SDRAM_RFDC_RFFD_ENCODE(rffd));
- /* do the small memory test */
- bxcr_num = short_mem_test();
-
/*------------------------------------------------------------------
* See if the rffd value passed.
*-----------------------------------------------------------------*/
- if (bxcr_num == MAXBXCF) {
+ if (short_mem_test()) {
if (fail_found == TRUE) {
pass_found = TRUE;
if (current_pass_length == 0)
@@ -2578,13 +2639,10 @@ static void DQS_calibration_process(void)
*-----------------------------------------------------------------*/
mtsdram(SDRAM_RQDC, rqdc_reg | SDRAM_RQDC_RQFD_ENCODE(rqfd));
- /* do the small memory test */
- bxcr_num = short_mem_test();
-
/*------------------------------------------------------------------
* See if the rffd value passed.
*-----------------------------------------------------------------*/
- if (bxcr_num == MAXBXCF) {
+ if (short_mem_test()) {
if (fail_found == TRUE) {
pass_found = TRUE;
if (current_pass_length == 0)
@@ -2612,17 +2670,28 @@ static void DQS_calibration_process(void)
}
}
+ rqfd_average = ((max_start + max_end) >> 1);
+
/*------------------------------------------------------------------
* Make sure we found the valid read passing window. Halt if not
*-----------------------------------------------------------------*/
if (window_found == FALSE) {
- printf("ERROR: Cannot determine a common read delay for the "
+ if (rqfd_start < SDRAM_RQDC_RQFD_MAX) {
+ putc('\b');
+ putc(slash[loopi++ % 8]);
+
+ /* try again from with a different RQFD start value */
+ rqfd_start++;
+ goto calibration_loop;
+ }
+
+ printf("\nERROR: Cannot determine a common read delay for the "
"DIMM(s) installed.\n");
debug("%s[%d] ERROR : \n", __FUNCTION__,__LINE__);
hang();
}
- rqfd_average = ((max_start + max_end) >> 1);
+ blank_string(strlen(str));
if (rqfd_average < 0)
rqfd_average = 0;
@@ -2630,12 +2699,6 @@ static void DQS_calibration_process(void)
if (rqfd_average > SDRAM_RQDC_RQFD_MAX)
rqfd_average = SDRAM_RQDC_RQFD_MAX;
- /*------------------------------------------------------------------
- * Restore the ECC variable to what it originally was
- *-----------------------------------------------------------------*/
- mfsdram(SDRAM_MCOPT1, val);
- mtsdram(SDRAM_MCOPT1, (val & ~SDRAM_MCOPT1_MCHK_MASK) | ecc_temp);
-
mtsdram(SDRAM_RQDC,
(rqdc_reg & ~SDRAM_RQDC_RQFD_MASK) |
SDRAM_RQDC_RQFD_ENCODE(rqfd_average));
diff --git a/cpu/ppc4xx/Makefile b/cpu/ppc4xx/Makefile
index 1347e0f9f0..66fd02ccd8 100644
--- a/cpu/ppc4xx/Makefile
+++ b/cpu/ppc4xx/Makefile
@@ -29,7 +29,7 @@ START = start.o resetvec.o kgdb.o
SOBJS = dcr.o
COBJS = 405gp_pci.o 440spe_pcie.o 4xx_enet.o \
bedbug_405.o commproc.o \
- cpu.o cpu_init.o i2c.o interrupts.o \
+ cpu.o cpu_init.o gpio.o i2c.o interrupts.o \
miiphy.o ndfc.o sdram.o serial.o \
40x_spd_sdram.o 44x_spd_ddr.o 44x_spd_ddr2.o speed.o \
tlb.o traps.o usb_ohci.o usbdev.o usb.o \
diff --git a/cpu/ppc4xx/cpu.c b/cpu/ppc4xx/cpu.c
index 2d8740ccea..8e6bc84db0 100644
--- a/cpu/ppc4xx/cpu.c
+++ b/cpu/ppc4xx/cpu.c
@@ -125,6 +125,7 @@ int i2c_bootrom_enabled(void)
return (val & SDR0_SDCS_SDD);
#endif
}
+#endif
#if defined(CONFIG_440GX)
#define SDR0_PINSTP_SHIFT 29
@@ -178,16 +179,37 @@ static char *bootstrap_str[] = {
};
#endif
+#if defined(CONFIG_405EZ)
+#define SDR0_PINSTP_SHIFT 28
+static char *bootstrap_str[] = {
+ "EBC (8 bits)",
+ "SPI (fast)",
+ "NAND (512 page, 4 addr cycle)",
+ "I2C (Addr 0x50)",
+ "EBC (32 bits)",
+ "I2C (Addr 0x50)",
+ "NAND (2K page, 5 addr cycle)",
+ "I2C (Addr 0x50)",
+ "EBC (16 bits)",
+ "Reserved",
+ "NAND (2K page, 4 addr cycle)",
+ "I2C (Addr 0x50)",
+ "NAND (512 page, 3 addr cycle)",
+ "I2C (Addr 0x50)",
+ "SPI (slow)",
+ "I2C (Addr 0x50)",
+};
+#endif
+
#if defined(SDR0_PINSTP_SHIFT)
static int bootstrap_option(void)
{
unsigned long val;
- mfsdr(sdr_pinstp, val);
- return ((val & 0xe0000000) >> SDR0_PINSTP_SHIFT);
+ mfsdr(SDR_PINSTP, val);
+ return ((val & 0xf0000000) >> SDR0_PINSTP_SHIFT);
}
#endif /* SDR0_PINSTP_SHIFT */
-#endif
#if defined(CONFIG_440)
@@ -403,11 +425,11 @@ int checkcpu (void)
#if defined(I2C_BOOTROM)
printf (" I2C boot EEPROM %sabled\n", i2c_bootrom_enabled() ? "en" : "dis");
+#endif /* I2C_BOOTROM */
#if defined(SDR0_PINSTP_SHIFT)
printf (" Bootstrap Option %c - ", (char)bootstrap_option() + 'A');
printf ("Boot ROM Location %s\n", bootstrap_str[bootstrap_option()]);
#endif /* SDR0_PINSTP_SHIFT */
-#endif /* I2C_BOOTROM */
#if defined(CONFIG_PCI)
printf (" Internal PCI arbiter %sabled", pci_arbiter_enabled() ? "en" : "dis");
diff --git a/cpu/ppc4xx/cpu_init.c b/cpu/ppc4xx/cpu_init.c
index 9d1cd1343d..66e8637260 100644
--- a/cpu/ppc4xx/cpu_init.c
+++ b/cpu/ppc4xx/cpu_init.c
@@ -25,6 +25,7 @@
#include <watchdog.h>
#include <ppc4xx_enet.h>
#include <asm/processor.h>
+#include <asm/gpio.h>
#include <ppc4xx.h>
#if defined(CONFIG_405GP) || defined(CONFIG_405EP)
@@ -98,118 +99,6 @@ DECLARE_GLOBAL_DATA_PTR;
# endif
#endif /* CFG_INIT_DCACHE_CS */
-#if defined(CFG_440_GPIO_TABLE)
-gpio_param_s gpio_tab[GPIO_GROUP_MAX][GPIO_MAX] = CFG_440_GPIO_TABLE;
-
-void set_chip_gpio_configuration(gpio_param_s (*gpio_tab)[GPIO_GROUP_MAX][GPIO_MAX])
-{
- unsigned char i=0, j=0, reg_offset = 0, gpio_core;
- unsigned long gpio_reg, gpio_core_add;
-
- for (gpio_core=0; gpio_core<GPIO_GROUP_MAX; gpio_core++) {
- j = 0;
- reg_offset = 0;
- /* GPIO config of the GPIOs 0 to 31 */
- for (i=0; i<GPIO_MAX; i++, j++) {
- if (i == GPIO_MAX/2) {
- reg_offset = 4;
- j = i-16;
- }
-
- gpio_core_add = (*gpio_tab)[gpio_core][i].add;
-
- if (((*gpio_tab)[gpio_core][i].in_out == GPIO_IN) ||
- ((*gpio_tab)[gpio_core][i].in_out == GPIO_BI)) {
-
- switch ((*gpio_tab)[gpio_core][i].alt_nb) {
- case GPIO_SEL:
- break;
-
- case GPIO_ALT1:
- gpio_reg = in32(GPIO_IS1(gpio_core_add+reg_offset))
- & ~(GPIO_MASK >> (j*2));
- gpio_reg = gpio_reg | (GPIO_IN_SEL >> (j*2));
- out32(GPIO_IS1(gpio_core_add+reg_offset), gpio_reg);
- break;
-
- case GPIO_ALT2:
- gpio_reg = in32(GPIO_IS2(gpio_core_add+reg_offset))
- & ~(GPIO_MASK >> (j*2));
- gpio_reg = gpio_reg | (GPIO_IN_SEL >> (j*2));
- out32(GPIO_IS2(gpio_core_add+reg_offset), gpio_reg);
- break;
-
- case GPIO_ALT3:
- gpio_reg = in32(GPIO_IS3(gpio_core_add+reg_offset))
- & ~(GPIO_MASK >> (j*2));
- gpio_reg = gpio_reg | (GPIO_IN_SEL >> (j*2));
- out32(GPIO_IS3(gpio_core_add+reg_offset), gpio_reg);
- break;
- }
- }
-
- if (((*gpio_tab)[gpio_core][i].in_out == GPIO_OUT) ||
- ((*gpio_tab)[gpio_core][i].in_out == GPIO_BI)) {
-
- switch ((*gpio_tab)[gpio_core][i].alt_nb) {
- case GPIO_SEL:
- if (gpio_core == GPIO0) {
- gpio_reg = in32(GPIO0_TCR) | (0x80000000 >> (j));
- out32(GPIO0_TCR, gpio_reg);
- }
-
- if (gpio_core == GPIO1) {
- gpio_reg = in32(GPIO1_TCR) | (0x80000000 >> (j));
- out32(GPIO1_TCR, gpio_reg);
- }
-
- gpio_reg = in32(GPIO_OS(gpio_core_add+reg_offset))
- & ~(GPIO_MASK >> (j*2));
- out32(GPIO_OS(gpio_core_add+reg_offset), gpio_reg);
- gpio_reg = in32(GPIO_TS(gpio_core_add+reg_offset))
- & ~(GPIO_MASK >> (j*2));
- out32(GPIO_TS(gpio_core_add+reg_offset), gpio_reg);
- break;
-
- case GPIO_ALT1:
- gpio_reg = in32(GPIO_OS(gpio_core_add+reg_offset))
- & ~(GPIO_MASK >> (j*2));
- gpio_reg = gpio_reg | (GPIO_ALT1_SEL >> (j*2));
- out32(GPIO_OS(gpio_core_add+reg_offset), gpio_reg);
- gpio_reg = in32(GPIO_TS(gpio_core_add+reg_offset))
- & ~(GPIO_MASK >> (j*2));
- gpio_reg = gpio_reg | (GPIO_ALT1_SEL >> (j*2));
- out32(GPIO_TS(gpio_core_add+reg_offset), gpio_reg);
- break;
-
- case GPIO_ALT2:
- gpio_reg = in32(GPIO_OS(gpio_core_add+reg_offset))
- & ~(GPIO_MASK >> (j*2));
- gpio_reg = gpio_reg | (GPIO_ALT2_SEL >> (j*2));
- out32(GPIO_OS(gpio_core_add+reg_offset), gpio_reg);
- gpio_reg = in32(GPIO_TS(gpio_core_add+reg_offset))
- & ~(GPIO_MASK >> (j*2));
- gpio_reg = gpio_reg | (GPIO_ALT2_SEL >> (j*2));
- out32(GPIO_TS(gpio_core_add+reg_offset), gpio_reg);
- break;
-
- case GPIO_ALT3:
- gpio_reg = in32(GPIO_OS(gpio_core_add+reg_offset))
- & ~(GPIO_MASK >> (j*2));
- gpio_reg = gpio_reg | (GPIO_ALT3_SEL >> (j*2));
- out32(GPIO_OS(gpio_core_add+reg_offset), gpio_reg);
- gpio_reg = in32(GPIO_TS(gpio_core_add+reg_offset))
- & ~(GPIO_MASK >> (j*2));
- gpio_reg = gpio_reg | (GPIO_ALT3_SEL >> (j*2));
- out32(GPIO_TS(gpio_core_add+reg_offset), gpio_reg);
- break;
- }
- }
- }
- }
-}
-#endif /* CFG_440_GPIO_TABLE */
-
/*
* Breath some life into the CPU...
*
@@ -248,7 +137,7 @@ cpu_init_f (void)
#endif /* CONFIG_405EP */
#if defined(CFG_440_GPIO_TABLE)
- set_chip_gpio_configuration(&gpio_tab);
+ gpio_set_chip_configuration();
#endif /* CFG_440_GPIO_TABLE */
/*
diff --git a/cpu/ppc4xx/gpio.c b/cpu/ppc4xx/gpio.c
new file mode 100644
index 0000000000..dd84e58a1f
--- /dev/null
+++ b/cpu/ppc4xx/gpio.c
@@ -0,0 +1,214 @@
+/*
+ * (C) Copyright 2007
+ * Stefan Roese, DENX Software Engineering, sr@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/processor.h>
+#include <asm/io.h>
+#include <asm/gpio.h>
+
+#if defined(CFG_440_GPIO_TABLE)
+gpio_param_s gpio_tab[GPIO_GROUP_MAX][GPIO_MAX] = CFG_440_GPIO_TABLE;
+#endif
+
+#if defined(GPIO0_OSRL)
+/* Only some 4xx variants support alternate funtions on the GPIO's */
+void gpio_config(int pin, int in_out, int gpio_alt, int out_val)
+{
+ u32 mask;
+ u32 mask2;
+ u32 val;
+ u32 offs = 0;
+ u32 offs2 = 0;
+ int pin2 = pin << 1;
+
+ if (pin >= GPIO_MAX) {
+ offs = 0x100;
+ pin -= GPIO_MAX;
+ }
+
+ if (pin >= GPIO_MAX/2) {
+ offs2 = 0x100;
+ pin2 = (pin - GPIO_MAX/2) << 1;
+ }
+
+ mask = 0x80000000 >> pin;
+ mask2 = 0xc0000000 >> (pin2 << 1);
+
+ /* first set TCR to 0 */
+ out32(GPIO0_TCR + offs, in32(GPIO0_TCR + offs) & ~mask);
+
+ if (in_out == GPIO_OUT) {
+ val = in32(GPIO0_OSRL + offs + offs2) & ~mask2;
+ switch (gpio_alt) {
+ case GPIO_ALT1:
+ val |= GPIO_ALT1_SEL >> pin2;
+ break;
+ case GPIO_ALT2:
+ val |= GPIO_ALT2_SEL >> pin2;
+ break;
+ case GPIO_ALT3:
+ val |= GPIO_ALT3_SEL >> pin2;
+ break;
+ }
+ out32(GPIO0_OSRL + offs + offs2, val);
+
+ /* setup requested output value */
+ if (out_val == GPIO_OUT_0)
+ out32(GPIO0_OR + offs, in32(GPIO0_OR + offs) & ~mask);
+ else if (out_val == GPIO_OUT_1)
+ out32(GPIO0_OR + offs, in32(GPIO0_OR + offs) | mask);
+
+ /* now configure TCR to drive output if selected */
+ out32(GPIO0_TCR + offs, in32(GPIO0_TCR + offs) | mask);
+ } else {
+ val = in32(GPIO0_ISR1L + offs + offs2) & ~mask2;
+ val |= GPIO_IN_SEL >> pin2;
+ out32(GPIO0_ISR1L + offs + offs2, val);
+ }
+}
+#endif /* GPIO_OSRL */
+
+void gpio_write_bit(int pin, int val)
+{
+ u32 offs = 0;
+
+ if (pin >= GPIO_MAX) {
+ offs = 0x100;
+ pin -= GPIO_MAX;
+ }
+
+ if (val)
+ out32(GPIO0_OR + offs, in32(GPIO0_OR + offs) | GPIO_VAL(pin));
+ else
+ out32(GPIO0_OR + offs, in32(GPIO0_OR + offs) & ~GPIO_VAL(pin));
+}
+
+#if defined(CFG_440_GPIO_TABLE)
+void gpio_set_chip_configuration(void)
+{
+ unsigned char i=0, j=0, offs=0, gpio_core;
+ unsigned long reg, core_add;
+
+ for (gpio_core=0; gpio_core<GPIO_GROUP_MAX; gpio_core++) {
+ j = 0;
+ offs = 0;
+ /* GPIO config of the GPIOs 0 to 31 */
+ for (i=0; i<GPIO_MAX; i++, j++) {
+ if (i == GPIO_MAX/2) {
+ offs = 4;
+ j = i-16;
+ }
+
+ core_add = gpio_tab[gpio_core][i].add;
+
+ if ((gpio_tab[gpio_core][i].in_out == GPIO_IN) ||
+ (gpio_tab[gpio_core][i].in_out == GPIO_BI)) {
+
+ switch (gpio_tab[gpio_core][i].alt_nb) {
+ case GPIO_SEL:
+ break;
+
+ case GPIO_ALT1:
+ reg = in32(GPIO_IS1(core_add+offs))
+ & ~(GPIO_MASK >> (j*2));
+ reg = reg | (GPIO_IN_SEL >> (j*2));
+ out32(GPIO_IS1(core_add+offs), reg);
+ break;
+
+ case GPIO_ALT2:
+ reg = in32(GPIO_IS2(core_add+offs))
+ & ~(GPIO_MASK >> (j*2));
+ reg = reg | (GPIO_IN_SEL >> (j*2));
+ out32(GPIO_IS2(core_add+offs), reg);
+ break;
+
+ case GPIO_ALT3:
+ reg = in32(GPIO_IS3(core_add+offs))
+ & ~(GPIO_MASK >> (j*2));
+ reg = reg | (GPIO_IN_SEL >> (j*2));
+ out32(GPIO_IS3(core_add+offs), reg);
+ break;
+ }
+ }
+
+ if ((gpio_tab[gpio_core][i].in_out == GPIO_OUT) ||
+ (gpio_tab[gpio_core][i].in_out == GPIO_BI)) {
+
+ switch (gpio_tab[gpio_core][i].alt_nb) {
+ case GPIO_SEL:
+ if (gpio_core == GPIO0) {
+ reg = in32(GPIO0_TCR) | (0x80000000 >> (j));
+ out32(GPIO0_TCR, reg);
+ }
+
+ if (gpio_core == GPIO1) {
+ reg = in32(GPIO1_TCR) | (0x80000000 >> (j));
+ out32(GPIO1_TCR, reg);
+ }
+
+ reg = in32(GPIO_OS(core_add+offs))
+ & ~(GPIO_MASK >> (j*2));
+ out32(GPIO_OS(core_add+offs), reg);
+ reg = in32(GPIO_TS(core_add+offs))
+ & ~(GPIO_MASK >> (j*2));
+ out32(GPIO_TS(core_add+offs), reg);
+ break;
+
+ case GPIO_ALT1:
+ reg = in32(GPIO_OS(core_add+offs))
+ & ~(GPIO_MASK >> (j*2));
+ reg = reg | (GPIO_ALT1_SEL >> (j*2));
+ out32(GPIO_OS(core_add+offs), reg);
+ reg = in32(GPIO_TS(core_add+offs))
+ & ~(GPIO_MASK >> (j*2));
+ reg = reg | (GPIO_ALT1_SEL >> (j*2));
+ out32(GPIO_TS(core_add+offs), reg);
+ break;
+
+ case GPIO_ALT2:
+ reg = in32(GPIO_OS(core_add+offs))
+ & ~(GPIO_MASK >> (j*2));
+ reg = reg | (GPIO_ALT2_SEL >> (j*2));
+ out32(GPIO_OS(core_add+offs), reg);
+ reg = in32(GPIO_TS(core_add+offs))
+ & ~(GPIO_MASK >> (j*2));
+ reg = reg | (GPIO_ALT2_SEL >> (j*2));
+ out32(GPIO_TS(core_add+offs), reg);
+ break;
+
+ case GPIO_ALT3:
+ reg = in32(GPIO_OS(core_add+offs))
+ & ~(GPIO_MASK >> (j*2));
+ reg = reg | (GPIO_ALT3_SEL >> (j*2));
+ out32(GPIO_OS(core_add+offs), reg);
+ reg = in32(GPIO_TS(core_add+offs))
+ & ~(GPIO_MASK >> (j*2));
+ reg = reg | (GPIO_ALT3_SEL >> (j*2));
+ out32(GPIO_TS(core_add+offs), reg);
+ break;
+ }
+ }
+ }
+ }
+}
+#endif /* CFG_440_GPIO_TABLE */
diff --git a/cpu/ppc4xx/i2c.c b/cpu/ppc4xx/i2c.c
index 8f4da8621d..47c264e222 100644
--- a/cpu/ppc4xx/i2c.c
+++ b/cpu/ppc4xx/i2c.c
@@ -91,7 +91,6 @@ static void _i2c_bus_reset(void)
void i2c_init(int speed, int slaveadd)
{
- sys_info_t sysInfo;
unsigned long freqOPB;
int val, divisor;
int bus;
@@ -124,8 +123,7 @@ void i2c_init(int speed, int slaveadd)
/* Clock divide Register */
/* get OPB frequency */
- get_sys_info(&sysInfo);
- freqOPB = sysInfo.freqPLB / sysInfo.pllOpbDiv;
+ freqOPB = get_OPB_freq();
/* set divisor according to freqOPB */
divisor = (freqOPB - 1) / 10000000;
if (divisor == 0)
diff --git a/cpu/ppc4xx/start.S b/cpu/ppc4xx/start.S
index d918b3ec1f..a96083caa5 100644
--- a/cpu/ppc4xx/start.S
+++ b/cpu/ppc4xx/start.S
@@ -2,6 +2,7 @@
* Copyright (C) 1998 Dan Malek <dmalek@jlc.net>
* Copyright (C) 1999 Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
* Copyright (C) 2000,2001,2002 Wolfgang Denk <wd@denx.de>
+ * Copyright (C) 2007 Stefan Roese <sr@denx.de>, DENX Software Engineering
*
* See file CREDITS for list of people who contributed to this
* project.
@@ -757,7 +758,6 @@ _start:
#endif /* CONFIG_405EP */
#if defined(CFG_OCM_DATA_ADDR) && defined(CFG_OCM_DATA_SIZE)
-/* test-only... (clean up later when NAND booting is supported) */
#if defined(CONFIG_405EZ)
/********************************************************************
* Setup OCM - On Chip Memory - PPC405EZ uses OCM Controller V2
@@ -786,41 +786,7 @@ _start:
mtdcr ocmdsisdpc,r4
isync
-
-#if defined(CONFIG_NAND_SPL)
- /*
- * 405EZ can boot from NAND Flash.
- * If we are booting the SPL (Pre-loader), copy code from
- * the mapped 4K NAND Flash to the OCM
- */
- li r4,(CFG_NAND_BOOT_SPL_SIZE >> 2) - 1
- mtctr r4
- lis r2,CFG_NAND_BOOT_SPL_SRC@h
- ori r2,r2,CFG_NAND_BOOT_SPL_SRC@l
- lis r3,CFG_NAND_BOOT_SPL_DST@h
- ori r3,r3,CFG_NAND_BOOT_SPL_DST@l
-spl_loop:
- lwzu r4,4(r2)
- stwu r4,4(r3)
- bdnz spl_loop
-
- /*
- * Jump to code in OCM Ram
- */
- bl 00f
-00: mflr r10
- lis r3,(CFG_NAND_BOOT_SPL_SRC - CFG_NAND_BOOT_SPL_DST)@h
- ori r3,r3,(CFG_NAND_BOOT_SPL_SRC - CFG_NAND_BOOT_SPL_DST)@l
- sub r10,r10,r3
- addi r10,r10,28
- mtlr r10
- blr
-start_ram:
- sync
- isync
-#endif
-#else
-/* ...test-only */
+#else /* CONFIG_405EZ */
/********************************************************************
* Setup OCM - On Chip Memory
*******************************************************************/
@@ -828,14 +794,15 @@ start_ram:
lis r0, 0x7FFF
ori r0, r0, 0xFFFF
mfdcr r3, ocmiscntl /* get instr-side IRAM config */
- mfdcr r4, ocmdscntl /* get data-side IRAM config */
- and r3, r3, r0 /* disable data-side IRAM */
- and r4, r4, r0 /* disable data-side IRAM */
- mtdcr ocmiscntl, r3 /* set instr-side IRAM config */
- mtdcr ocmdscntl, r4 /* set data-side IRAM config */
+ mfdcr r4, ocmdscntl /* get data-side IRAM config */
+ and r3, r3, r0 /* disable data-side IRAM */
+ and r4, r4, r0 /* disable data-side IRAM */
+ mtdcr ocmiscntl, r3 /* set instr-side IRAM config */
+ mtdcr ocmdscntl, r4 /* set data-side IRAM config */
isync
- addis r3, 0, CFG_OCM_DATA_ADDR@h /* OCM location */
+ lis r3,CFG_OCM_DATA_ADDR@h /* OCM location */
+ ori r3,r3,CFG_OCM_DATA_ADDR@l
mtdcr ocmdsarc, r3
addis r4, 0, 0xC000 /* OCM data area enabled */
mtdcr ocmdscntl, r4
@@ -1925,11 +1892,11 @@ pll_wait:
#endif /* CONFIG_405EP */
#if defined(CONFIG_440)
-#define function_prolog(func_name) .text; \
+#define function_prolog(func_name) .text; \
.align 2; \
.globl func_name; \
func_name:
-#define function_epilog(func_name) .type func_name,@function; \
+#define function_epilog(func_name) .type func_name,@function; \
.size func_name,.-func_name
/*----------------------------------------------------------------------------+
@@ -1985,13 +1952,13 @@ pll_wait:
+----------------------------------------------------------------------------*/
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
+ 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)
@@ -2000,26 +1967,26 @@ pll_wait:
| 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
+ 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
+ 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
+ mtmsr r9
blr
function_epilog(dflush)
#endif /* CONFIG_440 */