* [PATCH] powerpc: Add MPC837x PCIE controller RC mode support
@ 2008-01-02 11:16 Li Li
2008-01-02 11:53 ` Arnd Bergmann
` (2 more replies)
0 siblings, 3 replies; 10+ messages in thread
From: Li Li @ 2008-01-02 11:16 UTC (permalink / raw)
To: Kumar Gala, kim phillips, Wood Scott, linuxppc-dev
* The MPC837x PCIE controller hardware resources and SerDes are initiated in u-boot.
* Merge the MPC837x PCIE code into arch/powerpc/sysdev/fsl_pci.c
* The MPC837x PCIE controller`s configure address bit field is uniqe:
bus number: bits 31-24
device number: bits 23-19
function number: bits 18-16
ext reg number: bits 11-8
reg number: bits 7-2
* Add mpc837x_exclude_device to fixup a controller bug.
* Add flag variant to mpc83xx_add_bridge function.
Signed-off-by: Tony Li <tony.li@freescale.com>
---
arch/powerpc/boot/dts/mpc8377_mds.dts | 54 ++++++++--
arch/powerpc/boot/dts/mpc8378_mds.dts | 54 ++++++++--
arch/powerpc/platforms/83xx/Kconfig | 2 +
arch/powerpc/platforms/83xx/mpc8313_rdb.c | 10 ++-
arch/powerpc/platforms/83xx/mpc832x_mds.c | 12 ++-
arch/powerpc/platforms/83xx/mpc832x_rdb.c | 10 ++-
arch/powerpc/platforms/83xx/mpc834x_itx.c | 10 ++-
arch/powerpc/platforms/83xx/mpc834x_mds.c | 10 ++-
arch/powerpc/platforms/83xx/mpc836x_mds.c | 12 ++-
arch/powerpc/platforms/83xx/mpc837x_mds.c | 39 +++++++-
arch/powerpc/platforms/83xx/mpc83xx.h | 6 +-
arch/powerpc/platforms/83xx/pci.c | 29 ++++--
arch/powerpc/sysdev/fsl_pci.c | 159 +++++++++++++++++++++++++++++
arch/powerpc/sysdev/fsl_pci.h | 3 +
include/asm-powerpc/pci-bridge.h | 1 +
include/linux/pci_ids.h | 4 +
16 files changed, 375 insertions(+), 40 deletions(-)
diff --git a/arch/powerpc/boot/dts/mpc8377_mds.dts b/arch/powerpc/boot/dts/mpc8377_mds.dts
index 4402e39..4af3802 100644
--- a/arch/powerpc/boot/dts/mpc8377_mds.dts
+++ b/arch/powerpc/boot/dts/mpc8377_mds.dts
@@ -197,14 +197,6 @@
clock = <d#100>;
};
- serdes2:serdes@e3100 {
- compatible = "fsl,serdes";
- reg = <e3100 100>;
- vdd-1v;
- protocol = "pcie";
- clock = <d#100>;
- };
-
/* IPIC
* interrupts cell = <intr #, sense>
* sense values match linux IORESOURCE_IRQ_* defines:
@@ -279,4 +271,50 @@
compatible = "fsl,mpc8349-pci";
device_type = "pci";
};
+
+ pcie@e0009000 {
+ interrupt-map-mask = <f800 0 0 7>;
+ interrupt-map = <
+ 0000 0 0 1 &ipic 1 8
+ 0000 0 0 2 &ipic 1 8
+ 0000 0 0 3 &ipic 1 8
+ 0000 0 0 4 &ipic 1 8
+ >;
+ interrupt-parent = < &ipic >;
+ interrupts = <1 8>;
+ bus-range = <0 0>;
+ ranges = <02000000 0 A0000000 A0000000 0 10000000
+ 01000000 0 00000000 B1000000 0 00800000>;
+ clock-frequency = <0>;
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+ reg = <e0009000 00001000
+ b0000000 01000000>;
+ compatible = "fsl,mpc8377-pcie";
+ device_type = "pci";
+ };
+
+ pcie@e000a000 {
+ interrupt-map-mask = <f800 0 0 7>;
+ interrupt-map = <
+ 0000 0 0 1 &ipic 2 8
+ 0000 0 0 2 &ipic 2 8
+ 0000 0 0 3 &ipic 2 8
+ 0000 0 0 4 &ipic 2 8
+ >;
+ interrupt-parent = < &ipic >;
+ interrupts = <2 8>;
+ bus-range = <0 0>;
+ ranges = <02000000 0 C0000000 C0000000 0 10000000
+ 01000000 0 00000000 D1000000 0 00800000>;
+ clock-frequency = <0>;
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+ reg = <e000a000 00001000
+ d0000000 01000000>;
+ compatible = "fsl,mpc8377-pcie";
+ device_type = "pci";
+ };
};
diff --git a/arch/powerpc/boot/dts/mpc8378_mds.dts b/arch/powerpc/boot/dts/mpc8378_mds.dts
index 54171f4..de9d40c 100644
--- a/arch/powerpc/boot/dts/mpc8378_mds.dts
+++ b/arch/powerpc/boot/dts/mpc8378_mds.dts
@@ -179,14 +179,6 @@
clock = <d#100>;
};
- serdes2:serdes@e3100 {
- compatible = "fsl,serdes";
- reg = <e3100 100>;
- vdd-1v;
- protocol = "pcie";
- clock = <d#100>;
- };
-
/* IPIC
* interrupts cell = <intr #, sense>
* sense values match linux IORESOURCE_IRQ_* defines:
@@ -261,4 +253,50 @@
compatible = "fsl,mpc8349-pci";
device_type = "pci";
};
+
+ pcie@e0009000 {
+ interrupt-map-mask = <f800 0 0 7>;
+ interrupt-map = <
+ 0000 0 0 1 &ipic 1 8
+ 0000 0 0 2 &ipic 1 8
+ 0000 0 0 3 &ipic 1 8
+ 0000 0 0 4 &ipic 1 8
+ >;
+ interrupt-parent = < &ipic >;
+ interrupts = <1 8>;
+ bus-range = <0 0>;
+ ranges = <02000000 0 A0000000 A0000000 0 10000000
+ 01000000 0 00000000 B1000000 0 00800000>;
+ clock-frequency = <0>;
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+ reg = <e0009000 00001000
+ b0000000 01000000>;
+ compatible = "fsl,mpc8377-pcie";
+ device_type = "pci";
+ };
+
+ pcie@e000a000 {
+ interrupt-map-mask = <f800 0 0 7>;
+ interrupt-map = <
+ 0000 0 0 1 &ipic 2 8
+ 0000 0 0 2 &ipic 2 8
+ 0000 0 0 3 &ipic 2 8
+ 0000 0 0 4 &ipic 2 8
+ >;
+ interrupt-parent = < &ipic >;
+ interrupts = <2 8>;
+ bus-range = <0 0>;
+ ranges = <02000000 0 C0000000 C0000000 0 10000000
+ 01000000 0 00000000 D1000000 0 00800000>;
+ clock-frequency = <0>;
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+ reg = <e000a000 00001000
+ d0000000 01000000>;
+ compatible = "fsl,mpc8377-pcie";
+ device_type = "pci";
+ };
};
diff --git a/arch/powerpc/platforms/83xx/Kconfig b/arch/powerpc/platforms/83xx/Kconfig
index 0c61e7a..0b4bfb5 100644
--- a/arch/powerpc/platforms/83xx/Kconfig
+++ b/arch/powerpc/platforms/83xx/Kconfig
@@ -86,4 +86,6 @@ config PPC_MPC837x
select PPC_UDBG_16550
select PPC_INDIRECT_PCI
select FSL_SERDES
+ select FSL_PCI if PCI
default y if MPC837x_MDS
+
diff --git a/arch/powerpc/platforms/83xx/mpc8313_rdb.c b/arch/powerpc/platforms/83xx/mpc8313_rdb.c
index 33766b8..25d8df4 100644
--- a/arch/powerpc/platforms/83xx/mpc8313_rdb.c
+++ b/arch/powerpc/platforms/83xx/mpc8313_rdb.c
@@ -37,14 +37,20 @@ static void __init mpc8313_rdb_setup_arch(void)
{
#ifdef CONFIG_PCI
struct device_node *np;
+ int primary_pci_bus = 1;
#endif
if (ppc_md.progress)
ppc_md.progress("mpc8313_rdb_setup_arch()", 0);
#ifdef CONFIG_PCI
- for_each_compatible_node(np, "pci", "fsl,mpc8349-pci")
- mpc83xx_add_bridge(np);
+ for_each_compatible_node(np, "pci", "fsl,mpc8349-pci") {
+ if (primary_pci_bus) {
+ mpc83xx_add_bridge(np, PPC_83XX_PCI | PPC_83XX_PCI_PRIMARY);
+ primary_pci_bus = 0;
+ } else
+ mpc83xx_add_bridge(np, PPC_83XX_PCI);
+ }
#endif
mpc831x_usb_cfg();
}
diff --git a/arch/powerpc/platforms/83xx/mpc832x_mds.c b/arch/powerpc/platforms/83xx/mpc832x_mds.c
index 972fa85..ddb0b2e 100644
--- a/arch/powerpc/platforms/83xx/mpc832x_mds.c
+++ b/arch/powerpc/platforms/83xx/mpc832x_mds.c
@@ -58,6 +58,9 @@ static u8 *bcsr_regs = NULL;
static void __init mpc832x_sys_setup_arch(void)
{
struct device_node *np;
+#ifdef CONFIG_PCI
+ int primary_pci_bus = 1;
+#endif
if (ppc_md.progress)
ppc_md.progress("mpc832x_sys_setup_arch()", 0);
@@ -73,8 +76,13 @@ static void __init mpc832x_sys_setup_arch(void)
}
#ifdef CONFIG_PCI
- for_each_compatible_node(np, "pci", "fsl,mpc8349-pci")
- mpc83xx_add_bridge(np);
+ for_each_compatible_node(np, "pci", "fsl,mpc8349-pci") {
+ if (primary_pci_bus) {
+ mpc83xx_add_bridge(np, PPC_83XX_PCI | PPC_83XX_PCI_PRIMARY);
+ primary_pci_bus = 0;
+ } else
+ mpc83xx_add_bridge(np, PPC_83XX_PCI);
+ }
#endif
#ifdef CONFIG_QUICC_ENGINE
diff --git a/arch/powerpc/platforms/83xx/mpc832x_rdb.c b/arch/powerpc/platforms/83xx/mpc832x_rdb.c
index fbca336..aef35f5 100644
--- a/arch/powerpc/platforms/83xx/mpc832x_rdb.c
+++ b/arch/powerpc/platforms/83xx/mpc832x_rdb.c
@@ -87,14 +87,20 @@ static void __init mpc832x_rdb_setup_arch(void)
{
#if defined(CONFIG_PCI) || defined(CONFIG_QUICC_ENGINE)
struct device_node *np;
+ int primary_pci_bus = 1;
#endif
if (ppc_md.progress)
ppc_md.progress("mpc832x_rdb_setup_arch()", 0);
#ifdef CONFIG_PCI
- for_each_compatible_node(np, "pci", "fsl,mpc8349-pci")
- mpc83xx_add_bridge(np);
+ for_each_compatible_node(np, "pci", "fsl,mpc8349-pci") {
+ if (primary_pci_bus) {
+ mpc83xx_add_bridge(np, PPC_83XX_PCI | PPC_83XX_PCI_PRIMARY);
+ primary_pci_bus = 0;
+ } else
+ mpc83xx_add_bridge(np, PPC_83XX_PCI);
+ }
#endif
#ifdef CONFIG_QUICC_ENGINE
diff --git a/arch/powerpc/platforms/83xx/mpc834x_itx.c b/arch/powerpc/platforms/83xx/mpc834x_itx.c
index aa76819..c428f62 100644
--- a/arch/powerpc/platforms/83xx/mpc834x_itx.c
+++ b/arch/powerpc/platforms/83xx/mpc834x_itx.c
@@ -46,14 +46,20 @@ static void __init mpc834x_itx_setup_arch(void)
{
#ifdef CONFIG_PCI
struct device_node *np;
+ int primary_pci_bus = 1;
#endif
if (ppc_md.progress)
ppc_md.progress("mpc834x_itx_setup_arch()", 0);
#ifdef CONFIG_PCI
- for_each_compatible_node(np, "pci", "fsl,mpc8349-pci")
- mpc83xx_add_bridge(np);
+ for_each_compatible_node(np, "pci", "fsl,mpc8349-pci") {
+ if (primary_pci_bus) {
+ mpc83xx_add_bridge(np, PPC_83XX_PCI | PPC_83XX_PCI_PRIMARY);
+ primary_pci_bus = 0;
+ } else
+ mpc83xx_add_bridge(np, PPC_83XX_PCI);
+ }
#endif
mpc834x_usb_cfg();
diff --git a/arch/powerpc/platforms/83xx/mpc834x_mds.c b/arch/powerpc/platforms/83xx/mpc834x_mds.c
index 00aed7c..e86dce8 100644
--- a/arch/powerpc/platforms/83xx/mpc834x_mds.c
+++ b/arch/powerpc/platforms/83xx/mpc834x_mds.c
@@ -77,14 +77,20 @@ static void __init mpc834x_mds_setup_arch(void)
{
#ifdef CONFIG_PCI
struct device_node *np;
+ int primary_pci_bus = 1;
#endif
if (ppc_md.progress)
ppc_md.progress("mpc834x_mds_setup_arch()", 0);
#ifdef CONFIG_PCI
- for_each_compatible_node(np, "pci", "fsl,mpc8349-pci")
- mpc83xx_add_bridge(np);
+ for_each_compatible_node(np, "pci", "fsl,mpc8349-pci") {
+ if (primary_pci_bus) {
+ mpc83xx_add_bridge(np, PPC_83XX_PCI | PPC_83XX_PCI_PRIMARY);
+ primary_pci_bus = 0;
+ } else
+ mpc83xx_add_bridge(np, PPC_83XX_PCI);
+ }
#endif
mpc834xemds_usb_cfg();
diff --git a/arch/powerpc/platforms/83xx/mpc836x_mds.c b/arch/powerpc/platforms/83xx/mpc836x_mds.c
index 0f3855c..6e6670c 100644
--- a/arch/powerpc/platforms/83xx/mpc836x_mds.c
+++ b/arch/powerpc/platforms/83xx/mpc836x_mds.c
@@ -64,6 +64,9 @@ static u8 *bcsr_regs = NULL;
static void __init mpc836x_mds_setup_arch(void)
{
struct device_node *np;
+#ifdef CONFIG_PCI
+ int primary_pci_bus = 1;
+#endif
if (ppc_md.progress)
ppc_md.progress("mpc836x_mds_setup_arch()", 0);
@@ -79,8 +82,13 @@ static void __init mpc836x_mds_setup_arch(void)
}
#ifdef CONFIG_PCI
- for_each_compatible_node(np, "pci", "fsl,mpc8349-pci")
- mpc83xx_add_bridge(np);
+ for_each_compatible_node(np, "pci", "fsl,mpc8349-pci") {
+ if (primary_pci_bus) {
+ mpc83xx_add_bridge(np, PPC_83XX_PCI | PPC_83XX_PCI_PRIMARY);
+ primary_pci_bus = 0;
+ } else
+ mpc83xx_add_bridge(np, PPC_83XX_PCI);
+ }
#endif
#ifdef CONFIG_QUICC_ENGINE
diff --git a/arch/powerpc/platforms/83xx/mpc837x_mds.c b/arch/powerpc/platforms/83xx/mpc837x_mds.c
index 166c111..ec2fa9f 100644
--- a/arch/powerpc/platforms/83xx/mpc837x_mds.c
+++ b/arch/powerpc/platforms/83xx/mpc837x_mds.c
@@ -25,8 +25,27 @@
#ifndef CONFIG_PCI
unsigned long isa_io_base = 0;
unsigned long isa_mem_base = 0;
+
#endif
+#ifdef CONFIG_PCI
+static int mpc837x_exclude_device(struct pci_controller *hose,
+ u_char bus, u_char devfn)
+{
+ struct pci_bus *pci_bus;
+
+ if (hose->indirect_type & PPC_INDIRECT_TYPE_MPC83XX_PCIE) {
+ pci_bus = pci_find_bus(hose->global_number, bus);
+ if ((bus == hose->first_busno) ||
+ (pci_bus->primary == hose->first_busno)) {
+ if (devfn & 0xf8)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ }
+ }
+
+ return PCIBIOS_SUCCESSFUL;
+}
+#endif
/* ************************************************************************
*
* Setup the architecture
@@ -36,14 +55,30 @@ static void __init mpc837x_mds_setup_arch(void)
{
#ifdef CONFIG_PCI
struct device_node *np;
+ int primary_pci_bus = 1;
#endif
if (ppc_md.progress)
ppc_md.progress("mpc837x_mds_setup_arch()", 0);
#ifdef CONFIG_PCI
- for_each_compatible_node(np, "pci", "fsl,mpc8349-pci")
- mpc83xx_add_bridge(np);
+ for_each_compatible_node(np, "pci", "fsl,mpc8349-pci") {
+ if (primary_pci_bus) {
+ mpc83xx_add_bridge(np, PPC_83XX_PCI | PPC_83XX_PCI_PRIMARY);
+ primary_pci_bus = 0;
+ } else
+ mpc83xx_add_bridge(np, PPC_83XX_PCI);
+ }
+
+ for_each_compatible_node(np, "pci", "fsl,mpc8377-pcie") {
+ if (primary_pci_bus) {
+ mpc83xx_add_bridge(np, PPC_83XX_PCIE | PPC_83XX_PCI_PRIMARY);
+ primary_pci_bus = 0;
+ } else
+ mpc83xx_add_bridge(np, PPC_83XX_PCIE);
+ }
+
+ ppc_md.pci_exclude_device = mpc837x_exclude_device;
#endif
}
diff --git a/arch/powerpc/platforms/83xx/mpc83xx.h b/arch/powerpc/platforms/83xx/mpc83xx.h
index b778cb4..552e9bf 100644
--- a/arch/powerpc/platforms/83xx/mpc83xx.h
+++ b/arch/powerpc/platforms/83xx/mpc83xx.h
@@ -47,8 +47,10 @@
* Declaration for the various functions exported by the
* mpc83xx_* files. Mostly for use by mpc83xx_setup
*/
-
-extern int mpc83xx_add_bridge(struct device_node *dev);
+#define PPC_83XX_PCI_PRIMARY 0x1
+#define PPC_83XX_PCI 0x2
+#define PPC_83XX_PCIE 0x4
+extern int mpc83xx_add_bridge(struct device_node *dev, int flags);
extern void mpc83xx_restart(char *cmd);
extern long mpc83xx_time_init(void);
extern int mpc834x_usb_cfg(void);
diff --git a/arch/powerpc/platforms/83xx/pci.c b/arch/powerpc/platforms/83xx/pci.c
index 80425d7..7a3382a 100644
--- a/arch/powerpc/platforms/83xx/pci.c
+++ b/arch/powerpc/platforms/83xx/pci.c
@@ -24,6 +24,9 @@
#include <asm/pci-bridge.h>
#include <asm/prom.h>
#include <sysdev/fsl_soc.h>
+#include <sysdev/fsl_pci.h>
+
+#include "mpc83xx.h"
#undef DEBUG
@@ -33,13 +36,13 @@
#define DBG(x...)
#endif
-int __init mpc83xx_add_bridge(struct device_node *dev)
+int __init mpc83xx_add_bridge(struct device_node *dev, int flags)
{
int len;
struct pci_controller *hose;
struct resource rsrc;
const int *bus_range;
- int primary = 1, has_address = 0;
+ int has_address = 0;
phys_addr_t immr = get_immrbase();
DBG("Adding PCI host bridge %s\n", dev->full_name);
@@ -63,16 +66,23 @@ int __init mpc83xx_add_bridge(struct device_node *dev)
hose->last_busno = bus_range ? bus_range[1] : 0xff;
/* MPC83xx supports up to two host controllers one at 0x8500 from immrbar
- * the other at 0x8600, we consider the 0x8500 the primary controller
+ * the other at 0x8600.
*/
/* PCI 1 */
- if ((rsrc.start & 0xfffff) == 0x8500) {
+ if ((rsrc.start & 0xfffff) == 0x8500)
setup_indirect_pci(hose, immr + 0x8300, immr + 0x8304, 0);
- }
/* PCI 2 */
- if ((rsrc.start & 0xfffff) == 0x8600) {
+ if ((rsrc.start & 0xfffff) == 0x8600)
setup_indirect_pci(hose, immr + 0x8380, immr + 0x8384, 0);
- primary = 0;
+
+ if (flags & PPC_83XX_PCIE) {
+ struct resource cfg_space;
+
+ if (of_address_to_resource(dev, 1, &cfg_space)) {
+ printk("PCIE RC losts configure space. Skip it\n");
+ return 1;
+ }
+ mpc83xx_setup_pcie(hose, &rsrc, &cfg_space);
}
printk(KERN_INFO "Found MPC83xx PCI host bridge at 0x%016llx. "
@@ -85,7 +95,10 @@ int __init mpc83xx_add_bridge(struct device_node *dev)
/* Interpret the "ranges" property */
/* This also maps the I/O region and sets isa_io/mem_base */
- pci_process_bridge_OF_ranges(hose, dev, primary);
+ if (flags & PPC_83XX_PCI_PRIMARY)
+ pci_process_bridge_OF_ranges(hose, dev, 1);
+ else
+ pci_process_bridge_OF_ranges(hose, dev, 0);
return 0;
}
diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c
index 33df4c3..dfd9a40 100644
--- a/arch/powerpc/sysdev/fsl_pci.c
+++ b/arch/powerpc/sysdev/fsl_pci.c
@@ -240,6 +240,165 @@ int __init fsl_add_bridge(struct device_node *dev, int is_primary)
return 0;
}
+/* MPC83xx PCIE routines*/
+/* PCIE Registers */
+#define PEX_LTSSM_STAT 0x404
+#define PEX_LTSSM_STAT_L0 0x16
+#define PEX_GCLK_RATIO 0x440
+
+/* With the convention of u-boot, the PCIE outbound window 0 serves
+ * as configuration transactions outbound */
+#define PEX_OUTWIN0_TAL 0xCA8
+#define PEX_OUTWIN0_TAH 0xCAC
+
+void remap_cfg_outbound(void * __iomem reg_base, u32 tal, u32 tah)
+{
+ out_le32(reg_base + PEX_OUTWIN0_TAL, tal);
+ out_le32(reg_base + PEX_OUTWIN0_TAH, tah);
+}
+
+static int mpc83xx_read_config_pcie(struct pci_bus *bus,
+ uint devfn, int offset, int len, u32 *val)
+{
+ struct pci_controller *hose = bus->sysdata;
+ void __iomem *cfg_addr;
+ static u32 orig_busno = 0;
+ u32 bus_no;
+
+ if (hose->indirect_type & PPC_INDIRECT_TYPE_NO_PCIE_LINK)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ if (ppc_md.pci_exclude_device)
+ if (ppc_md.pci_exclude_device(hose, bus->number, devfn))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ switch (len) {
+ case 2:
+ if (offset & 1)
+ return -EINVAL;
+ break;
+ case 4:
+ if (offset & 3)
+ return -EINVAL;
+ break;
+ }
+
+ if ((bus->number == hose->first_busno) &&
+ (hose->indirect_type & PPC_INDIRECT_TYPE_MPC83XX_PCIE))
+ cfg_addr = (void __iomem *)((ulong) hose->cfg_data + (offset & 0xfff));
+ else {
+ bus_no = bus->number - hose->first_busno;
+ if (bus_no != orig_busno) {
+ remap_cfg_outbound((void __iomem *)hose->cfg_data, bus_no, 0);
+ orig_busno = bus_no;
+ }
+ cfg_addr = (void __iomem *)((ulong) hose->cfg_addr +
+ ((devfn << 16) | (offset & 0xfff)));
+ }
+
+ switch (len) {
+ case 1:
+ *val = in_8(cfg_addr);
+ break;
+ case 2:
+ *val = in_le16(cfg_addr);
+ break;
+ default:
+ *val = in_le32(cfg_addr);
+ break;
+ }
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int mpc83xx_write_config_pcie(struct pci_bus *bus,
+ uint devfn, int offset, int len, u32 val)
+{
+ struct pci_controller *hose = bus->sysdata;
+ void __iomem *cfg_addr;
+ static u32 orig_busno = 0;
+ u32 bus_no;
+
+ if (hose->indirect_type & PPC_INDIRECT_TYPE_NO_PCIE_LINK)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ if (ppc_md.pci_exclude_device)
+ if (ppc_md.pci_exclude_device(hose, bus->number, devfn))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ switch (len) {
+ case 2:
+ if (offset & 1)
+ return -EINVAL;
+ break;
+ case 4:
+ if (offset & 3)
+ return -EINVAL;
+ break;
+ }
+
+
+ if ((bus->number == hose->first_busno) &&
+ (hose->indirect_type & PPC_INDIRECT_TYPE_MPC83XX_PCIE))
+ cfg_addr = (void __iomem *)((ulong) hose->cfg_data + (offset & 0xfff));
+ else {
+ bus_no = bus->number - hose->first_busno;
+ if (bus_no != orig_busno) {
+ remap_cfg_outbound((void __iomem *)hose->cfg_data, bus_no, 0);
+ orig_busno = bus_no;
+ }
+ cfg_addr = (void __iomem *)((ulong) hose->cfg_addr +
+ ((devfn << 16) | (offset & 0xfff)));
+ }
+
+ switch (len) {
+ case 1:
+ out_8(cfg_addr, val);
+ break;
+ case 2:
+ out_le16(cfg_addr, val);
+ break;
+ default:
+ out_le32(cfg_addr, val);
+ break;
+ }
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops mpc83xx_pcie_ops = {
+ mpc83xx_read_config_pcie,
+ mpc83xx_write_config_pcie
+};
+
+void __init mpc83xx_setup_pcie(struct pci_controller *hose,
+ struct resource *reg, struct resource *cfg_space)
+{
+ void __iomem *hose_cfg_header, *mbase;
+ u32 val;
+
+ hose_cfg_header = ioremap(reg->start, reg->end - reg->start + 1);
+
+ val = in_le32(hose_cfg_header + PEX_LTSSM_STAT);
+ if (val < PEX_LTSSM_STAT_L0)
+ hose->indirect_type |= PPC_INDIRECT_TYPE_NO_PCIE_LINK;
+ hose->indirect_type |= PPC_INDIRECT_TYPE_MPC83XX_PCIE;
+
+ mbase = ioremap(cfg_space->start & PAGE_MASK, cfg_space->end - cfg_space->start + 1);
+ hose->ops = &mpc83xx_pcie_ops;
+ hose->cfg_addr = mbase + (cfg_space->start & ~PAGE_MASK);
+
+ /* The MPC83xx PCIE implements direct access configure space
+ * routines instead of indirect ones. So, the cfg_data field is free.
+ * The MPC83xx PCIE RC configure header is memory-mapped,
+ * we use cfg_data as this header pointer */
+ hose->cfg_data = hose_cfg_header;
+}
+
+DECLARE_PCI_FIXUP_EARLY(0x1957, PCI_DEVICE_ID_MPC8377E, quirk_fsl_pcie_transparent);
+DECLARE_PCI_FIXUP_EARLY(0x1957, PCI_DEVICE_ID_MPC8377, quirk_fsl_pcie_transparent);
+DECLARE_PCI_FIXUP_EARLY(0x1957, PCI_DEVICE_ID_MPC8378E, quirk_fsl_pcie_transparent);
+DECLARE_PCI_FIXUP_EARLY(0x1957, PCI_DEVICE_ID_MPC8378, quirk_fsl_pcie_transparent);
DECLARE_PCI_FIXUP_EARLY(0x1957, PCI_DEVICE_ID_MPC8548E, quirk_fsl_pcie_transparent);
DECLARE_PCI_FIXUP_EARLY(0x1957, PCI_DEVICE_ID_MPC8548, quirk_fsl_pcie_transparent);
DECLARE_PCI_FIXUP_EARLY(0x1957, PCI_DEVICE_ID_MPC8543E, quirk_fsl_pcie_transparent);
diff --git a/arch/powerpc/sysdev/fsl_pci.h b/arch/powerpc/sysdev/fsl_pci.h
index 37b04ad..a70ee0f 100644
--- a/arch/powerpc/sysdev/fsl_pci.h
+++ b/arch/powerpc/sysdev/fsl_pci.h
@@ -84,5 +84,8 @@ struct ccsr_pci {
extern int fsl_add_bridge(struct device_node *dev, int is_primary);
extern void fsl_pcibios_fixup_bus(struct pci_bus *bus);
+extern void mpc83xx_setup_pcie(struct pci_controller *hose,
+ struct resource *reg, struct resource *cfg_space);
+
#endif /* __POWERPC_FSL_PCI_H */
#endif /* __KERNEL__ */
diff --git a/include/asm-powerpc/pci-bridge.h b/include/asm-powerpc/pci-bridge.h
index dc31845..372598b 100644
--- a/include/asm-powerpc/pci-bridge.h
+++ b/include/asm-powerpc/pci-bridge.h
@@ -56,6 +56,7 @@ struct pci_controller {
#define PPC_INDIRECT_TYPE_SURPRESS_PRIMARY_BUS (0x00000004)
#define PPC_INDIRECT_TYPE_NO_PCIE_LINK (0x00000008)
#define PPC_INDIRECT_TYPE_BIG_ENDIAN (0x00000010)
+#define PPC_INDIRECT_TYPE_MPC83XX_PCIE (0x00000020)
u32 indirect_type;
/* Currently, we limit ourselves to 1 IO range and 3 mem
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index 1ee009e..f84caa7 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -2111,6 +2111,10 @@
#define PCI_DEVICE_ID_TDI_EHCI 0x0101
#define PCI_VENDOR_ID_FREESCALE 0x1957
+#define PCI_DEVICE_ID_MPC8378E 0x00c4
+#define PCI_DEVICE_ID_MPC8378 0x00c5
+#define PCI_DEVICE_ID_MPC8377E 0x00c6
+#define PCI_DEVICE_ID_MPC8377 0x00c7
#define PCI_DEVICE_ID_MPC8548E 0x0012
#define PCI_DEVICE_ID_MPC8548 0x0013
#define PCI_DEVICE_ID_MPC8543E 0x0014
--
1.5.3
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH] powerpc: Add MPC837x PCIE controller RC mode support
2008-01-02 11:16 [PATCH] powerpc: Add MPC837x PCIE controller RC mode support Li Li
@ 2008-01-02 11:53 ` Arnd Bergmann
2008-01-03 6:40 ` Li Li
2008-01-02 15:23 ` Kumar Gala
2008-01-02 15:51 ` Olof Johansson
2 siblings, 1 reply; 10+ messages in thread
From: Arnd Bergmann @ 2008-01-02 11:53 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Wood Scott, kim phillips, Li Li
On Wednesday 02 January 2008, Li Li wrote:
> =A0#ifdef CONFIG_PCI
> -=A0=A0=A0=A0=A0=A0=A0for_each_compatible_node(np, "pci", "fsl,mpc8349-pc=
i")
> -=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0mpc83xx_add_bridge(np);
> +=A0=A0=A0=A0=A0=A0=A0for_each_compatible_node(np, "pci", "fsl,mpc8349-pc=
i") {
> +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0if (primary_pci_bus) {
> +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0mpc=
83xx_add_bridge(np, PPC_83XX_PCI | PPC_83XX_PCI_PRIMARY);
> +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0pri=
mary_pci_bus =3D 0;
> +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0} else
> +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0mpc=
83xx_add_bridge(np, PPC_83XX_PCI);
> +=A0=A0=A0=A0=A0=A0=A0}
> +
> +=A0=A0=A0=A0=A0=A0=A0for_each_compatible_node(np, "pci", "fsl,mpc8377-pc=
ie") {
> +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0if (primary_pci_bus) {
> +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0mpc=
83xx_add_bridge(np, PPC_83XX_PCIE | PPC_83XX_PCI_PRIMARY);
> +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0pri=
mary_pci_bus =3D 0;
> +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0} else
> +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0mpc=
83xx_add_bridge(np, PPC_83XX_PCIE);
> +=A0=A0=A0=A0=A0=A0=A0}
> +
> +=A0=A0=A0=A0=A0=A0=A0ppc_md.pci_exclude_device =3D mpc837x_exclude_devic=
e;
> =A0#endif
A few comments on how I think this can be improved:
* Instead of duplicating this code across all platforms, make a single
function that does the probing in one place (including the #ifdef
CONFIG_PCI).
* Better yet, get rid of mpc83xx_add_bridge and make it possible for the
mpc83xx code to use the of_pci_phb_driver from
arch/powerpc/kernel/of_platform.c. This used to be impossible because
of the differences between 32 and 64 bit code for PCI probing, but
I think with the work than benh put into unifying the two, we should
be pretty close now.
* The detection method for the primary bus is somewhat fragile, because
we depend on the order of the nodes in the device tree, which is not
specified to have a meaning. /Maybe/ there could be a property in
(at most) one of the PCI host bridge nodes saying that this specific bus
is the primary one.
* Since you are using exactly the same probing code for pci and pcie,
you may want to check for a more generic "compatible" property than
the specific model, so you can use the same code for both.
Arnd <><
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] powerpc: Add MPC837x PCIE controller RC mode support
2008-01-02 11:16 [PATCH] powerpc: Add MPC837x PCIE controller RC mode support Li Li
2008-01-02 11:53 ` Arnd Bergmann
@ 2008-01-02 15:23 ` Kumar Gala
2008-01-03 5:56 ` Li Li
2008-01-02 15:51 ` Olof Johansson
2 siblings, 1 reply; 10+ messages in thread
From: Kumar Gala @ 2008-01-02 15:23 UTC (permalink / raw)
To: Li Li; +Cc: Wood Scott, linuxppc-dev, kim phillips
On Jan 2, 2008, at 5:16 AM, Li Li wrote:
> * The MPC837x PCIE controller hardware resources and SerDes are
> initiated in u-boot.
> * Merge the MPC837x PCIE code into arch/powerpc/sysdev/fsl_pci.c
> * The MPC837x PCIE controller`s configure address bit field is uniqe:
> bus number: bits 31-24
> device number: bits 23-19
> function number: bits 18-16
> ext reg number: bits 11-8
> reg number: bits 7-2
> * Add mpc837x_exclude_device to fixup a controller bug.
what is the bug that is being worked around?
- k
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] powerpc: Add MPC837x PCIE controller RC mode support
2008-01-02 11:16 [PATCH] powerpc: Add MPC837x PCIE controller RC mode support Li Li
2008-01-02 11:53 ` Arnd Bergmann
2008-01-02 15:23 ` Kumar Gala
@ 2008-01-02 15:51 ` Olof Johansson
2 siblings, 0 replies; 10+ messages in thread
From: Olof Johansson @ 2008-01-02 15:51 UTC (permalink / raw)
To: Li Li; +Cc: Wood Scott, linuxppc-dev, kim phillips
On Wed, Jan 02, 2008 at 07:16:45PM +0800, Li Li wrote:
> diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
> index 1ee009e..f84caa7 100644
> --- a/include/linux/pci_ids.h
> +++ b/include/linux/pci_ids.h
> @@ -2111,6 +2111,10 @@
> #define PCI_DEVICE_ID_TDI_EHCI 0x0101
>
> #define PCI_VENDOR_ID_FREESCALE 0x1957
> +#define PCI_DEVICE_ID_MPC8378E 0x00c4
> +#define PCI_DEVICE_ID_MPC8378 0x00c5
> +#define PCI_DEVICE_ID_MPC8377E 0x00c6
> +#define PCI_DEVICE_ID_MPC8377 0x00c7
> #define PCI_DEVICE_ID_MPC8548E 0x0012
> #define PCI_DEVICE_ID_MPC8548 0x0013
> #define PCI_DEVICE_ID_MPC8543E 0x0014
In general it's not needed to add device ID's to the global table,
especially when they're only used once or twice. Just use the hex constant
in the driver instead.
-Olof
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] powerpc: Add MPC837x PCIE controller RC mode support
2008-01-02 15:23 ` Kumar Gala
@ 2008-01-03 5:56 ` Li Li
0 siblings, 0 replies; 10+ messages in thread
From: Li Li @ 2008-01-03 5:56 UTC (permalink / raw)
To: Kumar Gala; +Cc: Wood Scott, linuxppc-dev, Phillips Kim, Li Tony
On Wed, 2008-01-02 at 23:23 +0800, Kumar Gala wrote:
>
> On Jan 2, 2008, at 5:16 AM, Li Li wrote:
>
> > * The MPC837x PCIE controller hardware resources and SerDes are
> > initiated in u-boot.
> > * Merge the MPC837x PCIE code into arch/powerpc/sysdev/fsl_pci.c
> > * The MPC837x PCIE controller`s configure address bit field is
> uniqe:
> > bus number: bits 31-24
> > device number: bits 23-19
> > function number: bits 18-16
> > ext reg number: bits 11-8
> > reg number: bits 7-2
> > * Add mpc837x_exclude_device to fixup a controller bug.
>
> what is the bug that is being worked around?
>
For Type 0 configure transactions, the PCIE controller do not check the
device number bits and just assume the device number bits are 0.
- tony
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] powerpc: Add MPC837x PCIE controller RC mode support
2008-01-02 11:53 ` Arnd Bergmann
@ 2008-01-03 6:40 ` Li Li
2008-01-03 8:14 ` Arnd Bergmann
0 siblings, 1 reply; 10+ messages in thread
From: Li Li @ 2008-01-03 6:40 UTC (permalink / raw)
To: Arnd Bergmann; +Cc: Wood Scott, linuxppc-dev, Phillips Kim, Li Tony
On Wed, 2008-01-02 at 19:53 +0800, Arnd Bergmann wrote:
> On Wednesday 02 January 2008, Li Li wrote:
> > #ifdef CONFIG_PCI
> > - for_each_compatible_node(np, "pci", "fsl,mpc8349-pci")
> > - mpc83xx_add_bridge(np);
> > + for_each_compatible_node(np, "pci", "fsl,mpc8349-pci") {
> > + if (primary_pci_bus) {
> > + mpc83xx_add_bridge(np, PPC_83XX_PCI |
> PPC_83XX_PCI_PRIMARY);
> > + primary_pci_bus = 0;
> > + } else
> > + mpc83xx_add_bridge(np, PPC_83XX_PCI);
> > + }
> > +
> > + for_each_compatible_node(np, "pci", "fsl,mpc8377-pcie") {
> > + if (primary_pci_bus) {
> > + mpc83xx_add_bridge(np, PPC_83XX_PCIE |
> PPC_83XX_PCI_PRIMARY);
> > + primary_pci_bus = 0;
> > + } else
> > + mpc83xx_add_bridge(np, PPC_83XX_PCIE);
> > + }
> > +
> > + ppc_md.pci_exclude_device = mpc837x_exclude_device;
> > #endif
>
> A few comments on how I think this can be improved:
>
> * Instead of duplicating this code across all platforms, make a
> single
> function that does the probing in one place (including the #ifdef
> CONFIG_PCI).
>
This code appears in 834x board in first and then copied from one board
to another. It is a legacy issue. :(
Yes. it is the time to remove this duplicates.
> * Better yet, get rid of mpc83xx_add_bridge and make it possible for
> the
> mpc83xx code to use the of_pci_phb_driver from
> arch/powerpc/kernel/of_platform.c. This used to be impossible because
> of the differences between 32 and 64 bit code for PCI probing, but
> I think with the work than benh put into unifying the two, we should
> be pretty close now.
>
This is really a huge task and almost affects all exist boards. We need
more opinions in here.
> * The detection method for the primary bus is somewhat fragile,
> because
> we depend on the order of the nodes in the device tree, which is not
> specified to have a meaning. /Maybe/ there could be a property in
> (at most) one of the PCI host bridge nodes saying that this specific
> bus
> is the primary one.
>
Put this primary in code is more save than in dts.
The dts lacks error checking function. If provide error dts such as two
pci hosts both has primary property will occur chaos.
> * Since you are using exactly the same probing code for pci and pcie,
> you may want to check for a more generic "compatible" property than
> the specific model, so you can use the same code for both.
>
> Arnd <><
>
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] powerpc: Add MPC837x PCIE controller RC mode support
2008-01-03 6:40 ` Li Li
@ 2008-01-03 8:14 ` Arnd Bergmann
2008-01-03 8:31 ` Li Li
0 siblings, 1 reply; 10+ messages in thread
From: Arnd Bergmann @ 2008-01-03 8:14 UTC (permalink / raw)
To: Li Li; +Cc: Wood Scott, linuxppc-dev, Phillips Kim, Li Tony
On Thursday 03 January 2008, Li Li wrote:
> > * The detection method for the primary bus is somewhat fragile,
> > because
> > we depend on the order of the nodes in the device tree, which is not
> > specified to have a meaning. /Maybe/ there could be a property in
> > (at most) one of the PCI host bridge nodes saying that this specific
> > bus
> > is the primary one.
> >
>
> Put this primary in code is more save than in dts.
> The dts lacks error checking function. If provide error dts such as two
> pci hosts both has primary property will occur chaos.
It's easy enough to just panic() if you find more than one primary bus,
since the information from the device tree is static enough that one
will know how to fix this after seeing the error.
Arnd <><
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] powerpc: Add MPC837x PCIE controller RC mode support
2008-01-03 8:14 ` Arnd Bergmann
@ 2008-01-03 8:31 ` Li Li
2008-01-03 10:14 ` Arnd Bergmann
0 siblings, 1 reply; 10+ messages in thread
From: Li Li @ 2008-01-03 8:31 UTC (permalink / raw)
To: Arnd Bergmann; +Cc: Wood Scott, linuxppc-dev, Phillips Kim, Li Tony
On Thu, 2008-01-03 at 16:14 +0800, Arnd Bergmann wrote:
> On Thursday 03 January 2008, Li Li wrote:
> > > * The detection method for the primary bus is somewhat fragile,
> > > because
> > > we depend on the order of the nodes in the device tree, which is
> not
> > > specified to have a meaning. /Maybe/ there could be a property in
> > > (at most) one of the PCI host bridge nodes saying that this
> specific
> > > bus
> > > is the primary one.
> > >
> >
> > Put this primary in code is more save than in dts.
> > The dts lacks error checking function. If provide error dts such as
> two
> > pci hosts both has primary property will occur chaos.
>
> It's easy enough to just panic() if you find more than one primary
> bus,
> since the information from the device tree is static enough that one
> will know how to fix this after seeing the error.
>
It is just a case. what about if do not find primary pci host.
The current code can prevent this potential error and make system
robust.
- Tony
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] powerpc: Add MPC837x PCIE controller RC mode support
2008-01-03 10:14 ` Arnd Bergmann
@ 2008-01-03 10:08 ` Li Li
0 siblings, 0 replies; 10+ messages in thread
From: Li Li @ 2008-01-03 10:08 UTC (permalink / raw)
To: Arnd Bergmann; +Cc: Phillips Kim, linuxppc-dev, Li Tony, Wood Scott
On Thu, 2008-01-03 at 18:14 +0800, Arnd Bergmann wrote:
> After some more research, I noticed that the distinction between
> primary and secondary host bridges will go away _anyway_, so
> I guess we shouldn't worry about it too much.
>
> On powerpc64, we already don't care, as the
> arch/powerpc/kernel/isa-bridge.c
> code takes care of legacy I/O areas there, instead of the PCI code.
> It's only needed on machines with legacy ISA devices (PC keyboard,
> floppy, ...), and those can be converted to use the isa-bridge code
> at some point.
>
This is really a good new :)
- Tony
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] powerpc: Add MPC837x PCIE controller RC mode support
2008-01-03 8:31 ` Li Li
@ 2008-01-03 10:14 ` Arnd Bergmann
2008-01-03 10:08 ` Li Li
0 siblings, 1 reply; 10+ messages in thread
From: Arnd Bergmann @ 2008-01-03 10:14 UTC (permalink / raw)
To: Li Li; +Cc: Phillips Kim, linuxppc-dev, Li Tony, Wood Scott
On Thursday 03 January 2008, Li Li wrote:
>
> > It's easy enough to just panic() if you find more than one primary
> > bus,
> > since the information from the device tree is static enough that one
> > will know how to fix this after seeing the error.
> >
>
> It is just a case. what about if do not find primary pci host.
> The current code can prevent this potential error and make system
> robust.
After some more research, I noticed that the distinction between
primary and secondary host bridges will go away _anyway_, so
I guess we shouldn't worry about it too much.
On powerpc64, we already don't care, as the arch/powerpc/kernel/isa-bridge.c
code takes care of legacy I/O areas there, instead of the PCI code.
It's only needed on machines with legacy ISA devices (PC keyboard,
floppy, ...), and those can be converted to use the isa-bridge code
at some point.
Arnd <><
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2008-01-03 10:22 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-01-02 11:16 [PATCH] powerpc: Add MPC837x PCIE controller RC mode support Li Li
2008-01-02 11:53 ` Arnd Bergmann
2008-01-03 6:40 ` Li Li
2008-01-03 8:14 ` Arnd Bergmann
2008-01-03 8:31 ` Li Li
2008-01-03 10:14 ` Arnd Bergmann
2008-01-03 10:08 ` Li Li
2008-01-02 15:23 ` Kumar Gala
2008-01-03 5:56 ` Li Li
2008-01-02 15:51 ` Olof Johansson
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).