summaryrefslogtreecommitdiff
path: root/cpu/ppc4xx
diff options
context:
space:
mode:
Diffstat (limited to 'cpu/ppc4xx')
-rw-r--r--cpu/ppc4xx/405gp_pci.c17
-rw-r--r--cpu/ppc4xx/440spe_pcie.c141
-rw-r--r--cpu/ppc4xx/440spe_pcie.h7
-rw-r--r--cpu/ppc4xx/44x_spd_ddr.c3
-rw-r--r--cpu/ppc4xx/44x_spd_ddr2.c60
-rw-r--r--cpu/ppc4xx/4xx_enet.c24
-rw-r--r--cpu/ppc4xx/gpio.c6
-rw-r--r--cpu/ppc4xx/sdram.c32
-rw-r--r--cpu/ppc4xx/sdram.h2
-rw-r--r--cpu/ppc4xx/serial.c9
-rw-r--r--cpu/ppc4xx/speed.c33
-rw-r--r--cpu/ppc4xx/start.S61
-rw-r--r--cpu/ppc4xx/tlb.c62
-rw-r--r--cpu/ppc4xx/traps.c45
-rw-r--r--cpu/ppc4xx/usb.c6
15 files changed, 383 insertions, 125 deletions
diff --git a/cpu/ppc4xx/405gp_pci.c b/cpu/ppc4xx/405gp_pci.c
index 2837929..282e7a1 100644
--- a/cpu/ppc4xx/405gp_pci.c
+++ b/cpu/ppc4xx/405gp_pci.c
@@ -443,7 +443,7 @@ void pci_init_board(void)
static struct pci_controller ppc440_hose = {0};
-void pci_440_init (struct pci_controller *hose)
+int pci_440_init (struct pci_controller *hose)
{
int reg_num = 0;
@@ -459,7 +459,7 @@ void pci_440_init (struct pci_controller *hose)
if ((strap & SDR0_SDSTP1_PISE_MASK) == 0) {
printf("PCI: SDR0_STRP1[PISE] not set.\n");
printf("PCI: Configuration aborted.\n");
- return;
+ return -1;
}
#elif defined(CONFIG_440GP)
unsigned long strap;
@@ -468,7 +468,7 @@ void pci_440_init (struct pci_controller *hose)
if ((strap & CPC0_STRP1_PISE_MASK) == 0) {
printf("PCI: CPC0_STRP1[PISE] not set.\n");
printf("PCI: Configuration aborted.\n");
- return;
+ return -1;
}
#endif
#endif /* CONFIG_DISABLE_PISE_TEST */
@@ -477,7 +477,7 @@ void pci_440_init (struct pci_controller *hose)
* PCI controller init
*--------------------------------------------------------------------------*/
hose->first_busno = 0;
- hose->last_busno = 0xff;
+ hose->last_busno = 0;
/* PCI I/O space */
pci_set_region(hose->regions + reg_num++,
@@ -515,7 +515,7 @@ void pci_440_init (struct pci_controller *hose)
if (pci_pre_init (hose) == 0) {
printf("PCI: Board-specific initialization failed.\n");
printf("PCI: Configuration aborted.\n");
- return;
+ return -1;
}
pci_register_hose( hose );
@@ -578,13 +578,16 @@ void pci_440_init (struct pci_controller *hose)
#endif
hose->last_busno = pci_hose_scan(hose);
}
+ return hose->last_busno;
}
void pci_init_board(void)
{
- pci_440_init (&ppc440_hose);
+ int busno;
+
+ busno = pci_440_init (&ppc440_hose);
#if defined(CONFIG_440SPE)
- pcie_setup_hoses();
+ pcie_setup_hoses(busno + 1);
#endif
}
diff --git a/cpu/ppc4xx/440spe_pcie.c b/cpu/ppc4xx/440spe_pcie.c
index d6c4be5..3eac0ae 100644
--- a/cpu/ppc4xx/440spe_pcie.c
+++ b/cpu/ppc4xx/440spe_pcie.c
@@ -1,5 +1,5 @@
/*
- * (C) Copyright 2006
+ * (C) Copyright 2006 - 2007
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
* Copyright (c) 2005 Cisco Systems. All rights reserved.
@@ -40,19 +40,81 @@ enum {
LNKW_X8 = 0x8
};
+static u8* pcie_get_base(struct pci_controller *hose, unsigned int devfn)
+{
+ u8 *base = (u8*)hose->cfg_data;
+
+ /* use local configuration space for the first bus */
+ if (PCI_BUS(devfn) == 0) {
+ if (hose->cfg_data == (u8*)CFG_PCIE0_CFGBASE)
+ base = (u8*)CFG_PCIE0_XCFGBASE;
+ if (hose->cfg_data == (u8*)CFG_PCIE1_CFGBASE)
+ base = (u8*)CFG_PCIE1_XCFGBASE;
+ if (hose->cfg_data == (u8*)CFG_PCIE2_CFGBASE)
+ base = (u8*)CFG_PCIE2_XCFGBASE;
+ }
+
+ return base;
+}
+
+static void pcie_dmer_disable(void)
+{
+ mtdcr (DCRN_PEGPL_CFG(DCRN_PCIE0_BASE),
+ mfdcr (DCRN_PEGPL_CFG(DCRN_PCIE0_BASE)) | GPL_DMER_MASK_DISA);
+ mtdcr (DCRN_PEGPL_CFG(DCRN_PCIE1_BASE),
+ mfdcr (DCRN_PEGPL_CFG(DCRN_PCIE1_BASE)) | GPL_DMER_MASK_DISA);
+ mtdcr (DCRN_PEGPL_CFG(DCRN_PCIE2_BASE),
+ mfdcr (DCRN_PEGPL_CFG(DCRN_PCIE2_BASE)) | GPL_DMER_MASK_DISA);
+}
+
+static void pcie_dmer_enable(void)
+{
+ mtdcr (DCRN_PEGPL_CFG (DCRN_PCIE0_BASE),
+ mfdcr (DCRN_PEGPL_CFG(DCRN_PCIE0_BASE)) & ~GPL_DMER_MASK_DISA);
+ mtdcr (DCRN_PEGPL_CFG (DCRN_PCIE1_BASE),
+ mfdcr (DCRN_PEGPL_CFG(DCRN_PCIE1_BASE)) & ~GPL_DMER_MASK_DISA);
+ mtdcr (DCRN_PEGPL_CFG (DCRN_PCIE2_BASE),
+ mfdcr (DCRN_PEGPL_CFG(DCRN_PCIE2_BASE)) & ~GPL_DMER_MASK_DISA);
+}
+
static int pcie_read_config(struct pci_controller *hose, unsigned int devfn,
int offset, int len, u32 *val) {
+ u8 *address;
*val = 0;
+
+ /*
+ * Bus numbers are relative to hose->first_busno
+ */
+ devfn -= PCI_BDF(hose->first_busno, 0, 0);
+
/*
- * 440SPE implements only one function per port
+ * NOTICE: configuration space ranges are currenlty mapped only for
+ * the first 16 buses, so such limit must be imposed. In case more
+ * buses are required the TLB settings in board/amcc/<board>/init.S
+ * need to be altered accordingly (one bus takes 1 MB of memory space).
*/
- if (!((PCI_FUNC(devfn) == 0) && (PCI_DEV(devfn) == 1)))
+ if (PCI_BUS(devfn) >= 16)
return 0;
- devfn = PCI_BDF(0,0,0);
+ /*
+ * Only single device/single function is supported for the primary and
+ * secondary buses of the 440SPe host bridge.
+ */
+ if ((!((PCI_FUNC(devfn) == 0) && (PCI_DEV(devfn) == 0))) &&
+ ((PCI_BUS(devfn) == 0) || (PCI_BUS(devfn) == 1)))
+ return 0;
+
+ address = pcie_get_base(hose, devfn);
offset += devfn << 4;
+ /*
+ * Reading from configuration space of non-existing device can
+ * generate transaction errors. For the read duration we suppress
+ * assertion of machine check exceptions to avoid those.
+ */
+ pcie_dmer_disable ();
+
switch (len) {
case 1:
*val = in_8(hose->cfg_data + offset);
@@ -61,24 +123,43 @@ static int pcie_read_config(struct pci_controller *hose, unsigned int devfn,
*val = in_le16((u16 *)(hose->cfg_data + offset));
break;
default:
- *val = in_le32((u32 *)(hose->cfg_data + offset));
+ *val = in_le32((u32*)(hose->cfg_data + offset));
break;
}
+
+ pcie_dmer_enable ();
+
return 0;
}
static int pcie_write_config(struct pci_controller *hose, unsigned int devfn,
int offset, int len, u32 val) {
+ u8 *address;
+
+ /*
+ * Bus numbers are relative to hose->first_busno
+ */
+ devfn -= PCI_BDF(hose->first_busno, 0, 0);
+
/*
- * 440SPE implements only one function per port
+ * Same constraints as in pcie_read_config().
*/
- if (!((PCI_FUNC(devfn) == 0) && (PCI_DEV(devfn) == 1)))
+ if (PCI_BUS(devfn) >= 16)
return 0;
- devfn = PCI_BDF(0,0,0);
+ if ((!((PCI_FUNC(devfn) == 0) && (PCI_DEV(devfn) == 0))) &&
+ ((PCI_BUS(devfn) == 0) || (PCI_BUS(devfn) == 1)))
+ return 0;
+
+ address = pcie_get_base(hose, devfn);
offset += devfn << 4;
+ /*
+ * Suppress MCK exceptions, similar to pcie_read_config()
+ */
+ pcie_dmer_disable ();
+
switch (len) {
case 1:
out_8(hose->cfg_data + offset, val);
@@ -90,6 +171,9 @@ static int pcie_write_config(struct pci_controller *hose, unsigned int devfn,
out_le32((u32 *)(hose->cfg_data + offset), val);
break;
}
+
+ pcie_dmer_enable ();
+
return 0;
}
@@ -98,7 +182,7 @@ int pcie_read_config_byte(struct pci_controller *hose,pci_dev_t dev,int offset,u
u32 v;
int rv;
- rv = pcie_read_config(hose, dev, offset, 1, &v);
+ rv = pcie_read_config(hose, dev, offset, 1, &v);
*val = (u8)v;
return rv;
}
@@ -755,12 +839,12 @@ void ppc440spe_setup_pcie_rootpoint(struct pci_controller *hose, int port)
volatile void *rmbase = NULL;
pci_set_ops(hose,
- pcie_read_config_byte,
- pcie_read_config_word,
- pcie_read_config_dword,
- pcie_write_config_byte,
- pcie_write_config_word,
- pcie_write_config_dword);
+ pcie_read_config_byte,
+ pcie_read_config_word,
+ pcie_read_config_dword,
+ pcie_write_config_byte,
+ pcie_write_config_word,
+ pcie_write_config_dword);
switch (port) {
case 0:
@@ -842,6 +926,29 @@ void ppc440spe_setup_pcie_rootpoint(struct pci_controller *hose, int port)
in_le16((u16 *)(mbase + PCI_COMMAND)) |
PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
printf("PCIE:%d successfully set as rootpoint\n",port);
+
+ /* Set Device and Vendor Id */
+ switch (port) {
+ case 0:
+ out_le16(mbase + 0x200, 0xaaa0);
+ out_le16(mbase + 0x202, 0xbed0);
+ break;
+ case 1:
+ out_le16(mbase + 0x200, 0xaaa1);
+ out_le16(mbase + 0x202, 0xbed1);
+ break;
+ case 2:
+ out_le16(mbase + 0x200, 0xaaa2);
+ out_le16(mbase + 0x202, 0xbed2);
+ break;
+ default:
+ out_le16(mbase + 0x200, 0xaaa3);
+ out_le16(mbase + 0x202, 0xbed3);
+ }
+
+ /* Set Class Code to PCI-PCI bridge and Revision Id to 1 */
+ out_le32(mbase + 0x208, 0x06040001);
+
}
int ppc440spe_setup_pcie_endpoint(struct pci_controller *hose, int port)
@@ -919,8 +1026,8 @@ int ppc440spe_setup_pcie_endpoint(struct pci_controller *hose, int port)
/* Enable I/O, Mem, and Busmaster cycles */
out_le16((u16 *)(mbase + PCI_COMMAND),
- in_le16((u16 *)(mbase + PCI_COMMAND)) |
- PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
+ in_le16((u16 *)(mbase + PCI_COMMAND)) |
+ PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
out_le16(mbase + 0x200,0xcaad); /* Setting vendor ID */
out_le16(mbase + 0x202,0xfeed); /* Setting device ID */
attempts = 10;
diff --git a/cpu/ppc4xx/440spe_pcie.h b/cpu/ppc4xx/440spe_pcie.h
index 2becc77..38745eb 100644
--- a/cpu/ppc4xx/440spe_pcie.h
+++ b/cpu/ppc4xx/440spe_pcie.h
@@ -38,6 +38,7 @@
#define DCRN_PEGPL_REGBAL(base) (base + 0x13)
#define DCRN_PEGPL_REGMSK(base) (base + 0x14)
#define DCRN_PEGPL_SPECIAL(base) (base + 0x15)
+#define DCRN_PEGPL_CFG(base) (base + 0x16)
/*
* System DCRs (SDRs)
@@ -145,8 +146,8 @@
#define PECFG_PIMEN 0x33c
#define PECFG_PIM0LAL 0x340
#define PECFG_PIM0LAH 0x344
-#define PECFG_PIM1LAL 0x348
-#define PECFG_PIM1LAH 0x34c
+#define PECFG_PIM1LAL 0x348
+#define PECFG_PIM1LAH 0x34c
#define PECFG_PIM01SAL 0x350
#define PECFG_PIM01SAH 0x354
@@ -161,6 +162,8 @@
mtdcr(DCRN_SDR0_CFGADDR, offset); \
mtdcr(DCRN_SDR0_CFGDATA,data);})
+#define GPL_DMER_MASK_DISA 0x02000000
+
int ppc440spe_init_pcie(void);
int ppc440spe_init_pcie_rootport(int port);
void yucca_setup_pcie_fpga_rootpoint(int port);
diff --git a/cpu/ppc4xx/44x_spd_ddr.c b/cpu/ppc4xx/44x_spd_ddr.c
index 6d6fba1..4a4c6f2 100644
--- a/cpu/ppc4xx/44x_spd_ddr.c
+++ b/cpu/ppc4xx/44x_spd_ddr.c
@@ -269,9 +269,8 @@ struct bank_param {
typedef struct bank_param BANKPARMS;
#ifdef CFG_SIMULATE_SPD_EEPROM
-extern unsigned char cfg_simulate_spd_eeprom[128];
+extern const unsigned char cfg_simulate_spd_eeprom[128];
#endif
-void program_tlb(u32 phys_addr, u32 virt_addr, u32 size, u32 tlb_word2_i_value);
static unsigned char spd_read(uchar chip, uint addr);
static void get_spd_info(unsigned long *dimm_populated,
diff --git a/cpu/ppc4xx/44x_spd_ddr2.c b/cpu/ppc4xx/44x_spd_ddr2.c
index 5fef27b..67ba5bd 100644
--- a/cpu/ppc4xx/44x_spd_ddr2.c
+++ b/cpu/ppc4xx/44x_spd_ddr2.c
@@ -109,7 +109,7 @@
/* Defines for the Read Cycle Delay test */
#define NUMMEMTESTS 8
#define NUMMEMWORDS 8
-#define NUMLOOPS 256 /* memory test loops */
+#define NUMLOOPS 64 /* memory test loops */
#undef CONFIG_ECC_ERROR_RESET /* test-only: see description below, at check_ecc() */
@@ -138,6 +138,26 @@ void __spd_ddr_init_hang (void)
}
void spd_ddr_init_hang (void) __attribute__((weak, alias("__spd_ddr_init_hang")));
+/*
+ * To provide an interface for board specific config values in this common
+ * DDR setup code, we implement he "weak" default functions here. They return
+ * the default value back to the caller.
+ *
+ * Please see include/configs/yucca.h for an example fora board specific
+ * implementation.
+ */
+u32 __ddr_wrdtr(u32 default_val)
+{
+ return default_val;
+}
+u32 ddr_wrdtr(u32) __attribute__((weak, alias("__ddr_wrdtr")));
+
+u32 __ddr_clktr(u32 default_val)
+{
+ return default_val;
+}
+u32 ddr_clktr(u32) __attribute__((weak, alias("__ddr_clktr")));
+
/* Private Structure Definitions */
@@ -154,7 +174,6 @@ typedef enum ddr_cas_id {
* Prototypes
*-----------------------------------------------------------------------------*/
static unsigned long sdram_memsize(void);
-void program_tlb(u32 phys_addr, u32 virt_addr, u32 size, u32 tlb_word2_i_value);
static void get_spd_info(unsigned long *dimm_populated,
unsigned char *iic0_dimm_addr,
unsigned long num_dimm_banks);
@@ -216,9 +235,7 @@ static void test(void);
#else
static void DQS_calibration_process(void);
#endif
-#if defined(DEBUG)
static void ppc440sp_sdram_register_dump(void);
-#endif
int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
void dcbz_area(u32 start_address, u32 num_bytes);
void dflush(void);
@@ -469,17 +486,14 @@ long int initdram(int board_type)
*-----------------------------------------------------------------*/
mfsdram(SDRAM_WRDTR, val);
mtsdram(SDRAM_WRDTR, (val & ~(SDRAM_WRDTR_LLWP_MASK | SDRAM_WRDTR_WTR_MASK)) |
- (SDRAM_WRDTR_LLWP_1_CYC | SDRAM_WRDTR_WTR_90_DEG_ADV));
+ ddr_wrdtr(SDRAM_WRDTR_LLWP_1_CYC | SDRAM_WRDTR_WTR_90_DEG_ADV));
/*------------------------------------------------------------------
* Set the SDRAM Clock Timing Register
*-----------------------------------------------------------------*/
mfsdram(SDRAM_CLKTR, val);
-#ifdef CFG_44x_DDR2_CKTR_180
- mtsdram(SDRAM_CLKTR, (val & ~SDRAM_CLKTR_CLKP_MASK) | SDRAM_CLKTR_CLKP_180_DEG_ADV);
-#else
- mtsdram(SDRAM_CLKTR, (val & ~SDRAM_CLKTR_CLKP_MASK) | SDRAM_CLKTR_CLKP_0_DEG);
-#endif
+ mtsdram(SDRAM_CLKTR, (val & ~SDRAM_CLKTR_CLKP_MASK) |
+ ddr_clktr(SDRAM_CLKTR_CLKP_0_DEG));
/*------------------------------------------------------------------
* Program the BxCF registers.
@@ -538,7 +552,12 @@ long int initdram(int board_type)
dram_size = sdram_memsize();
/* and program tlb entries for this size (dynamic) */
- program_tlb(0, 0, dram_size, MY_TLB_WORD2_I_ENABLE);
+
+ /*
+ * Program TLB entries with caches enabled, for best performace
+ * while auto-calibrating and ECC generation
+ */
+ program_tlb(0, 0, dram_size, 0);
/*------------------------------------------------------------------
* DQS calibration.
@@ -549,12 +568,18 @@ long int initdram(int board_type)
/*------------------------------------------------------------------
* If ecc is enabled, initialize the parity bits.
*-----------------------------------------------------------------*/
- program_ecc(dimm_populated, iic0_dimm_addr, num_dimm_banks, MY_TLB_WORD2_I_ENABLE);
+ program_ecc(dimm_populated, iic0_dimm_addr, num_dimm_banks, 0);
#endif
-#ifdef DEBUG
+ /*
+ * Now after initialization (auto-calibration and ECC generation)
+ * remove the TLB entries with caches enabled and program again with
+ * desired cache functionality
+ */
+ remove_tlb(0, dram_size);
+ program_tlb(0, 0, dram_size, MY_TLB_WORD2_I_ENABLE);
+
ppc440sp_sdram_register_dump();
-#endif
return dram_size;
}
@@ -596,7 +621,6 @@ 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;
@@ -617,7 +641,6 @@ void board_add_ram_info(int use_default)
val = (val & SDRAM_MMODE_DCL_MASK) >> 4;
printf(", CL%d)", val);
}
-#endif
/*------------------------------------------------------------------
* For the memory DIMMs installed, this routine verifies that they
@@ -2703,6 +2726,7 @@ calibration_loop:
printf("\nERROR: Cannot determine a common read delay for the "
"DIMM(s) installed.\n");
debug("%s[%d] ERROR : \n", __FUNCTION__,__LINE__);
+ ppc440sp_sdram_register_dump();
spd_ddr_init_hang ();
}
@@ -3028,5 +3052,9 @@ static void ppc440sp_sdram_register_dump(void)
dcr_data = mfdcr(SDRAM_R3BAS);
printf(" MQ3_B0BAS = 0x%08X\n", dcr_data);
}
+#else
+static void ppc440sp_sdram_register_dump(void)
+{
+}
#endif
#endif /* CONFIG_SPD_EEPROM */
diff --git a/cpu/ppc4xx/4xx_enet.c b/cpu/ppc4xx/4xx_enet.c
index d782791..71a9e37 100644
--- a/cpu/ppc4xx/4xx_enet.c
+++ b/cpu/ppc4xx/4xx_enet.c
@@ -138,7 +138,8 @@
#define BI_PHYMODE_MII 7
#endif
-#if defined(CONFIG_440SPE) || defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
+#if defined(CONFIG_440SPE) || defined(CONFIG_440EPX) || \
+ defined(CONFIG_440GRX) || defined(CONFIG_440SP)
#define SDR0_MFR_ETH_CLK_SEL_V(n) ((0x01<<27) / (n+1))
#endif
@@ -408,7 +409,8 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
int ethgroup = -1;
#endif
#endif
-#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || defined(CONFIG_440SPE)
+#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
+ defined(CONFIG_440SP) || defined(CONFIG_440SPE)
unsigned long mfr;
#endif
@@ -500,7 +502,8 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
__asm__ volatile ("eieio");
/* reset emac so we have access to the phy */
-#if defined(CONFIG_440SPE) || defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
+#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
+ defined(CONFIG_440SP) || defined(CONFIG_440SPE)
/* provide clocks for EMAC internal loopback */
mfsdr (sdr_mfr, mfr);
mfr |= SDR0_MFR_ETH_CLK_SEL_V(devnum);
@@ -518,7 +521,8 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
if (failsafe <= 0)
printf("\nProblem resetting EMAC!\n");
-#if defined(CONFIG_440SPE) || defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
+#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
+ defined(CONFIG_440SP) || defined(CONFIG_440SPE)
/* remove clocks for EMAC internal loopback */
mfsdr (sdr_mfr, mfr);
mfr &= ~SDR0_MFR_ETH_CLK_SEL_V(devnum);
@@ -920,8 +924,8 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
/* set speed */
if (speed == _1000BASET) {
-#if defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
- defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
+#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
+ defined(CONFIG_440SP) || defined(CONFIG_440SPE)
unsigned long pfc1;
mfsdr (sdr_pfc1, pfc1);
@@ -1415,10 +1419,8 @@ static void enet_rcv (struct eth_device *dev, unsigned long malisr)
if ((MAL_RX_CTRL_EMPTY & hw_p->rx[i].ctrl)
|| (loop_count >= NUM_RX_BUFF))
break;
+
loop_count++;
- hw_p->rx_slot++;
- if (NUM_RX_BUFF == hw_p->rx_slot)
- hw_p->rx_slot = 0;
handled++;
data_len = (unsigned long) hw_p->rx[i].data_len; /* Get len */
if (data_len) {
@@ -1468,6 +1470,10 @@ static void enet_rcv (struct eth_device *dev, unsigned long malisr)
if (NUM_RX_BUFF == hw_p->rx_i_index)
hw_p->rx_i_index = 0;
+ hw_p->rx_slot++;
+ if (NUM_RX_BUFF == hw_p->rx_slot)
+ hw_p->rx_slot = 0;
+
/* AS.HARNOIS
* free receive buffer only when
* buffer has been handled (eth_rx)
diff --git a/cpu/ppc4xx/gpio.c b/cpu/ppc4xx/gpio.c
index 5235203..50f2fdf 100644
--- a/cpu/ppc4xx/gpio.c
+++ b/cpu/ppc4xx/gpio.c
@@ -186,6 +186,7 @@ void gpio_set_chip_configuration(void)
out32(GPIO0_TCR, reg);
}
+#ifdef GPIO1
if (gpio_core == GPIO1) {
/*
* Setup output value
@@ -193,16 +194,17 @@ void gpio_set_chip_configuration(void)
* 0 -> low level
* else -> don't touch
*/
- reg = in32(GPIO0_OR);
+ reg = in32(GPIO1_OR);
if (gpio_tab[gpio_core][i].out_val == GPIO_OUT_1)
reg |= (0x80000000 >> (i));
else if (gpio_tab[gpio_core][i].out_val == GPIO_OUT_0)
reg &= ~(0x80000000 >> (i));
- out32(GPIO0_OR, reg);
+ out32(GPIO1_OR, reg);
reg = in32(GPIO1_TCR) | (0x80000000 >> (i));
out32(GPIO1_TCR, reg);
}
+#endif /* GPIO1 */
reg = in32(GPIO_OS(core_add+offs))
& ~(GPIO_MASK >> (j*2));
diff --git a/cpu/ppc4xx/sdram.c b/cpu/ppc4xx/sdram.c
index d520cd3..2724d91 100644
--- a/cpu/ppc4xx/sdram.c
+++ b/cpu/ppc4xx/sdram.c
@@ -187,14 +187,14 @@ void sdram_init(void)
/*
* Disable memory controller.
*/
- mtsdram0(mem_mcopt1, 0x00000000);
+ mtsdram(mem_mcopt1, 0x00000000);
/*
* Set MB0CF for bank 0.
*/
- mtsdram0(mem_mb0cf, mb0cf[i].reg);
- mtsdram0(mem_sdtr1, sdtr1);
- mtsdram0(mem_rtr, compute_rtr(speed, mb0cf[i].rows, 64));
+ mtsdram(mem_mb0cf, mb0cf[i].reg);
+ mtsdram(mem_sdtr1, sdtr1);
+ mtsdram(mem_rtr, compute_rtr(speed, mb0cf[i].rows, 64));
udelay(200);
@@ -203,14 +203,34 @@ void sdram_init(void)
* Set DC_EN to '1' and BRD_PRF to '01' for 16 byte PLB Burst
* read/prefetch.
*/
- mtsdram0(mem_mcopt1, 0x80800000);
+ mtsdram(mem_mcopt1, 0x80800000);
udelay(10000);
if (get_ram_size(0, mb0cf[i].size) == mb0cf[i].size) {
/*
- * OK, size detected -> all done
+ * OK, size detected. Enable second bank if
+ * defined (assumes same type as bank 0)
*/
+#ifdef CONFIG_SDRAM_BANK1
+ u32 b1cr = mb0cf[i].size | mb0cf[i].reg;
+
+ mtsdram(mem_mcopt1, 0x00000000);
+ mtsdram(mem_mb1cf, b1cr); /* SDRAM0_B1CR */
+ mtsdram(mem_mcopt1, 0x80800000);
+ udelay(10000);
+
+ /*
+ * Check if 2nd bank is really available.
+ * If the size not equal to the size of the first
+ * bank, then disable the 2nd bank completely.
+ */
+ if (get_ram_size((long *)mb0cf[i].size, mb0cf[i].size) !=
+ mb0cf[i].size) {
+ mtsdram(mem_mb1cf, 0);
+ mtsdram(mem_mcopt1, 0);
+ }
+#endif
return;
}
}
diff --git a/cpu/ppc4xx/sdram.h b/cpu/ppc4xx/sdram.h
index 62b5442..4fb9b1a 100644
--- a/cpu/ppc4xx/sdram.h
+++ b/cpu/ppc4xx/sdram.h
@@ -29,8 +29,6 @@
#include <config.h>
-#define mtsdram0(reg, data) mtdcr(memcfga,reg);mtdcr(memcfgd,data)
-
#define ONE_BILLION 1000000000
struct sdram_conf_s {
diff --git a/cpu/ppc4xx/serial.c b/cpu/ppc4xx/serial.c
index 3f67136..60712b1 100644
--- a/cpu/ppc4xx/serial.c
+++ b/cpu/ppc4xx/serial.c
@@ -448,12 +448,17 @@ static void serial_divs (int baudrate, unsigned long *pudiv,
unsigned long i;
unsigned long est; /* current estimate */
unsigned long plloutb;
+ unsigned long cpr_pllc;
u32 reg;
+ /* check the pll feedback source */
+ mfcpr(cprpllc, cpr_pllc);
+
get_sys_info(&sysinfo);
- plloutb = ((CONFIG_SYS_CLK_FREQ * sysinfo.pllFwdDiv * sysinfo.pllFbkDiv)
- / sysinfo.pllFwdDivB);
+ plloutb = ((CONFIG_SYS_CLK_FREQ * ((cpr_pllc & PLLC_SRC_MASK) ?
+ sysinfo.pllFwdDivB : sysinfo.pllFwdDiv) * sysinfo.pllFbkDiv) /
+ sysinfo.pllFwdDivB);
udiv = 256; /* Assume lowest possible serial clk */
div = plloutb / (16 * baudrate); /* total divisor */
umin = (plloutb / get_OPB_freq()) << 1; /* 2 x OPB divisor */
diff --git a/cpu/ppc4xx/speed.c b/cpu/ppc4xx/speed.c
index 028b11a..da5330a 100644
--- a/cpu/ppc4xx/speed.c
+++ b/cpu/ppc4xx/speed.c
@@ -771,6 +771,7 @@ ulong get_PCI_freq (void)
void get_sys_info (PPC405_SYS_INFO * sysInfo)
{
unsigned long cpr_plld;
+ unsigned long cpr_pllc;
unsigned long cpr_primad;
unsigned long sysClkPeriodPs = ONE_BILLION / (CONFIG_SYS_CLK_FREQ/1000);
unsigned long primad_cpudv;
@@ -780,6 +781,7 @@ void get_sys_info (PPC405_SYS_INFO * sysInfo)
* Read PLL Mode registers
*/
mfcpr(cprplld, cpr_plld);
+ mfcpr(cprpllc, cpr_pllc);
/*
* Determine forward divider A
@@ -787,20 +789,18 @@ void get_sys_info (PPC405_SYS_INFO * sysInfo)
sysInfo->pllFwdDiv = ((cpr_plld & PLLD_FWDVA_MASK) >> 16);
/*
- * Determine forward divider B (should be equal to A)
+ * Determine forward divider B
*/
sysInfo->pllFwdDivB = ((cpr_plld & PLLD_FWDVB_MASK) >> 8);
- if (sysInfo->pllFwdDivB == 0) {
+ if (sysInfo->pllFwdDivB == 0)
sysInfo->pllFwdDivB = 8;
- }
/*
* Determine FBK_DIV.
*/
sysInfo->pllFbkDiv = ((cpr_plld & PLLD_FBDV_MASK) >> 24);
- if (sysInfo->pllFbkDiv == 0) {
+ if (sysInfo->pllFbkDiv == 0)
sysInfo->pllFbkDiv = 256;
- }
/*
* Read CPR_PRIMAD register
@@ -810,30 +810,30 @@ void get_sys_info (PPC405_SYS_INFO * sysInfo)
* Determine PLB_DIV.
*/
sysInfo->pllPlbDiv = ((cpr_primad & PRIMAD_PLBDV_MASK) >> 16);
- if (sysInfo->pllPlbDiv == 0) {
+ if (sysInfo->pllPlbDiv == 0)
sysInfo->pllPlbDiv = 16;
- }
/*
* Determine EXTBUS_DIV.
*/
sysInfo->pllExtBusDiv = (cpr_primad & PRIMAD_EBCDV_MASK);
- if (sysInfo->pllExtBusDiv == 0) {
+ if (sysInfo->pllExtBusDiv == 0)
sysInfo->pllExtBusDiv = 16;
- }
/*
* Determine OPB_DIV.
*/
sysInfo->pllOpbDiv = ((cpr_primad & PRIMAD_OPBDV_MASK) >> 8);
- if (sysInfo->pllOpbDiv == 0) {
+ if (sysInfo->pllOpbDiv == 0)
sysInfo->pllOpbDiv = 16;
- }
/*
* Determine the M factor
*/
- m = sysInfo->pllFbkDiv * sysInfo->pllFwdDivB;
+ if (cpr_pllc & PLLC_SRC_MASK)
+ m = sysInfo->pllFbkDiv * sysInfo->pllFwdDivB;
+ else
+ m = sysInfo->pllFbkDiv * sysInfo->pllFwdDiv;
/*
* Determine VCO clock frequency
@@ -845,16 +845,17 @@ void get_sys_info (PPC405_SYS_INFO * sysInfo)
* Determine CPU clock frequency
*/
primad_cpudv = ((cpr_primad & PRIMAD_CPUDV_MASK) >> 24);
- if (primad_cpudv == 0) {
+ if (primad_cpudv == 0)
primad_cpudv = 16;
- }
- sysInfo->freqProcessor = (CONFIG_SYS_CLK_FREQ * sysInfo->pllFbkDiv) / primad_cpudv;
+ sysInfo->freqProcessor = (CONFIG_SYS_CLK_FREQ * m) /
+ sysInfo->pllFwdDiv / primad_cpudv;
/*
* Determine PLB clock frequency
*/
- sysInfo->freqPLB = (CONFIG_SYS_CLK_FREQ * sysInfo->pllFbkDiv) / sysInfo->pllPlbDiv;
+ sysInfo->freqPLB = (CONFIG_SYS_CLK_FREQ * m) /
+ sysInfo->pllFwdDiv / sysInfo->pllPlbDiv;
}
/********************************************
diff --git a/cpu/ppc4xx/start.S b/cpu/ppc4xx/start.S
index 8ecaaea..9626b65 100644
--- a/cpu/ppc4xx/start.S
+++ b/cpu/ppc4xx/start.S
@@ -1870,28 +1870,6 @@ ppc405ep_init:
mtdcr ebccfgd,r3
#endif
-#ifndef CFG_CPC0_PCI
- li r3,CPC0_PCI_HOST_CFG_EN
-#ifdef CONFIG_BUBINGA
- /*
- !-----------------------------------------------------------------------
- ! Check FPGA for PCI internal/external arbitration
- ! If board is set to internal arbitration, update cpc0_pci
- !-----------------------------------------------------------------------
- */
- addis r5,r0,FPGA_REG1@h /* set offset for FPGA_REG1 */
- ori r5,r5,FPGA_REG1@l
- lbz r5,0x0(r5) /* read to get PCI arb selection */
- andi. r6,r5,FPGA_REG1_PCI_INT_ARB /* using internal arbiter ?*/
- beq ..pci_cfg_set /* if not set, then bypass reg write*/
-#endif
- ori r3,r3,CPC0_PCI_ARBIT_EN
-#else /* CFG_CPC0_PCI */
- li r3,CFG_CPC0_PCI
-#endif /* CFG_CPC0_PCI */
-..pci_cfg_set:
- mtdcr CPC0_PCI, r3 /* Enable internal arbiter*/
-
/*
!-----------------------------------------------------------------------
! Check to see if chip is in bypass mode.
@@ -1947,11 +1925,50 @@ ppc405ep_init:
..no_pllset:
#endif /* CONFIG_BUBINGA */
+#ifdef CONFIG_TAIHU
+ mfdcr r4, CPC0_BOOT
+ andi. r5, r4, CPC0_BOOT_SEP@l
+ bne strap_1 /* serial eeprom present */
+ addis r5,0,CPLD_REG0_ADDR@h
+ ori r5,r5,CPLD_REG0_ADDR@l
+ andi. r5, r5, 0x10
+ bne _pci_66mhz
+#endif /* CONFIG_TAIHU */
+
+#if defined(CONFIG_ZEUS)
+ mfdcr r4, CPC0_BOOT
+ andi. r5, r4, CPC0_BOOT_SEP@l
+ bne strap_1 /* serial eeprom present */
+ lis r3,0x0000
+ addi r3,r3,0x3030
+ lis r4,0x8042
+ addi r4,r4,0x223e
+ b 1f
+strap_1:
+ mfdcr r3, CPC0_PLLMR0
+ mfdcr r4, CPC0_PLLMR1
+ b 1f
+#endif
+
addis r3,0,PLLMR0_DEFAULT@h /* PLLMR0 default value */
ori r3,r3,PLLMR0_DEFAULT@l /* */
addis r4,0,PLLMR1_DEFAULT@h /* PLLMR1 default value */
ori r4,r4,PLLMR1_DEFAULT@l /* */
+#ifdef CONFIG_TAIHU
+ b 1f
+_pci_66mhz:
+ addis r3,0,PLLMR0_DEFAULT_PCI66@h
+ ori r3,r3,PLLMR0_DEFAULT_PCI66@l
+ addis r4,0,PLLMR1_DEFAULT_PCI66@h
+ ori r4,r4,PLLMR1_DEFAULT_PCI66@l
+ b 1f
+strap_1:
+ mfdcr r3, CPC0_PLLMR0
+ mfdcr r4, CPC0_PLLMR1
+#endif /* CONFIG_TAIHU */
+
+1:
b pll_write /* Write the CPC0_PLLMR with new value */
pll_done:
diff --git a/cpu/ppc4xx/tlb.c b/cpu/ppc4xx/tlb.c
index 049a785..098694c 100644
--- a/cpu/ppc4xx/tlb.c
+++ b/cpu/ppc4xx/tlb.c
@@ -25,7 +25,6 @@
#if defined(CONFIG_440)
-#include <ppc4xx.h>
#include <ppc440.h>
#include <asm/io.h>
#include <asm/mmu.h>
@@ -36,6 +35,67 @@ typedef struct region {
unsigned long tlb_word2_i_value;
} region_t;
+void remove_tlb(u32 vaddr, u32 size)
+{
+ int i;
+ u32 tlb_word0_value;
+ u32 tlb_vaddr;
+ u32 tlb_size = 0;
+
+ /* First, find the index of a TLB entry not being used */
+ for (i=0; i<PPC4XX_TLB_SIZE; i++) {
+ tlb_word0_value = mftlb1(i);
+ tlb_vaddr = TLB_WORD0_EPN_DECODE(tlb_word0_value);
+ if (((tlb_word0_value & TLB_WORD0_V_MASK) == TLB_WORD0_V_ENABLE) &&
+ (tlb_vaddr >= vaddr)) {
+ /*
+ * TLB is enabled and start address is lower or equal
+ * than the area we are looking for. Now we only have
+ * to check the size/end address for a match.
+ */
+ switch (tlb_word0_value & TLB_WORD0_SIZE_MASK) {
+ case TLB_WORD0_SIZE_1KB:
+ tlb_size = 1 << 10;
+ break;
+ case TLB_WORD0_SIZE_4KB:
+ tlb_size = 4 << 10;
+ break;
+ case TLB_WORD0_SIZE_16KB:
+ tlb_size = 16 << 10;
+ break;
+ case TLB_WORD0_SIZE_64KB:
+ tlb_size = 64 << 10;
+ break;
+ case TLB_WORD0_SIZE_256KB:
+ tlb_size = 256 << 10;
+ break;
+ case TLB_WORD0_SIZE_1MB:
+ tlb_size = 1 << 20;
+ break;
+ case TLB_WORD0_SIZE_16MB:
+ tlb_size = 16 << 20;
+ break;
+ case TLB_WORD0_SIZE_256MB:
+ tlb_size = 256 << 20;
+ break;
+ }
+
+ /*
+ * Now check the end-address if it's in the range
+ */
+ if ((tlb_vaddr + tlb_size - 1) <= (vaddr + size - 1))
+ /*
+ * Found a TLB in the range.
+ * Disable it by writing 0 to tlb0 word.
+ */
+ mttlb1(i, 0);
+ }
+ }
+
+ /* Execute an ISYNC instruction so that the new TLB entry takes effect */
+ asm("isync");
+}
+
static int add_tlb_entry(unsigned long phys_addr,
unsigned long virt_addr,
unsigned long tlb_word0_size_value,
diff --git a/cpu/ppc4xx/traps.c b/cpu/ppc4xx/traps.c
index 899cdbd..38b6f89 100644
--- a/cpu/ppc4xx/traps.c
+++ b/cpu/ppc4xx/traps.c
@@ -147,14 +147,15 @@ MachineCheckException(struct pt_regs *regs)
unsigned long fixup, val;
#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
u32 value2;
+ int corr_ecc = 0;
+ int uncorr_ecc = 0;
#endif
- /* Probing PCI using config cycles cause this exception
- * when a device is not present. Catch it and return to
- * the PCI exception handler.
- */
if ((fixup = search_exception_table(regs->nip)) != 0) {
regs->nip = fixup;
+ val = mfspr(MCSR);
+ /* Clear MCSR */
+ mtspr(SPRN_MCSR, val);
return;
}
@@ -214,14 +215,22 @@ MachineCheckException(struct pt_regs *regs)
printf("DDR0: At least one interrupt active\n");
if (val & 0x40)
printf("DDR0: DRAM initialization complete.\n");
- if (val & 0x20)
+ if (val & 0x20) {
printf("DDR0: Multiple uncorrectable ECC events.\n");
- if (val & 0x10)
+ uncorr_ecc = 1;
+ }
+ if (val & 0x10) {
printf("DDR0: Single uncorrectable ECC event.\n");
- if (val & 0x08)
+ uncorr_ecc = 1;
+ }
+ if (val & 0x08) {
printf("DDR0: Multiple correctable ECC events.\n");
- if (val & 0x04)
+ corr_ecc = 1;
+ }
+ if (val & 0x04) {
printf("DDR0: Single correctable ECC event.\n");
+ corr_ecc = 1;
+ }
if (val & 0x02)
printf("Multiple accesses outside the defined"
" physical memory space detected\n");
@@ -252,11 +261,11 @@ MachineCheckException(struct pt_regs *regs)
printf("DDR0: No DDR0 error know 0x%x %p\n", val, value2);
}
mfsdram(DDR0_23, val);
- if ( (val >> 16) & 0xff)
+ if (((val >> 16) & 0xff) && corr_ecc)
printf("DDR0: Syndrome for correctable ECC event 0x%x\n",
(val >> 16) & 0xff);
mfsdram(DDR0_23, val);
- if ( (val >> 8) & 0xff)
+ if (((val >> 8) & 0xff) && uncorr_ecc)
printf("DDR0: Syndrome for uncorrectable ECC event 0x%x\n",
(val >> 8) & 0xff);
mfsdram(DDR0_33, val);
@@ -264,28 +273,28 @@ MachineCheckException(struct pt_regs *regs)
printf("DDR0: Address of command that caused an "
"Out-of-Range interrupt %p\n", val);
mfsdram(DDR0_34, val);
- if (val)
+ if (val && uncorr_ecc)
printf("DDR0: Address of uncorrectable ECC event %p\n", val);
mfsdram(DDR0_35, val);
- if (val)
+ if (val && uncorr_ecc)
printf("DDR0: Address of uncorrectable ECC event %p\n", val);
mfsdram(DDR0_36, val);
- if (val)
+ if (val && uncorr_ecc)
printf("DDR0: Data of uncorrectable ECC event 0x%08x\n", val);
mfsdram(DDR0_37, val);
- if (val)
+ if (val && uncorr_ecc)
printf("DDR0: Data of uncorrectable ECC event 0x%08x\n", val);
mfsdram(DDR0_38, val);
- if (val)
+ if (val && corr_ecc)
printf("DDR0: Address of correctable ECC event %p\n", val);
mfsdram(DDR0_39, val);
- if (val)
+ if (val && corr_ecc)
printf("DDR0: Address of correctable ECC event %p\n", val);
mfsdram(DDR0_40, val);
- if (val)
+ if (val && corr_ecc)
printf("DDR0: Data of correctable ECC event 0x%08x\n", val);
mfsdram(DDR0_41, val);
- if (val)
+ if (val && corr_ecc)
printf("DDR0: Data of correctable ECC event 0x%08x\n", val);
#endif /* CONFIG_440EPX */
#endif /* CONFIG_440 */
diff --git a/cpu/ppc4xx/usb.c b/cpu/ppc4xx/usb.c
index 2837b37..272ed8c 100644
--- a/cpu/ppc4xx/usb.c
+++ b/cpu/ppc4xx/usb.c
@@ -27,7 +27,7 @@
#include "usbdev.h"
-int usb_cpu_init()
+int usb_cpu_init(void)
{
#if defined(CONFIG_440EP) || defined(CONFIG_440EPX)
@@ -37,12 +37,12 @@ int usb_cpu_init()
return 0;
}
-int usb_cpu_stop()
+int usb_cpu_stop(void)
{
return 0;
}
-int usb_cpu_init_fail()
+int usb_cpu_init_fail(void)
{
return 0;
}