summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRafal Jaworowski <raj@semihalf.com>2006-08-10 12:43:17 +0200
committerRafal Jaworowski <raj@pollux.denx.de>2006-08-10 12:43:17 +0200
commit692519b1edfd5803cd2a841921492889f46f0ce3 (patch)
tree1a761268c5b203444769a19257a317d09ce396c4
parentedd6cf20e1be63f84e0f5af0280473cf31f0e86c (diff)
Add support for PCI-Express on PPC440SPe (Yucca board).
-rw-r--r--CHANGELOG2
-rw-r--r--board/amcc/yucca/init.S62
-rw-r--r--board/amcc/yucca/yucca.c130
-rw-r--r--cpu/ppc4xx/405gp_pci.c5
-rw-r--r--cpu/ppc4xx/440spe_pcie.c593
-rw-r--r--cpu/ppc4xx/440spe_pcie.h162
-rw-r--r--cpu/ppc4xx/Makefile3
-rw-r--r--cpu/ppc4xx/cpu.c11
-rw-r--r--cpu/ppc4xx/start.S16
-rw-r--r--include/common.h4
-rw-r--r--include/configs/yucca.h32
11 files changed, 1000 insertions, 20 deletions
diff --git a/CHANGELOG b/CHANGELOG
index de02125bd63..0c70d3cfcdb 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -2,6 +2,8 @@
Changes since U-Boot 1.1.4:
======================================================================
+* Add initial support for PCI-Express on PPC440SPe (Yucca board).
+
* Fix timer problems on AMCC yucca board.
Set Timer Clock Select to use CPU clock as a timer input source.
diff --git a/board/amcc/yucca/init.S b/board/amcc/yucca/init.S
index 8cf2636228b..a950eac44f9 100644
--- a/board/amcc/yucca/init.S
+++ b/board/amcc/yucca/init.S
@@ -82,9 +82,12 @@
*************************************************************************/
.section .bootpg,"ax"
- .globl tlbtab
-tlbtab:
+/**************************************************************************
+ * TLB table for revA
+ *************************************************************************/
+ .globl tlbtabA
+tlbtabA:
tlbtab_start
tlbentry(0xfff00000, SZ_16M, 0xfff00000, 4, AC_R|AC_W|AC_X|SA_G)
@@ -94,12 +97,63 @@ tlbtab:
tlbentry(CFG_SDRAM_BASE + 0x30000000, SZ_256M, 0x30000000, 0, AC_R|AC_W|AC_X|SA_G|SA_I)
tlbentry(CFG_ISRAM_BASE, SZ_256K, 0x00000000, 4, AC_R|AC_W|AC_X|SA_I)
- tlbentry(CFG_FPGA_BASE,SZ_1K, 0xE2000000, 4,AC_R|AC_W|SA_I)
+ tlbentry(CFG_FPGA_BASE, SZ_1K, 0xE2000000, 4,AC_R|AC_W|SA_I)
- tlbentry(CFG_OPER_FLASH,SZ_16M,0xE7000000, 4,AC_R|AC_W|AC_X|SA_G|SA_I)
+ tlbentry(CFG_OPER_FLASH, SZ_16M, 0xE7000000, 4,AC_R|AC_W|AC_X|SA_G|SA_I)
tlbentry(CFG_PERIPHERAL_BASE, SZ_4K, 0xF0000000, 4, AC_R|AC_W|SA_G|SA_I)
tlbentry(CFG_PCI_BASE, SZ_256M, 0x00000000, 0xC, AC_R|AC_W|SA_G|SA_I)
tlbentry(CFG_PCI_MEMBASE, SZ_256M, 0x10000000, 0xC, AC_R|AC_W|SA_G|SA_I)
+ tlbentry(CFG_PCIE_MEMBASE, SZ_256M, 0xB0000000, 0xD, AC_R|AC_W|SA_G|SA_I)
+
+ tlbentry(CFG_PCIE0_CFGBASE, SZ_16M, 0x40000000, 0xC, AC_R|AC_W|SA_G|SA_I)
+ tlbentry(CFG_PCIE1_CFGBASE, SZ_16M, 0x80000000, 0xC, AC_R|AC_W|SA_G|SA_I)
+ tlbentry(CFG_PCIE2_CFGBASE, SZ_16M, 0xC0000000, 0xC, AC_R|AC_W|SA_G|SA_I)
+ tlbentry(CFG_PCIE0_XCFGBASE, SZ_4K, 0x50000000, 0xC, AC_R|AC_W|SA_G|SA_I)
+ tlbentry(CFG_PCIE1_XCFGBASE, SZ_4K, 0x90000000, 0xC, AC_R|AC_W|SA_G|SA_I)
+ tlbentry(CFG_PCIE2_XCFGBASE, SZ_4K, 0xD0000000, 0xC, AC_R|AC_W|SA_G|SA_I)
+
+ tlbentry(CFG_PCIE1_REGBASE, SZ_1K, 0x60000400, 0xD, AC_R|AC_W|SA_G|SA_I)
+ tlbentry(CFG_PCIE3_REGBASE, SZ_1K, 0x60001400, 0xD, AC_R|AC_W|SA_G|SA_I)
+ tlbentry(CFG_PCIE5_REGBASE, SZ_1K, 0x60002400, 0xD, AC_R|AC_W|SA_G|SA_I)
tlbtab_end
+/**************************************************************************
+ * TLB table for revB
+ *
+ * Notice: revB of the 440SPe chip is very strict about PLB real addressess
+ * and ranges to be mapped for config space: it seems to only work with
+ * d_nnnn_nnnn range (hangs the core upon config transaction attempts when
+ * set otherwise) while revA uses c_nnnn_nnnn.
+ *************************************************************************/
+ .globl tlbtabB
+tlbtabB:
+ tlbtab_start
+ tlbentry(0xfff00000, SZ_16M, 0xfff00000, 4, AC_R|AC_W|AC_X|SA_G)
+
+ tlbentry(CFG_SDRAM_BASE, SZ_256M, 0x00000000, 0, AC_R|AC_W|AC_X|SA_G|SA_I)
+ tlbentry(CFG_SDRAM_BASE + 0x10000000, SZ_256M, 0x10000000, 0, AC_R|AC_W|AC_X|SA_G|SA_I)
+ tlbentry(CFG_SDRAM_BASE + 0x20000000, SZ_256M, 0x20000000, 0, AC_R|AC_W|AC_X|SA_G|SA_I)
+ tlbentry(CFG_SDRAM_BASE + 0x30000000, SZ_256M, 0x30000000, 0, AC_R|AC_W|AC_X|SA_G|SA_I)
+
+ tlbentry(CFG_ISRAM_BASE, SZ_256K, 0x00000000, 4, AC_R|AC_W|AC_X|SA_I)
+ tlbentry(CFG_FPGA_BASE, SZ_1K, 0xE2000000, 4,AC_R|AC_W|SA_I)
+
+ tlbentry(CFG_OPER_FLASH, SZ_16M, 0xE7000000, 4,AC_R|AC_W|AC_X|SA_G|SA_I)
+ tlbentry(CFG_PERIPHERAL_BASE, SZ_4K, 0xF0000000, 4, AC_R|AC_W|SA_G|SA_I)
+
+ tlbentry(CFG_PCI_BASE, SZ_256M, 0x00000000, 0xC, AC_R|AC_W|SA_G|SA_I)
+ tlbentry(CFG_PCI_MEMBASE, SZ_256M, 0x10000000, 0xC, AC_R|AC_W|SA_G|SA_I)
+ tlbentry(CFG_PCIE_MEMBASE, SZ_256M, 0xB0000000, 0xD, AC_R|AC_W|SA_G|SA_I)
+
+ tlbentry(CFG_PCIE0_CFGBASE, SZ_1K, 0x00100000, 0xD, AC_R|AC_W|SA_G|SA_I)
+ tlbentry(CFG_PCIE1_CFGBASE, SZ_1K, 0x20100000, 0xD, AC_R|AC_W|SA_G|SA_I)
+ tlbentry(CFG_PCIE2_CFGBASE, SZ_1K, 0x40100000, 0xD, AC_R|AC_W|SA_G|SA_I)
+ tlbentry(CFG_PCIE0_XCFGBASE, SZ_1K, 0x10000000, 0xD, AC_R|AC_W|SA_G|SA_I)
+ tlbentry(CFG_PCIE1_XCFGBASE, SZ_1K, 0x30000000, 0xD, AC_R|AC_W|SA_G|SA_I)
+ tlbentry(CFG_PCIE2_XCFGBASE, SZ_1K, 0x50000000, 0xD, AC_R|AC_W|SA_G|SA_I)
+
+ tlbentry(CFG_PCIE1_REGBASE, SZ_1K, 0x60000400, 0xD, AC_R|AC_W|SA_G|SA_I)
+ tlbentry(CFG_PCIE3_REGBASE, SZ_1K, 0x60001400, 0xD, AC_R|AC_W|SA_G|SA_I)
+ tlbentry(CFG_PCIE5_REGBASE, SZ_1K, 0x60002400, 0xD, AC_R|AC_W|SA_G|SA_I)
+ tlbtab_end
diff --git a/board/amcc/yucca/yucca.c b/board/amcc/yucca/yucca.c
index 1ae3a549b9b..a6589ec262a 100644
--- a/board/amcc/yucca/yucca.c
+++ b/board/amcc/yucca/yucca.c
@@ -21,12 +21,16 @@
* MA 02111-1307 USA
*
* Port to AMCC-440SPE Evaluation Board SOP - April 2005
+ *
+ * PCIe supporting routines derived from Linux 440SPe PCIe driver.
*/
#include <common.h>
#include <ppc4xx.h>
#include <asm/processor.h>
#include <i2c.h>
+#include <asm-ppc/io.h>
+
#include "yucca.h"
void fpga_init (void);
@@ -39,6 +43,9 @@ int get_console_port(void);
unsigned long ppcMfcpr(unsigned long cpr_reg);
unsigned long ppcMfsdr(unsigned long sdr_reg);
+int ppc440spe_init_pcie_rootport(int port);
+void ppc440spe_setup_pcie(struct pci_controller *hose, int port);
+
#define DEBUG_ENV
#ifdef DEBUG_ENV
#define DEBUGF(fmt,args...) printf(fmt ,##args)
@@ -908,6 +915,7 @@ void pci_target_init(struct pci_controller * hose )
}
#endif /* defined(CONFIG_PCI) && defined(CFG_PCI_TARGET_INIT) */
+#if defined(CONFIG_PCI)
/*************************************************************************
* is_pci_host
*
@@ -923,12 +931,131 @@ void pci_target_init(struct pci_controller * hose )
*
*
************************************************************************/
-#if defined(CONFIG_PCI)
int is_pci_host(struct pci_controller *hose)
{
/* The yucca board is always configured as host. */
return 1;
}
+
+
+int yucca_pcie_card_present(int port)
+{
+ u16 reg;
+
+ reg = in_be16((u16 *)FPGA_REG1C);
+ switch(port) {
+ case 0:
+ return !(reg & FPGA_REG1C_PE0_PRSNT);
+ case 1:
+ return !(reg & FPGA_REG1C_PE1_PRSNT);
+ case 2:
+ return !(reg & FPGA_REG1C_PE2_PRSNT);
+ default:
+ return 0;
+ }
+}
+
+/*
+ * For the given slot, set rootpoint mode, send power to the slot,
+ * turn on the green LED and turn off the yellow LED, enable the clock
+ * and turn off reset.
+ */
+void yucca_setup_pcie_fpga_rootpoint(int port)
+{
+ u16 power, clock, green_led, yellow_led, reset_off, rootpoint, endpoint;
+
+ switch(port) {
+ case 0:
+ rootpoint = FPGA_REG1C_PE0_ROOTPOINT;
+ endpoint = 0;
+ power = FPGA_REG1A_PE0_PWRON;
+ green_led = FPGA_REG1A_PE0_GLED;
+ clock = FPGA_REG1A_PE0_REFCLK_ENABLE;
+ yellow_led = FPGA_REG1A_PE0_YLED;
+ reset_off = FPGA_REG1C_PE0_PERST;
+ break;
+ case 1:
+ rootpoint = 0;
+ endpoint = FPGA_REG1C_PE1_ENDPOINT;
+ power = FPGA_REG1A_PE1_PWRON;
+ green_led = FPGA_REG1A_PE1_GLED;
+ clock = FPGA_REG1A_PE1_REFCLK_ENABLE;
+ yellow_led = FPGA_REG1A_PE1_YLED;
+ reset_off = FPGA_REG1C_PE1_PERST;
+ break;
+ case 2:
+ rootpoint = 0;
+ endpoint = FPGA_REG1C_PE2_ENDPOINT;
+ power = FPGA_REG1A_PE2_PWRON;
+ green_led = FPGA_REG1A_PE2_GLED;
+ clock = FPGA_REG1A_PE2_REFCLK_ENABLE;
+ yellow_led = FPGA_REG1A_PE2_YLED;
+ reset_off = FPGA_REG1C_PE2_PERST;
+ break;
+
+ default:
+ return;
+ }
+
+ out_be16((u16 *)FPGA_REG1A,
+ ~(power | clock | green_led) &
+ (yellow_led | in_be16((u16 *)FPGA_REG1A)));
+
+ out_be16((u16 *)FPGA_REG1C,
+ ~(endpoint | reset_off) &
+ (rootpoint | in_be16((u16 *)FPGA_REG1C)));
+ /*
+ * Leave device in reset for a while after powering on the
+ * slot to give it a chance to initialize.
+ */
+ udelay(250 * 1000);
+
+ out_be16((u16 *)FPGA_REG1C, reset_off | in_be16((u16 *)FPGA_REG1C));
+}
+
+
+static struct pci_controller pcie_hose[3] = {{0},{0},{0}};
+
+void pcie_setup_hoses(void)
+{
+ struct pci_controller *hose;
+ int i, bus;
+
+ /*
+ * assume we're called after the PCIX hose is initialized, which takes
+ * bus ID 0 and therefore start numbering PCIe's from 1.
+ */
+ bus = 1;
+ for (i = 0; i <= 2; i++) {
+ /* Check for yucca card presence */
+ if (!yucca_pcie_card_present(i))
+ continue;
+
+ yucca_setup_pcie_fpga_rootpoint(i);
+ if (ppc440spe_init_pcie_rootport(i)) {
+ printf("PCIE%d: initialization failed\n", i);
+ continue;
+ }
+
+ hose = &pcie_hose[i];
+ hose->first_busno = bus;
+ hose->last_busno = bus;
+ bus++;
+
+ /* setup mem resource */
+ pci_set_region(hose->regions + 0,
+ CFG_PCIE_MEMBASE + i * CFG_PCIE_MEMSIZE,
+ CFG_PCIE_MEMBASE + i * CFG_PCIE_MEMSIZE,
+ CFG_PCIE_MEMSIZE,
+ PCI_REGION_MEM
+ );
+ hose->region_count = 1;
+ pci_register_hose(hose);
+
+ ppc440spe_setup_pcie(hose, i);
+ hose->last_busno = pci_hose_scan(hose);
+ }
+}
#endif /* defined(CONFIG_PCI) */
int misc_init_f (void)
@@ -1094,4 +1221,3 @@ unsigned long ppcMfsdr(unsigned long sdr_reg)
return (sdr_value);
}
-
diff --git a/cpu/ppc4xx/405gp_pci.c b/cpu/ppc4xx/405gp_pci.c
index cf5eccb01fd..0b0686bcf71 100644
--- a/cpu/ppc4xx/405gp_pci.c
+++ b/cpu/ppc4xx/405gp_pci.c
@@ -315,7 +315,6 @@ void pci_405gp_init(struct pci_controller *hose)
#ifdef CONFIG_PCI_SCAN_SHOW
printf("PCI: Bus Dev VenId DevId Class Int\n");
#endif
-
hose->last_busno = pci_hose_scan(hose);
}
#endif /* CONFIG_PCI_PNP */
@@ -563,10 +562,12 @@ void pci_440_init (struct pci_controller *hose)
}
}
-
void pci_init_board(void)
{
pci_440_init (&ppc440_hose);
+#if defined(CONFIG_440SPE)
+ pcie_setup_hoses();
+#endif
}
#endif /* CONFIG_440 & CONFIG_PCI */
diff --git a/cpu/ppc4xx/440spe_pcie.c b/cpu/ppc4xx/440spe_pcie.c
new file mode 100644
index 00000000000..cbc93dd0228
--- /dev/null
+++ b/cpu/ppc4xx/440spe_pcie.c
@@ -0,0 +1,593 @@
+/*
+ * (C) Copyright 2006
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * Copyright (c) 2005 Cisco Systems. All rights reserved.
+ * Roland Dreier <rolandd@cisco.com>
+ *
+ * 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.
+ *
+ */
+
+#include <asm/processor.h>
+#include <asm-ppc/io.h>
+#include <ppc4xx.h>
+#include <common.h>
+#include <pci.h>
+
+#include "440spe_pcie.h"
+
+#if defined(CONFIG_440SPE)
+#if defined(CONFIG_PCI)
+
+enum {
+ PTYPE_ENDPOINT = 0x0,
+ PTYPE_LEGACY_ENDPOINT = 0x1,
+ PTYPE_ROOT_PORT = 0x4,
+
+ LNKW_X1 = 0x1,
+ LNKW_X4 = 0x4,
+ LNKW_X8 = 0x8
+};
+
+static int pcie_read_config(struct pci_controller *hose, unsigned int devfn,
+ int offset, int len, u32 *val) {
+
+ *val = 0;
+ /*
+ * 440SPE implements only one function per port
+ */
+ if (!((PCI_FUNC(devfn) == 0) && (PCI_DEV(devfn) == 1)))
+ return 0;
+
+ devfn = PCI_BDF(0,0,0);
+ offset += devfn << 4;
+
+ switch (len) {
+ case 1:
+ *val = in_8(hose->cfg_data + offset);
+ break;
+ case 2:
+ *val = in_le16((u16 *)(hose->cfg_data + offset));
+ break;
+ default:
+ *val = in_le32((u32 *)(hose->cfg_data + offset));
+ break;
+ }
+ return 0;
+}
+
+static int pcie_write_config(struct pci_controller *hose, unsigned int devfn,
+ int offset, int len, u32 val) {
+
+ /*
+ * 440SPE implements only one function per port
+ */
+ if (!((PCI_FUNC(devfn) == 0) && (PCI_DEV(devfn) == 1)))
+ return 0;
+
+ devfn = PCI_BDF(0,0,0);
+ offset += devfn << 4;
+
+ switch (len) {
+ case 1:
+ out_8(hose->cfg_data + offset, val);
+ break;
+ case 2:
+ out_le16((u16 *)(hose->cfg_data + offset), val);
+ break;
+ default:
+ out_le32((u32 *)(hose->cfg_data + offset), val);
+ break;
+ }
+ return 0;
+}
+
+int pcie_read_config_byte(struct pci_controller *hose,pci_dev_t dev,int offset,u8 *val)
+{
+ u32 v;
+ int rv;
+
+ rv = pcie_read_config(hose, dev, offset, 1, &v);
+ *val = (u8)v;
+ return rv;
+}
+
+int pcie_read_config_word(struct pci_controller *hose,pci_dev_t dev,int offset,u16 *val)
+{
+ u32 v;
+ int rv;
+
+ rv = pcie_read_config(hose, dev, offset, 2, &v);
+ *val = (u16)v;
+ return rv;
+}
+
+int pcie_read_config_dword(struct pci_controller *hose,pci_dev_t dev,int offset,u32 *val)
+{
+ u32 v;
+ int rv;
+
+ rv = pcie_read_config(hose, dev, offset, 3, &v);
+ *val = (u32)v;
+ return rv;
+}
+
+int pcie_write_config_byte(struct pci_controller *hose,pci_dev_t dev,int offset,u8 val)
+{
+ return pcie_write_config(hose,(u32)dev,offset,1,val);
+}
+
+int pcie_write_config_word(struct pci_controller *hose,pci_dev_t dev,int offset,u16 val)
+{
+ return pcie_write_config(hose,(u32)dev,offset,2,(u32 )val);
+}
+
+int pcie_write_config_dword(struct pci_controller *hose,pci_dev_t dev,int offset,u32 val)
+{
+ return pcie_write_config(hose,(u32)dev,offset,3,(u32 )val);
+}
+
+static void ppc440spe_setup_utl(u32 port) {
+
+ volatile void *utl_base = NULL;
+
+ /*
+ * Map UTL registers
+ */
+ switch (port) {
+ case 0:
+ mtdcr(DCRN_PEGPL_REGBAH(PCIE0), 0x0000000d);
+ mtdcr(DCRN_PEGPL_REGBAL(PCIE0), 0x60000400);
+ mtdcr(DCRN_PEGPL_REGMSK(PCIE0), 0xFFFFFC01);
+ mtdcr(DCRN_PEGPL_SPECIAL(PCIE0), 0x68782800);
+ utl_base = (unsigned int *)(CFG_PCIE1_REGBASE);
+ break;
+
+ case 1:
+ mtdcr(DCRN_PEGPL_REGBAH(PCIE1), 0x0000000d);
+ mtdcr(DCRN_PEGPL_REGBAL(PCIE1), 0x60001400);
+ mtdcr(DCRN_PEGPL_REGMSK(PCIE1), 0xFFFFFC01);
+ mtdcr(DCRN_PEGPL_SPECIAL(PCIE1), 0x68782800);
+ utl_base = (unsigned int *)(CFG_PCIE3_REGBASE);
+ break;
+
+ case 2:
+ mtdcr(DCRN_PEGPL_REGBAH(PCIE2), 0x0000000d);
+ mtdcr(DCRN_PEGPL_REGBAL(PCIE2), 0x60002400);
+ mtdcr(DCRN_PEGPL_REGMSK(PCIE2), 0xFFFFFC01);
+ mtdcr(DCRN_PEGPL_SPECIAL(PCIE2), 0x68782800);
+ utl_base = (unsigned int *)(CFG_PCIE5_REGBASE);
+ break;
+ }
+
+ /*
+ * Set buffer allocations and then assert VRB and TXE.
+ */
+ out_be32(utl_base + PEUTL_OUTTR, 0x08000000);
+ out_be32(utl_base + PEUTL_INTR, 0x02000000);
+ out_be32(utl_base + PEUTL_OPDBSZ, 0x10000000);
+ out_be32(utl_base + PEUTL_PBBSZ, 0x53000000);
+ out_be32(utl_base + PEUTL_IPHBSZ, 0x08000000);
+ out_be32(utl_base + PEUTL_IPDBSZ, 0x10000000);
+ out_be32(utl_base + PEUTL_RCIRQEN, 0x00f00000);
+ out_be32(utl_base + PEUTL_PCTL, 0x8080007d);
+}
+
+static int check_error(void)
+{
+ u32 valPE0, valPE1, valPE2;
+ int err = 0;
+
+ /* SDR0_PEGPLLLCT1 reset */
+ if (!(valPE0 = SDR_READ(PESDR0_PLLLCT1) & 0x01000000)) {
+ printf("PCIE: SDR0_PEGPLLLCT1 reset error 0x%x\n", valPE0);
+ }
+
+ valPE0 = SDR_READ(PESDR0_RCSSET);
+ valPE1 = SDR_READ(PESDR1_RCSSET);
+ valPE2 = SDR_READ(PESDR2_RCSSET);
+
+ /* SDR0_PExRCSSET rstgu */
+ if (!(valPE0 & 0x01000000) ||
+ !(valPE1 & 0x01000000) ||
+ !(valPE2 & 0x01000000)) {
+ printf("PCIE: SDR0_PExRCSSET rstgu error\n");
+ err = -1;
+ }
+
+ /* SDR0_PExRCSSET rstdl */
+ if (!(valPE0 & 0x00010000) ||
+ !(valPE1 & 0x00010000) ||
+ !(valPE2 & 0x00010000)) {
+ printf("PCIE: SDR0_PExRCSSET rstdl error\n");
+ err = -1;
+ }
+
+ /* SDR0_PExRCSSET rstpyn */
+ if ((valPE0 & 0x00001000) ||
+ (valPE1 & 0x00001000) ||
+ (valPE2 & 0x00001000)) {
+ printf("PCIE: SDR0_PExRCSSET rstpyn error\n");
+ err = -1;
+ }
+
+ /* SDR0_PExRCSSET hldplb */
+ if ((valPE0 & 0x10000000) ||
+ (valPE1 & 0x10000000) ||
+ (valPE2 & 0x10000000)) {
+ printf("PCIE: SDR0_PExRCSSET hldplb error\n");
+ err = -1;
+ }
+
+ /* SDR0_PExRCSSET rdy */
+ if ((valPE0 & 0x00100000) ||
+ (valPE1 & 0x00100000) ||
+ (valPE2 & 0x00100000)) {
+ printf("PCIE: SDR0_PExRCSSET rdy error\n");
+ err = -1;
+ }
+
+ /* SDR0_PExRCSSET shutdown */
+ if ((valPE0 & 0x00000100) ||
+ (valPE1 & 0x00000100) ||
+ (valPE2 & 0x00000100)) {
+ printf("PCIE: SDR0_PExRCSSET shutdown error\n");
+ err = -1;
+ }
+ return err;
+}
+
+/*
+ * Initialize PCI Express core
+ */
+int ppc440spe_init_pcie(void)
+{
+ int time_out = 20;
+
+ /* Set PLL clock receiver to LVPECL */
+ SDR_WRITE(PESDR0_PLLLCT1, SDR_READ(PESDR0_PLLLCT1) | 1 << 28);
+
+ if (check_error())
+ return -1;
+
+ if (!(SDR_READ(PESDR0_PLLLCT2) & 0x10000))
+ {
+ printf("PCIE: PESDR_PLLCT2 resistance calibration failed (0x%08x)\n",
+ SDR_READ(PESDR0_PLLLCT2));
+ return -1;
+ }
+ /* De-assert reset of PCIe PLL, wait for lock */
+ SDR_WRITE(PESDR0_PLLLCT1, SDR_READ(PESDR0_PLLLCT1) & ~(1 << 24));
+ udelay(3);
+
+ while(time_out) {
+ if (!(SDR_READ(PESDR0_PLLLCT3) & 0x10000000)) {
+ time_out--;
+ udelay(1);
+ } else
+ break;
+ }
+ if (!time_out) {
+ printf("PCIE: VCO output not locked\n");
+ return -1;
+ }
+ return 0;
+}
+
+int ppc440spe_init_pcie_rootport(int port)
+{
+ static int core_init;
+ volatile u32 val = 0;
+ int attempts;
+
+ if (!core_init) {
+ ++core_init;
+ if (ppc440spe_init_pcie())
+ return -1;
+ }
+
+ /*
+ * Initialize various parts of the PCI Express core for our port:
+ *
+ * - Set as a root port and enable max width
+ * (PXIE0 -> X8, PCIE1 and PCIE2 -> X4).
+ * - Set up UTL configuration.
+ * - Increase SERDES drive strength to levels suggested by AMCC.
+ * - De-assert RSTPYN, RSTDL and RSTGU.
+ *
+ * NOTICE for revB chip: PESDRn_UTLSET2 is not set - we leave it with
+ * default setting 0x11310000. The register has new fields,
+ * PESDRn_UTLSET2[LKINE] in particular: clearing it leads to PCIE core
+ * hang.
+ */
+ switch (port) {
+ case 0:
+ SDR_WRITE(PESDR0_DLPSET, 1 << 24 | PTYPE_ROOT_PORT << 20 | LNKW_X8 << 12);
+
+ SDR_WRITE(PESDR0_UTLSET1, 0x21222222);
+ if (!ppc440spe_revB())
+ SDR_WRITE(PESDR0_UTLSET2, 0x11000000);
+ SDR_WRITE(PESDR0_HSSL0SET1, 0x35000000);
+ SDR_WRITE(PESDR0_HSSL1SET1, 0x35000000);
+ SDR_WRITE(PESDR0_HSSL2SET1, 0x35000000);
+ SDR_WRITE(PESDR0_HSSL3SET1, 0x35000000);
+ SDR_WRITE(PESDR0_HSSL4SET1, 0x35000000);
+ SDR_WRITE(PESDR0_HSSL5SET1, 0x35000000);
+ SDR_WRITE(PESDR0_HSSL6SET1, 0x35000000);
+ SDR_WRITE(PESDR0_HSSL7SET1, 0x35000000);
+ SDR_WRITE(PESDR0_RCSSET,
+ (SDR_READ(PESDR0_RCSSET) & ~(1 << 24 | 1 << 16)) | 1 << 12);
+ break;
+
+ case 1:
+ SDR_WRITE(PESDR1_DLPSET, 1 << 24 | PTYPE_ROOT_PORT << 20 | LNKW_X4 << 12);
+ SDR_WRITE(PESDR1_UTLSET1, 0x21222222);
+ if (!ppc440spe_revB())
+ SDR_WRITE(PESDR1_UTLSET2, 0x11000000);
+ SDR_WRITE(PESDR1_HSSL0SET1, 0x35000000);
+ SDR_WRITE(PESDR1_HSSL1SET1, 0x35000000);
+ SDR_WRITE(PESDR1_HSSL2SET1, 0x35000000);
+ SDR_WRITE(PESDR1_HSSL3SET1, 0x35000000);
+ SDR_WRITE(PESDR1_RCSSET,
+ (SDR_READ(PESDR1_RCSSET) & ~(1 << 24 | 1 << 16)) | 1 << 12);
+ break;
+
+ case 2:
+ SDR_WRITE(PESDR2_DLPSET, 1 << 24 | PTYPE_ROOT_PORT << 20 | LNKW_X4 << 12);
+ SDR_WRITE(PESDR2_UTLSET1, 0x21222222);
+ if (!ppc440spe_revB())
+ SDR_WRITE(PESDR2_UTLSET2, 0x11000000);
+ SDR_WRITE(PESDR2_HSSL0SET1, 0x35000000);
+ SDR_WRITE(PESDR2_HSSL1SET1, 0x35000000);
+ SDR_WRITE(PESDR2_HSSL2SET1, 0x35000000);
+ SDR_WRITE(PESDR2_HSSL3SET1, 0x35000000);
+ SDR_WRITE(PESDR2_RCSSET,
+ (SDR_READ(PESDR2_RCSSET) & ~(1 << 24 | 1 << 16)) | 1 << 12);
+ break;
+ }
+ /*
+ * Notice: the following delay has critical impact on device
+ * initialization - if too short (<50ms) the link doesn't get up.
+ */
+ mdelay(100);
+
+ switch (port) {
+ case 0: val = SDR_READ(PESDR0_RCSSTS); break;
+ case 1: val = SDR_READ(PESDR1_RCSSTS); break;
+ case 2: val = SDR_READ(PESDR2_RCSSTS); break;
+ }
+
+ if (val & (1 << 20)) {
+ printf("PCIE%d: PGRST failed %08x\n", port, val);
+ return -1;
+ }
+
+ /*
+ * Verify link is up
+ */
+ val = 0;
+ switch (port)
+ {
+ case 0:
+ val = SDR_READ(PESDR0_LOOP);
+ break;
+ case 1:
+ val = SDR_READ(PESDR1_LOOP);
+ break;
+ case 2:
+ val = SDR_READ(PESDR2_LOOP);
+ break;
+ }
+ if (!(val & 0x00001000)) {
+ printf("PCIE%d: link is not up.\n", port);
+ return -1;
+ }
+
+ /*
+ * Setup UTL registers - but only on revA!
+ * We use default settings for revB chip.
+ */
+ if (!ppc440spe_revB())
+ ppc440spe_setup_utl(port);
+
+ /*
+ * We map PCI Express configuration access into the 512MB regions
+ *
+ * NOTICE: revB is very strict about PLB real addressess and ranges to
+ * be mapped for config space; it seems to only work with d_nnnn_nnnn
+ * range (hangs the core upon config transaction attempts when set
+ * otherwise) while revA uses c_nnnn_nnnn.
+ *
+ * For revA:
+ * PCIE0: 0xc_4000_0000
+ * PCIE1: 0xc_8000_0000
+ * PCIE2: 0xc_c000_0000
+ *
+ * For revB:
+ * PCIE0: 0xd_0000_0000
+ * PCIE1: 0xd_2000_0000
+ * PCIE2: 0xd_4000_0000
+ */
+ switch (port) {
+ case 0:
+ if (ppc440spe_revB()) {
+ mtdcr(DCRN_PEGPL_CFGBAH(PCIE0), 0x0000000d);
+ mtdcr(DCRN_PEGPL_CFGBAL(PCIE0), 0x00000000);
+ } else {
+ /* revA */
+ mtdcr(DCRN_PEGPL_CFGBAH(PCIE0), 0x0000000c);
+ mtdcr(DCRN_PEGPL_CFGBAL(PCIE0), 0x40000000);
+ }
+ mtdcr(DCRN_PEGPL_CFGMSK(PCIE0), 0xe0000001); /* 512MB region, valid */
+ break;
+
+ case 1:
+ if (ppc440spe_revB()) {
+ mtdcr(DCRN_PEGPL_CFGBAH(PCIE1), 0x0000000d);
+ mtdcr(DCRN_PEGPL_CFGBAL(PCIE1), 0x20000000);
+ } else {
+ mtdcr(DCRN_PEGPL_CFGBAH(PCIE1), 0x0000000c);
+ mtdcr(DCRN_PEGPL_CFGBAL(PCIE1), 0x80000000);
+ }
+ mtdcr(DCRN_PEGPL_CFGMSK(PCIE1), 0xe0000001); /* 512MB region, valid */
+ break;
+
+ case 2:
+ if (ppc440spe_revB()) {
+ mtdcr(DCRN_PEGPL_CFGBAH(PCIE2), 0x0000000d);
+ mtdcr(DCRN_PEGPL_CFGBAL(PCIE2), 0x40000000);
+ } else {
+ mtdcr(DCRN_PEGPL_CFGBAH(PCIE2), 0x0000000c);
+ mtdcr(DCRN_PEGPL_CFGBAL(PCIE2), 0xc0000000);
+ }
+ mtdcr(DCRN_PEGPL_CFGMSK(PCIE2), 0xe0000001); /* 512MB region, valid */
+ break;
+ }
+
+ /*
+ * Check for VC0 active and assert RDY.
+ */
+ attempts = 10;
+ switch (port) {
+ case 0:
+ while(!(SDR_READ(PESDR0_RCSSTS) & (1 << 16))) {
+ if (!(attempts--)) {
+ printf("PCIE0: VC0 not active\n");
+ return -1;
+ }
+ mdelay(1000);
+ }
+ SDR_WRITE(PESDR0_RCSSET, SDR_READ(PESDR0_RCSSET) | 1 << 20);
+ break;
+ case 1:
+ while(!(SDR_READ(PESDR1_RCSSTS) & (1 << 16))) {
+ if (!(attempts--)) {
+ printf("PCIE1: VC0 not active\n");
+ return -1;
+ }
+ mdelay(1000);
+ }
+
+ SDR_WRITE(PESDR1_RCSSET, SDR_READ(PESDR1_RCSSET) | 1 << 20);
+ break;
+ case 2:
+ while(!(SDR_READ(PESDR2_RCSSTS) & (1 << 16))) {
+ if (!(attempts--)) {
+ printf("PCIE2: VC0 not active\n");
+ return -1;
+ }
+ mdelay(1000);
+ }
+
+ SDR_WRITE(PESDR2_RCSSET, SDR_READ(PESDR2_RCSSET) | 1 << 20);
+ break;
+ }
+ mdelay(100);
+
+ return 0;
+}
+
+void ppc440spe_setup_pcie(struct pci_controller *hose, int port)
+{
+ volatile void *mbase = 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);
+
+ switch(port) {
+ case 0:
+ mbase = (u32 *)CFG_PCIE0_XCFGBASE;
+ hose->cfg_data = (u8 *)CFG_PCIE0_CFGBASE;
+ break;
+ case 1:
+ mbase = (u32 *)CFG_PCIE1_XCFGBASE;
+ hose->cfg_data = (u8 *)CFG_PCIE1_CFGBASE;
+ break;
+ case 2:
+ mbase = (u32 *)CFG_PCIE2_XCFGBASE;
+ hose->cfg_data = (u8 *)CFG_PCIE2_CFGBASE;
+ break;
+ }
+
+ /*
+ * Set bus numbers on our root port
+ */
+ if (ppc440spe_revB()) {
+ out_8((u8 *)mbase + PCI_PRIMARY_BUS, 0);
+ out_8((u8 *)mbase + PCI_SECONDARY_BUS, 1);
+ out_8((u8 *)mbase + PCI_SUBORDINATE_BUS, 1);
+ } else {
+ out_8((u8 *)mbase + PCI_PRIMARY_BUS, 0);
+ out_8((u8 *)mbase + PCI_SECONDARY_BUS, 0);
+ }
+
+ /*
+ * Set up outbound translation to hose->mem_space from PLB
+ * addresses at an offset of 0xd_0000_0000. We set the low
+ * bits of the mask to 11 to turn off splitting into 8
+ * subregions and to enable the outbound translation.
+ */
+ out_le32(mbase + PECFG_POM0LAH, 0x00000000);
+ out_le32(mbase + PECFG_POM0LAL, (CFG_PCIE_MEMBASE +
+ port * CFG_PCIE_MEMSIZE));
+
+ switch (port) {
+ case 0:
+ mtdcr(DCRN_PEGPL_OMR1BAH(PCIE0), 0x0000000d);
+ mtdcr(DCRN_PEGPL_OMR1BAL(PCIE0), CFG_PCIE_MEMBASE +
+ port * CFG_PCIE_MEMSIZE);
+ mtdcr(DCRN_PEGPL_OMR1MSKH(PCIE0), 0x7fffffff);
+ mtdcr(DCRN_PEGPL_OMR1MSKL(PCIE0),
+ ~(CFG_PCIE_MEMSIZE - 1) | 3);
+ break;
+ case 1:
+ mtdcr(DCRN_PEGPL_OMR1BAH(PCIE1), 0x0000000d);
+ mtdcr(DCRN_PEGPL_OMR1BAL(PCIE1), (CFG_PCIE_MEMBASE +
+ port * CFG_PCIE_MEMSIZE));
+ mtdcr(DCRN_PEGPL_OMR1MSKH(PCIE1), 0x7fffffff);
+ mtdcr(DCRN_PEGPL_OMR1MSKL(PCIE1),
+ ~(CFG_PCIE_MEMSIZE - 1) | 3);
+ break;
+ case 2:
+ mtdcr(DCRN_PEGPL_OMR1BAH(PCIE2), 0x0000000d);
+ mtdcr(DCRN_PEGPL_OMR1BAL(PCIE2), (CFG_PCIE_MEMBASE +
+ port * CFG_PCIE_MEMSIZE));
+ mtdcr(DCRN_PEGPL_OMR1MSKH(PCIE2), 0x7fffffff);
+ mtdcr(DCRN_PEGPL_OMR1MSKL(PCIE2),
+ ~(CFG_PCIE_MEMSIZE - 1) | 3);
+ break;
+ }
+
+ /* Set up 16GB inbound memory window at 0 */
+ out_le32(mbase + PCI_BASE_ADDRESS_0, 0);
+ out_le32(mbase + PCI_BASE_ADDRESS_1, 0);
+ out_le32(mbase + PECFG_BAR0HMPA, 0x7fffffc);
+ out_le32(mbase + PECFG_BAR0LMPA, 0);
+ out_le32(mbase + PECFG_PIM0LAL, 0);
+ out_le32(mbase + PECFG_PIM0LAH, 0);
+ out_le32(mbase + PECFG_PIMEN, 0x1);
+
+ /* 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);
+}
+#endif /* CONFIG_PCI */
+#endif /* CONFIG_440SPE */
diff --git a/cpu/ppc4xx/440spe_pcie.h b/cpu/ppc4xx/440spe_pcie.h
new file mode 100644
index 00000000000..47df7620a6d
--- /dev/null
+++ b/cpu/ppc4xx/440spe_pcie.h
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 2005 Cisco Systems. All rights reserved.
+ * Roland Dreier <rolandd@cisco.com>
+ *
+ * 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.
+ */
+
+#include <ppc4xx.h>
+#ifndef __440SPE_PCIE_H
+#define __440SPE_PCIE_H
+
+#define mdelay(n) ({unsigned long __ms=(n); while (__ms--) udelay(1000);})
+
+#define DCRN_SDR0_CFGADDR 0x00e
+#define DCRN_SDR0_CFGDATA 0x00f
+
+#define DCRN_PCIE0_BASE 0x100
+#define DCRN_PCIE1_BASE 0x120
+#define DCRN_PCIE2_BASE 0x140
+#define PCIE0 DCRN_PCIE0_BASE
+#define PCIE1 DCRN_PCIE1_BASE
+#define PCIE2 DCRN_PCIE2_BASE
+
+#define DCRN_PEGPL_CFGBAH(base) (base + 0x00)
+#define DCRN_PEGPL_CFGBAL(base) (base + 0x01)
+#define DCRN_PEGPL_CFGMSK(base) (base + 0x02)
+#define DCRN_PEGPL_MSGBAH(base) (base + 0x03)
+#define DCRN_PEGPL_MSGBAL(base) (base + 0x04)
+#define DCRN_PEGPL_MSGMSK(base) (base + 0x05)
+#define DCRN_PEGPL_OMR1BAH(base) (base + 0x06)
+#define DCRN_PEGPL_OMR1BAL(base) (base + 0x07)
+#define DCRN_PEGPL_OMR1MSKH(base) (base + 0x08)
+#define DCRN_PEGPL_OMR1MSKL(base) (base + 0x09)
+#define DCRN_PEGPL_REGBAH(base) (base + 0x12)
+#define DCRN_PEGPL_REGBAL(base) (base + 0x13)
+#define DCRN_PEGPL_REGMSK(base) (base + 0x14)
+#define DCRN_PEGPL_SPECIAL(base) (base + 0x15)
+
+/*
+ * System DCRs (SDRs)
+ */
+#define PESDR0_PLLLCT1 0x03a0
+#define PESDR0_PLLLCT2 0x03a1
+#define PESDR0_PLLLCT3 0x03a2
+
+#define PESDR0_UTLSET1 0x0300
+#define PESDR0_UTLSET2 0x0301
+#define PESDR0_DLPSET 0x0302
+#define PESDR0_LOOP 0x0303
+#define PESDR0_RCSSET 0x0304
+#define PESDR0_RCSSTS 0x0305
+#define PESDR0_HSSL0SET1 0x0306
+#define PESDR0_HSSL0SET2 0x0307
+#define PESDR0_HSSL0STS 0x0308
+#define PESDR0_HSSL1SET1 0x0309
+#define PESDR0_HSSL1SET2 0x030a
+#define PESDR0_HSSL1STS 0x030b
+#define PESDR0_HSSL2SET1 0x030c
+#define PESDR0_HSSL2SET2 0x030d
+#define PESDR0_HSSL2STS 0x030e
+#define PESDR0_HSSL3SET1 0x030f
+#define PESDR0_HSSL3SET2 0x0310
+#define PESDR0_HSSL3STS 0x0311
+#define PESDR0_HSSL4SET1 0x0312
+#define PESDR0_HSSL4SET2 0x0313
+#define PESDR0_HSSL4STS 0x0314
+#define PESDR0_HSSL5SET1 0x0315
+#define PESDR0_HSSL5SET2 0x0316
+#define PESDR0_HSSL5STS 0x0317
+#define PESDR0_HSSL6SET1 0x0318
+#define PESDR0_HSSL6SET2 0x0319
+#define PESDR0_HSSL6STS 0x031a
+#define PESDR0_HSSL7SET1 0x031b
+#define PESDR0_HSSL7SET2 0x031c
+#define PESDR0_HSSL7STS 0x031d
+#define PESDR0_HSSCTLSET 0x031e
+#define PESDR0_LANE_ABCD 0x031f
+#define PESDR0_LANE_EFGH 0x0320
+
+#define PESDR1_UTLSET1 0x0340
+#define PESDR1_UTLSET2 0x0341
+#define PESDR1_DLPSET 0x0342
+#define PESDR1_LOOP 0x0343
+#define PESDR1_RCSSET 0x0344
+#define PESDR1_RCSSTS 0x0345
+#define PESDR1_HSSL0SET1 0x0346
+#define PESDR1_HSSL0SET2 0x0347
+#define PESDR1_HSSL0STS 0x0348
+#define PESDR1_HSSL1SET1 0x0349
+#define PESDR1_HSSL1SET2 0x034a
+#define PESDR1_HSSL1STS 0x034b
+#define PESDR1_HSSL2SET1 0x034c
+#define PESDR1_HSSL2SET2 0x034d
+#define PESDR1_HSSL2STS 0x034e
+#define PESDR1_HSSL3SET1 0x034f
+#define PESDR1_HSSL3SET2 0x0350
+#define PESDR1_HSSL3STS 0x0351
+#define PESDR1_HSSCTLSET 0x0352
+#define PESDR1_LANE_ABCD 0x0353
+
+#define PESDR2_UTLSET1 0x0370
+#define PESDR2_UTLSET2 0x0371
+#define PESDR2_DLPSET 0x0372
+#define PESDR2_LOOP 0x0373
+#define PESDR2_RCSSET 0x0374
+#define PESDR2_RCSSTS 0x0375
+#define PESDR2_HSSL0SET1 0x0376
+#define PESDR2_HSSL0SET2 0x0377
+#define PESDR2_HSSL0STS 0x0378
+#define PESDR2_HSSL1SET1 0x0379
+#define PESDR2_HSSL1SET2 0x037a
+#define PESDR2_HSSL1STS 0x037b
+#define PESDR2_HSSL2SET1 0x037c
+#define PESDR2_HSSL2SET2 0x037d
+#define PESDR2_HSSL2STS 0x037e
+#define PESDR2_HSSL3SET1 0x037f
+#define PESDR2_HSSL3SET2 0x0380
+#define PESDR2_HSSL3STS 0x0381
+#define PESDR2_HSSCTLSET 0x0382
+#define PESDR2_LANE_ABCD 0x0383
+
+/*
+ * UTL register offsets
+ */
+#define PEUTL_PBBSZ 0x20
+#define PEUTL_OPDBSZ 0x68
+#define PEUTL_IPHBSZ 0x70
+#define PEUTL_IPDBSZ 0x78
+#define PEUTL_OUTTR 0x90
+#define PEUTL_INTR 0x98
+#define PEUTL_PCTL 0xa0
+#define PEUTL_RCIRQEN 0xb8
+
+/*
+ * Config space register offsets
+ */
+#define PECFG_BAR0LMPA 0x210
+#define PECFG_BAR0HMPA 0x214
+#define PECFG_PIMEN 0x33c
+#define PECFG_PIM0LAL 0x340
+#define PECFG_PIM0LAH 0x344
+#define PECFG_POM0LAL 0x380
+#define PECFG_POM0LAH 0x384
+
+#define SDR_READ(offset) ({\
+ mtdcr(DCRN_SDR0_CFGADDR, offset); \
+ mfdcr(DCRN_SDR0_CFGDATA);})
+
+#define SDR_WRITE(offset, data) ({\
+ mtdcr(DCRN_SDR0_CFGADDR, offset); \
+ mtdcr(DCRN_SDR0_CFGDATA,data);})
+
+int ppc440spe_init_pcie(void);
+int ppc440spe_init_pcie_rootport(int port);
+void yucca_setup_pcie_fpga_rootpoint(int port);
+void ppc440spe_setup_pcie(struct pci_controller *hose, int port);
+int yucca_pcie_card_present(int port);
+int pcie_hose_scan(struct pci_controller *hose, int bus);
+#endif /* __440SPE_PCIE_H */
diff --git a/cpu/ppc4xx/Makefile b/cpu/ppc4xx/Makefile
index c5634570054..7d6990f9a87 100644
--- a/cpu/ppc4xx/Makefile
+++ b/cpu/ppc4xx/Makefile
@@ -31,7 +31,8 @@ COBJS = 405gp_pci.o 4xx_enet.o \
bedbug_405.o commproc.o \
cpu.o cpu_init.o i2c.o interrupts.o \
miiphy.o sdram.o serial.o \
- spd_sdram.o speed.o traps.o usb_ohci.o usbdev.o
+ spd_sdram.o speed.o traps.o usb_ohci.o usbdev.o \
+ 440spe_pcie.o
OBJS = $(AOBJS) $(COBJS)
diff --git a/cpu/ppc4xx/cpu.c b/cpu/ppc4xx/cpu.c
index 71303bcc49f..bc51fbfdbed 100644
--- a/cpu/ppc4xx/cpu.c
+++ b/cpu/ppc4xx/cpu.c
@@ -315,6 +315,17 @@ int checkcpu (void)
return 0;
}
+#if defined (CONFIG_440SPE)
+int ppc440spe_revB() {
+ unsigned int pvr;
+
+ pvr = get_pvr();
+ if (pvr == PVR_440SPe_RB)
+ return 1;
+ else
+ return 0;
+}
+#endif
/* ------------------------------------------------------------------------- */
diff --git a/cpu/ppc4xx/start.S b/cpu/ppc4xx/start.S
index 0a6f81de449..6d6d75fd30f 100644
--- a/cpu/ppc4xx/start.S
+++ b/cpu/ppc4xx/start.S
@@ -315,7 +315,23 @@ rsttlb: tlbwe r0,r1,0x0000 /* Invalidate all entries (V=0)*/
/*----------------------------------------------------------------*/
/* TLB entry setup -- step thru tlbtab */
/*----------------------------------------------------------------*/
+#if defined(CONFIG_440SPE)
+ /*----------------------------------------------------------------*/
+ /* We have different TLB tables for revA and rev B of 440SPe */
+ /*----------------------------------------------------------------*/
+ mfspr r1, PVR
+ lis r0,0x5342
+ ori r0,r0,0x1891
+ cmpw r7,r1,r0
+ bne r7,..revA
+ bl tlbtabB
+ b ..goon
+..revA:
+ bl tlbtabA
+..goon:
+#else
bl tlbtab /* Get tlbtab pointer */
+#endif
mr r5,r0
li r1,0x003f /* 64 TLB entries max */
mtctr r1
diff --git a/include/common.h b/include/common.h
index 6d7c41ad2b6..5f00f91f3fb 100644
--- a/include/common.h
+++ b/include/common.h
@@ -244,6 +244,9 @@ void pciinfo (int, int);
void pci_master_init (struct pci_controller *);
# endif
int is_pci_host (struct pci_controller *);
+#if defined(CONFIG_440SPE)
+ void pcie_setup_hoses(void);
+#endif
#endif
int misc_init_f (void);
@@ -461,6 +464,7 @@ void get_sys_info ( sys_info_t * );
# if defined(CONFIG_440SPE)
unsigned long determine_sysper(void);
unsigned long determine_pci_clock_per(void);
+ int ppc440spe_revB(void);
# endif
# else
typedef PPC405_SYS_INFO sys_info_t;
diff --git a/include/configs/yucca.h b/include/configs/yucca.h
index 0e58e7e1024..9dd9e5eae48 100644
--- a/include/configs/yucca.h
+++ b/include/configs/yucca.h
@@ -63,17 +63,26 @@
#define CFG_PERIPHERAL_BASE 0xa0000000 /* internal peripherals */
#define CFG_ISRAM_BASE 0x90000000 /* internal SRAM */
-#define CFG_PCI_MEMBASE 0x80000000 /* mapped pci memory */
-#define CFG_PCI_MEMBASE1 0x90000000 /* mapped pci memory */
-#define CFG_PCI_MEMBASE2 0xa0000000 /* mapped pci memory */
-#define CFG_PCI_MEMBASE3 0xb0000000 /* mapped pci memory */
-
+#define CFG_PCI_MEMBASE 0x80000000 /* mapped PCI memory */
#define CFG_PCI_BASE 0xd0000000 /* internal PCI regs */
-#define CFG_PCI_TARGBASE 0x80000000 /*PCIaddr mapped to CFG_PCI_MEMBASE*/
+#define CFG_PCI_TARGBASE CFG_PCI_MEMBASE
+
+#define CFG_PCIE_MEMBASE 0xB0000000 /* mapped PCIe memory */
+#define CFG_PCIE_MEMSIZE 0x01000000
-/* #define CFG_PCI_BASE_IO 0xB8000000 */ /* internal PCI I-O */
-/* #define CFG_PCI_BASE_REGS 0xBEC00000 */ /* internal PCI regs */
-/* #define CFG_PCI_BASE_CYCLE 0xBED00000 */ /* internal PCI regs */
+#define CFG_PCIE0_CFGBASE 0xc0000000
+#define CFG_PCIE0_XCFGBASE 0xc0000400
+#define CFG_PCIE1_CFGBASE 0xc0001000
+#define CFG_PCIE1_XCFGBASE 0xc0001400
+#define CFG_PCIE2_CFGBASE 0xc0002000
+#define CFG_PCIE2_XCFGBASE 0xc0002400
+
+#define CFG_PCIE0_REGBASE 0xc0003000
+#define CFG_PCIE1_REGBASE 0xc0003400
+#define CFG_PCIE2_REGBASE 0xc0004000
+#define CFG_PCIE3_REGBASE 0xc0004400
+#define CFG_PCIE4_REGBASE 0xc0005000
+#define CFG_PCIE5_REGBASE 0xc0005400
/* System RAM mapped to PCI space */
#define CONFIG_PCI_SYS_MEM_BUS CFG_SDRAM_BASE
@@ -292,6 +301,7 @@
*/
/* Support for Intel 82557/82559/82559ER chips. */
#define CONFIG_EEPRO100
+
/*
* For booting Linux, the board info and command line data
* have to be in the first 8 MB of memory, since this is
@@ -506,8 +516,8 @@
#define FPGA_REG1C_PE1_WAKE 0x0040
#define FPGA_REG1C_PE2_WAKE 0x0020
#define FPGA_REG1C_PE0_PERST 0x0010
-#define FPGA_REG1C_PE1_PERST 0x0080
-#define FPGA_REG1C_PE2_PERST 0x0040
+#define FPGA_REG1C_PE1_PERST 0x0008
+#define FPGA_REG1C_PE2_PERST 0x0004
/*----------------------------------------------------------------------------+
| Defines