Add aarch64 ACPI pci-e patches headed for 4.8
This commit is contained in:
parent
7a27e68a31
commit
a84c0224bb
1247
arm64-pcie-acpi.patch
Normal file
1247
arm64-pcie-acpi.patch
Normal file
File diff suppressed because it is too large
Load Diff
508
arm64-pcie-quirks-xgene.patch
Normal file
508
arm64-pcie-quirks-xgene.patch
Normal file
@ -0,0 +1,508 @@
|
||||
From 767b70aa55d013f0c7589955f410d488fed5776a Mon Sep 17 00:00:00 2001
|
||||
From: Peter Robinson <pbrobinson@gmail.com>
|
||||
Date: Tue, 5 Jul 2016 23:49:39 +0100
|
||||
Subject: [PATCH 1/4] Some platforms may not be fully compliant with generic
|
||||
set of PCI config accessors. For these cases we implement the way to
|
||||
overwrite accessors set. Algorithm traverses available quirk list, matches
|
||||
against <oem_id, oem_table_id, domain, bus number> tuple and returns
|
||||
corresponding PCI config ops. oem_id and oem_table_id come from MCFG table
|
||||
standard header. All quirks can be defined using DECLARE_ACPI_MCFG_FIXUP()
|
||||
macro and kept self contained. Example:
|
||||
|
||||
/* Custom PCI config ops */
|
||||
static struct pci_generic_ecam_ops foo_pci_ops = {
|
||||
.bus_shift = 24,
|
||||
.pci_ops = {
|
||||
.map_bus = pci_ecam_map_bus,
|
||||
.read = foo_ecam_config_read,
|
||||
.write = foo_ecam_config_write,
|
||||
}
|
||||
};
|
||||
|
||||
DECLARE_ACPI_MCFG_FIXUP(&foo_pci_ops, <oem_id_str>, <oem_table_id>, <domain_nr>, <bus_nr>);
|
||||
|
||||
Signed-off-by: Tomasz Nowicki <tn@semihalf.com>
|
||||
Signed-off-by: Dongdong Liu <liudongdong3@huawei.com>
|
||||
---
|
||||
drivers/acpi/pci_mcfg.c | 41 ++++++++++++++++++++++++++++++++++++---
|
||||
include/asm-generic/vmlinux.lds.h | 7 +++++++
|
||||
include/linux/pci-acpi.h | 20 +++++++++++++++++++
|
||||
3 files changed, 65 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/drivers/acpi/pci_mcfg.c b/drivers/acpi/pci_mcfg.c
|
||||
index d3c3e85..deb0077 100644
|
||||
--- a/drivers/acpi/pci_mcfg.c
|
||||
+++ b/drivers/acpi/pci_mcfg.c
|
||||
@@ -22,6 +22,10 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/pci-acpi.h>
|
||||
+#include <linux/pci-ecam.h>
|
||||
+
|
||||
+/* Root pointer to the mapped MCFG table */
|
||||
+static struct acpi_table_mcfg *mcfg_table;
|
||||
|
||||
/* Structure to hold entries from the MCFG table */
|
||||
struct mcfg_entry {
|
||||
@@ -35,6 +39,38 @@ struct mcfg_entry {
|
||||
/* List to save mcfg entries */
|
||||
static LIST_HEAD(pci_mcfg_list);
|
||||
|
||||
+extern struct pci_cfg_fixup __start_acpi_mcfg_fixups[];
|
||||
+extern struct pci_cfg_fixup __end_acpi_mcfg_fixups[];
|
||||
+
|
||||
+struct pci_ecam_ops *pci_mcfg_get_ops(struct acpi_pci_root *root)
|
||||
+{
|
||||
+ int bus_num = root->secondary.start;
|
||||
+ int domain = root->segment;
|
||||
+ struct pci_cfg_fixup *f;
|
||||
+
|
||||
+ if (!mcfg_table)
|
||||
+ return &pci_generic_ecam_ops;
|
||||
+
|
||||
+ /*
|
||||
+ * Match against platform specific quirks and return corresponding
|
||||
+ * CAM ops.
|
||||
+ *
|
||||
+ * First match against PCI topology <domain:bus> then use OEM ID and
|
||||
+ * OEM revision from MCFG table standard header.
|
||||
+ */
|
||||
+ for (f = __start_acpi_mcfg_fixups; f < __end_acpi_mcfg_fixups; f++) {
|
||||
+ if ((f->domain == domain || f->domain == PCI_MCFG_DOMAIN_ANY) &&
|
||||
+ (f->bus_num == bus_num || f->bus_num == PCI_MCFG_BUS_ANY) &&
|
||||
+ (!strncmp(f->oem_id, mcfg_table->header.oem_id,
|
||||
+ ACPI_OEM_ID_SIZE)) &&
|
||||
+ (!strncmp(f->oem_table_id, mcfg_table->header.oem_table_id,
|
||||
+ ACPI_OEM_TABLE_ID_SIZE)))
|
||||
+ return f->ops;
|
||||
+ }
|
||||
+ /* No quirks, use ECAM */
|
||||
+ return &pci_generic_ecam_ops;
|
||||
+}
|
||||
+
|
||||
phys_addr_t pci_mcfg_lookup(u16 seg, struct resource *bus_res)
|
||||
{
|
||||
struct mcfg_entry *e;
|
||||
@@ -54,7 +90,6 @@ phys_addr_t pci_mcfg_lookup(u16 seg, struct resource *bus_res)
|
||||
|
||||
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;
|
||||
@@ -64,8 +99,8 @@ static __init int pci_mcfg_parse(struct acpi_table_header *header)
|
||||
|
||||
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];
|
||||
+ mcfg_table = (struct acpi_table_mcfg *)header;
|
||||
+ mptr = (struct acpi_mcfg_allocation *) &mcfg_table[1];
|
||||
|
||||
arr = kcalloc(n, sizeof(*arr), GFP_KERNEL);
|
||||
if (!arr)
|
||||
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
|
||||
index 6a67ab9..43604fc 100644
|
||||
--- a/include/asm-generic/vmlinux.lds.h
|
||||
+++ b/include/asm-generic/vmlinux.lds.h
|
||||
@@ -300,6 +300,13 @@
|
||||
VMLINUX_SYMBOL(__end_pci_fixups_suspend_late) = .; \
|
||||
} \
|
||||
\
|
||||
+ /* ACPI MCFG quirks */ \
|
||||
+ .acpi_fixup : AT(ADDR(.acpi_fixup) - LOAD_OFFSET) { \
|
||||
+ VMLINUX_SYMBOL(__start_acpi_mcfg_fixups) = .; \
|
||||
+ *(.acpi_fixup_mcfg) \
|
||||
+ VMLINUX_SYMBOL(__end_acpi_mcfg_fixups) = .; \
|
||||
+ } \
|
||||
+ \
|
||||
/* Built-in firmware blobs */ \
|
||||
.builtin_fw : AT(ADDR(.builtin_fw) - LOAD_OFFSET) { \
|
||||
VMLINUX_SYMBOL(__start_builtin_fw) = .; \
|
||||
diff --git a/include/linux/pci-acpi.h b/include/linux/pci-acpi.h
|
||||
index 7d63a66..c8a6559 100644
|
||||
--- a/include/linux/pci-acpi.h
|
||||
+++ b/include/linux/pci-acpi.h
|
||||
@@ -25,6 +25,7 @@ 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);
|
||||
+extern struct pci_ecam_ops *pci_mcfg_get_ops(struct acpi_pci_root *root);
|
||||
|
||||
static inline acpi_handle acpi_find_root_bridge_handle(struct pci_dev *pdev)
|
||||
{
|
||||
@@ -72,6 +73,25 @@ struct acpi_pci_root_ops {
|
||||
int (*prepare_resources)(struct acpi_pci_root_info *info);
|
||||
};
|
||||
|
||||
+struct pci_cfg_fixup {
|
||||
+ struct pci_ecam_ops *ops;
|
||||
+ char *oem_id;
|
||||
+ char *oem_table_id;
|
||||
+ int domain;
|
||||
+ int bus_num;
|
||||
+};
|
||||
+
|
||||
+#define PCI_MCFG_DOMAIN_ANY -1
|
||||
+#define PCI_MCFG_BUS_ANY -1
|
||||
+
|
||||
+/* Designate a routine to fix up buggy MCFG */
|
||||
+#define DECLARE_ACPI_MCFG_FIXUP(ops, oem_id, oem_table_id, dom, bus) \
|
||||
+ static const struct pci_cfg_fixup \
|
||||
+ __mcfg_fixup_##oem_id##oem_table_id##dom##bus \
|
||||
+ __used __attribute__((__section__(".acpi_fixup_mcfg"), \
|
||||
+ aligned((sizeof(void *))))) = \
|
||||
+ { ops, oem_id, oem_table_id, dom, bus };
|
||||
+
|
||||
extern int acpi_pci_probe_root_resources(struct acpi_pci_root_info *info);
|
||||
extern struct pci_bus *acpi_pci_root_create(struct acpi_pci_root *root,
|
||||
struct acpi_pci_root_ops *ops,
|
||||
--
|
||||
2.7.4
|
||||
|
||||
From 4f86a9b006b25dd7336043dab26058ed6fb2802d Mon Sep 17 00:00:00 2001
|
||||
From: Peter Robinson <pbrobinson@gmail.com>
|
||||
Date: Tue, 5 Jul 2016 23:52:46 +0100
|
||||
Subject: [PATCH 2/4] pci_generic_ecam_ops is used by default. Since there are
|
||||
platforms which have non-compliant ECAM space we need to overwrite these
|
||||
accessors prior to PCI buses enumeration. In order to do that we call
|
||||
pci_mcfg_get_ops to retrieve pci_ecam_ops structure so that we can use proper
|
||||
PCI config space accessors and bus_shift.
|
||||
|
||||
pci_generic_ecam_ops is still used for platforms free from quirks.
|
||||
|
||||
Signed-off-by: Tomasz Nowicki <tn@semihalf.com>
|
||||
---
|
||||
arch/arm64/kernel/pci.c | 7 ++++---
|
||||
1 file changed, 4 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/arch/arm64/kernel/pci.c b/arch/arm64/kernel/pci.c
|
||||
index 94cd43c..a891bda 100644
|
||||
--- a/arch/arm64/kernel/pci.c
|
||||
+++ b/arch/arm64/kernel/pci.c
|
||||
@@ -139,6 +139,7 @@ pci_acpi_setup_ecam_mapping(struct acpi_pci_root *root)
|
||||
struct pci_config_window *cfg;
|
||||
struct resource cfgres;
|
||||
unsigned int bsz;
|
||||
+ struct pci_ecam_ops *ops;
|
||||
|
||||
/* Use address from _CBA if present, otherwise lookup MCFG */
|
||||
if (!root->mcfg_addr)
|
||||
@@ -150,12 +151,12 @@ pci_acpi_setup_ecam_mapping(struct acpi_pci_root *root)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
- bsz = 1 << pci_generic_ecam_ops.bus_shift;
|
||||
+ ops = pci_mcfg_get_ops(root);
|
||||
+ bsz = 1 << 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);
|
||||
+ cfg = pci_ecam_create(&root->device->dev, &cfgres, bus_res, ops);
|
||||
if (IS_ERR(cfg)) {
|
||||
dev_err(&root->device->dev, "%04x:%pR error %ld mapping ECAM\n",
|
||||
seg, bus_res, PTR_ERR(cfg));
|
||||
--
|
||||
2.7.4
|
||||
|
||||
From cbdbd697bd6d716eb9d1705ee55445432e73eabb Mon Sep 17 00:00:00 2001
|
||||
From: Peter Robinson <pbrobinson@gmail.com>
|
||||
Date: Tue, 5 Jul 2016 23:53:59 +0100
|
||||
Subject: [PATCH 3/4] The ECAM quirk matching criteria per the discussion on
|
||||
https://lkml.org/lkml/2016/6/13/944 includes: OEM ID, OEM Table ID and OEM
|
||||
Revision. So this patch adds OEM Table ID into the check to match platform
|
||||
specific ECAM quirks as well.
|
||||
|
||||
This patch also improve strncmp check using strlen and
|
||||
min_t to ignore the padding spaces in OEM ID and OEM
|
||||
Table ID.
|
||||
|
||||
Signed-off-by: Duc Dang <dhdang@apm.com>
|
||||
---
|
||||
drivers/acpi/pci_mcfg.c | 7 +++++--
|
||||
include/linux/pci-acpi.h | 7 ++++---
|
||||
2 files changed, 9 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/drivers/acpi/pci_mcfg.c b/drivers/acpi/pci_mcfg.c
|
||||
index deb0077..307ca9a 100644
|
||||
--- a/drivers/acpi/pci_mcfg.c
|
||||
+++ b/drivers/acpi/pci_mcfg.c
|
||||
@@ -62,9 +62,12 @@ struct pci_ecam_ops *pci_mcfg_get_ops(struct acpi_pci_root *root)
|
||||
if ((f->domain == domain || f->domain == PCI_MCFG_DOMAIN_ANY) &&
|
||||
(f->bus_num == bus_num || f->bus_num == PCI_MCFG_BUS_ANY) &&
|
||||
(!strncmp(f->oem_id, mcfg_table->header.oem_id,
|
||||
- ACPI_OEM_ID_SIZE)) &&
|
||||
+ min_t(size_t, strlen(f->oem_id),
|
||||
+ ACPI_OEM_ID_SIZE))) &&
|
||||
(!strncmp(f->oem_table_id, mcfg_table->header.oem_table_id,
|
||||
- ACPI_OEM_TABLE_ID_SIZE)))
|
||||
+ min_t(size_t, strlen(f->oem_table_id),
|
||||
+ ACPI_OEM_TABLE_ID_SIZE))) &&
|
||||
+ (f->oem_revision == mcfg_table->header.oem_revision))
|
||||
return f->ops;
|
||||
}
|
||||
/* No quirks, use ECAM */
|
||||
diff --git a/include/linux/pci-acpi.h b/include/linux/pci-acpi.h
|
||||
index c8a6559..5148c8d 100644
|
||||
--- a/include/linux/pci-acpi.h
|
||||
+++ b/include/linux/pci-acpi.h
|
||||
@@ -77,6 +77,7 @@ struct pci_cfg_fixup {
|
||||
struct pci_ecam_ops *ops;
|
||||
char *oem_id;
|
||||
char *oem_table_id;
|
||||
+ u32 oem_revision;
|
||||
int domain;
|
||||
int bus_num;
|
||||
};
|
||||
@@ -85,12 +86,12 @@ struct pci_cfg_fixup {
|
||||
#define PCI_MCFG_BUS_ANY -1
|
||||
|
||||
/* Designate a routine to fix up buggy MCFG */
|
||||
-#define DECLARE_ACPI_MCFG_FIXUP(ops, oem_id, oem_table_id, dom, bus) \
|
||||
+#define DECLARE_ACPI_MCFG_FIXUP(ops, oem_id, oem_table_id, rev, dom, bus) \
|
||||
static const struct pci_cfg_fixup \
|
||||
- __mcfg_fixup_##oem_id##oem_table_id##dom##bus \
|
||||
+ __mcfg_fixup_##oem_id##oem_table_id##rev##dom##bus \
|
||||
__used __attribute__((__section__(".acpi_fixup_mcfg"), \
|
||||
aligned((sizeof(void *))))) = \
|
||||
- { ops, oem_id, oem_table_id, dom, bus };
|
||||
+ { ops, oem_id, oem_table_id, rev, dom, bus };
|
||||
|
||||
extern int acpi_pci_probe_root_resources(struct acpi_pci_root_info *info);
|
||||
extern struct pci_bus *acpi_pci_root_create(struct acpi_pci_root *root,
|
||||
--
|
||||
2.7.4
|
||||
|
||||
From 78766cf255bc6aafac2f57372a0446f78322da19 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Robinson <pbrobinson@gmail.com>
|
||||
Date: Tue, 5 Jul 2016 23:55:11 +0100
|
||||
Subject: [PATCH 4/4] X-Gene PCIe controller does not fully support ECAM. This
|
||||
patch adds required ECAM fixup to allow X-Gene PCIe controller to be
|
||||
functional in ACPI boot mode.
|
||||
|
||||
Signed-off-by: Duc Dang <dhdang@apm.com>
|
||||
---
|
||||
drivers/pci/host/Makefile | 2 +-
|
||||
drivers/pci/host/pci-xgene-ecam.c | 194 ++++++++++++++++++++++++++++++++++++++
|
||||
2 files changed, 195 insertions(+), 1 deletion(-)
|
||||
create mode 100644 drivers/pci/host/pci-xgene-ecam.c
|
||||
|
||||
diff --git a/drivers/pci/host/Makefile b/drivers/pci/host/Makefile
|
||||
index 9c8698e..3480696 100644
|
||||
--- a/drivers/pci/host/Makefile
|
||||
+++ b/drivers/pci/host/Makefile
|
||||
@@ -14,7 +14,7 @@ obj-$(CONFIG_PCIE_SPEAR13XX) += pcie-spear13xx.o
|
||||
obj-$(CONFIG_PCI_KEYSTONE) += pci-keystone-dw.o pci-keystone.o
|
||||
obj-$(CONFIG_PCIE_XILINX) += pcie-xilinx.o
|
||||
obj-$(CONFIG_PCIE_XILINX_NWL) += pcie-xilinx-nwl.o
|
||||
-obj-$(CONFIG_PCI_XGENE) += pci-xgene.o
|
||||
+obj-$(CONFIG_PCI_XGENE) += pci-xgene.o pci-xgene-ecam.o
|
||||
obj-$(CONFIG_PCI_XGENE_MSI) += pci-xgene-msi.o
|
||||
obj-$(CONFIG_PCI_LAYERSCAPE) += pci-layerscape.o
|
||||
obj-$(CONFIG_PCI_VERSATILE) += pci-versatile.o
|
||||
diff --git a/drivers/pci/host/pci-xgene-ecam.c b/drivers/pci/host/pci-xgene-ecam.c
|
||||
new file mode 100644
|
||||
index 0000000..1bea63f
|
||||
--- /dev/null
|
||||
+++ b/drivers/pci/host/pci-xgene-ecam.c
|
||||
@@ -0,0 +1,194 @@
|
||||
+/*
|
||||
+ * APM X-Gene PCIe ECAM fixup driver
|
||||
+ *
|
||||
+ * Copyright (c) 2016, Applied Micro Circuits Corporation
|
||||
+ * Author:
|
||||
+ * Duc Dang <dhdang@apm.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.
|
||||
+ *
|
||||
+ * 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.
|
||||
+ *
|
||||
+ * You should have received a copy of the GNU General Public License
|
||||
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/of_address.h>
|
||||
+#include <linux/of_pci.h>
|
||||
+#include <linux/pci-acpi.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+#include <linux/pci-ecam.h>
|
||||
+
|
||||
+#ifdef CONFIG_ACPI
|
||||
+#define RTDID 0x160
|
||||
+#define ROOT_CAP_AND_CTRL 0x5C
|
||||
+
|
||||
+/* PCIe IP version */
|
||||
+#define XGENE_PCIE_IP_VER_UNKN 0
|
||||
+#define XGENE_PCIE_IP_VER_1 1
|
||||
+
|
||||
+#define APM_OEM_ID "APM"
|
||||
+#define APM_XGENE_OEM_TABLE_ID "XGENE"
|
||||
+#define APM_XGENE_OEM_REV 0x00000002
|
||||
+
|
||||
+struct xgene_pcie_acpi_root {
|
||||
+ void __iomem *csr_base;
|
||||
+ u32 version;
|
||||
+};
|
||||
+
|
||||
+static acpi_status xgene_pcie_find_csr_base(struct acpi_resource *acpi_res,
|
||||
+ void *data)
|
||||
+{
|
||||
+ struct xgene_pcie_acpi_root *root = data;
|
||||
+ struct acpi_resource_fixed_memory32 *fixed32;
|
||||
+
|
||||
+ if (acpi_res->type == ACPI_RESOURCE_TYPE_FIXED_MEMORY32) {
|
||||
+ fixed32 = &acpi_res->data.fixed_memory32;
|
||||
+ root->csr_base = ioremap(fixed32->address,
|
||||
+ fixed32->address_length);
|
||||
+ return AE_CTRL_TERMINATE;
|
||||
+ }
|
||||
+
|
||||
+ return AE_OK;
|
||||
+}
|
||||
+
|
||||
+static int xgene_pcie_ecam_init(struct pci_config_window *cfg)
|
||||
+{
|
||||
+ struct xgene_pcie_acpi_root *xgene_root;
|
||||
+ struct device *dev = cfg->parent;
|
||||
+ struct acpi_device *adev = to_acpi_device(dev);
|
||||
+ acpi_handle handle = acpi_device_handle(adev);
|
||||
+
|
||||
+ xgene_root = devm_kzalloc(dev, sizeof(*xgene_root), GFP_KERNEL);
|
||||
+ if (!xgene_root)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ acpi_walk_resources(handle, METHOD_NAME__CRS,
|
||||
+ xgene_pcie_find_csr_base, xgene_root);
|
||||
+
|
||||
+ if (!xgene_root->csr_base) {
|
||||
+ kfree(xgene_root);
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
+
|
||||
+ xgene_root->version = XGENE_PCIE_IP_VER_1;
|
||||
+
|
||||
+ cfg->priv = xgene_root;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * For Configuration request, RTDID register is used as Bus Number,
|
||||
+ * Device Number and Function number of the header fields.
|
||||
+ */
|
||||
+static void xgene_pcie_set_rtdid_reg(struct pci_bus *bus, uint devfn)
|
||||
+{
|
||||
+ struct pci_config_window *cfg = bus->sysdata;
|
||||
+ struct xgene_pcie_acpi_root *port = cfg->priv;
|
||||
+ unsigned int b, d, f;
|
||||
+ u32 rtdid_val = 0;
|
||||
+
|
||||
+ b = bus->number;
|
||||
+ d = PCI_SLOT(devfn);
|
||||
+ f = PCI_FUNC(devfn);
|
||||
+
|
||||
+ if (!pci_is_root_bus(bus))
|
||||
+ rtdid_val = (b << 8) | (d << 3) | f;
|
||||
+
|
||||
+ writel(rtdid_val, port->csr_base + RTDID);
|
||||
+ /* read the register back to ensure flush */
|
||||
+ readl(port->csr_base + RTDID);
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * X-Gene PCIe port uses BAR0-BAR1 of RC's configuration space as
|
||||
+ * the translation from PCI bus to native BUS. Entire DDR region
|
||||
+ * is mapped into PCIe space using these registers, so it can be
|
||||
+ * reached by DMA from EP devices. The BAR0/1 of bridge should be
|
||||
+ * hidden during enumeration to avoid the sizing and resource allocation
|
||||
+ * by PCIe core.
|
||||
+ */
|
||||
+static bool xgene_pcie_hide_rc_bars(struct pci_bus *bus, int offset)
|
||||
+{
|
||||
+ if (pci_is_root_bus(bus) && ((offset == PCI_BASE_ADDRESS_0) ||
|
||||
+ (offset == PCI_BASE_ADDRESS_1)))
|
||||
+ return true;
|
||||
+
|
||||
+ return false;
|
||||
+}
|
||||
+
|
||||
+void __iomem *xgene_pcie_ecam_map_bus(struct pci_bus *bus,
|
||||
+ unsigned int devfn, int where)
|
||||
+{
|
||||
+ struct pci_config_window *cfg = bus->sysdata;
|
||||
+ unsigned int busn = bus->number;
|
||||
+ void __iomem *base;
|
||||
+
|
||||
+ if (busn < cfg->busr.start || busn > cfg->busr.end)
|
||||
+ return NULL;
|
||||
+
|
||||
+ if ((pci_is_root_bus(bus) && devfn != 0) ||
|
||||
+ xgene_pcie_hide_rc_bars(bus, where))
|
||||
+ return NULL;
|
||||
+
|
||||
+ xgene_pcie_set_rtdid_reg(bus, devfn);
|
||||
+
|
||||
+ if (busn > cfg->busr.start)
|
||||
+ base = cfg->win + (1 << cfg->ops->bus_shift);
|
||||
+ else
|
||||
+ base = cfg->win;
|
||||
+
|
||||
+ return base + where;
|
||||
+}
|
||||
+
|
||||
+static int xgene_pcie_config_read32(struct pci_bus *bus, unsigned int devfn,
|
||||
+ int where, int size, u32 *val)
|
||||
+{
|
||||
+ struct pci_config_window *cfg = bus->sysdata;
|
||||
+ struct xgene_pcie_acpi_root *port = cfg->priv;
|
||||
+
|
||||
+ if (pci_generic_config_read32(bus, devfn, where & ~0x3, 4, val) !=
|
||||
+ PCIBIOS_SUCCESSFUL)
|
||||
+ return PCIBIOS_DEVICE_NOT_FOUND;
|
||||
+
|
||||
+ /*
|
||||
+ * The v1 controller has a bug in its Configuration Request
|
||||
+ * Retry Status (CRS) logic: when CRS is enabled and we read the
|
||||
+ * Vendor and Device ID of a non-existent device, the controller
|
||||
+ * fabricates return data of 0xFFFF0001 ("device exists but is not
|
||||
+ * ready") instead of 0xFFFFFFFF ("device does not exist"). This
|
||||
+ * causes the PCI core to retry the read until it times out.
|
||||
+ * Avoid this by not claiming to support CRS.
|
||||
+ */
|
||||
+ if (pci_is_root_bus(bus) && (port->version == XGENE_PCIE_IP_VER_1) &&
|
||||
+ ((where & ~0x3) == ROOT_CAP_AND_CTRL))
|
||||
+ *val &= ~(PCI_EXP_RTCAP_CRSVIS << 16);
|
||||
+
|
||||
+ if (size <= 2)
|
||||
+ *val = (*val >> (8 * (where & 3))) & ((1 << (size * 8)) - 1);
|
||||
+
|
||||
+ return PCIBIOS_SUCCESSFUL;
|
||||
+}
|
||||
+
|
||||
+static struct pci_ecam_ops xgene_pcie_ecam_ops = {
|
||||
+ .bus_shift = 16,
|
||||
+ .init = xgene_pcie_ecam_init,
|
||||
+ .pci_ops = {
|
||||
+ .map_bus = xgene_pcie_ecam_map_bus,
|
||||
+ .read = xgene_pcie_config_read32,
|
||||
+ .write = pci_generic_config_write,
|
||||
+ }
|
||||
+};
|
||||
+
|
||||
+DECLARE_ACPI_MCFG_FIXUP(&xgene_pcie_ecam_ops, APM_OEM_ID,
|
||||
+ APM_XGENE_OEM_TABLE_ID, APM_XGENE_OEM_REV,
|
||||
+ PCI_MCFG_DOMAIN_ANY, PCI_MCFG_BUS_ANY);
|
||||
+#endif
|
||||
--
|
||||
2.7.4
|
||||
|
@ -506,6 +506,9 @@ Patch422: geekbox-v4-device-tree-support.patch
|
||||
# This has major conflicts and needs to be rebased
|
||||
# Patch423: Initial-AllWinner-A64-and-PINE64-support.patch
|
||||
|
||||
Patch424: arm64-pcie-acpi.patch
|
||||
Patch425: arm64-pcie-quirks-xgene.patch
|
||||
|
||||
# http://www.spinics.net/lists/linux-tegra/msg26029.html
|
||||
Patch426: usb-phy-tegra-Add-38.4MHz-clock-table-entry.patch
|
||||
|
||||
@ -2159,6 +2162,9 @@ fi
|
||||
#
|
||||
#
|
||||
%changelog
|
||||
* Tue Jul 19 2016 Peter Robinson <pbrobinson@fedoraproject.org>
|
||||
- Add aarch64 ACPI pci-e patches headed for 4.8
|
||||
|
||||
* Mon Jul 18 2016 Laura Abbott <labbott@redhat.com> - 4.7.0-0.rc7.git4.1
|
||||
- Linux v4.7-rc7-92-g47ef4ad
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user