@@ -11,6 +11,7 @@
* published by the Free Software Foundation.
*/
+#include <linux/acpi.h>
#include <linux/irq.h>
#include <linux/irqdomain.h>
#include <linux/kernel.h>
@@ -19,6 +20,7 @@
#include <linux/of_address.h>
#include <linux/of_pci.h>
#include <linux/pci.h>
+#include <linux/pci-acpi.h>
#include <linux/pci_regs.h>
#include <linux/platform_device.h>
#include <linux/types.h>
@@ -46,7 +48,6 @@
#define PCIE_MSI_INTR0_ENABLE 0x828
#define PCIE_MSI_INTR0_MASK 0x82C
#define PCIE_MSI_INTR0_STATUS 0x830
-
#define PCIE_ATU_VIEWPORT 0x900
#define PCIE_ATU_REGION_INBOUND (0x1 << 31)
#define PCIE_ATU_REGION_OUTBOUND (0x0 << 31)
@@ -69,7 +70,7 @@
#define PCIE_ATU_FUNC(x) (((x) & 0x7) << 16)
#define PCIE_ATU_UPPER_TARGET 0x91C
-static struct pci_ops dw_pcie_ops;
+struct pci_ops dw_pcie_ops;
int dw_pcie_cfg_read(void __iomem *addr, int size, u32 *val)
{
@@ -657,8 +658,22 @@ static int dw_pcie_valid_config(struct pcie_port *pp,
static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
int size, u32 *val)
{
- struct pcie_port *pp = bus->sysdata;
int ret;
+ struct pcie_port *pp;
+ struct pci_bus *bridge_bus;
+
+ for (bridge_bus = bus; bridge_bus->parent;
+ bridge_bus = bridge_bus->parent)
+ ;
+
+ if (has_acpi_companion(bridge_bus->bridge)) {
+#ifdef CONFIG_ACPI_PCI_HOST_GENERIC
+ struct acpi_pci_root *root = bus->sysdata;
+
+ pp = root->sysdata;
+#endif /* CONFIG_ACPI_PCI_HOST_GENERIC */
+ } else
+ pp = bus->sysdata;
if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0) {
*val = 0xffffffff;
@@ -681,8 +696,22 @@ static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
static int dw_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
int where, int size, u32 val)
{
- struct pcie_port *pp = bus->sysdata;
int ret;
+ struct pcie_port *pp;
+ struct pci_bus *bridge_bus;
+
+ for (bridge_bus = bus; bridge_bus->parent;
+ bridge_bus = bridge_bus->parent)
+ ;
+
+ if (has_acpi_companion(bridge_bus->bridge)) {
+#ifdef CONFIG_ACPI_PCI_HOST_GENERIC
+ struct acpi_pci_root *root = bus->sysdata;
+
+ pp = root->sysdata;
+#endif /* CONFIG_ACPI_PCI_HOST_GENERIC */
+ } else
+ pp = bus->sysdata;
if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0)
return PCIBIOS_DEVICE_NOT_FOUND;
@@ -700,7 +729,7 @@ static int dw_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
return ret;
}
-static struct pci_ops dw_pcie_ops = {
+struct pci_ops dw_pcie_ops = {
.read = dw_pcie_rd_conf,
.write = dw_pcie_wr_conf,
};
@@ -80,4 +80,5 @@ int dw_pcie_link_up(struct pcie_port *pp);
void dw_pcie_setup_rc(struct pcie_port *pp);
int dw_pcie_host_init(struct pcie_port *pp);
+extern struct pci_ops dw_pcie_ops;
#endif /* _PCIE_DESIGNWARE_H */