|
@@ -40,6 +40,23 @@ 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),
|
|
@@ -60,18 +77,35 @@ static void pcie_dmer_enable(void)
|
|
|
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;
|
|
|
|
|
|
/*
|
|
@@ -101,13 +135,24 @@ static int pcie_read_config(struct pci_controller *hose, unsigned int devfn,
|
|
|
static int pcie_write_config(struct pci_controller *hose, unsigned int devfn,
|
|
|
int offset, int len, u32 val) {
|
|
|
|
|
|
+ u8 *address;
|
|
|
+
|
|
|
/*
|
|
|
- * 440SPE implements only one function per port
|
|
|
+ * Bus numbers are relative to hose->first_busno
|
|
|
*/
|
|
|
- if (!((PCI_FUNC(devfn) == 0) && (PCI_DEV(devfn) == 1)))
|
|
|
+ devfn -= PCI_BDF(hose->first_busno, 0, 0);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Same constraints as in pcie_read_config().
|
|
|
+ */
|
|
|
+ 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;
|
|
|
|
|
|
/*
|
|
@@ -137,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;
|
|
|
}
|
|
@@ -794,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:
|
|
@@ -822,14 +867,9 @@ void ppc440spe_setup_pcie_rootpoint(struct pci_controller *hose, int port)
|
|
|
/*
|
|
|
* 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);
|
|
|
- }
|
|
|
+ out_8((u8 *)mbase + PCI_PRIMARY_BUS, 0);
|
|
|
+ out_8((u8 *)mbase + PCI_SECONDARY_BUS, 1);
|
|
|
+ out_8((u8 *)mbase + PCI_SUBORDINATE_BUS, 1);
|
|
|
|
|
|
/*
|
|
|
* Set up outbound translation to hose->mem_space from PLB
|
|
@@ -886,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)
|
|
@@ -963,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;
|