summaryrefslogtreecommitdiffstats
path: root/arm64-pcie-acpi.patch
diff options
context:
space:
mode:
Diffstat (limited to 'arm64-pcie-acpi.patch')
-rw-r--r--arm64-pcie-acpi.patch1247
1 files changed, 0 insertions, 1247 deletions
diff --git a/arm64-pcie-acpi.patch b/arm64-pcie-acpi.patch
deleted file mode 100644
index e9a359db6..000000000
--- a/arm64-pcie-acpi.patch
+++ /dev/null
@@ -1,1247 +0,0 @@
-From 1fc02559de87cd88339a83ad05baa9c2b5bd1ac0 Mon Sep 17 00:00:00 2001
-From: Jayachandran C <jchandra@broadcom.com>
-Date: Fri, 10 Jun 2016 21:55:09 +0200
-Subject: [PATCH 01/11] PCI/ECAM: Move ecam.h to linux/include/pci-ecam.h
-
-This header will be used from arch/arm64 for ACPI PCI implementation
-so it needs to be moved out of drivers/pci.
-
-Update users of the header file to use the new name. No functional
-changes.
-
-Signed-off-by: Jayachandran C <jchandra@broadcom.com>
-Acked-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
----
- drivers/pci/ecam.c | 3 +-
- drivers/pci/ecam.h | 67 -------------------------------------
- drivers/pci/host/pci-host-common.c | 3 +-
- drivers/pci/host/pci-host-generic.c | 3 +-
- drivers/pci/host/pci-thunder-ecam.c | 3 +-
- drivers/pci/host/pci-thunder-pem.c | 3 +-
- include/linux/pci-ecam.h | 67 +++++++++++++++++++++++++++++++++++++
- 7 files changed, 72 insertions(+), 77 deletions(-)
- delete mode 100644 drivers/pci/ecam.h
- create mode 100644 include/linux/pci-ecam.h
-
-diff --git a/drivers/pci/ecam.c b/drivers/pci/ecam.c
-index f9832ad..820e26b 100644
---- a/drivers/pci/ecam.c
-+++ b/drivers/pci/ecam.c
-@@ -19,10 +19,9 @@
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/pci.h>
-+#include <linux/pci-ecam.h>
- #include <linux/slab.h>
-
--#include "ecam.h"
--
- /*
- * On 64-bit systems, we do a single ioremap for the whole config space
- * since we have enough virtual address range available. On 32-bit, we
-diff --git a/drivers/pci/ecam.h b/drivers/pci/ecam.h
-deleted file mode 100644
-index 9878beb..0000000
---- a/drivers/pci/ecam.h
-+++ /dev/null
-@@ -1,67 +0,0 @@
--/*
-- * Copyright 2016 Broadcom
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License, version 2, as
-- * published by the Free Software Foundation (the "GPL").
-- *
-- * 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 version 2 (GPLv2) for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * version 2 (GPLv2) along with this source code.
-- */
--#ifndef DRIVERS_PCI_ECAM_H
--#define DRIVERS_PCI_ECAM_H
--
--#include <linux/kernel.h>
--#include <linux/platform_device.h>
--
--/*
-- * struct to hold pci ops and bus shift of the config window
-- * for a PCI controller.
-- */
--struct pci_config_window;
--struct pci_ecam_ops {
-- unsigned int bus_shift;
-- struct pci_ops pci_ops;
-- int (*init)(struct device *,
-- struct pci_config_window *);
--};
--
--/*
-- * struct to hold the mappings of a config space window. This
-- * is expected to be used as sysdata for PCI controllers that
-- * use ECAM.
-- */
--struct pci_config_window {
-- struct resource res;
-- struct resource busr;
-- void *priv;
-- struct pci_ecam_ops *ops;
-- union {
-- void __iomem *win; /* 64-bit single mapping */
-- void __iomem **winp; /* 32-bit per-bus mapping */
-- };
--};
--
--/* create and free pci_config_window */
--struct pci_config_window *pci_ecam_create(struct device *dev,
-- struct resource *cfgres, struct resource *busr,
-- struct pci_ecam_ops *ops);
--void pci_ecam_free(struct pci_config_window *cfg);
--
--/* map_bus when ->sysdata is an instance of pci_config_window */
--void __iomem *pci_ecam_map_bus(struct pci_bus *bus, unsigned int devfn,
-- int where);
--/* default ECAM ops */
--extern struct pci_ecam_ops pci_generic_ecam_ops;
--
--#ifdef CONFIG_PCI_HOST_GENERIC
--/* for DT-based PCI controllers that support ECAM */
--int pci_host_common_probe(struct platform_device *pdev,
-- struct pci_ecam_ops *ops);
--#endif
--#endif
-diff --git a/drivers/pci/host/pci-host-common.c b/drivers/pci/host/pci-host-common.c
-index 8cba7ab..c18b9e3 100644
---- a/drivers/pci/host/pci-host-common.c
-+++ b/drivers/pci/host/pci-host-common.c
-@@ -20,10 +20,9 @@
- #include <linux/module.h>
- #include <linux/of_address.h>
- #include <linux/of_pci.h>
-+#include <linux/pci-ecam.h>
- #include <linux/platform_device.h>
-
--#include "../ecam.h"
--
- static int gen_pci_parse_request_of_pci_ranges(struct device *dev,
- struct list_head *resources, struct resource **bus_range)
- {
-diff --git a/drivers/pci/host/pci-host-generic.c b/drivers/pci/host/pci-host-generic.c
-index 6eaceab..f0ca6de 100644
---- a/drivers/pci/host/pci-host-generic.c
-+++ b/drivers/pci/host/pci-host-generic.c
-@@ -23,10 +23,9 @@
- #include <linux/module.h>
- #include <linux/of_address.h>
- #include <linux/of_pci.h>
-+#include <linux/pci-ecam.h>
- #include <linux/platform_device.h>
-
--#include "../ecam.h"
--
- static struct pci_ecam_ops gen_pci_cfg_cam_bus_ops = {
- .bus_shift = 16,
- .pci_ops = {
-diff --git a/drivers/pci/host/pci-thunder-ecam.c b/drivers/pci/host/pci-thunder-ecam.c
-index 540d030..a9fc1c9 100644
---- a/drivers/pci/host/pci-thunder-ecam.c
-+++ b/drivers/pci/host/pci-thunder-ecam.c
-@@ -11,10 +11,9 @@
- #include <linux/ioport.h>
- #include <linux/of_pci.h>
- #include <linux/of.h>
-+#include <linux/pci-ecam.h>
- #include <linux/platform_device.h>
-
--#include "../ecam.h"
--
- static void set_val(u32 v, int where, int size, u32 *val)
- {
- int shift = (where & 3) * 8;
-diff --git a/drivers/pci/host/pci-thunder-pem.c b/drivers/pci/host/pci-thunder-pem.c
-index 9b8ab94..5020d3d 100644
---- a/drivers/pci/host/pci-thunder-pem.c
-+++ b/drivers/pci/host/pci-thunder-pem.c
-@@ -18,10 +18,9 @@
- #include <linux/module.h>
- #include <linux/of_address.h>
- #include <linux/of_pci.h>
-+#include <linux/pci-ecam.h>
- #include <linux/platform_device.h>
-
--#include "../ecam.h"
--
- #define PEM_CFG_WR 0x28
- #define PEM_CFG_RD 0x30
-
-diff --git a/include/linux/pci-ecam.h b/include/linux/pci-ecam.h
-new file mode 100644
-index 0000000..9878beb
---- /dev/null
-+++ b/include/linux/pci-ecam.h
-@@ -0,0 +1,67 @@
-+/*
-+ * Copyright 2016 Broadcom
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License, version 2, as
-+ * published by the Free Software Foundation (the "GPL").
-+ *
-+ * 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 version 2 (GPLv2) for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * version 2 (GPLv2) along with this source code.
-+ */
-+#ifndef DRIVERS_PCI_ECAM_H
-+#define DRIVERS_PCI_ECAM_H
-+
-+#include <linux/kernel.h>
-+#include <linux/platform_device.h>
-+
-+/*
-+ * struct to hold pci ops and bus shift of the config window
-+ * for a PCI controller.
-+ */
-+struct pci_config_window;
-+struct pci_ecam_ops {
-+ unsigned int bus_shift;
-+ struct pci_ops pci_ops;
-+ int (*init)(struct device *,
-+ struct pci_config_window *);
-+};
-+
-+/*
-+ * struct to hold the mappings of a config space window. This
-+ * is expected to be used as sysdata for PCI controllers that
-+ * use ECAM.
-+ */
-+struct pci_config_window {
-+ struct resource res;
-+ struct resource busr;
-+ void *priv;
-+ struct pci_ecam_ops *ops;
-+ union {
-+ void __iomem *win; /* 64-bit single mapping */
-+ void __iomem **winp; /* 32-bit per-bus mapping */
-+ };
-+};
-+
-+/* create and free pci_config_window */
-+struct pci_config_window *pci_ecam_create(struct device *dev,
-+ struct resource *cfgres, struct resource *busr,
-+ struct pci_ecam_ops *ops);
-+void pci_ecam_free(struct pci_config_window *cfg);
-+
-+/* map_bus when ->sysdata is an instance of pci_config_window */
-+void __iomem *pci_ecam_map_bus(struct pci_bus *bus, unsigned int devfn,
-+ int where);
-+/* default ECAM ops */
-+extern struct pci_ecam_ops pci_generic_ecam_ops;
-+
-+#ifdef CONFIG_PCI_HOST_GENERIC
-+/* for DT-based PCI controllers that support ECAM */
-+int pci_host_common_probe(struct platform_device *pdev,
-+ struct pci_ecam_ops *ops);
-+#endif
-+#endif
---
-2.7.4
-
-From 5eb9996fc097629854f359f9ad3d959fdacb7f8f Mon Sep 17 00:00:00 2001
-From: Jayachandran C <jchandra@broadcom.com>
-Date: Fri, 10 Jun 2016 21:55:10 +0200
-Subject: [PATCH 02/11] PCI/ECAM: Add parent device field to pci_config_window
-
-Add a parent device field to struct pci_config_window. The parent
-is not saved now, but will be useful to save it in some cases.
-Specifically in case of ACPI for ARM64, it can be used to setup
-ACPI companion and domain.
-
-Since the parent dev is in struct pci_config_window now, we need
-not pass it to the init function as a separate argument.
-
-Signed-off-by: Jayachandran C <jchandra@broadcom.com>
-Acked-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
----
- drivers/pci/ecam.c | 3 ++-
- drivers/pci/host/pci-thunder-pem.c | 3 ++-
- include/linux/pci-ecam.h | 4 ++--
- 3 files changed, 6 insertions(+), 4 deletions(-)
-
-diff --git a/drivers/pci/ecam.c b/drivers/pci/ecam.c
-index 820e26b..66e0d71 100644
---- a/drivers/pci/ecam.c
-+++ b/drivers/pci/ecam.c
-@@ -51,6 +51,7 @@ struct pci_config_window *pci_ecam_create(struct device *dev,
- if (!cfg)
- return ERR_PTR(-ENOMEM);
-
-+ cfg->parent = dev;
- cfg->ops = ops;
- cfg->busr.start = busr->start;
- cfg->busr.end = busr->end;
-@@ -94,7 +95,7 @@ struct pci_config_window *pci_ecam_create(struct device *dev,
- }
-
- if (ops->init) {
-- err = ops->init(dev, cfg);
-+ err = ops->init(cfg);
- if (err)
- goto err_exit;
- }
-diff --git a/drivers/pci/host/pci-thunder-pem.c b/drivers/pci/host/pci-thunder-pem.c
-index 5020d3d..91f6fc6 100644
---- a/drivers/pci/host/pci-thunder-pem.c
-+++ b/drivers/pci/host/pci-thunder-pem.c
-@@ -284,8 +284,9 @@ static int thunder_pem_config_write(struct pci_bus *bus, unsigned int devfn,
- return pci_generic_config_write(bus, devfn, where, size, val);
- }
-
--static int thunder_pem_init(struct device *dev, struct pci_config_window *cfg)
-+static int thunder_pem_init(struct pci_config_window *cfg)
- {
-+ struct device *dev = cfg->parent;
- resource_size_t bar4_start;
- struct resource *res_pem;
- struct thunder_pem_pci *pem_pci;
-diff --git a/include/linux/pci-ecam.h b/include/linux/pci-ecam.h
-index 9878beb..7adad20 100644
---- a/include/linux/pci-ecam.h
-+++ b/include/linux/pci-ecam.h
-@@ -27,8 +27,7 @@ struct pci_config_window;
- struct pci_ecam_ops {
- unsigned int bus_shift;
- struct pci_ops pci_ops;
-- int (*init)(struct device *,
-- struct pci_config_window *);
-+ int (*init)(struct pci_config_window *);
- };
-
- /*
-@@ -45,6 +44,7 @@ struct pci_config_window {
- void __iomem *win; /* 64-bit single mapping */
- void __iomem **winp; /* 32-bit per-bus mapping */
- };
-+ struct device *parent;/* ECAM res was from this dev */
- };
-
- /* create and free pci_config_window */
---
-2.7.4
-
-From 6ed6c1365df5c9201e9b275e8ed4eaa64ef2ec0d Mon Sep 17 00:00:00 2001
-From: Sinan Kaya <okaya@codeaurora.org>
-Date: Fri, 10 Jun 2016 21:55:11 +0200
-Subject: [PATCH 03/11] PCI: Add new function to unmap IO resources
-
-We need to release I/O resources so that the same I/O resources
-can be allocated again in pci_remap_iospace(), like in PCI hotplug removal
-scenario. Therefore implement new pci_unmap_iospace() call which
-unmaps I/O space as the symmetry to pci_remap_iospace().
-
-Signed-off-by: Sinan Kaya <okaya@codeaurora.org>
-Signed-off-by: Tomasz Nowicki <tn@semihalf.com>
-Acked-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
----
- drivers/pci/pci.c | 18 ++++++++++++++++++
- include/linux/pci.h | 1 +
- 2 files changed, 19 insertions(+)
-
-diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
-index c8b4dbd..eb431b5 100644
---- a/drivers/pci/pci.c
-+++ b/drivers/pci/pci.c
-@@ -25,6 +25,7 @@
- #include <linux/device.h>
- #include <linux/pm_runtime.h>
- #include <linux/pci_hotplug.h>
-+#include <linux/vmalloc.h>
- #include <asm/setup.h>
- #include <linux/aer.h>
- #include "pci.h"
-@@ -3165,6 +3166,23 @@ int __weak pci_remap_iospace(const struct resource *res, phys_addr_t phys_addr)
- #endif
- }
-
-+/**
-+ * pci_unmap_iospace - Unmap the memory mapped I/O space
-+ * @res: resource to be unmapped
-+ *
-+ * Unmap the CPU virtual address @res from virtual address space.
-+ * Only architectures that have memory mapped IO functions defined
-+ * (and the PCI_IOBASE value defined) should call this function.
-+ */
-+void pci_unmap_iospace(struct resource *res)
-+{
-+#if defined(PCI_IOBASE) && defined(CONFIG_MMU)
-+ unsigned long vaddr = (unsigned long)PCI_IOBASE + res->start;
-+
-+ unmap_kernel_range(vaddr, resource_size(res));
-+#endif
-+}
-+
- static void __pci_set_master(struct pci_dev *dev, bool enable)
- {
- u16 old_cmd, cmd;
-diff --git a/include/linux/pci.h b/include/linux/pci.h
-index b67e4df..12349de 100644
---- a/include/linux/pci.h
-+++ b/include/linux/pci.h
-@@ -1167,6 +1167,7 @@ int pci_register_io_range(phys_addr_t addr, resource_size_t size);
- unsigned long pci_address_to_pio(phys_addr_t addr);
- phys_addr_t pci_pio_to_address(unsigned long pio);
- int pci_remap_iospace(const struct resource *res, phys_addr_t phys_addr);
-+void pci_unmap_iospace(struct resource *res);
-
- static inline pci_bus_addr_t pci_bus_address(struct pci_dev *pdev, int bar)
- {
---
-2.7.4
-
-From 62f4d54fc2d2882b9ebaa920189574f422e12207 Mon Sep 17 00:00:00 2001
-From: Jayachandran C <jchandra@broadcom.com>
-Date: Fri, 10 Jun 2016 21:55:12 +0200
-Subject: [PATCH 04/11] ACPI/PCI: Support IO resources when parsing PCI host
- bridge resources
-
-Platforms that have memory mapped IO port (such as ARM64) need special
-handling for PCI I/O resources. For host bridge's resource probing case
-these resources need to be fixed up with
-pci_register_io_range()/pci_remap_iospace() etc.
-
-The same I/O resources need to be released after hotplug
-removal so that it can be re-added back by the pci_remap_iospace()
-function during insertion. As a consequence unmap I/O resources
-with pci_unmap_iospace() when we release host bridge resources.
-
-Signed-off-by: Jayachandran C <jchandra@broadcom.com>
-Signed-off-by: Sinan Kaya <okaya@codeaurora.org>
-[ Tomasz: merged in Sinan's patch to unmap IO resources properly, updated changelog]
-Signed-off-by: Tomasz Nowicki <tn@semihalf.com>
-Reviewed-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
----
- drivers/acpi/pci_root.c | 39 +++++++++++++++++++++++++++++++++++++++
- 1 file changed, 39 insertions(+)
-
-diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
-index ae3fe4e..9a26dd1 100644
---- a/drivers/acpi/pci_root.c
-+++ b/drivers/acpi/pci_root.c
-@@ -720,6 +720,40 @@ next:
- }
- }
-
-+#ifdef PCI_IOBASE
-+static void acpi_pci_root_remap_iospace(struct resource_entry *entry)
-+{
-+ struct resource *res = entry->res;
-+ resource_size_t cpu_addr = res->start;
-+ resource_size_t pci_addr = cpu_addr - entry->offset;
-+ resource_size_t length = resource_size(res);
-+ unsigned long port;
-+
-+ if (pci_register_io_range(cpu_addr, length))
-+ goto err;
-+
-+ port = pci_address_to_pio(cpu_addr);
-+ if (port == (unsigned long)-1)
-+ goto err;
-+
-+ res->start = port;
-+ res->end = port + length - 1;
-+ entry->offset = port - pci_addr;
-+
-+ if (pci_remap_iospace(res, cpu_addr) < 0)
-+ goto err;
-+
-+ pr_info("Remapped I/O %pa to %pR\n", &cpu_addr, res);
-+ return;
-+err:
-+ res->flags |= IORESOURCE_DISABLED;
-+}
-+#else
-+static inline void acpi_pci_root_remap_iospace(struct resource_entry *entry)
-+{
-+}
-+#endif
-+
- int acpi_pci_probe_root_resources(struct acpi_pci_root_info *info)
- {
- int ret;
-@@ -740,6 +774,9 @@ int acpi_pci_probe_root_resources(struct acpi_pci_root_info *info)
- "no IO and memory resources present in _CRS\n");
- else {
- resource_list_for_each_entry_safe(entry, tmp, list) {
-+ if (entry->res->flags & IORESOURCE_IO)
-+ acpi_pci_root_remap_iospace(entry);
-+
- if (entry->res->flags & IORESOURCE_DISABLED)
- resource_list_destroy_entry(entry);
- else
-@@ -811,6 +848,8 @@ static void acpi_pci_root_release_info(struct pci_host_bridge *bridge)
-
- resource_list_for_each_entry(entry, &bridge->windows) {
- res = entry->res;
-+ if (res->flags & IORESOURCE_IO)
-+ pci_unmap_iospace(res);
- if (res->parent &&
- (res->flags & (IORESOURCE_MEM | IORESOURCE_IO)))
- release_resource(res);
---
-2.7.4
-
-From dd4f7822d702cca83baa1de7a5f69344ffb82af9 Mon Sep 17 00:00:00 2001
-From: Tomasz Nowicki <tn@semihalf.com>
-Date: Fri, 10 Jun 2016 21:55:13 +0200
-Subject: [PATCH 05/11] ACPI/PCI: Add generic MCFG table handling
-
-According to PCI firmware specifications, on systems booting with ACPI,
-PCI configuration for a host bridge must be set-up through the MCFG table
-regions for non-hotpluggable bridges and _CBA method for hotpluggable ones.
-
-Current MCFG table handling code, as implemented for x86, cannot be
-easily generalized owing to x86 specific quirks handling and related
-code, which makes it hard to reuse on other architectures.
-
-In order to implement MCFG PCI configuration handling for new platforms
-booting with ACPI (eg ARM64) this patch re-implements MCFG handling from
-scratch in a streamlined fashion and provides (through a generic
-interface available to all arches):
-
-- Simplified MCFG table parsing (executed through the pci_mmcfg_late_init()
- hook as in current x86)
-- MCFG regions look-up interface through domain:bus_start:bus_end tuple
-
-The new MCFG regions handling interface is added to generic ACPI code
-so that existing architectures (eg x86) can be moved over to it and
-architectures relying on MCFG for ACPI PCI config space can rely on it
-without having to resort to arch specific implementations.
-
-Signed-off-by: Tomasz Nowicki <tn@semihalf.com>
-Signed-off-by: Jayachandran C <jchandra@broadcom.com>
-Reviewed-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
----
- drivers/acpi/Kconfig | 3 ++
- drivers/acpi/Makefile | 1 +
- drivers/acpi/pci_mcfg.c | 92 ++++++++++++++++++++++++++++++++++++++++++++++++
- include/linux/pci-acpi.h | 2 ++
- include/linux/pci.h | 2 +-
- 5 files changed, 99 insertions(+), 1 deletion(-)
- create mode 100644 drivers/acpi/pci_mcfg.c
-
-diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
-index b7e2e77..f98c328 100644
---- a/drivers/acpi/Kconfig
-+++ b/drivers/acpi/Kconfig
-@@ -217,6 +217,9 @@ config ACPI_PROCESSOR_IDLE
- bool
- select CPU_IDLE
-
-+config ACPI_MCFG
-+ bool
-+
- config ACPI_CPPC_LIB
- bool
- depends on ACPI_PROCESSOR
-diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
-index 251ce85..632e81f 100644
---- a/drivers/acpi/Makefile
-+++ b/drivers/acpi/Makefile
-@@ -40,6 +40,7 @@ acpi-$(CONFIG_ARCH_MIGHT_HAVE_ACPI_PDC) += processor_pdc.o
- acpi-y += ec.o
- acpi-$(CONFIG_ACPI_DOCK) += dock.o
- acpi-y += pci_root.o pci_link.o pci_irq.o
-+obj-$(CONFIG_ACPI_MCFG) += pci_mcfg.o
- acpi-y += acpi_lpss.o acpi_apd.o
- acpi-y += acpi_platform.o
- acpi-y += acpi_pnp.o
-diff --git a/drivers/acpi/pci_mcfg.c b/drivers/acpi/pci_mcfg.c
-new file mode 100644
-index 0000000..d3c3e85
---- /dev/null
-+++ b/drivers/acpi/pci_mcfg.c
-@@ -0,0 +1,92 @@
-+/*
-+ * Copyright (C) 2016 Broadcom
-+ * Author: Jayachandran C <jchandra@broadcom.com>
-+ * Copyright (C) 2016 Semihalf
-+ * Author: Tomasz Nowicki <tn@semihalf.com>
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License, version 2, as
-+ * published by the Free Software Foundation (the "GPL").
-+ *
-+ * 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 version 2 (GPLv2) for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * version 2 (GPLv2) along with this source code.
-+ */
-+
-+#define pr_fmt(fmt) "ACPI: " fmt
-+
-+#include <linux/kernel.h>
-+#include <linux/pci.h>
-+#include <linux/pci-acpi.h>
-+
-+/* Structure to hold entries from the MCFG table */
-+struct mcfg_entry {
-+ struct list_head list;
-+ phys_addr_t addr;
-+ u16 segment;
-+ u8 bus_start;
-+ u8 bus_end;
-+};
-+
-+/* List to save mcfg entries */
-+static LIST_HEAD(pci_mcfg_list);
-+
-+phys_addr_t pci_mcfg_lookup(u16 seg, struct resource *bus_res)
-+{
-+ struct mcfg_entry *e;
-+
-+ /*
-+ * We expect exact match, unless MCFG entry end bus covers more than
-+ * specified by caller.
-+ */
-+ list_for_each_entry(e, &pci_mcfg_list, list) {
-+ if (e->segment == seg && e->bus_start == bus_res->start &&
-+ e->bus_end >= bus_res->end)
-+ return e->addr;
-+ }
-+
-+ return 0;
-+}
-+
-+static __init int pci_mcfg_parse(struct acpi_table_header *header)
-+{
-+ struct acpi_table_mcfg *mcfg;
-+ struct acpi_mcfg_allocation *mptr;
-+ struct mcfg_entry *e, *arr;
-+ int i, n;
-+
-+ if (header->length < sizeof(struct acpi_table_mcfg))
-+ return -EINVAL;
-+
-+ n = (header->length - sizeof(struct acpi_table_mcfg)) /
-+ sizeof(struct acpi_mcfg_allocation);
-+ mcfg = (struct acpi_table_mcfg *)header;
-+ mptr = (struct acpi_mcfg_allocation *) &mcfg[1];
-+
-+ arr = kcalloc(n, sizeof(*arr), GFP_KERNEL);
-+ if (!arr)
-+ return -ENOMEM;
-+
-+ for (i = 0, e = arr; i < n; i++, mptr++, e++) {
-+ e->segment = mptr->pci_segment;
-+ e->addr = mptr->address;
-+ e->bus_start = mptr->start_bus_number;
-+ e->bus_end = mptr->end_bus_number;
-+ list_add(&e->list, &pci_mcfg_list);
-+ }
-+
-+ pr_info("MCFG table detected, %d entries\n", n);
-+ return 0;
-+}
-+
-+/* Interface called by ACPI - parse and save MCFG table */
-+void __init pci_mmcfg_late_init(void)
-+{
-+ int err = acpi_table_parse(ACPI_SIG_MCFG, pci_mcfg_parse);
-+ if (err)
-+ pr_err("Failed to parse MCFG (%d)\n", err);
-+}
-diff --git a/include/linux/pci-acpi.h b/include/linux/pci-acpi.h
-index 89ab057..7d63a66 100644
---- a/include/linux/pci-acpi.h
-+++ b/include/linux/pci-acpi.h
-@@ -24,6 +24,8 @@ static inline acpi_status pci_acpi_remove_pm_notifier(struct acpi_device *dev)
- }
- extern phys_addr_t acpi_pci_root_get_mcfg_addr(acpi_handle handle);
-
-+extern phys_addr_t pci_mcfg_lookup(u16 domain, struct resource *bus_res);
-+
- static inline acpi_handle acpi_find_root_bridge_handle(struct pci_dev *pdev)
- {
- struct pci_bus *pbus = pdev->bus;
-diff --git a/include/linux/pci.h b/include/linux/pci.h
-index 12349de..ce03d65 100644
---- a/include/linux/pci.h
-+++ b/include/linux/pci.h
-@@ -1723,7 +1723,7 @@ void pcibios_free_irq(struct pci_dev *dev);
- extern struct dev_pm_ops pcibios_pm_ops;
- #endif
-
--#ifdef CONFIG_PCI_MMCONFIG
-+#if defined(CONFIG_PCI_MMCONFIG) || defined(CONFIG_ACPI_MCFG)
- void __init pci_mmcfg_early_init(void);
- void __init pci_mmcfg_late_init(void);
- #else
---
-2.7.4
-
-From fc1907f9c79f9a0a0c2f4d579896e678915fec48 Mon Sep 17 00:00:00 2001
-From: Tomasz Nowicki <tn@semihalf.com>
-Date: Fri, 10 Jun 2016 21:55:14 +0200
-Subject: [PATCH 06/11] PCI: Refactor generic bus domain assignment
-
-Change the way PCI bus domain number is assigned and improve function
-name to reflect what function does. No functional changes.
-
-Instead of assigning bus domain number inside of pci_bus_assign_domain_nr()
-simply return domain number and let pci_create_root_bus() do assignment.
-This way pci_create_root_bus() setups bus structure data in the consistent
-way. Since pci_bus_assign_domain_nr() now does not assign but retrieves
-domain number instead, rename it to pci_bus_find_domain_nr().
-
-Signed-off-by: Tomasz Nowicki <tn@semihalf.com>
-Reviewed-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
----
- drivers/pci/pci.c | 4 ++--
- drivers/pci/probe.c | 4 +++-
- include/linux/pci.h | 7 +------
- 3 files changed, 6 insertions(+), 9 deletions(-)
-
-diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
-index eb431b5..b9a7833 100644
---- a/drivers/pci/pci.c
-+++ b/drivers/pci/pci.c
-@@ -4941,7 +4941,7 @@ int pci_get_new_domain_nr(void)
- }
-
- #ifdef CONFIG_PCI_DOMAINS_GENERIC
--void pci_bus_assign_domain_nr(struct pci_bus *bus, struct device *parent)
-+int pci_bus_find_domain_nr(struct pci_bus *bus, struct device *parent)
- {
- static int use_dt_domains = -1;
- int domain = -1;
-@@ -4985,7 +4985,7 @@ void pci_bus_assign_domain_nr(struct pci_bus *bus, struct device *parent)
- domain = -1;
- }
-
-- bus->domain_nr = domain;
-+ return domain;
- }
- #endif
- #endif
-diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
-index 8e3ef72..380d46d 100644
---- a/drivers/pci/probe.c
-+++ b/drivers/pci/probe.c
-@@ -2127,7 +2127,9 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
- b->sysdata = sysdata;
- b->ops = ops;
- b->number = b->busn_res.start = bus;
-- pci_bus_assign_domain_nr(b, parent);
-+#ifdef CONFIG_PCI_DOMAINS_GENERIC
-+ b->domain_nr = pci_bus_find_domain_nr(b, parent);
-+#endif
- b2 = pci_find_bus(pci_domain_nr(b), bus);
- if (b2) {
- /* If we already got to this bus through a different bridge, ignore it */
-diff --git a/include/linux/pci.h b/include/linux/pci.h
-index ce03d65..48839e8 100644
---- a/include/linux/pci.h
-+++ b/include/linux/pci.h
-@@ -1390,12 +1390,7 @@ static inline int pci_domain_nr(struct pci_bus *bus)
- {
- return bus->domain_nr;
- }
--void pci_bus_assign_domain_nr(struct pci_bus *bus, struct device *parent);
--#else
--static inline void pci_bus_assign_domain_nr(struct pci_bus *bus,
-- struct device *parent)
--{
--}
-+int pci_bus_find_domain_nr(struct pci_bus *bus, struct device *parent);
- #endif
-
- /* some architectures require additional setup to direct VGA traffic */
---
-2.7.4
-
-From d6d45ae1d58658111d5e838c41b9ed4729bbb81e Mon Sep 17 00:00:00 2001
-From: Tomasz Nowicki <tn@semihalf.com>
-Date: Fri, 10 Jun 2016 21:55:15 +0200
-Subject: [PATCH 07/11] PCI: Factor DT specific pci_bus_find_domain_nr() code
- out
-
-pci_bus_find_domain_nr() retrieves the host bridge domain number in a DT
-specific way. Factor our pci_bus_find_domain_nr() in a separate DT
-function (ie of_pci_bus_find_domain_nr()) so that DT code is self
-contained, paving the way for retrieving domain number in
-pci_bus_find_domain_nr() with additional firmware methods (ie ACPI).
-
-Signed-off-by: Tomasz Nowicki <tn@semihalf.com>
-Reviewed-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
----
- drivers/pci/pci.c | 7 ++++++-
- 1 file changed, 6 insertions(+), 1 deletion(-)
-
-diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
-index b9a7833..97f7cd4 100644
---- a/drivers/pci/pci.c
-+++ b/drivers/pci/pci.c
-@@ -4941,7 +4941,7 @@ int pci_get_new_domain_nr(void)
- }
-
- #ifdef CONFIG_PCI_DOMAINS_GENERIC
--int pci_bus_find_domain_nr(struct pci_bus *bus, struct device *parent)
-+static int of_pci_bus_find_domain_nr(struct device *parent)
- {
- static int use_dt_domains = -1;
- int domain = -1;
-@@ -4987,6 +4987,11 @@ int pci_bus_find_domain_nr(struct pci_bus *bus, struct device *parent)
-
- return domain;
- }
-+
-+int pci_bus_find_domain_nr(struct pci_bus *bus, struct device *parent)
-+{
-+ return of_pci_bus_find_domain_nr(parent);
-+}
- #endif
- #endif
-
---
-2.7.4
-
-From 92d59511fd365d3c0c31d074b5e96cf48c58f68b Mon Sep 17 00:00:00 2001
-From: Peter Robinson <pbrobinson@gmail.com>
-Date: Thu, 30 Jun 2016 16:56:24 +0100
-Subject: [PATCH 08/11] ARM64/PCI: Add ACPI hook to assign domain number
-
-PCI core code provides a config option (CONFIG_PCI_DOMAINS_GENERIC)
-that allows assigning the PCI bus domain number generically by
-relying on device tree bindings, and falling back to a simple counter
-when the respective DT properties (ie "linux,pci-domain") are not
-specified in the host bridge device tree node.
-
-In a similar way, when a system is booted through ACPI, architectures
-that are selecting CONFIG_PCI_DOMAINS_GENERIC (ie ARM64) require kernel
-hooks to retrieve the domain number so that the PCI bus domain number
-set-up can be handled seamlessly with DT and ACPI in generic core code
-when CONFIG_PCI_DOMAINS_GENERIC is selected.
-
-Since currently it is not possible to retrieve a pointer to the PCI
-host bridge ACPI device backing the host bridge from core PCI code
-(which would allow retrieving the domain number in an arch agnostic
-way through the ACPI _SEG method), an arch specific ACPI hook has to
-be declared and implemented by all arches that rely on
-CONFIG_PCI_DOMAINS_GENERIC to retrieve the domain number and set it
-up in core PCI code.
-
-For the aforementioned reasons, introduce acpi_pci_bus_find_domain_nr()
-hook to retrieve the domain number on a per-arch basis when the system
-boots through ACPI. ARM64 dummy implementation of the same is provided
-in first place in preparation for ARM64 ACPI based PCI host controller
-driver.
-
-acpi_pci_bus_find_domain_nr() is called from generic
-pci_bus_find_domain_nr() as an ACPI option to DT domain assignment.
-
-Signed-off-by: Tomasz Nowicki <tn@semihalf.com>
-Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
----
- arch/arm64/kernel/pci.c | 7 +++++++
- drivers/pci/pci.c | 4 +++-
- include/linux/pci.h | 7 +++++++
- 3 files changed, 17 insertions(+), 1 deletion(-)
-
-diff --git a/arch/arm64/kernel/pci.c b/arch/arm64/kernel/pci.c
-index 3c4e308..d5d3d26 100644
---- a/arch/arm64/kernel/pci.c
-+++ b/arch/arm64/kernel/pci.c
-@@ -17,6 +17,7 @@
- #include <linux/mm.h>
- #include <linux/of_pci.h>
- #include <linux/of_platform.h>
-+#include <linux/pci.h>
- #include <linux/slab.h>
-
- /*
-@@ -85,6 +86,12 @@ EXPORT_SYMBOL(pcibus_to_node);
- #endif
-
- #ifdef CONFIG_ACPI
-+
-+int acpi_pci_bus_find_domain_nr(struct pci_bus *bus)
-+{
-+ return 0;
-+}
-+
- /* Root bridge scanning */
- struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
- {
-diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
-index 97f7cd4..4834cee 100644
---- a/drivers/pci/pci.c
-+++ b/drivers/pci/pci.c
-@@ -7,6 +7,7 @@
- * Copyright 1997 -- 2000 Martin Mares <mj@ucw.cz>
- */
-
-+#include <linux/acpi.h>
- #include <linux/kernel.h>
- #include <linux/delay.h>
- #include <linux/init.h>
-@@ -4990,7 +4991,8 @@ static int of_pci_bus_find_domain_nr(struct device *parent)
-
- int pci_bus_find_domain_nr(struct pci_bus *bus, struct device *parent)
- {
-- return of_pci_bus_find_domain_nr(parent);
-+ return acpi_disabled ? of_pci_bus_find_domain_nr(parent) :
-+ acpi_pci_bus_find_domain_nr(bus);
- }
- #endif
- #endif
-diff --git a/include/linux/pci.h b/include/linux/pci.h
-index 48839e8..49ba8af 100644
---- a/include/linux/pci.h
-+++ b/include/linux/pci.h
-@@ -1390,6 +1390,13 @@ static inline int pci_domain_nr(struct pci_bus *bus)
- {
- return bus->domain_nr;
- }
-+/* Arch specific ACPI hook to set-up domain number */
-+#ifdef CONFIG_ACPI
-+int acpi_pci_bus_find_domain_nr(struct pci_bus *bus);
-+#else
-+static inline int acpi_pci_bus_find_domain_nr(struct pci_bus *bus)
-+{ return 0; }
-+#endif
- int pci_bus_find_domain_nr(struct pci_bus *bus, struct device *parent);
- #endif
-
---
-2.7.4
-
-From bb06753d2e163d8100a017f06a6d9dd195d68a76 Mon Sep 17 00:00:00 2001
-From: Tomasz Nowicki <tn@semihalf.com>
-Date: Fri, 10 Jun 2016 21:55:17 +0200
-Subject: [PATCH 09/11] ARM64/PCI: ACPI support for legacy IRQs parsing and
- consolidation with DT code
-
-To enable PCI legacy IRQs on platforms booting with ACPI, arch code
-should include ACPI specific callbacks that parse and set-up the
-device IRQ number, equivalent to the DT boot path. Owing to the current
-ACPI core scan handlers implementation, ACPI PCI legacy IRQs bindings
-cannot be parsed at device add time, since that would trigger ACPI scan
-handlers ordering issues depending on how the ACPI tables are defined.
-
-To solve this problem and consolidate FW PCI legacy IRQs parsing in
-one single pcibios callback (pending final removal), this patch moves
-DT PCI IRQ parsing to the pcibios_alloc_irq() callback (called by
-PCI core code at device probe time) and adds ACPI PCI legacy IRQs
-parsing to the same callback too, so that FW PCI legacy IRQs parsing
-is confined in one single arch callback that can be easily removed
-when code parsing PCI legacy IRQs is consolidated and moved to core
-PCI code.
-
-Signed-off-by: Tomasz Nowicki <tn@semihalf.com>
-Suggested-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
----
- arch/arm64/kernel/pci.c | 11 ++++++++---
- 1 file changed, 8 insertions(+), 3 deletions(-)
-
-diff --git a/arch/arm64/kernel/pci.c b/arch/arm64/kernel/pci.c
-index d5d3d26..b3b8a2c 100644
---- a/arch/arm64/kernel/pci.c
-+++ b/arch/arm64/kernel/pci.c
-@@ -51,11 +51,16 @@ int pcibios_enable_device(struct pci_dev *dev, int mask)
- }
-
- /*
-- * Try to assign the IRQ number from DT when adding a new device
-+ * Try to assign the IRQ number when probing a new device
- */
--int pcibios_add_device(struct pci_dev *dev)
-+int pcibios_alloc_irq(struct pci_dev *dev)
- {
-- dev->irq = of_irq_parse_and_map_pci(dev, 0, 0);
-+ if (acpi_disabled)
-+ dev->irq = of_irq_parse_and_map_pci(dev, 0, 0);
-+#ifdef CONFIG_ACPI
-+ else
-+ return acpi_pci_irq_enable(dev);
-+#endif
-
- return 0;
- }
---
-2.7.4
-
-From b6e298840f532192a589f8ade128dec3fef3a4c6 Mon Sep 17 00:00:00 2001
-From: Tomasz Nowicki <tn@semihalf.com>
-Date: Fri, 10 Jun 2016 21:55:18 +0200
-Subject: [PATCH 10/11] ARM64/PCI: Implement ACPI low-level calls to access
- PCI_Config region from AML
-
-ACPI spec6.1 - chapter: 5.5.2.4 defines OperationRegion (Declare Operation
-Region). Following the spec: " [...] An Operation Region is a specific
-region of operation within an address space that is declared as a subset
-of the entire address space using a starting address (offset) and a length.
-Control methods must have exclusive access to any address accessed via
-fields declared in Operation Regions. [...]".
-
-OperationRegion allows to declare various of operation region address space
-identifiers including PCI_Config. PCI_Config is meant to access PCI
-configuration space from the ASL. So every time ASL opcode operates
-on PCI_Config space region, ASL interpreter dispatches accesses to OS
-low-level calls - raw_pci_write() and raw_pci_read() for Linux - so-called
-ACPI RAW accessors.
-
-In order to support PCI_Config operation region, implement mentioned
-raw_pci_write() and raw_pci_read() calls so they find associated bus
-and call read/write ops.
-
-Waiting for clarification in the ACPI specifications in relation
-to PCI_Config space handling before PCI bus enumeration is completed,
-current code does not support PCI_Config region accesses before PCI bus
-enumeration whilst providing full AML PCI_Config access availability
-when the PCI bus enumeration is completed by the kernel so that
-RAW accessors can look-up PCI operations through the struct pci_bus
-associated with a PCI bus.
-
-Signed-off-by: Tomasz Nowicki <tn@semihalf.com>
-Signed-off-by: Jayachandran C <jchandra@broadcom.com>
-Reviewed-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
----
- arch/arm64/kernel/pci.c | 12 ++++++++++--
- 1 file changed, 10 insertions(+), 2 deletions(-)
-
-diff --git a/arch/arm64/kernel/pci.c b/arch/arm64/kernel/pci.c
-index b3b8a2c..328f857 100644
---- a/arch/arm64/kernel/pci.c
-+++ b/arch/arm64/kernel/pci.c
-@@ -71,13 +71,21 @@ int pcibios_alloc_irq(struct pci_dev *dev)
- int raw_pci_read(unsigned int domain, unsigned int bus,
- unsigned int devfn, int reg, int len, u32 *val)
- {
-- return -ENXIO;
-+ struct pci_bus *b = pci_find_bus(domain, bus);
-+
-+ if (!b)
-+ return PCIBIOS_DEVICE_NOT_FOUND;
-+ return b->ops->read(b, devfn, reg, len, val);
- }
-
- int raw_pci_write(unsigned int domain, unsigned int bus,
- unsigned int devfn, int reg, int len, u32 val)
- {
-- return -ENXIO;
-+ struct pci_bus *b = pci_find_bus(domain, bus);
-+
-+ if (!b)
-+ return PCIBIOS_DEVICE_NOT_FOUND;
-+ return b->ops->write(b, devfn, reg, len, val);
- }
-
- #ifdef CONFIG_NUMA
---
-2.7.4
-
-From 3b8cff3fa89ba3ef6f1cf09a0667aa470b7fad0b Mon Sep 17 00:00:00 2001
-From: Tomasz Nowicki <tn@semihalf.com>
-Date: Fri, 10 Jun 2016 21:55:19 +0200
-Subject: [PATCH 11/11] ARM64/PCI: Support for ACPI based PCI host controller
-
-Implement pci_acpi_scan_root and other arch-specific call so that ARM64
-can start using ACPI to setup and enumerate PCI buses.
-
-Prior to buses enumeration the pci_acpi_scan_root() implementation looks
-for configuration space start address (obtained through ACPI _CBA method or
-MCFG interface). If succeed, it uses ECAM library to create new mapping.
-Then it attaches generic ECAM ops (pci_generic_ecam_ops) which are used
-for accessing configuration space later on.
-
-On ARM64, we need to use generic domains (CONFIG_PCI_DOMAINS_GENERIC).
-In order to achieve that for ACPI case implement
-acpi_pci_bus_find_domain_nr() body so that it retrieves pci_config_window
-structure from bus sysdata and eventually gets domain number from
-acpi_pci_root structure.
-
-ACPI requires to run acpi_pci_{add|remove}_bus while new PCI bus is created.
-This allows to do some ACPI-specific additional configuration, like
-PCI hotplug slot enumeration. In order to fulfill these requirements,
-we implement arch-specific pcibios_{add|remove}_bus calls
-and call acpi_pci_{add|remove}_bus from there.
-
-Signed-off-by: Tomasz Nowicki <tn@semihalf.com>
-Signed-off-by: Jayachandran C <jchandra@broadcom.com>
-Reviewed-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
----
- arch/arm64/Kconfig | 2 +
- arch/arm64/kernel/pci.c | 116 ++++++++++++++++++++++++++++++++++++++++++++++--
- 2 files changed, 115 insertions(+), 3 deletions(-)
-
-diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
-index 5a0a691..4806cde 100644
---- a/arch/arm64/Kconfig
-+++ b/arch/arm64/Kconfig
-@@ -3,6 +3,7 @@ config ARM64
- select ACPI_CCA_REQUIRED if ACPI
- select ACPI_GENERIC_GSI if ACPI
- select ACPI_REDUCED_HARDWARE_ONLY if ACPI
-+ select ACPI_MCFG if ACPI
- select ARCH_HAS_DEVMEM_IS_ALLOWED
- select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
- select ARCH_HAS_ELF_RANDOMIZE
-@@ -96,6 +97,7 @@ config ARM64
- select OF_EARLY_FLATTREE
- select OF_NUMA if NUMA && OF
- select OF_RESERVED_MEM
-+ select PCI_ECAM if ACPI
- select PERF_USE_VMALLOC
- select POWER_RESET
- select POWER_SUPPLY
-diff --git a/arch/arm64/kernel/pci.c b/arch/arm64/kernel/pci.c
-index 328f857..94cd43c 100644
---- a/arch/arm64/kernel/pci.c
-+++ b/arch/arm64/kernel/pci.c
-@@ -18,6 +18,8 @@
- #include <linux/of_pci.h>
- #include <linux/of_platform.h>
- #include <linux/pci.h>
-+#include <linux/pci-acpi.h>
-+#include <linux/pci-ecam.h>
- #include <linux/slab.h>
-
- /*
-@@ -100,15 +102,123 @@ EXPORT_SYMBOL(pcibus_to_node);
-
- #ifdef CONFIG_ACPI
-
-+struct acpi_pci_generic_root_info {
-+ struct acpi_pci_root_info common;
-+ struct pci_config_window *cfg; /* config space mapping */
-+};
-+
- int acpi_pci_bus_find_domain_nr(struct pci_bus *bus)
- {
-+ struct pci_config_window *cfg = bus->sysdata;
-+ struct acpi_device *adev = to_acpi_device(cfg->parent);
-+ struct acpi_pci_root *root = acpi_driver_data(adev);
-+
-+ return root->segment;
-+}
-+
-+int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
-+{
-+ if (!acpi_disabled) {
-+ struct pci_config_window *cfg = bridge->bus->sysdata;
-+ struct acpi_device *adev = to_acpi_device(cfg->parent);
-+ ACPI_COMPANION_SET(&bridge->dev, adev);
-+ }
-+
- return 0;
- }
-
--/* Root bridge scanning */
-+/*
-+ * Lookup the bus range for the domain in MCFG, and set up config space
-+ * mapping.
-+ */
-+static struct pci_config_window *
-+pci_acpi_setup_ecam_mapping(struct acpi_pci_root *root)
-+{
-+ struct resource *bus_res = &root->secondary;
-+ u16 seg = root->segment;
-+ struct pci_config_window *cfg;
-+ struct resource cfgres;
-+ unsigned int bsz;
-+
-+ /* Use address from _CBA if present, otherwise lookup MCFG */
-+ if (!root->mcfg_addr)
-+ root->mcfg_addr = pci_mcfg_lookup(seg, bus_res);
-+
-+ if (!root->mcfg_addr) {
-+ dev_err(&root->device->dev, "%04x:%pR ECAM region not found\n",
-+ seg, bus_res);
-+ return NULL;
-+ }
-+
-+ bsz = 1 << pci_generic_ecam_ops.bus_shift;
-+ cfgres.start = root->mcfg_addr + bus_res->start * bsz;
-+ cfgres.end = cfgres.start + resource_size(bus_res) * bsz - 1;
-+ cfgres.flags = IORESOURCE_MEM;
-+ cfg = pci_ecam_create(&root->device->dev, &cfgres, bus_res,
-+ &pci_generic_ecam_ops);
-+ if (IS_ERR(cfg)) {
-+ dev_err(&root->device->dev, "%04x:%pR error %ld mapping ECAM\n",
-+ seg, bus_res, PTR_ERR(cfg));
-+ return NULL;
-+ }
-+
-+ return cfg;
-+}
-+
-+/* release_info: free resources allocated by init_info */
-+static void pci_acpi_generic_release_info(struct acpi_pci_root_info *ci)
-+{
-+ struct acpi_pci_generic_root_info *ri;
-+
-+ ri = container_of(ci, struct acpi_pci_generic_root_info, common);
-+ pci_ecam_free(ri->cfg);
-+ kfree(ri);
-+}
-+
-+static struct acpi_pci_root_ops acpi_pci_root_ops = {
-+ .release_info = pci_acpi_generic_release_info,
-+};
-+
-+/* Interface called from ACPI code to setup PCI host controller */
- struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
- {
-- /* TODO: Should be revisited when implementing PCI on ACPI */
-- return NULL;
-+ int node = acpi_get_node(root->device->handle);
-+ struct acpi_pci_generic_root_info *ri;
-+ struct pci_bus *bus, *child;
-+
-+ ri = kzalloc_node(sizeof(*ri), GFP_KERNEL, node);
-+ if (!ri)
-+ return NULL;
-+
-+ ri->cfg = pci_acpi_setup_ecam_mapping(root);
-+ if (!ri->cfg) {
-+ kfree(ri);
-+ return NULL;
-+ }
-+
-+ acpi_pci_root_ops.pci_ops = &ri->cfg->ops->pci_ops;
-+ bus = acpi_pci_root_create(root, &acpi_pci_root_ops, &ri->common,
-+ ri->cfg);
-+ if (!bus)
-+ return NULL;
-+
-+ pci_bus_size_bridges(bus);
-+ pci_bus_assign_resources(bus);
-+
-+ list_for_each_entry(child, &bus->children, node)
-+ pcie_bus_configure_settings(child);
-+
-+ return bus;
-+}
-+
-+void pcibios_add_bus(struct pci_bus *bus)
-+{
-+ acpi_pci_add_bus(bus);
- }
-+
-+void pcibios_remove_bus(struct pci_bus *bus)
-+{
-+ acpi_pci_remove_bus(bus);
-+}
-+
- #endif
---
-2.7.4
-