Home Home > GIT Browse
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichal Kubecek <mkubecek@suse.cz>2019-11-27 15:14:32 +0100
committerMichal Kubecek <mkubecek@suse.cz>2019-11-27 15:14:32 +0100
commitdae51bda5d04f284bef79d646bd98f08f9ee417b (patch)
tree610d80b1f2895cc34f117c76f297c1f180cdb48b
parentc0f484c7bad2cbffa449e6c3e9f8adb6abb9776d (diff)
parent606157791b2ed6f5f1c5d4e31436225b9947a92b (diff)
Merge branch 'users/nsaenzjulienne/SLE15-SP2/for-next' into SLE15-SP2
-rw-r--r--config/arm64/default1
-rw-r--r--patches.suse/PCI-mobiveil-Make-mobiveil_host_init-can-be-used-to-.patch107
-rw-r--r--patches.suse/PCI-mobiveil-Refactor-Mobiveil-PCIe-Host-Bridge-IP-d.patch74
-rw-r--r--patches.suse/arm64-mm-fix-unused-variable-warning-in-zone_sizes_init.patch41
-rw-r--r--patches.suse/arm64-mm-reserve-cma-and-crashkernel-in-zone_dma32.patch47
-rw-r--r--patches.suse/dma-direct-avoid-a-forward-declaration-for-phys_to_dma.patch74
-rw-r--r--patches.suse/dma-direct-check-for-overflows-on-32-bit-dma-addresses.patch66
-rw-r--r--patches.suse/dma-direct-exclude-dma_direct_map_resource-from-the-min_low_pfn-check.patch116
-rw-r--r--patches.suse/dma-direct-unify-the-dma_capable-definitions.patch114
-rw-r--r--patches.suse/dma-mapping-treat-dev-bus_dma_mask-as-a-dma-limit.patch355
-rw-r--r--patches.suse/linux-log2-h-add-roundup-rounddown_pow_two64-family-of-functions.patch190
-rw-r--r--patches.suse/of-address-fix-of_pci_range_parser_one-translation-of-dma-addresses.patch76
-rw-r--r--patches.suse/of-address-follow-dma-parent-for-dma-coherent.patch35
-rw-r--r--patches.suse/of-address-introduce-of_get_next_dma_parent-helper.patch44
-rw-r--r--patches.suse/of-address-translate-dma-ranges-for-parent-nodes-missing-dma-ranges.patch45
-rw-r--r--patches.suse/of-factor-out-addr-size-cells-parsing.patch108
-rw-r--r--patches.suse/of-make-of_dma_get_range-work-on-bus-nodes.patch109
-rw-r--r--patches.suse/pci-aardvark-use-pci_parse_request_of_pci_ranges.patch126
-rw-r--r--patches.suse/pci-altera-use-pci_parse_request_of_pci_ranges.patch111
-rw-r--r--patches.suse/pci-brcmstb-add-broadcom-stb-pcie-host-controller-driver.patch843
-rw-r--r--patches.suse/pci-brcmstb-add-msi-capability.patch409
-rw-r--r--patches.suse/pci-dwc-use-pci_parse_request_of_pci_ranges.patch77
-rw-r--r--patches.suse/pci-export-pci_parse_request_of_pci_ranges.patch33
-rw-r--r--patches.suse/pci-faraday-use-pci_parse_request_of_pci_ranges.patch121
-rw-r--r--patches.suse/pci-ftpci100-use-inbound-resources-for-setup.patch88
-rw-r--r--patches.suse/pci-iproc-use-inbound-resources-for-setup.patch145
-rw-r--r--patches.suse/pci-iproc-use-pci_parse_request_of_pci_ranges.patch83
-rw-r--r--patches.suse/pci-mediatek-use-pci_parse_request_of_pci_ranges.patch103
-rw-r--r--patches.suse/pci-mobiveil-use-pci_parse_request_of_pci_ranges.patch132
-rw-r--r--patches.suse/pci-of-add-inbound-resource-parsing-to-helpers.patch408
-rw-r--r--patches.suse/pci-rcar-use-inbound-resources-for-setup.patch110
-rw-r--r--patches.suse/pci-rockchip-drop-storing-driver-private-outbound-resource-data.patch153
-rw-r--r--patches.suse/pci-rockchip-use-pci_parse_request_of_pci_ranges.patch138
-rw-r--r--patches.suse/pci-v3-semi-use-inbound-resources-for-setup.patch108
-rw-r--r--patches.suse/pci-v3-semi-use-pci_parse_request_of_pci_ranges.patch127
-rw-r--r--patches.suse/pci-versatile-enable-compile_test.patch38
-rw-r--r--patches.suse/pci-versatile-remove-usage-of-phys_offset.patch55
-rw-r--r--patches.suse/pci-versatile-use-pci_parse_request_of_pci_ranges.patch126
-rw-r--r--patches.suse/pci-xgene-use-inbound-resources-for-setup.patch94
-rw-r--r--patches.suse/pci-xgene-use-pci_parse_request_of_pci_ranges.patch139
-rw-r--r--patches.suse/pci-xilinx-nwl-use-pci_parse_request_of_pci_ranges.patch94
-rw-r--r--patches.suse/pci-xilinx-use-pci_parse_request_of_pci_ranges.patch81
-rw-r--r--patches.suse/resource-add-a-resource_list_first_type-helper.patch41
-rw-r--r--patches.suse/x86-pci-sta2x11-use-default-dma-address-translation.patch268
-rw-r--r--series.conf48
-rw-r--r--supported.conf1
46 files changed, 5755 insertions, 147 deletions
diff --git a/config/arm64/default b/config/arm64/default
index 21758685d2..474d9956e7 100644
--- a/config/arm64/default
+++ b/config/arm64/default
@@ -2002,6 +2002,7 @@ CONFIG_PCIE_ROCKCHIP=y
CONFIG_PCIE_ROCKCHIP_HOST=m
CONFIG_PCIE_ROCKCHIP_EP=y
CONFIG_PCIE_MEDIATEK=y
+CONFIG_PCIE_BRCMSTB=m
#
# DesignWare PCI Core Support
diff --git a/patches.suse/PCI-mobiveil-Make-mobiveil_host_init-can-be-used-to-.patch b/patches.suse/PCI-mobiveil-Make-mobiveil_host_init-can-be-used-to-.patch
index 9242a5ed63..b457ccce14 100644
--- a/patches.suse/PCI-mobiveil-Make-mobiveil_host_init-can-be-used-to-.patch
+++ b/patches.suse/PCI-mobiveil-Make-mobiveil_host_init-can-be-used-to-.patch
@@ -14,21 +14,20 @@ Signed-off-by: Hou Zhiqiang <Zhiqiang.Hou@nxp.com>
Reviewed-by: Subrahmanya Lingappa <l.subrahmanya@mobiveil.co.in>
Signed-off-by: Mian Yousaf Kaukab <yousaf.kaukab@suse.com>
---
- .../pci/controller/mobiveil/pcie-mobiveil-host.c | 43 +++++++++++-----------
- drivers/pci/controller/mobiveil/pcie-mobiveil.h | 3 +-
- 2 files changed, 24 insertions(+), 22 deletions(-)
+ drivers/pci/controller/mobiveil/pcie-mobiveil-host.c | 19 ++++++++++++-------
+ drivers/pci/controller/mobiveil/pcie-mobiveil.h | 1 +
+ 2 files changed, 13 insertions(+), 7 deletions(-)
-diff --git a/drivers/pci/controller/mobiveil/pcie-mobiveil-host.c b/drivers/pci/controller/mobiveil/pcie-mobiveil-host.c
-index 995487c4f760..775754522363 100644
--- a/drivers/pci/controller/mobiveil/pcie-mobiveil-host.c
+++ b/drivers/pci/controller/mobiveil/pcie-mobiveil-host.c
-@@ -215,16 +215,21 @@ static void mobiveil_pcie_enable_msi(struct mobiveil_pcie *pcie)
+@@ -215,17 +215,22 @@ static void mobiveil_pcie_enable_msi(str
writel_relaxed(1, pcie->apb_csr_base + MSI_ENABLE_OFFSET);
}
-static int mobiveil_host_init(struct mobiveil_pcie *pcie)
+int mobiveil_host_init(struct mobiveil_pcie *pcie, bool reinit)
{
+ struct pci_host_bridge *bridge = pci_host_bridge_from_priv(pcie);
u32 value, pab_ctrl, type;
struct resource_entry *win;
@@ -50,38 +49,7 @@ index 995487c4f760..775754522363 100644
/*
* program Bus Master Enable Bit in Command Register in PAB Config
-@@ -270,7 +275,7 @@ static int mobiveil_host_init(struct mobiveil_pcie *pcie)
- program_ib_windows(pcie, WIN_NUM_0, 0, 0, MEM_WINDOW_TYPE, IB_WIN_SIZE);
-
- /* Get the I/O and memory ranges from DT */
-- resource_list_for_each_entry(win, &pcie->resources) {
-+ resource_list_for_each_entry(win, pcie->resources) {
- if (resource_type(win->res) == IORESOURCE_MEM) {
- type = MEM_WINDOW_TYPE;
- } else if (resource_type(win->res) == IORESOURCE_IO) {
-@@ -541,8 +546,6 @@ int mobiveil_pcie_host_probe(struct mobiveil_pcie *pcie)
- resource_size_t iobase;
- int ret;
-
-- INIT_LIST_HEAD(&pcie->resources);
--
- ret = mobiveil_pcie_parse_dt(pcie);
- if (ret) {
- dev_err(dev, "Parsing DT failed, ret: %x\n", ret);
-@@ -551,34 +554,35 @@ int mobiveil_pcie_host_probe(struct mobiveil_pcie *pcie)
-
- /* parse the host bridge base addresses from the device tree file */
- ret = devm_of_pci_get_host_bridge_resources(dev, 0, 0xff,
-- &pcie->resources, &iobase);
-+ &bridge->windows, &iobase);
- if (ret) {
- dev_err(dev, "Getting bridge resources failed\n");
- return ret;
- }
-
-+ pcie->resources = &bridge->windows;
-+
- /*
+@@ -559,7 +564,7 @@ int mobiveil_pcie_host_probe(struct mobi
* configure all inbound and outbound windows and prepare the RC for
* config access
*/
@@ -89,66 +57,10 @@ index 995487c4f760..775754522363 100644
+ ret = mobiveil_host_init(pcie, false);
if (ret) {
dev_err(dev, "Failed to initialize host\n");
-- goto error;
-+ return ret;
- }
-
- ret = mobiveil_pcie_interrupt_init(pcie);
- if (ret) {
- dev_err(dev, "Interrupt init failed\n");
-- goto error;
-+ return ret;
- }
-
-- ret = devm_request_pci_bus_resources(dev, &pcie->resources);
-+ ret = devm_request_pci_bus_resources(dev, pcie->resources);
- if (ret)
-- goto error;
-+ return ret;
-
- /* Initialize bridge */
-- list_splice_init(&pcie->resources, &bridge->windows);
- bridge->dev.parent = dev;
- bridge->sysdata = pcie;
- bridge->busnr = pcie->rp.root_bus_nr;
-@@ -589,13 +593,13 @@ int mobiveil_pcie_host_probe(struct mobiveil_pcie *pcie)
- ret = mobiveil_bringup_link(pcie);
- if (ret) {
- dev_info(dev, "link bring-up failed\n");
-- goto error;
-+ return ret;
- }
-
- /* setup the kernel resources for the newly added PCIe root bus */
- ret = pci_scan_root_bus_bridge(bridge);
- if (ret)
-- goto error;
-+ return ret;
-
- bus = bridge->bus;
-
-@@ -605,7 +609,4 @@ int mobiveil_pcie_host_probe(struct mobiveil_pcie *pcie)
- pci_bus_add_devices(bus);
-
- return 0;
--error:
-- pci_free_resource_list(&pcie->resources);
-- return ret;
- }
-diff --git a/drivers/pci/controller/mobiveil/pcie-mobiveil.h b/drivers/pci/controller/mobiveil/pcie-mobiveil.h
-index 4825e30030cd..4f17a9837fe9 100644
+ return ret;
--- a/drivers/pci/controller/mobiveil/pcie-mobiveil.h
+++ b/drivers/pci/controller/mobiveil/pcie-mobiveil.h
-@@ -153,7 +153,7 @@ struct mobiveil_pab_ops {
-
- struct mobiveil_pcie {
- struct platform_device *pdev;
-- struct list_head resources;
-+ struct list_head *resources;
- void __iomem *csr_axi_slave_base; /* PAB registers base */
- phys_addr_t pcie_reg_base; /* Physical PCIe Controller Base */
- void __iomem *apb_csr_base; /* MSI register base */
-@@ -167,6 +167,7 @@ struct mobiveil_pcie {
+@@ -166,6 +166,7 @@ struct mobiveil_pcie {
};
int mobiveil_pcie_host_probe(struct mobiveil_pcie *pcie);
@@ -156,6 +68,3 @@ index 4825e30030cd..4f17a9837fe9 100644
bool mobiveil_pcie_link_up(struct mobiveil_pcie *pcie);
int mobiveil_bringup_link(struct mobiveil_pcie *pcie);
void program_ob_windows(struct mobiveil_pcie *pcie, int win_num, u64 cpu_addr,
---
-2.16.4
-
diff --git a/patches.suse/PCI-mobiveil-Refactor-Mobiveil-PCIe-Host-Bridge-IP-d.patch b/patches.suse/PCI-mobiveil-Refactor-Mobiveil-PCIe-Host-Bridge-IP-d.patch
index 8b49eecadc..71a2bfdaa3 100644
--- a/patches.suse/PCI-mobiveil-Refactor-Mobiveil-PCIe-Host-Bridge-IP-d.patch
+++ b/patches.suse/PCI-mobiveil-Refactor-Mobiveil-PCIe-Host-Bridge-IP-d.patch
@@ -22,12 +22,12 @@ Signed-off-by: Mian Yousaf Kaukab <yousaf.kaukab@suse.com>
drivers/pci/controller/Makefile | 2
drivers/pci/controller/mobiveil/Kconfig | 24
drivers/pci/controller/mobiveil/Makefile | 4
- drivers/pci/controller/mobiveil/pcie-mobiveil-host.c | 611 ++++++++++++
+ drivers/pci/controller/mobiveil/pcie-mobiveil-host.c | 601 +++++++++++
drivers/pci/controller/mobiveil/pcie-mobiveil-plat.c | 59 +
drivers/pci/controller/mobiveil/pcie-mobiveil.c | 227 ++++
- drivers/pci/controller/mobiveil/pcie-mobiveil.h | 189 +++
- drivers/pci/controller/pcie-mobiveil.c | 964 -------------------
- 11 files changed, 1118 insertions(+), 977 deletions(-)
+ drivers/pci/controller/mobiveil/pcie-mobiveil.h | 188 +++
+ drivers/pci/controller/pcie-mobiveil.c | 953 -------------------
+ 11 files changed, 1107 insertions(+), 966 deletions(-)
create mode 100644 drivers/pci/controller/mobiveil/Kconfig
create mode 100644 drivers/pci/controller/mobiveil/Makefile
create mode 100644 drivers/pci/controller/mobiveil/pcie-mobiveil-host.c
@@ -38,7 +38,7 @@ Signed-off-by: Mian Yousaf Kaukab <yousaf.kaukab@suse.com>
--- a/MAINTAINERS
+++ b/MAINTAINERS
-@@ -12341,7 +12341,7 @@ M: Hou Zhiqiang <Zhiqiang.Hou@nxp.com>
+@@ -12343,7 +12343,7 @@ M: Hou Zhiqiang <Zhiqiang.Hou@nxp.com>
L: linux-pci@vger.kernel.org
S: Supported
F: Documentation/devicetree/bindings/pci/mobiveil-pcie.txt
@@ -77,7 +77,7 @@ Signed-off-by: Mian Yousaf Kaukab <yousaf.kaukab@suse.com>
config PCIE_TANGO_SMP8759
bool "Tango SMP8759 PCIe controller (DANGEROUS)"
depends on ARCH_TANGO && PCI_MSI && OF
-@@ -282,4 +272,5 @@ config VMD
+@@ -289,4 +279,5 @@ config PCI_HYPERV_INTERFACE
have a common interface with the Hyper-V PCI frontend driver.
source "drivers/pci/controller/dwc/Kconfig"
@@ -85,7 +85,7 @@ Signed-off-by: Mian Yousaf Kaukab <yousaf.kaukab@suse.com>
endmenu
--- a/drivers/pci/controller/Makefile
+++ b/drivers/pci/controller/Makefile
-@@ -26,11 +26,11 @@ obj-$(CONFIG_PCIE_ROCKCHIP) += pcie-rock
+@@ -27,11 +27,11 @@ obj-$(CONFIG_PCIE_ROCKCHIP) += pcie-rock
obj-$(CONFIG_PCIE_ROCKCHIP_EP) += pcie-rockchip-ep.o
obj-$(CONFIG_PCIE_ROCKCHIP_HOST) += pcie-rockchip-host.o
obj-$(CONFIG_PCIE_MEDIATEK) += pcie-mediatek.o
@@ -134,7 +134,7 @@ Signed-off-by: Mian Yousaf Kaukab <yousaf.kaukab@suse.com>
+obj-$(CONFIG_PCIE_MOBIVEIL_PLAT) += pcie-mobiveil-plat.o
--- /dev/null
+++ b/drivers/pci/controller/mobiveil/pcie-mobiveil-host.c
-@@ -0,0 +1,611 @@
+@@ -0,0 +1,601 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * PCIe host controller driver for Mobiveil PCIe Host controller
@@ -354,6 +354,7 @@ Signed-off-by: Mian Yousaf Kaukab <yousaf.kaukab@suse.com>
+
+static int mobiveil_host_init(struct mobiveil_pcie *pcie)
+{
++ struct pci_host_bridge *bridge = pci_host_bridge_from_priv(pcie);
+ u32 value, pab_ctrl, type;
+ struct resource_entry *win;
+
@@ -407,7 +408,7 @@ Signed-off-by: Mian Yousaf Kaukab <yousaf.kaukab@suse.com>
+ program_ib_windows(pcie, WIN_NUM_0, 0, 0, MEM_WINDOW_TYPE, IB_WIN_SIZE);
+
+ /* Get the I/O and memory ranges from DT */
-+ resource_list_for_each_entry(win, &pcie->resources) {
++ resource_list_for_each_entry(win, &bridge->windows) {
+ if (resource_type(win->res) == IORESOURCE_MEM) {
+ type = MEM_WINDOW_TYPE;
+ } else if (resource_type(win->res) == IORESOURCE_IO) {
@@ -675,11 +676,8 @@ Signed-off-by: Mian Yousaf Kaukab <yousaf.kaukab@suse.com>
+ struct pci_bus *child;
+ struct pci_host_bridge *bridge = pcie->bridge;
+ struct device *dev = &pcie->pdev->dev;
-+ resource_size_t iobase;
+ int ret;
+
-+ INIT_LIST_HEAD(&pcie->resources);
-+
+ ret = mobiveil_pcie_parse_dt(pcie);
+ if (ret) {
+ dev_err(dev, "Parsing DT failed, ret: %x\n", ret);
@@ -687,8 +685,8 @@ Signed-off-by: Mian Yousaf Kaukab <yousaf.kaukab@suse.com>
+ }
+
+ /* parse the host bridge base addresses from the device tree file */
-+ ret = devm_of_pci_get_host_bridge_resources(dev, 0, 0xff,
-+ &pcie->resources, &iobase);
++ ret = pci_parse_request_of_pci_ranges(dev, &bridge->windows,
++ &bridge->dma_ranges, NULL);
+ if (ret) {
+ dev_err(dev, "Getting bridge resources failed\n");
+ return ret;
@@ -701,21 +699,16 @@ Signed-off-by: Mian Yousaf Kaukab <yousaf.kaukab@suse.com>
+ ret = mobiveil_host_init(pcie);
+ if (ret) {
+ dev_err(dev, "Failed to initialize host\n");
-+ goto error;
++ return ret;
+ }
+
+ ret = mobiveil_pcie_interrupt_init(pcie);
+ if (ret) {
+ dev_err(dev, "Interrupt init failed\n");
-+ goto error;
++ return ret;
+ }
+
-+ ret = devm_request_pci_bus_resources(dev, &pcie->resources);
-+ if (ret)
-+ goto error;
-+
+ /* Initialize bridge */
-+ list_splice_init(&pcie->resources, &bridge->windows);
+ bridge->dev.parent = dev;
+ bridge->sysdata = pcie;
+ bridge->busnr = pcie->rp.root_bus_nr;
@@ -726,13 +719,13 @@ Signed-off-by: Mian Yousaf Kaukab <yousaf.kaukab@suse.com>
+ ret = mobiveil_bringup_link(pcie);
+ if (ret) {
+ dev_info(dev, "link bring-up failed\n");
-+ goto error;
++ return ret;
+ }
+
+ /* setup the kernel resources for the newly added PCIe root bus */
+ ret = pci_scan_root_bus_bridge(bridge);
+ if (ret)
-+ goto error;
++ return ret;
+
+ bus = bridge->bus;
+
@@ -742,9 +735,6 @@ Signed-off-by: Mian Yousaf Kaukab <yousaf.kaukab@suse.com>
+ pci_bus_add_devices(bus);
+
+ return 0;
-+error:
-+ pci_free_resource_list(&pcie->resources);
-+ return ret;
+}
--- /dev/null
+++ b/drivers/pci/controller/mobiveil/pcie-mobiveil-plat.c
@@ -1040,7 +1030,7 @@ Signed-off-by: Mian Yousaf Kaukab <yousaf.kaukab@suse.com>
+}
--- /dev/null
+++ b/drivers/pci/controller/mobiveil/pcie-mobiveil.h
-@@ -0,0 +1,189 @@
+@@ -0,0 +1,188 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * PCIe host controller driver for Mobiveil PCIe Host controller
@@ -1196,7 +1186,6 @@ Signed-off-by: Mian Yousaf Kaukab <yousaf.kaukab@suse.com>
+
+struct mobiveil_pcie {
+ struct platform_device *pdev;
-+ struct list_head resources;
+ void __iomem *csr_axi_slave_base; /* PAB registers base */
+ phys_addr_t pcie_reg_base; /* Physical PCIe Controller Base */
+ void __iomem *apb_csr_base; /* MSI register base */
@@ -1232,7 +1221,7 @@ Signed-off-by: Mian Yousaf Kaukab <yousaf.kaukab@suse.com>
+#endif /* _PCIE_MOBIVEIL_H */
--- a/drivers/pci/controller/pcie-mobiveil.c
+++ /dev/null
-@@ -1,964 +0,0 @@
+@@ -1,953 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * PCIe host controller driver for Mobiveil PCIe Host controller
@@ -1375,7 +1364,6 @@ Signed-off-by: Mian Yousaf Kaukab <yousaf.kaukab@suse.com>
-
-struct mobiveil_pcie {
- struct platform_device *pdev;
-- struct list_head resources;
- void __iomem *config_axi_slave_base; /* endpoint config base */
- void __iomem *csr_axi_slave_base; /* root port config base */
- void __iomem *apb_csr_base; /* MSI register base */
@@ -1810,6 +1798,7 @@ Signed-off-by: Mian Yousaf Kaukab <yousaf.kaukab@suse.com>
-
-static int mobiveil_host_init(struct mobiveil_pcie *pcie)
-{
+- struct pci_host_bridge *bridge = pci_host_bridge_from_priv(pcie);
- u32 value, pab_ctrl, type;
- struct resource_entry *win;
-
@@ -1866,7 +1855,7 @@ Signed-off-by: Mian Yousaf Kaukab <yousaf.kaukab@suse.com>
- program_ib_windows(pcie, WIN_NUM_0, 0, 0, MEM_WINDOW_TYPE, IB_WIN_SIZE);
-
- /* Get the I/O and memory ranges from DT */
-- resource_list_for_each_entry(win, &pcie->resources) {
+- resource_list_for_each_entry(win, &bridge->windows) {
- if (resource_type(win->res) == IORESOURCE_MEM)
- type = MEM_WINDOW_TYPE;
- else if (resource_type(win->res) == IORESOURCE_IO)
@@ -2092,7 +2081,6 @@ Signed-off-by: Mian Yousaf Kaukab <yousaf.kaukab@suse.com>
- struct pci_bus *child;
- struct pci_host_bridge *bridge;
- struct device *dev = &pdev->dev;
-- resource_size_t iobase;
- int ret;
-
- /* allocate the PCIe port */
@@ -2110,11 +2098,9 @@ Signed-off-by: Mian Yousaf Kaukab <yousaf.kaukab@suse.com>
- return ret;
- }
-
-- INIT_LIST_HEAD(&pcie->resources);
--
- /* parse the host bridge base addresses from the device tree file */
-- ret = devm_of_pci_get_host_bridge_resources(dev, 0, 0xff,
-- &pcie->resources, &iobase);
+- ret = pci_parse_request_of_pci_ranges(dev, &bridge->windows,
+- &bridge->dma_ranges, NULL);
- if (ret) {
- dev_err(dev, "Getting bridge resources failed\n");
- return ret;
@@ -2127,24 +2113,19 @@ Signed-off-by: Mian Yousaf Kaukab <yousaf.kaukab@suse.com>
- ret = mobiveil_host_init(pcie);
- if (ret) {
- dev_err(dev, "Failed to initialize host\n");
-- goto error;
+- return ret;
- }
-
- /* initialize the IRQ domains */
- ret = mobiveil_pcie_init_irq_domain(pcie);
- if (ret) {
- dev_err(dev, "Failed creating IRQ Domain\n");
-- goto error;
+- return ret;
- }
-
- irq_set_chained_handler_and_data(pcie->irq, mobiveil_pcie_isr, pcie);
-
-- ret = devm_request_pci_bus_resources(dev, &pcie->resources);
-- if (ret)
-- goto error;
--
- /* Initialize bridge */
-- list_splice_init(&pcie->resources, &bridge->windows);
- bridge->dev.parent = dev;
- bridge->sysdata = pcie;
- bridge->busnr = pcie->root_bus_nr;
@@ -2155,13 +2136,13 @@ Signed-off-by: Mian Yousaf Kaukab <yousaf.kaukab@suse.com>
- ret = mobiveil_bringup_link(pcie);
- if (ret) {
- dev_info(dev, "link bring-up failed\n");
-- goto error;
+- return ret;
- }
-
- /* setup the kernel resources for the newly added PCIe root bus */
- ret = pci_scan_root_bus_bridge(bridge);
- if (ret)
-- goto error;
+- return ret;
-
- bus = bridge->bus;
-
@@ -2171,9 +2152,6 @@ Signed-off-by: Mian Yousaf Kaukab <yousaf.kaukab@suse.com>
- pci_bus_add_devices(bus);
-
- return 0;
--error:
-- pci_free_resource_list(&pcie->resources);
-- return ret;
-}
-
-static const struct of_device_id mobiveil_pcie_of_match[] = {
diff --git a/patches.suse/arm64-mm-fix-unused-variable-warning-in-zone_sizes_init.patch b/patches.suse/arm64-mm-fix-unused-variable-warning-in-zone_sizes_init.patch
new file mode 100644
index 0000000000..cdd8feb253
--- /dev/null
+++ b/patches.suse/arm64-mm-fix-unused-variable-warning-in-zone_sizes_init.patch
@@ -0,0 +1,41 @@
+From: Nathan Chancellor <natechancellor@gmail.com>
+Date: Wed, 16 Oct 2019 07:47:14 -0700
+Subject: arm64: mm: Fix unused variable warning in zone_sizes_init
+Git-commit: 4399d430700d3974ed6c5a1b1380bc6527f17e99
+Patch-mainline: v5.5-rc1
+References: jsc#SLE-7772
+
+When building arm64 allnoconfig, CONFIG_ZONE_DMA and CONFIG_ZONE_DMA32
+get disabled so there is a warning about max_dma being unused.
+
+../arch/arm64/mm/init.c:215:16: warning: unused variable 'max_dma'
+[-Wunused-variable]
+ unsigned long max_dma = min;
+ ^
+1 warning generated.
+
+Add __maybe_unused to make this clear to the compiler.
+
+Fixes: 1a8e1cef7603 ("arm64: use both ZONE_DMA and ZONE_DMA32")
+Reviewed-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Signed-off-by: Nathan Chancellor <natechancellor@gmail.com>
+Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
+Acked-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+---
+ arch/arm64/mm/init.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
+index 44f07fdf7a59..71b45c58218b 100644
+--- a/arch/arm64/mm/init.c
++++ b/arch/arm64/mm/init.c
+@@ -212,7 +212,7 @@ static void __init zone_sizes_init(unsigned long min, unsigned long max)
+ struct memblock_region *reg;
+ unsigned long zone_size[MAX_NR_ZONES], zhole_size[MAX_NR_ZONES];
+ unsigned long max_dma32 = min;
+- unsigned long max_dma = min;
++ unsigned long __maybe_unused max_dma = min;
+
+ memset(zone_size, 0, sizeof(zone_size));
+
+
diff --git a/patches.suse/arm64-mm-reserve-cma-and-crashkernel-in-zone_dma32.patch b/patches.suse/arm64-mm-reserve-cma-and-crashkernel-in-zone_dma32.patch
new file mode 100644
index 0000000000..c157d5816d
--- /dev/null
+++ b/patches.suse/arm64-mm-reserve-cma-and-crashkernel-in-zone_dma32.patch
@@ -0,0 +1,47 @@
+From: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Date: Thu, 7 Nov 2019 10:56:11 +0100
+Subject: arm64: mm: reserve CMA and crashkernel in ZONE_DMA32
+Git-commit: bff3b04460a80f425442fe8e5c6ee8c3ebef611f
+Patch-mainline: v5.5-rc1
+References: jsc#SLE-7772
+
+With the introduction of ZONE_DMA in arm64 we moved the default CMA and
+crashkernel reservation into that area. This caused a regression on big
+machines that need big CMA and crashkernel reservations. Note that
+ZONE_DMA is only 1GB big.
+
+Restore the previous behavior as the wide majority of devices are OK
+with reserving these in ZONE_DMA32. The ones that need them in ZONE_DMA
+will configure it explicitly.
+
+Fixes: 1a8e1cef7603 ("arm64: use both ZONE_DMA and ZONE_DMA32")
+Reported-by: Qian Cai <cai@lca.pw>
+Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
+---
+ arch/arm64/mm/init.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
+index 35f27b839101..d933589c48e8 100644
+--- a/arch/arm64/mm/init.c
++++ b/arch/arm64/mm/init.c
+@@ -91,7 +91,7 @@ static void __init reserve_crashkernel(void)
+
+ if (crash_base == 0) {
+ /* Current arm64 boot protocol requires 2MB alignment */
+- crash_base = memblock_find_in_range(0, ARCH_LOW_ADDRESS_LIMIT,
++ crash_base = memblock_find_in_range(0, arm64_dma32_phys_limit,
+ crash_size, SZ_2M);
+ if (crash_base == 0) {
+ pr_warn("cannot allocate crashkernel (size:0x%llx)\n",
+@@ -459,7 +459,7 @@ void __init arm64_memblock_init(void)
+
+ high_memory = __va(memblock_end_of_DRAM() - 1) + 1;
+
+- dma_contiguous_reserve(arm64_dma_phys_limit ? : arm64_dma32_phys_limit);
++ dma_contiguous_reserve(arm64_dma32_phys_limit);
+ }
+
+ void __init bootmem_init(void)
+
diff --git a/patches.suse/dma-direct-avoid-a-forward-declaration-for-phys_to_dma.patch b/patches.suse/dma-direct-avoid-a-forward-declaration-for-phys_to_dma.patch
new file mode 100644
index 0000000000..c9916e9e87
--- /dev/null
+++ b/patches.suse/dma-direct-avoid-a-forward-declaration-for-phys_to_dma.patch
@@ -0,0 +1,74 @@
+From: Christoph Hellwig <hch@lst.de>
+Date: Tue, 12 Nov 2019 17:07:43 +0100
+Subject: dma-direct: avoid a forward declaration for phys_to_dma
+Git-commit: c7345159f7db6fb69ec1c3b3f8f28cd05c731be2
+Patch-mainline: Queued
+Git-repo: git://git.infradead.org/users/hch/dma-mapping.git
+References: jsc#SLE-7772
+
+Move dma_capable down a bit so that we don't need a forward declaration
+for phys_to_dma.
+
+Signed-off-by: Christoph Hellwig <hch@lst.de>
+Reviewed-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Acked-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+---
+ include/linux/dma-direct.h | 30 ++++++++++++++----------------
+ 1 file changed, 14 insertions(+), 16 deletions(-)
+
+diff --git a/include/linux/dma-direct.h b/include/linux/dma-direct.h
+index 991f8aa2676e..f8959f75e496 100644
+--- a/include/linux/dma-direct.h
++++ b/include/linux/dma-direct.h
+@@ -6,8 +6,6 @@
+ #include <linux/memblock.h> /* for min_low_pfn */
+ #include <linux/mem_encrypt.h>
+
+-static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr);
+-
+ #ifdef CONFIG_ARCH_HAS_PHYS_TO_DMA
+ #include <asm/dma-direct.h>
+ #else
+@@ -26,20 +24,6 @@ static inline phys_addr_t __dma_to_phys(struct device *dev, dma_addr_t dev_addr)
+ }
+ #endif /* !CONFIG_ARCH_HAS_PHYS_TO_DMA */
+
+-static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
+-{
+- dma_addr_t end = addr + size - 1;
+-
+- if (!dev->dma_mask)
+- return false;
+-
+- if (!IS_ENABLED(CONFIG_ARCH_DMA_ADDR_T_64BIT) &&
+- min(addr, end) < phys_to_dma(dev, PFN_PHYS(min_low_pfn)))
+- return false;
+-
+- return end <= min_not_zero(*dev->dma_mask, dev->bus_dma_mask);
+-}
+-
+ #ifdef CONFIG_ARCH_HAS_FORCE_DMA_UNENCRYPTED
+ bool force_dma_unencrypted(struct device *dev);
+ #else
+@@ -65,6 +49,20 @@ static inline phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr)
+ return __sme_clr(__dma_to_phys(dev, daddr));
+ }
+
++static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
++{
++ dma_addr_t end = addr + size - 1;
++
++ if (!dev->dma_mask)
++ return false;
++
++ if (!IS_ENABLED(CONFIG_ARCH_DMA_ADDR_T_64BIT) &&
++ min(addr, end) < phys_to_dma(dev, PFN_PHYS(min_low_pfn)))
++ return false;
++
++ return end <= min_not_zero(*dev->dma_mask, dev->bus_dma_mask);
++}
++
+ u64 dma_direct_get_required_mask(struct device *dev);
+ void *dma_direct_alloc(struct device *dev, size_t size, dma_addr_t *dma_handle,
+ gfp_t gfp, unsigned long attrs);
+
diff --git a/patches.suse/dma-direct-check-for-overflows-on-32-bit-dma-addresses.patch b/patches.suse/dma-direct-check-for-overflows-on-32-bit-dma-addresses.patch
new file mode 100644
index 0000000000..7a9ac941a4
--- /dev/null
+++ b/patches.suse/dma-direct-check-for-overflows-on-32-bit-dma-addresses.patch
@@ -0,0 +1,66 @@
+From: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Date: Thu, 7 Nov 2019 16:06:44 +0100
+Subject: dma-direct: check for overflows on 32 bit DMA addresses
+Git-commit: b12d66278dd627cbe1ea7c000aa4715aaf8830c8
+Patch-mainline: Queued in subsystem maintainer repository
+Git-repo: git://git.infradead.org/users/hch/dma-mapping.git
+References: jsc#SLE-7772
+
+As seen on the new Raspberry Pi 4 and sta2x11's DMA implementation it is
+possible for a device configured with 32 bit DMA addresses and a partial
+DMA mapping located at the end of the address space to overflow. It
+happens when a higher physical address, not DMAable, is translated to
+it's DMA counterpart.
+
+For example the Raspberry Pi 4, configurable up to 4 GB of memory, has
+an interconnect capable of addressing the lower 1 GB of physical memory
+with a DMA offset of 0xc0000000. It transpires that, any attempt to
+translate physical addresses higher than the first GB will result in an
+overflow which dma_capable() can't detect as it only checks for
+addresses bigger then the maximum allowed DMA address.
+
+Fix this by verifying in dma_capable() if the DMA address range provided
+is at any point lower than the minimum possible DMA address on the bus.
+
+Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Signed-off-by: Christoph Hellwig <hch@lst.de>
+---
+ include/linux/dma-direct.h | 12 ++++++++++--
+ 1 file changed, 10 insertions(+), 2 deletions(-)
+
+diff --git a/include/linux/dma-direct.h b/include/linux/dma-direct.h
+index bcd953fb1f5a..6db863c3eb93 100644
+--- a/include/linux/dma-direct.h
++++ b/include/linux/dma-direct.h
+@@ -3,8 +3,11 @@
+ #define _LINUX_DMA_DIRECT_H 1
+
+ #include <linux/dma-mapping.h>
++#include <linux/memblock.h> /* for min_low_pfn */
+ #include <linux/mem_encrypt.h>
+
++static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr);
++
+ #ifdef CONFIG_ARCH_HAS_PHYS_TO_DMA
+ #include <asm/dma-direct.h>
+ #else
+@@ -24,11 +27,16 @@ static inline phys_addr_t __dma_to_phys(struct device *dev, dma_addr_t dev_addr)
+
+ static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
+ {
++ dma_addr_t end = addr + size - 1;
++
+ if (!dev->dma_mask)
+ return false;
+
+- return addr + size - 1 <=
+- min_not_zero(*dev->dma_mask, dev->bus_dma_mask);
++ if (!IS_ENABLED(CONFIG_ARCH_DMA_ADDR_T_64BIT) &&
++ min(addr, end) < phys_to_dma(dev, PFN_PHYS(min_low_pfn)))
++ return false;
++
++ return end <= min_not_zero(*dev->dma_mask, dev->bus_dma_mask);
+ }
+ #endif /* !CONFIG_ARCH_HAS_PHYS_TO_DMA */
+
+
diff --git a/patches.suse/dma-direct-exclude-dma_direct_map_resource-from-the-min_low_pfn-check.patch b/patches.suse/dma-direct-exclude-dma_direct_map_resource-from-the-min_low_pfn-check.patch
new file mode 100644
index 0000000000..a2c9416ec4
--- /dev/null
+++ b/patches.suse/dma-direct-exclude-dma_direct_map_resource-from-the-min_low_pfn-check.patch
@@ -0,0 +1,116 @@
+From: Christoph Hellwig <hch@lst.de>
+Date: Tue, 19 Nov 2019 17:38:58 +0100
+Subject: dma-direct: exclude dma_direct_map_resource from the min_low_pfn check
+Git-commit: 68a33b1794665ba8a1d1ef1d3bfcc7c587d380a6
+Patch-mainline: Queued
+Git-repo: git://git.infradead.org/users/hch/dma-mapping.git
+References: jsc#SLE-7772
+
+The valid memory address check in dma_capable only makes sense when mapping
+normal memory, not when using dma_map_resource to map a device resource.
+Add a new boolean argument to dma_capable to exclude that check for the
+dma_map_resource case.
+
+Fixes: b12d66278dd6 ("dma-direct: check for overflows on 32 bit DMA addresses")
+Reported-by: Marek Szyprowski <m.szyprowski@samsung.com>
+Signed-off-by: Christoph Hellwig <hch@lst.de>
+Acked-by: Marek Szyprowski <m.szyprowski@samsung.com>
+Tested-by: Marek Szyprowski <m.szyprowski@samsung.com>
+Acked-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+---
+ arch/x86/kernel/amd_gart_64.c | 4 ++--
+ drivers/xen/swiotlb-xen.c | 4 ++--
+ include/linux/dma-direct.h | 5 +++--
+ kernel/dma/direct.c | 4 ++--
+ kernel/dma/swiotlb.c | 2 +-
+ 5 files changed, 10 insertions(+), 9 deletions(-)
+
+--- a/arch/x86/kernel/amd_gart_64.c
++++ b/arch/x86/kernel/amd_gart_64.c
+@@ -185,13 +185,13 @@ static void iommu_full(struct device *de
+ static inline int
+ need_iommu(struct device *dev, unsigned long addr, size_t size)
+ {
+- return force_iommu || !dma_capable(dev, addr, size);
++ return force_iommu || !dma_capable(dev, addr, size, true);
+ }
+
+ static inline int
+ nonforced_iommu(struct device *dev, unsigned long addr, size_t size)
+ {
+- return !dma_capable(dev, addr, size);
++ return !dma_capable(dev, addr, size, true);
+ }
+
+ /* Map a single continuous physical area into the IOMMU.
+--- a/drivers/xen/swiotlb-xen.c
++++ b/drivers/xen/swiotlb-xen.c
+@@ -375,7 +375,7 @@ static dma_addr_t xen_swiotlb_map_page(s
+ * we can safely return the device addr and not worry about bounce
+ * buffering it.
+ */
+- if (dma_capable(dev, dev_addr, size) &&
++ if (dma_capable(dev, dev_addr, size, true) &&
+ !range_straddles_page_boundary(phys, size) &&
+ !xen_arch_need_swiotlb(dev, phys, dev_addr) &&
+ swiotlb_force != SWIOTLB_FORCE)
+@@ -396,7 +396,7 @@ static dma_addr_t xen_swiotlb_map_page(s
+ /*
+ * Ensure that the address returned is DMA'ble
+ */
+- if (unlikely(!dma_capable(dev, dev_addr, size))) {
++ if (unlikely(!dma_capable(dev, dev_addr, size, true))) {
+ swiotlb_tbl_unmap_single(dev, map, size, dir,
+ attrs | DMA_ATTR_SKIP_CPU_SYNC);
+ return DMA_MAPPING_ERROR;
+--- a/include/linux/dma-direct.h
++++ b/include/linux/dma-direct.h
+@@ -49,14 +49,15 @@ static inline phys_addr_t dma_to_phys(st
+ return __sme_clr(__dma_to_phys(dev, daddr));
+ }
+
+-static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
++static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size,
++ bool is_ram)
+ {
+ dma_addr_t end = addr + size - 1;
+
+ if (!dev->dma_mask)
+ return false;
+
+- if (!IS_ENABLED(CONFIG_ARCH_DMA_ADDR_T_64BIT) &&
++ if (is_ram && !IS_ENABLED(CONFIG_ARCH_DMA_ADDR_T_64BIT) &&
+ min(addr, end) < phys_to_dma(dev, PFN_PHYS(min_low_pfn)))
+ return false;
+
+--- a/kernel/dma/direct.c
++++ b/kernel/dma/direct.c
+@@ -326,7 +326,7 @@ static inline bool dma_direct_possible(s
+ size_t size)
+ {
+ return swiotlb_force != SWIOTLB_FORCE &&
+- dma_capable(dev, dma_addr, size);
++ dma_capable(dev, dma_addr, size, true);
+ }
+
+ dma_addr_t dma_direct_map_page(struct device *dev, struct page *page,
+@@ -375,7 +375,7 @@ dma_addr_t dma_direct_map_resource(struc
+ {
+ dma_addr_t dma_addr = paddr;
+
+- if (unlikely(!dma_direct_possible(dev, dma_addr, size))) {
++ if (unlikely(!dma_capable(dev, dma_addr, size, false))) {
+ report_addr(dev, dma_addr, size);
+ return DMA_MAPPING_ERROR;
+ }
+--- a/kernel/dma/swiotlb.c
++++ b/kernel/dma/swiotlb.c
+@@ -671,7 +671,7 @@ bool swiotlb_map(struct device *dev, phy
+
+ /* Ensure that the address returned is DMA'ble */
+ *dma_addr = __phys_to_dma(dev, *phys);
+- if (unlikely(!dma_capable(dev, *dma_addr, size))) {
++ if (unlikely(!dma_capable(dev, *dma_addr, size, true))) {
+ swiotlb_tbl_unmap_single(dev, *phys, size, dir,
+ attrs | DMA_ATTR_SKIP_CPU_SYNC);
+ return false;
diff --git a/patches.suse/dma-direct-unify-the-dma_capable-definitions.patch b/patches.suse/dma-direct-unify-the-dma_capable-definitions.patch
new file mode 100644
index 0000000000..4a42f8b4eb
--- /dev/null
+++ b/patches.suse/dma-direct-unify-the-dma_capable-definitions.patch
@@ -0,0 +1,114 @@
+From: Christoph Hellwig <hch@lst.de>
+Date: Tue, 12 Nov 2019 17:06:04 +0100
+Subject: dma-direct: unify the dma_capable definitions
+Git-commit: 130c1ccbf55330b55e82612a6e54eebb82c9d746
+Patch-mainline: Queued
+Git-repo: git://git.infradead.org/users/hch/dma-mapping.git
+References: jsc#SLE-7772
+
+Currently each architectures that wants to override dma_to_phys and
+phys_to_dma also has to provide dma_capable. But there isn't really
+any good reason for that. powerpc and mips just have copies of the
+generic one minus the latests fix, and the arm one was the inspiration
+for said fix, but misses the bus_dma_mask handling.
+Make all architectures use the generic version instead.
+
+Signed-off-by: Christoph Hellwig <hch@lst.de>
+Acked-by: Michael Ellerman <mpe@ellerman.id.au> (powerpc)
+Reviewed-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Acked-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+---
+ arch/arm/include/asm/dma-direct.h | 19 -------------------
+ arch/mips/include/asm/dma-direct.h | 8 --------
+ arch/powerpc/include/asm/dma-direct.h | 9 ---------
+ include/linux/dma-direct.h | 2 +-
+ 4 files changed, 1 insertion(+), 37 deletions(-)
+
+diff --git a/arch/arm/include/asm/dma-direct.h b/arch/arm/include/asm/dma-direct.h
+index b67e5fc1fe43..7c3001a6a775 100644
+--- a/arch/arm/include/asm/dma-direct.h
++++ b/arch/arm/include/asm/dma-direct.h
+@@ -14,23 +14,4 @@ static inline phys_addr_t __dma_to_phys(struct device *dev, dma_addr_t dev_addr)
+ return __pfn_to_phys(dma_to_pfn(dev, dev_addr)) + offset;
+ }
+
+-static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
+-{
+- u64 limit, mask;
+-
+- if (!dev->dma_mask)
+- return 0;
+-
+- mask = *dev->dma_mask;
+-
+- limit = (mask + 1) & ~mask;
+- if (limit && size > limit)
+- return 0;
+-
+- if ((addr | (addr + size - 1)) & ~mask)
+- return 0;
+-
+- return 1;
+-}
+-
+ #endif /* ASM_ARM_DMA_DIRECT_H */
+diff --git a/arch/mips/include/asm/dma-direct.h b/arch/mips/include/asm/dma-direct.h
+index b5c240806e1b..14e352651ce9 100644
+--- a/arch/mips/include/asm/dma-direct.h
++++ b/arch/mips/include/asm/dma-direct.h
+@@ -2,14 +2,6 @@
+ #ifndef _MIPS_DMA_DIRECT_H
+ #define _MIPS_DMA_DIRECT_H 1
+
+-static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
+-{
+- if (!dev->dma_mask)
+- return false;
+-
+- return addr + size - 1 <= *dev->dma_mask;
+-}
+-
+ dma_addr_t __phys_to_dma(struct device *dev, phys_addr_t paddr);
+ phys_addr_t __dma_to_phys(struct device *dev, dma_addr_t daddr);
+
+diff --git a/arch/powerpc/include/asm/dma-direct.h b/arch/powerpc/include/asm/dma-direct.h
+index a2912b47102c..e29e8a236b8d 100644
+--- a/arch/powerpc/include/asm/dma-direct.h
++++ b/arch/powerpc/include/asm/dma-direct.h
+@@ -2,15 +2,6 @@
+ #ifndef ASM_POWERPC_DMA_DIRECT_H
+ #define ASM_POWERPC_DMA_DIRECT_H 1
+
+-static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
+-{
+- if (!dev->dma_mask)
+- return false;
+-
+- return addr + size - 1 <=
+- min_not_zero(*dev->dma_mask, dev->bus_dma_mask);
+-}
+-
+ static inline dma_addr_t __phys_to_dma(struct device *dev, phys_addr_t paddr)
+ {
+ if (!dev)
+diff --git a/include/linux/dma-direct.h b/include/linux/dma-direct.h
+index 6db863c3eb93..991f8aa2676e 100644
+--- a/include/linux/dma-direct.h
++++ b/include/linux/dma-direct.h
+@@ -24,6 +24,7 @@ static inline phys_addr_t __dma_to_phys(struct device *dev, dma_addr_t dev_addr)
+
+ return paddr + ((phys_addr_t)dev->dma_pfn_offset << PAGE_SHIFT);
+ }
++#endif /* !CONFIG_ARCH_HAS_PHYS_TO_DMA */
+
+ static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
+ {
+@@ -38,7 +39,6 @@ static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
+
+ return end <= min_not_zero(*dev->dma_mask, dev->bus_dma_mask);
+ }
+-#endif /* !CONFIG_ARCH_HAS_PHYS_TO_DMA */
+
+ #ifdef CONFIG_ARCH_HAS_FORCE_DMA_UNENCRYPTED
+ bool force_dma_unencrypted(struct device *dev);
+
diff --git a/patches.suse/dma-mapping-treat-dev-bus_dma_mask-as-a-dma-limit.patch b/patches.suse/dma-mapping-treat-dev-bus_dma_mask-as-a-dma-limit.patch
new file mode 100644
index 0000000000..2052e5a0b4
--- /dev/null
+++ b/patches.suse/dma-mapping-treat-dev-bus_dma_mask-as-a-dma-limit.patch
@@ -0,0 +1,355 @@
+From: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Date: Thu, 21 Nov 2019 10:26:44 +0100
+Subject: dma-mapping: treat dev->bus_dma_mask as a DMA limit
+Git-commit: a7ba70f1787f977f970cd116076c6fce4b9e01cc
+Patch-mainline: Queued in subsystem maintainer repo
+Git-repo: git://git.infradead.org/users/hch/dma-mapping.git
+References: jsc#SLE-7772
+
+Using a mask to represent bus DMA constraints has a set of limitations.
+The biggest one being it can only hold a power of two (minus one). The
+DMA mapping code is already aware of this and treats dev->bus_dma_mask
+as a limit. This quirk is already used by some architectures although
+still rare.
+
+With the introduction of the Raspberry Pi 4 we've found a new contender
+for the use of bus DMA limits, as its PCIe bus can only address the
+lower 3GB of memory (of a total of 4GB). This is impossible to represent
+with a mask. To make things worse the device-tree code rounds non power
+of two bus DMA limits to the next power of two, which is unacceptable in
+this case.
+
+In the light of this, rename dev->bus_dma_mask to dev->bus_dma_limit all
+over the tree and treat it as such. Note that dev->bus_dma_limit should
+contain the higher accessible DMA address.
+
+Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Reviewed-by: Robin Murphy <robin.murphy@arm.com>
+Signed-off-by: Christoph Hellwig <hch@lst.de>
+---
+ arch/mips/pci/fixup-sb1250.c | 16 ++++++++--------
+ arch/powerpc/sysdev/fsl_pci.c | 6 +++---
+ arch/x86/kernel/pci-dma.c | 2 +-
+ arch/x86/mm/mem_encrypt.c | 2 +-
+ arch/x86/pci/sta2x11-fixup.c | 2 +-
+ drivers/acpi/arm64/iort.c | 20 +++++++-------------
+ drivers/iommu/dma-iommu.c | 3 +--
+ drivers/of/device.c | 9 +++++----
+ include/linux/device.h | 6 +++---
+ include/linux/dma-direct.h | 2 +-
+ include/linux/dma-mapping.h | 2 +-
+ kernel/dma/direct.c | 27 +++++++++++++--------------
+ 12 files changed, 45 insertions(+), 52 deletions(-)
+
+--- a/arch/mips/pci/fixup-sb1250.c
++++ b/arch/mips/pci/fixup-sb1250.c
+@@ -21,22 +21,22 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SI
+
+ /*
+ * The BCM1250, etc. PCI host bridge does not support DAC on its 32-bit
+- * bus, so we set the bus's DMA mask accordingly. However the HT link
++ * bus, so we set the bus's DMA limit accordingly. However the HT link
+ * down the artificial PCI-HT bridge supports 40-bit addressing and the
+ * SP1011 HT-PCI bridge downstream supports both DAC and a 64-bit bus
+ * width, so we record the PCI-HT bridge's secondary and subordinate bus
+- * numbers and do not set the mask for devices present in the inclusive
++ * numbers and do not set the limit for devices present in the inclusive
+ * range of those.
+ */
+-struct sb1250_bus_dma_mask_exclude {
++struct sb1250_bus_dma_limit_exclude {
+ bool set;
+ unsigned char start;
+ unsigned char end;
+ };
+
+-static int sb1250_bus_dma_mask(struct pci_dev *dev, void *data)
++static int sb1250_bus_dma_limit(struct pci_dev *dev, void *data)
+ {
+- struct sb1250_bus_dma_mask_exclude *exclude = data;
++ struct sb1250_bus_dma_limit_exclude *exclude = data;
+ bool exclude_this;
+ bool ht_bridge;
+
+@@ -55,7 +55,7 @@ static int sb1250_bus_dma_mask(struct pc
+ exclude->start, exclude->end);
+ } else {
+ dev_dbg(&dev->dev, "disabling DAC for device");
+- dev->dev.bus_dma_mask = DMA_BIT_MASK(32);
++ dev->dev.bus_dma_limit = DMA_BIT_MASK(32);
+ }
+
+ return 0;
+@@ -63,9 +63,9 @@ static int sb1250_bus_dma_mask(struct pc
+
+ static void quirk_sb1250_pci_dac(struct pci_dev *dev)
+ {
+- struct sb1250_bus_dma_mask_exclude exclude = { .set = false };
++ struct sb1250_bus_dma_limit_exclude exclude = { .set = false };
+
+- pci_walk_bus(dev->bus, sb1250_bus_dma_mask, &exclude);
++ pci_walk_bus(dev->bus, sb1250_bus_dma_limit, &exclude);
+ }
+ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SIBYTE, PCI_DEVICE_ID_BCM1250_PCI,
+ quirk_sb1250_pci_dac);
+--- a/arch/powerpc/sysdev/fsl_pci.c
++++ b/arch/powerpc/sysdev/fsl_pci.c
+@@ -115,8 +115,8 @@ static void pci_dma_dev_setup_swiotlb(st
+ {
+ struct pci_controller *hose = pci_bus_to_host(pdev->bus);
+
+- pdev->dev.bus_dma_mask =
+- hose->dma_window_base_cur + hose->dma_window_size;
++ pdev->dev.bus_dma_limit =
++ hose->dma_window_base_cur + hose->dma_window_size - 1;
+ }
+
+ static void setup_swiotlb_ops(struct pci_controller *hose)
+@@ -135,7 +135,7 @@ static void fsl_pci_dma_set_mask(struct
+ * mapping that allows addressing any RAM address from across PCI.
+ */
+ if (dev_is_pci(dev) && dma_mask >= pci64_dma_offset * 2 - 1) {
+- dev->bus_dma_mask = 0;
++ dev->bus_dma_limit = 0;
+ dev->archdata.dma_offset = pci64_dma_offset;
+ }
+ }
+--- a/arch/x86/kernel/pci-dma.c
++++ b/arch/x86/kernel/pci-dma.c
+@@ -160,7 +160,7 @@ rootfs_initcall(pci_iommu_init);
+
+ static int via_no_dac_cb(struct pci_dev *pdev, void *data)
+ {
+- pdev->dev.bus_dma_mask = DMA_BIT_MASK(32);
++ pdev->dev.bus_dma_limit = DMA_BIT_MASK(32);
+ return 0;
+ }
+
+--- a/arch/x86/mm/mem_encrypt.c
++++ b/arch/x86/mm/mem_encrypt.c
+@@ -369,7 +369,7 @@ bool force_dma_unencrypted(struct device
+ if (sme_active()) {
+ u64 dma_enc_mask = DMA_BIT_MASK(__ffs64(sme_me_mask));
+ u64 dma_dev_mask = min_not_zero(dev->coherent_dma_mask,
+- dev->bus_dma_mask);
++ dev->bus_dma_limit);
+
+ if (dma_dev_mask <= dma_enc_mask)
+ return true;
+--- a/arch/x86/pci/sta2x11-fixup.c
++++ b/arch/x86/pci/sta2x11-fixup.c
+@@ -143,7 +143,7 @@ static void sta2x11_map_ep(struct pci_de
+
+ dev->dma_pfn_offset = PFN_DOWN(-amba_base);
+
+- dev->bus_dma_mask = max_amba_addr;
++ dev->bus_dma_limit = max_amba_addr;
+ pci_set_consistent_dma_mask(pdev, max_amba_addr);
+ pci_set_dma_mask(pdev, max_amba_addr);
+
+--- a/drivers/acpi/arm64/iort.c
++++ b/drivers/acpi/arm64/iort.c
+@@ -1057,8 +1057,8 @@ static int rc_dma_get_range(struct devic
+ */
+ void iort_dma_setup(struct device *dev, u64 *dma_addr, u64 *dma_size)
+ {
+- u64 mask, dmaaddr = 0, size = 0, offset = 0;
+- int ret, msb;
++ u64 end, mask, dmaaddr = 0, size = 0, offset = 0;
++ int ret;
+
+ /*
+ * If @dev is expected to be DMA-capable then the bus code that created
+@@ -1085,19 +1085,13 @@ void iort_dma_setup(struct device *dev,
+ }
+
+ if (!ret) {
+- msb = fls64(dmaaddr + size - 1);
+ /*
+- * Round-up to the power-of-two mask or set
+- * the mask to the whole 64-bit address space
+- * in case the DMA region covers the full
+- * memory window.
++ * Limit coherent and dma mask based on size retrieved from
++ * firmware.
+ */
+- mask = msb == 64 ? U64_MAX : (1ULL << msb) - 1;
+- /*
+- * Limit coherent and dma mask based on size
+- * retrieved from firmware.
+- */
+- dev->bus_dma_mask = mask;
++ end = dmaaddr + size - 1;
++ mask = DMA_BIT_MASK(ilog2(end) + 1);
++ dev->bus_dma_limit = end;
+ dev->coherent_dma_mask = mask;
+ *dev->dma_mask = mask;
+ }
+--- a/drivers/iommu/dma-iommu.c
++++ b/drivers/iommu/dma-iommu.c
+@@ -405,8 +405,7 @@ static dma_addr_t iommu_dma_alloc_iova(s
+ if (iova_len < (1 << (IOVA_RANGE_CACHE_MAX_SIZE - 1)))
+ iova_len = roundup_pow_of_two(iova_len);
+
+- if (dev->bus_dma_mask)
+- dma_limit &= dev->bus_dma_mask;
++ dma_limit = min_not_zero(dma_limit, dev->bus_dma_limit);
+
+ if (domain->geometry.force_aperture)
+ dma_limit = min(dma_limit, domain->geometry.aperture_end);
+--- a/drivers/of/device.c
++++ b/drivers/of/device.c
+@@ -93,7 +93,7 @@ int of_dma_configure(struct device *dev,
+ bool coherent;
+ unsigned long offset;
+ const struct iommu_ops *iommu;
+- u64 mask;
++ u64 mask, end;
+
+ ret = of_dma_get_range(np, &dma_addr, &paddr, &size);
+ if (ret < 0) {
+@@ -148,12 +148,13 @@ int of_dma_configure(struct device *dev,
+ * Limit coherent and dma mask based on size and default mask
+ * set by the driver.
+ */
+- mask = DMA_BIT_MASK(ilog2(dma_addr + size - 1) + 1);
++ end = dma_addr + size - 1;
++ mask = DMA_BIT_MASK(ilog2(end) + 1);
+ dev->coherent_dma_mask &= mask;
+ *dev->dma_mask &= mask;
+- /* ...but only set bus mask if we found valid dma-ranges earlier */
++ /* ...but only set bus limit if we found valid dma-ranges earlier */
+ if (!ret)
+- dev->bus_dma_mask = mask;
++ dev->bus_dma_limit = end;
+
+ coherent = of_dma_is_coherent(np);
+ dev_dbg(dev, "device is%sdma coherent\n",
+--- a/include/linux/device.h
++++ b/include/linux/device.h
+@@ -1056,8 +1056,8 @@ struct dev_links_info {
+ * @coherent_dma_mask: Like dma_mask, but for alloc_coherent mapping as not all
+ * hardware supports 64-bit addresses for consistent allocations
+ * such descriptors.
+- * @bus_dma_mask: Mask of an upstream bridge or bus which imposes a smaller DMA
+- * limit than the device itself supports.
++ * @bus_dma_limit: Limit of an upstream bridge or bus which imposes a smaller
++ * DMA limit than the device itself supports.
+ * @dma_pfn_offset: offset of DMA memory range relatively of RAM
+ * @dma_parms: A low level driver may set these to teach IOMMU code about
+ * segment limitations.
+@@ -1140,7 +1140,7 @@ struct device {
+ not all hardware supports
+ 64 bit addresses for consistent
+ allocations such descriptors. */
+- u64 bus_dma_mask; /* upstream dma_mask constraint */
++ u64 bus_dma_limit; /* upstream dma constraint */
+ unsigned long dma_pfn_offset;
+
+ struct device_dma_parameters *dma_parms;
+--- a/include/linux/dma-direct.h
++++ b/include/linux/dma-direct.h
+@@ -61,7 +61,7 @@ static inline bool dma_capable(struct de
+ min(addr, end) < phys_to_dma(dev, PFN_PHYS(min_low_pfn)))
+ return false;
+
+- return end <= min_not_zero(*dev->dma_mask, dev->bus_dma_mask);
++ return end <= min_not_zero(*dev->dma_mask, dev->bus_dma_limit);
+ }
+
+ u64 dma_direct_get_required_mask(struct device *dev);
+--- a/include/linux/dma-mapping.h
++++ b/include/linux/dma-mapping.h
+@@ -695,7 +695,7 @@ static inline int dma_coerce_mask_and_co
+ */
+ static inline bool dma_addressing_limited(struct device *dev)
+ {
+- return min_not_zero(dma_get_mask(dev), dev->bus_dma_mask) <
++ return min_not_zero(dma_get_mask(dev), dev->bus_dma_limit) <
+ dma_get_required_mask(dev);
+ }
+
+--- a/kernel/dma/direct.c
++++ b/kernel/dma/direct.c
+@@ -27,10 +27,10 @@ static void report_addr(struct device *d
+ {
+ if (!dev->dma_mask) {
+ dev_err_once(dev, "DMA map on device without dma_mask\n");
+- } else if (*dev->dma_mask >= DMA_BIT_MASK(32) || dev->bus_dma_mask) {
++ } else if (*dev->dma_mask >= DMA_BIT_MASK(32) || dev->bus_dma_limit) {
+ dev_err_once(dev,
+- "overflow %pad+%zu of DMA mask %llx bus mask %llx\n",
+- &dma_addr, size, *dev->dma_mask, dev->bus_dma_mask);
++ "overflow %pad+%zu of DMA mask %llx bus limit %llx\n",
++ &dma_addr, size, *dev->dma_mask, dev->bus_dma_limit);
+ }
+ WARN_ON_ONCE(1);
+ }
+@@ -51,15 +51,14 @@ u64 dma_direct_get_required_mask(struct
+ }
+
+ static gfp_t __dma_direct_optimal_gfp_mask(struct device *dev, u64 dma_mask,
+- u64 *phys_mask)
++ u64 *phys_limit)
+ {
+- if (dev->bus_dma_mask && dev->bus_dma_mask < dma_mask)
+- dma_mask = dev->bus_dma_mask;
++ u64 dma_limit = min_not_zero(dma_mask, dev->bus_dma_limit);
+
+ if (force_dma_unencrypted(dev))
+- *phys_mask = __dma_to_phys(dev, dma_mask);
++ *phys_limit = __dma_to_phys(dev, dma_limit);
+ else
+- *phys_mask = dma_to_phys(dev, dma_mask);
++ *phys_limit = dma_to_phys(dev, dma_limit);
+
+ /*
+ * Optimistically try the zone that the physical address mask falls
+@@ -69,9 +68,9 @@ static gfp_t __dma_direct_optimal_gfp_ma
+ * Note that GFP_DMA32 and GFP_DMA are no ops without the corresponding
+ * zones.
+ */
+- if (*phys_mask <= DMA_BIT_MASK(ARCH_ZONE_DMA_BITS))
++ if (*phys_limit <= DMA_BIT_MASK(ARCH_ZONE_DMA_BITS))
+ return GFP_DMA;
+- if (*phys_mask <= DMA_BIT_MASK(32))
++ if (*phys_limit <= DMA_BIT_MASK(32))
+ return GFP_DMA32;
+ return 0;
+ }
+@@ -79,7 +78,7 @@ static gfp_t __dma_direct_optimal_gfp_ma
+ static bool dma_coherent_ok(struct device *dev, phys_addr_t phys, size_t size)
+ {
+ return phys_to_dma_direct(dev, phys) + size - 1 <=
+- min_not_zero(dev->coherent_dma_mask, dev->bus_dma_mask);
++ min_not_zero(dev->coherent_dma_mask, dev->bus_dma_limit);
+ }
+
+ struct page *__dma_direct_alloc_pages(struct device *dev, size_t size,
+@@ -88,7 +87,7 @@ struct page *__dma_direct_alloc_pages(st
+ size_t alloc_size = PAGE_ALIGN(size);
+ int node = dev_to_node(dev);
+ struct page *page = NULL;
+- u64 phys_mask;
++ u64 phys_limit;
+
+ if (attrs & DMA_ATTR_NO_WARN)
+ gfp |= __GFP_NOWARN;
+@@ -96,7 +95,7 @@ struct page *__dma_direct_alloc_pages(st
+ /* we always manually zero the memory once we are done: */
+ gfp &= ~__GFP_ZERO;
+ gfp |= __dma_direct_optimal_gfp_mask(dev, dev->coherent_dma_mask,
+- &phys_mask);
++ &phys_limit);
+ page = dma_alloc_contiguous(dev, alloc_size, gfp);
+ if (page && !dma_coherent_ok(dev, page_to_phys(page), size)) {
+ dma_free_contiguous(dev, page, alloc_size);
+@@ -110,7 +109,7 @@ again:
+ page = NULL;
+
+ if (IS_ENABLED(CONFIG_ZONE_DMA32) &&
+- phys_mask < DMA_BIT_MASK(64) &&
++ phys_limit < DMA_BIT_MASK(64) &&
+ !(gfp & (GFP_DMA32 | GFP_DMA))) {
+ gfp |= GFP_DMA32;
+ goto again;
diff --git a/patches.suse/linux-log2-h-add-roundup-rounddown_pow_two64-family-of-functions.patch b/patches.suse/linux-log2-h-add-roundup-rounddown_pow_two64-family-of-functions.patch
new file mode 100644
index 0000000000..6265309460
--- /dev/null
+++ b/patches.suse/linux-log2-h-add-roundup-rounddown_pow_two64-family-of-functions.patch
@@ -0,0 +1,190 @@
+From: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Date: Thu, 7 Nov 2019 20:37:16 +0100
+Subject: linux/log2.h: Add roundup/rounddown_pow_two64() family of functions
+Patch-mainline: Submitted, https://lkml.org/lkml/2019/11/26/131
+References: jsc#SLE-7772
+
+Some users need to make sure their rounding function accepts and returns
+64bit long variables regardless of the architecture. Sadly
+roundup/rounddown_pow_two() takes and returns unsigned longs. Create a
+new generic 64bit variant of the function and cleanup rougue custom
+implementations.
+
+Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+
+---
+
+Changes since v2:
+ - Use u64
+ - rename function to roundup/down_pow_two_u64()
+ - use 1ULL instead of 1UL
+ - Include function usage in of/device.c and acpi/arm64/iort.c
+---
+ drivers/acpi/arm64/iort.c | 2 -
+ drivers/net/ethernet/mellanox/mlx4/en_clock.c | 3 +
+ drivers/of/device.c | 2 -
+ drivers/pci/controller/pcie-rockchip-ep.c | 9 +---
+ include/linux/log2.h | 52 ++++++++++++++++++++++++++
+ kernel/dma/direct.c | 3 +
+ 6 files changed, 61 insertions(+), 10 deletions(-)
+
+--- a/drivers/acpi/arm64/iort.c
++++ b/drivers/acpi/arm64/iort.c
+@@ -1090,7 +1090,7 @@ void iort_dma_setup(struct device *dev,
+ * firmware.
+ */
+ end = dmaaddr + size - 1;
+- mask = DMA_BIT_MASK(ilog2(end) + 1);
++ mask = roundup_pow_of_two_u64(end) - 1;
+ dev->bus_dma_limit = end;
+ dev->coherent_dma_mask = mask;
+ *dev->dma_mask = mask;
+--- a/drivers/net/ethernet/mellanox/mlx4/en_clock.c
++++ b/drivers/net/ethernet/mellanox/mlx4/en_clock.c
+@@ -33,6 +33,7 @@
+
+ #include <linux/mlx4/device.h>
+ #include <linux/clocksource.h>
++#include <linux/log2.h>
+
+ #include "mlx4_en.h"
+
+@@ -252,7 +253,7 @@ static u32 freq_to_shift(u16 freq)
+ {
+ u32 freq_khz = freq * 1000;
+ u64 max_val_cycles = freq_khz * 1000 * MLX4_EN_WRAP_AROUND_SEC;
+- u64 max_val_cycles_rounded = 1ULL << fls64(max_val_cycles - 1);
++ u64 max_val_cycles_rounded = roundup_pow_of_two_u64(max_val_cycles);
+ /* calculate max possible multiplier in order to fit in 64bit */
+ u64 max_mul = div64_u64(ULLONG_MAX, max_val_cycles_rounded);
+
+--- a/drivers/of/device.c
++++ b/drivers/of/device.c
+@@ -149,7 +149,7 @@ int of_dma_configure(struct device *dev,
+ * set by the driver.
+ */
+ end = dma_addr + size - 1;
+- mask = DMA_BIT_MASK(ilog2(end) + 1);
++ mask = roundup_pow_of_two_u64(end) - 1;
+ dev->coherent_dma_mask &= mask;
+ *dev->dma_mask &= mask;
+ /* ...but only set bus limit if we found valid dma-ranges earlier */
+--- a/drivers/pci/controller/pcie-rockchip-ep.c
++++ b/drivers/pci/controller/pcie-rockchip-ep.c
+@@ -16,6 +16,7 @@
+ #include <linux/platform_device.h>
+ #include <linux/pci-epf.h>
+ #include <linux/sizes.h>
++#include <linux/log2.h>
+
+ #include "pcie-rockchip.h"
+
+@@ -70,7 +71,7 @@ static void rockchip_pcie_prog_ep_ob_atu
+ u32 r, u32 type, u64 cpu_addr,
+ u64 pci_addr, size_t size)
+ {
+- u64 sz = 1ULL << fls64(size - 1);
++ u64 sz = roundup_pow_of_two_u64(size);
+ int num_pass_bits = ilog2(sz);
+ u32 addr0, addr1, desc0, desc1;
+ bool is_nor_msg = (type == AXI_WRAPPER_NOR_MSG);
+@@ -172,11 +173,7 @@ static int rockchip_pcie_ep_set_bar(stru
+ /* BAR size is 2^(aperture + 7) */
+ sz = max_t(size_t, epf_bar->size, MIN_EP_APERTURE);
+
+- /*
+- * roundup_pow_of_two() returns an unsigned long, which is not suited
+- * for 64bit values.
+- */
+- sz = 1ULL << fls64(sz - 1);
++ sz = roundup_pow_of_two_u64(sz);
+ aperture = ilog2(sz) - 7; /* 128B -> 0, 256B -> 1, 512B -> 2, ... */
+
+ if ((flags & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO) {
+--- a/include/linux/log2.h
++++ b/include/linux/log2.h
+@@ -68,6 +68,24 @@ unsigned long __rounddown_pow_of_two(uns
+ }
+
+ /**
++ * __roundup_pow_of_two_u64() - round 64bit value up to nearest power of two
++ * @n: value to round up
++ */
++static inline __attribute__((const)) u64 __roundup_pow_of_two_u64(u64 n)
++{
++ return 1ULL << fls64(n - 1);
++}
++
++/**
++ * __rounddown_pow_of_two_u64() - round 64bit value down to nearest power of two
++ * @n: value to round down
++ */
++static inline __attribute__((const)) u64 __rounddown_pow_of_two_u64(u64 n)
++{
++ return 1ULL << (fls64(n) - 1);
++}
++
++/**
+ * const_ilog2 - log base 2 of 32-bit or a 64-bit constant unsigned value
+ * @n: parameter
+ *
+@@ -194,6 +212,40 @@ unsigned long __rounddown_pow_of_two(uns
+ __rounddown_pow_of_two(n) \
+ )
+
++/**
++ * roundup_pow_of_two_u64 - round the given 64bit value up to nearest power of
++ * two
++ * @n: parameter
++ *
++ * round the given value up to the nearest power of two
++ * - the result is undefined when n == 0
++ * - this can be used to initialise global variables from constant data
++ */
++#define roundup_pow_of_two_u64(n) \
++( \
++ __builtin_constant_p(n) ? ( \
++ (n == 1) ? 1 : \
++ (1UL << (ilog2((n) - 1) + 1)) \
++ ) : \
++ __roundup_pow_of_two_u64(n) \
++)
++
++/**
++ * rounddown_pow_of_two_u64 - round the given 64bit value down to nearest power
++ * of two
++ * @n: parameter
++ *
++ * round the given value down to the nearest power of two
++ * - the result is undefined when n == 0
++ * - this can be used to initialise global variables from constant data
++ */
++#define rounddown_pow_of_two_u64(n) \
++( \
++ __builtin_constant_p(n) ? ( \
++ (1UL << ilog2(n))) : \
++ __rounddown_pow_of_two_u64(n) \
++)
++
+ static inline __attribute_const__
+ int __order_base_2(unsigned long n)
+ {
+--- a/kernel/dma/direct.c
++++ b/kernel/dma/direct.c
+@@ -14,6 +14,7 @@
+ #include <linux/pfn.h>
+ #include <linux/set_memory.h>
+ #include <linux/swiotlb.h>
++#include <linux/log2.h>
+
+ /*
+ * Most architectures use ZONE_DMA for the first 16 Megabytes, but
+@@ -47,7 +48,7 @@ u64 dma_direct_get_required_mask(struct
+ {
+ u64 max_dma = phys_to_dma_direct(dev, (max_pfn - 1) << PAGE_SHIFT);
+
+- return (1ULL << (fls64(max_dma) - 1)) * 2 - 1;
++ return rounddown_pow_of_two_u64(max_dma) * 2 - 1;
+ }
+
+ static gfp_t __dma_direct_optimal_gfp_mask(struct device *dev, u64 dma_mask,
diff --git a/patches.suse/of-address-fix-of_pci_range_parser_one-translation-of-dma-addresses.patch b/patches.suse/of-address-fix-of_pci_range_parser_one-translation-of-dma-addresses.patch
new file mode 100644
index 0000000000..498151250a
--- /dev/null
+++ b/patches.suse/of-address-fix-of_pci_range_parser_one-translation-of-dma-addresses.patch
@@ -0,0 +1,76 @@
+From: Rob Herring <robh@kernel.org>
+Date: Thu, 5 Sep 2019 10:47:26 +0100
+Subject: of/address: Fix of_pci_range_parser_one translation of DMA addresses
+Git-commit: 645c138636de3d6d6ed7d92edec39298fd6873d7
+Patch-mainline: Queued
+Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git
+References: jsc#SLE-7772
+
+of_pci_range_parser_one() has a bug when parsing dma-ranges. When it
+translates the parent address (aka cpu address in the code), 'ranges' is
+always being used. This happens to work because most users are just 1:1
+translation.
+
+Cc: Robin Murphy <robin.murphy@arm.com>
+Tested-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Reviewed-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Signed-off-by: Rob Herring <robh@kernel.org>
+Acked-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+---
+ drivers/of/address.c | 15 ++++++++++++---
+ include/linux/of_address.h | 1 +
+ 2 files changed, 13 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/of/address.c b/drivers/of/address.c
+index 1c291bd6bce2..5ce69d026584 100644
+--- a/drivers/of/address.c
++++ b/drivers/of/address.c
+@@ -243,6 +243,7 @@ static int parser_init(struct of_pci_range_parser *parser,
+ parser->node = node;
+ parser->pna = of_n_addr_cells(node);
+ parser->np = parser->pna + na + ns;
++ parser->dma = !strcmp(name, "dma-ranges");
+
+ parser->range = of_get_property(node, name, &rlen);
+ if (parser->range == NULL)
+@@ -281,7 +282,11 @@ struct of_pci_range *of_pci_range_parser_one(struct of_pci_range_parser *parser,
+ range->pci_space = be32_to_cpup(parser->range);
+ range->flags = of_bus_pci_get_flags(parser->range);
+ range->pci_addr = of_read_number(parser->range + 1, ns);
+- range->cpu_addr = of_translate_address(parser->node,
++ if (parser->dma)
++ range->cpu_addr = of_translate_dma_address(parser->node,
++ parser->range + na);
++ else
++ range->cpu_addr = of_translate_address(parser->node,
+ parser->range + na);
+ range->size = of_read_number(parser->range + parser->pna + na, ns);
+
+@@ -294,8 +299,12 @@ struct of_pci_range *of_pci_range_parser_one(struct of_pci_range_parser *parser,
+
+ flags = of_bus_pci_get_flags(parser->range);
+ pci_addr = of_read_number(parser->range + 1, ns);
+- cpu_addr = of_translate_address(parser->node,
+- parser->range + na);
++ if (parser->dma)
++ cpu_addr = of_translate_dma_address(parser->node,
++ parser->range + na);
++ else
++ cpu_addr = of_translate_address(parser->node,
++ parser->range + na);
+ size = of_read_number(parser->range + parser->pna + na, ns);
+
+ if (flags != range->flags)
+diff --git a/include/linux/of_address.h b/include/linux/of_address.h
+index ddda3936039c..eac7ab109df4 100644
+--- a/include/linux/of_address.h
++++ b/include/linux/of_address.h
+@@ -12,6 +12,7 @@ struct of_pci_range_parser {
+ const __be32 *end;
+ int np;
+ int pna;
++ bool dma;
+ };
+
+ struct of_pci_range {
+
diff --git a/patches.suse/of-address-follow-dma-parent-for-dma-coherent.patch b/patches.suse/of-address-follow-dma-parent-for-dma-coherent.patch
new file mode 100644
index 0000000000..73cf3ad5e1
--- /dev/null
+++ b/patches.suse/of-address-follow-dma-parent-for-dma-coherent.patch
@@ -0,0 +1,35 @@
+From: Robin Murphy <robin.murphy@arm.com>
+Date: Wed, 3 Jul 2019 14:47:31 +0100
+Subject: of: address: Follow DMA parent for "dma-coherent"
+Git-commit: c60bf3eb888a362100aa1bdbea351dab681e262a
+Patch-mainline: Queued
+Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git
+References: jsc#SLE-7772
+
+Much like for address translation, when checking for DMA coherence we
+should be sure to walk up the DMA hierarchy, rather than the MMIO one,
+now that we can accommodate them being different.
+
+Signed-off-by: Robin Murphy <robin.murphy@arm.com>
+Tested-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Reviewed-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Signed-off-by: Rob Herring <robh@kernel.org>
+Acked-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+---
+ drivers/of/address.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/of/address.c b/drivers/of/address.c
+index e9188c82fdae..3fd34f7ad772 100644
+--- a/drivers/of/address.c
++++ b/drivers/of/address.c
+@@ -999,7 +999,7 @@ bool of_dma_is_coherent(struct device_node *np)
+ of_node_put(node);
+ return true;
+ }
+- node = of_get_next_parent(node);
++ node = of_get_next_dma_parent(node);
+ }
+ of_node_put(node);
+ return false;
+
diff --git a/patches.suse/of-address-introduce-of_get_next_dma_parent-helper.patch b/patches.suse/of-address-introduce-of_get_next_dma_parent-helper.patch
new file mode 100644
index 0000000000..10a93e9596
--- /dev/null
+++ b/patches.suse/of-address-introduce-of_get_next_dma_parent-helper.patch
@@ -0,0 +1,44 @@
+From: Robin Murphy <robin.murphy@arm.com>
+Date: Wed, 3 Jul 2019 18:23:01 +0100
+Subject: of/address: Introduce of_get_next_dma_parent() helper
+Git-commit: 862ab5578f754117742c8b8c8e5ddf98bdb190ba
+Patch-mainline: Queued
+Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git
+References: jsc#SLE-7772
+
+Add of_get_next_dma_parent() helper which is similar to
+__of_get_dma_parent(), but can be used in iterators and decrements the
+ref count on the prior parent.
+
+Signed-off-by: Robin Murphy <robin.murphy@arm.com>
+Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
+Tested-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Reviewed-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Signed-off-by: Rob Herring <robh@kernel.org>
+Acked-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+---
+ drivers/of/address.c | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+diff --git a/drivers/of/address.c b/drivers/of/address.c
+index 53d2656c2269..e9188c82fdae 100644
+--- a/drivers/of/address.c
++++ b/drivers/of/address.c
+@@ -695,6 +695,16 @@ static struct device_node *__of_get_dma_parent(const struct device_node *np)
+ return of_node_get(args.np);
+ }
+
++static struct device_node *of_get_next_dma_parent(struct device_node *np)
++{
++ struct device_node *parent;
++
++ parent = __of_get_dma_parent(np);
++ of_node_put(np);
++
++ return parent;
++}
++
+ u64 of_translate_dma_address(struct device_node *dev, const __be32 *in_addr)
+ {
+ struct device_node *host;
+
diff --git a/patches.suse/of-address-translate-dma-ranges-for-parent-nodes-missing-dma-ranges.patch b/patches.suse/of-address-translate-dma-ranges-for-parent-nodes-missing-dma-ranges.patch
new file mode 100644
index 0000000000..37db6aed0f
--- /dev/null
+++ b/patches.suse/of-address-translate-dma-ranges-for-parent-nodes-missing-dma-ranges.patch
@@ -0,0 +1,45 @@
+From: Rob Herring <robh@kernel.org>
+Date: Wed, 4 Sep 2019 11:43:30 +0100
+Subject: of/address: Translate 'dma-ranges' for parent nodes missing
+ 'dma-ranges'
+Git-commit: 81db12ee15cb83926e290a8a3654a2dfebc80935
+Patch-mainline: Queued
+Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git
+References: jsc#SLE-7772
+
+'dma-ranges' frequently exists without parent nodes having 'dma-ranges'.
+While this is an error for 'ranges', this is fine because DMA capable
+devices always have a translatable DMA address. Also, with no
+'dma-ranges' at all, the assumption is that DMA addresses are 1:1 with
+no restrictions unless perhaps the device itself has implicit
+restrictions.
+
+Cc: Robin Murphy <robin.murphy@arm.com>
+Tested-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Reviewed-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Signed-off-by: Rob Herring <robh@kernel.org>
+Acked-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+---
+ drivers/of/address.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/of/address.c b/drivers/of/address.c
+index 887c0413f648..1c291bd6bce2 100644
+--- a/drivers/of/address.c
++++ b/drivers/of/address.c
+@@ -519,9 +519,13 @@ static int of_translate_one(struct device_node *parent, struct of_bus *bus,
+ *
+ * As far as we know, this damage only exists on Apple machines, so
+ * This code is only enabled on powerpc. --gcl
++ *
++ * This quirk also applies for 'dma-ranges' which frequently exist in
++ * child nodes without 'dma-ranges' in the parent nodes. --RobH
+ */
+ ranges = of_get_property(parent, rprop, &rlen);
+- if (ranges == NULL && !of_empty_ranges_quirk(parent)) {
++ if (ranges == NULL && !of_empty_ranges_quirk(parent) &&
++ strcmp(rprop, "dma-ranges")) {
+ pr_debug("no ranges; cannot translate\n");
+ return 1;
+ }
+
diff --git a/patches.suse/of-factor-out-addr-size-cells-parsing.patch b/patches.suse/of-factor-out-addr-size-cells-parsing.patch
new file mode 100644
index 0000000000..3f2acd2579
--- /dev/null
+++ b/patches.suse/of-factor-out-addr-size-cells-parsing.patch
@@ -0,0 +1,108 @@
+From: Robin Murphy <robin.murphy@arm.com>
+Date: Tue, 2 Jul 2019 18:42:39 +0100
+Subject: of: Factor out #{addr,size}-cells parsing
+Git-commit: b68ac8dc22ebbf003e26e44bf4dd3030c076df5a
+Patch-mainline: Queued
+Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git
+References: jsc#SLE-7772
+
+In some cases such as PCI host controllers, we may have a "parent bus"
+which is an OF leaf node, but still need to correctly parse ranges from
+the point of view of that bus. For that, factor out variants of the
+"#addr-cells" and "#size-cells" parsers which do not assume they have a
+device node and thus immediately traverse upwards before reading the
+relevant property.
+
+Signed-off-by: Robin Murphy <robin.murphy@arm.com>
+[robh: don't make of_bus_n_{addr,size}_cells() public]
+Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
+Tested-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Reviewed-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Signed-off-by: Rob Herring <robh@kernel.org>
+Acked-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+---
+ drivers/of/address.c | 2 ++
+ drivers/of/base.c | 32 ++++++++++++++++++++++----------
+ drivers/of/of_private.h | 3 +++
+ 3 files changed, 27 insertions(+), 10 deletions(-)
+
+--- a/drivers/of/address.c
++++ b/drivers/of/address.c
+@@ -14,6 +14,8 @@
+ #include <linux/slab.h>
+ #include <linux/string.h>
+
++#include "of_private.h"
++
+ /* Max address size we deal with */
+ #define OF_MAX_ADDR_CELLS 4
+ #define OF_CHECK_ADDR_COUNT(na) ((na) > 0 && (na) <= OF_MAX_ADDR_CELLS)
+--- a/drivers/of/base.c
++++ b/drivers/of/base.c
+@@ -86,34 +86,46 @@ static bool __of_node_is_type(const stru
+ return np && match && type && !strcmp(match, type);
+ }
+
+-int of_n_addr_cells(struct device_node *np)
++int of_bus_n_addr_cells(struct device_node *np)
+ {
+ u32 cells;
+
+- do {
+- if (np->parent)
+- np = np->parent;
++ for (; np; np = np->parent)
+ if (!of_property_read_u32(np, "#address-cells", &cells))
+ return cells;
+- } while (np->parent);
++
+ /* No #address-cells property for the root node */
+ return OF_ROOT_NODE_ADDR_CELLS_DEFAULT;
+ }
++
++int of_n_addr_cells(struct device_node *np)
++{
++ if (np->parent)
++ np = np->parent;
++
++ return of_bus_n_addr_cells(np);
++}
+ EXPORT_SYMBOL(of_n_addr_cells);
+
+-int of_n_size_cells(struct device_node *np)
++int of_bus_n_size_cells(struct device_node *np)
+ {
+ u32 cells;
+
+- do {
+- if (np->parent)
+- np = np->parent;
++ for (; np; np = np->parent)
+ if (!of_property_read_u32(np, "#size-cells", &cells))
+ return cells;
+- } while (np->parent);
++
+ /* No #size-cells property for the root node */
+ return OF_ROOT_NODE_SIZE_CELLS_DEFAULT;
+ }
++
++int of_n_size_cells(struct device_node *np)
++{
++ if (np->parent)
++ np = np->parent;
++
++ return of_bus_n_size_cells(np);
++}
+ EXPORT_SYMBOL(of_n_size_cells);
+
+ #ifdef CONFIG_NUMA
+--- a/drivers/of/of_private.h
++++ b/drivers/of/of_private.h
+@@ -158,4 +158,7 @@ extern void __of_sysfs_remove_bin_file(s
+ #define for_each_transaction_entry_reverse(_oft, _te) \
+ list_for_each_entry_reverse(_te, &(_oft)->te_list, node)
+
++extern int of_bus_n_addr_cells(struct device_node *np);
++extern int of_bus_n_size_cells(struct device_node *np);
++
+ #endif /* _LINUX_OF_PRIVATE_H */
diff --git a/patches.suse/of-make-of_dma_get_range-work-on-bus-nodes.patch b/patches.suse/of-make-of_dma_get_range-work-on-bus-nodes.patch
new file mode 100644
index 0000000000..9252fdec87
--- /dev/null
+++ b/patches.suse/of-make-of_dma_get_range-work-on-bus-nodes.patch
@@ -0,0 +1,109 @@
+From: Robin Murphy <robin.murphy@arm.com>
+Date: Wed, 3 Jul 2019 18:42:20 +0100
+Subject: of: Make of_dma_get_range() work on bus nodes
+Git-commit: 951d48855d86e72e0d6de73440fe09d363168064
+Patch-mainline: Queued
+Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git
+References: jsc#SLE-7772
+
+Since the "dma-ranges" property is only valid for a node representing a
+bus, of_dma_get_range() currently assumes the node passed in is a leaf
+representing a device, and starts the walk from its parent. In cases
+like PCI host controllers on typical FDT systems, however, where the PCI
+endpoints are probed dynamically the initial leaf node represents the
+'bus' itself, and this logic means we fail to consider any "dma-ranges"
+describing the host bridge itself. Rework the logic such that
+of_dma_get_range() also works correctly starting from a bus node
+containing "dma-ranges".
+
+While this does mean "dma-ranges" could incorrectly be in a device leaf
+node, there isn't really any way in this function to ensure that a leaf
+node is or isn't a bus node.
+
+Signed-off-by: Robin Murphy <robin.murphy@arm.com>
+[robh: Allow for the bus child node to still be passed in]
+Signed-off-by: Rob Herring <robh@kernel.org>
+Reviewed-by: Robin Murphy <robin.murphy@arm.com>
+Reviewed-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Tested-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Acked-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+---
+ drivers/of/address.c | 44 ++++++++++++++++++--------------------------
+ 1 file changed, 18 insertions(+), 26 deletions(-)
+
+--- a/drivers/of/address.c
++++ b/drivers/of/address.c
+@@ -949,47 +949,39 @@ int of_dma_get_range(struct device_node
+ const __be32 *ranges = NULL;
+ int len, naddr, nsize, pna;
+ int ret = 0;
++ bool found_dma_ranges = false;
+ u64 dmaaddr;
+
+- if (!node)
+- return -EINVAL;
+-
+- while (1) {
+- struct device_node *parent;
+-
+- naddr = of_n_addr_cells(node);
+- nsize = of_n_size_cells(node);
+-
+- parent = __of_get_dma_parent(node);
+- of_node_put(node);
+-
+- node = parent;
+- if (!node)
+- break;
+-
++ while (node) {
+ ranges = of_get_property(node, "dma-ranges", &len);
+
+ /* Ignore empty ranges, they imply no translation required */
+ if (ranges && len > 0)
+ break;
+
+- /*
+- * At least empty ranges has to be defined for parent node if
+- * DMA is supported
+- */
+- if (!ranges)
+- break;
++ /* Once we find 'dma-ranges', then a missing one is an error */
++ if (found_dma_ranges && !ranges) {
++ ret = -ENODEV;
++ goto out;
++ }
++ found_dma_ranges = true;
++
++ node = of_get_next_dma_parent(node);
+ }
+
+- if (!ranges) {
++ if (!node || !ranges) {
+ pr_debug("no dma-ranges found for node(%pOF)\n", np);
+ ret = -ENODEV;
+ goto out;
+ }
+
+- len /= sizeof(u32);
+-
++ naddr = of_bus_n_addr_cells(node);
++ nsize = of_bus_n_size_cells(node);
+ pna = of_n_addr_cells(node);
++ if ((len / sizeof(__be32)) % (pna + naddr + nsize)) {
++ ret = -EINVAL;
++ goto out;
++ }
+
+ /* dma-ranges format:
+ * DMA addr : naddr cells
+@@ -997,7 +989,7 @@ int of_dma_get_range(struct device_node
+ * size : nsize cells
+ */
+ dmaaddr = of_read_number(ranges, naddr);
+- *paddr = of_translate_dma_address(np, ranges);
++ *paddr = of_translate_dma_address(node, ranges + naddr);
+ if (*paddr == OF_BAD_ADDR) {
+ pr_err("translation of DMA address(%pad) to CPU address failed node(%pOF)\n",
+ dma_addr, np);
diff --git a/patches.suse/pci-aardvark-use-pci_parse_request_of_pci_ranges.patch b/patches.suse/pci-aardvark-use-pci_parse_request_of_pci_ranges.patch
new file mode 100644
index 0000000000..cc35bb4f7c
--- /dev/null
+++ b/patches.suse/pci-aardvark-use-pci_parse_request_of_pci_ranges.patch
@@ -0,0 +1,126 @@
+From: Rob Herring <robh@kernel.org>
+Date: Mon, 28 Oct 2019 11:32:34 -0500
+Subject: PCI: aardvark: Use pci_parse_request_of_pci_ranges()
+Git-commit: 4e5be6f81be72c980580676e31c2b542c0267757
+Patch-mainline: Queued in subsystem maintainer repository
+Git-repo: https://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci.git
+References: jsc#SLE-7772
+
+Convert aardvark to use the common pci_parse_request_of_pci_ranges().
+
+There's no need to assign the resources to a temporary list first. Just
+use bridge->windows directly and remove all the temporary list handling.
+
+Tested-by: Thomas Petazzoni <thomas.petazzoni@bootlin.com>
+Signed-off-by: Rob Herring <robh@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Reviewed-by: Andrew Murray <andrew.murray@arm.com>
+Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Cc: Bjorn Helgaas <bhelgaas@google.com>
+
+Acked-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+---
+ drivers/pci/controller/pci-aardvark.c | 60 +++--------------------------------
+ 1 file changed, 4 insertions(+), 56 deletions(-)
+
+diff --git a/drivers/pci/controller/pci-aardvark.c b/drivers/pci/controller/pci-aardvark.c
+index fc0fe4d4de49..9cbeba507f0c 100644
+--- a/drivers/pci/controller/pci-aardvark.c
++++ b/drivers/pci/controller/pci-aardvark.c
+@@ -186,7 +186,6 @@
+ struct advk_pcie {
+ struct platform_device *pdev;
+ void __iomem *base;
+- struct list_head resources;
+ struct irq_domain *irq_domain;
+ struct irq_chip irq_chip;
+ struct irq_domain *msi_domain;
+@@ -910,63 +909,11 @@ static irqreturn_t advk_pcie_irq_handler(int irq, void *arg)
+ return IRQ_HANDLED;
+ }
+
+-static int advk_pcie_parse_request_of_pci_ranges(struct advk_pcie *pcie)
+-{
+- int err, res_valid = 0;
+- struct device *dev = &pcie->pdev->dev;
+- struct resource_entry *win, *tmp;
+- resource_size_t iobase;
+-
+- INIT_LIST_HEAD(&pcie->resources);
+-
+- err = devm_of_pci_get_host_bridge_resources(dev, 0, 0xff,
+- &pcie->resources, &iobase);
+- if (err)
+- return err;
+-
+- err = devm_request_pci_bus_resources(dev, &pcie->resources);
+- if (err)
+- goto out_release_res;
+-
+- resource_list_for_each_entry_safe(win, tmp, &pcie->resources) {
+- struct resource *res = win->res;
+-
+- switch (resource_type(res)) {
+- case IORESOURCE_IO:
+- err = devm_pci_remap_iospace(dev, res, iobase);
+- if (err) {
+- dev_warn(dev, "error %d: failed to map resource %pR\n",
+- err, res);
+- resource_list_destroy_entry(win);
+- }
+- break;
+- case IORESOURCE_MEM:
+- res_valid |= !(res->flags & IORESOURCE_PREFETCH);
+- break;
+- case IORESOURCE_BUS:
+- pcie->root_bus_nr = res->start;
+- break;
+- }
+- }
+-
+- if (!res_valid) {
+- dev_err(dev, "non-prefetchable memory resource required\n");
+- err = -EINVAL;
+- goto out_release_res;
+- }
+-
+- return 0;
+-
+-out_release_res:
+- pci_free_resource_list(&pcie->resources);
+- return err;
+-}
+-
+ static int advk_pcie_probe(struct platform_device *pdev)
+ {
+ struct device *dev = &pdev->dev;
+ struct advk_pcie *pcie;
+- struct resource *res;
++ struct resource *res, *bus;
+ struct pci_host_bridge *bridge;
+ int ret, irq;
+
+@@ -991,11 +938,13 @@ static int advk_pcie_probe(struct platform_device *pdev)
+ return ret;
+ }
+
+- ret = advk_pcie_parse_request_of_pci_ranges(pcie);
++ ret = pci_parse_request_of_pci_ranges(dev, &bridge->windows,
++ &bus);
+ if (ret) {
+ dev_err(dev, "Failed to parse resources\n");
+ return ret;
+ }
++ pcie->root_bus_nr = bus->start;
+
+ advk_pcie_setup_hw(pcie);
+
+@@ -1014,7 +963,6 @@ static int advk_pcie_probe(struct platform_device *pdev)
+ return ret;
+ }
+
+- list_splice_init(&pcie->resources, &bridge->windows);
+ bridge->dev.parent = dev;
+ bridge->sysdata = pcie;
+ bridge->busnr = 0;
+
diff --git a/patches.suse/pci-altera-use-pci_parse_request_of_pci_ranges.patch b/patches.suse/pci-altera-use-pci_parse_request_of_pci_ranges.patch
new file mode 100644
index 0000000000..836c9e2eff
--- /dev/null
+++ b/patches.suse/pci-altera-use-pci_parse_request_of_pci_ranges.patch
@@ -0,0 +1,111 @@
+From: Rob Herring <robh@kernel.org>
+Date: Mon, 28 Oct 2019 11:32:35 -0500
+Subject: PCI: altera: Use pci_parse_request_of_pci_ranges()
+Git-commit: e634e3e0b790789ee16f4df503ccab13f1169134
+Patch-mainline: Queued in subsystem maintainer repository
+Git-repo: https://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci.git
+References: jsc#SLE-7772
+
+Convert altera host bridge to use the common
+pci_parse_request_of_pci_ranges().
+
+There's no need to assign the resources to a temporary list first. Just
+use bridge->windows directly and remove all the temporary list handling.
+
+If an I/O range is present, then it will now be mapped. It's expected
+that h/w which doesn't support I/O range will not define one.
+
+Signed-off-by: Rob Herring <robh@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Reviewed-by: Andrew Murray <andrew.murray@arm.com>
+Cc: Ley Foon Tan <lftan@altera.com>
+Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Cc: Bjorn Helgaas <bhelgaas@google.com>
+Cc: rfi@lists.rocketboards.org
+
+Acked-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+---
+ drivers/pci/controller/pcie-altera.c | 41 ++----------------------------------
+ 1 file changed, 2 insertions(+), 39 deletions(-)
+
+diff --git a/drivers/pci/controller/pcie-altera.c b/drivers/pci/controller/pcie-altera.c
+index d2497ca43828..ba025efeae28 100644
+--- a/drivers/pci/controller/pcie-altera.c
++++ b/drivers/pci/controller/pcie-altera.c
+@@ -92,7 +92,6 @@ struct altera_pcie {
+ u8 root_bus_nr;
+ struct irq_domain *irq_domain;
+ struct resource bus_range;
+- struct list_head resources;
+ const struct altera_pcie_data *pcie_data;
+ };
+
+@@ -670,39 +669,6 @@ static void altera_pcie_isr(struct irq_desc *desc)
+ chained_irq_exit(chip, desc);
+ }
+
+-static int altera_pcie_parse_request_of_pci_ranges(struct altera_pcie *pcie)
+-{
+- int err, res_valid = 0;
+- struct device *dev = &pcie->pdev->dev;
+- struct resource_entry *win;
+-
+- err = devm_of_pci_get_host_bridge_resources(dev, 0, 0xff,
+- &pcie->resources, NULL);
+- if (err)
+- return err;
+-
+- err = devm_request_pci_bus_resources(dev, &pcie->resources);
+- if (err)
+- goto out_release_res;
+-
+- resource_list_for_each_entry(win, &pcie->resources) {
+- struct resource *res = win->res;
+-
+- if (resource_type(res) == IORESOURCE_MEM)
+- res_valid |= !(res->flags & IORESOURCE_PREFETCH);
+- }
+-
+- if (res_valid)
+- return 0;
+-
+- dev_err(dev, "non-prefetchable memory resource required\n");
+- err = -EINVAL;
+-
+-out_release_res:
+- pci_free_resource_list(&pcie->resources);
+- return err;
+-}
+-
+ static int altera_pcie_init_irq_domain(struct altera_pcie *pcie)
+ {
+ struct device *dev = &pcie->pdev->dev;
+@@ -833,9 +799,8 @@ static int altera_pcie_probe(struct platform_device *pdev)
+ return ret;
+ }
+
+- INIT_LIST_HEAD(&pcie->resources);
+-
+- ret = altera_pcie_parse_request_of_pci_ranges(pcie);
++ ret = pci_parse_request_of_pci_ranges(dev, &bridge->windows,
++ NULL);
+ if (ret) {
+ dev_err(dev, "Failed add resources\n");
+ return ret;
+@@ -853,7 +818,6 @@ static int altera_pcie_probe(struct platform_device *pdev)
+ cra_writel(pcie, P2A_INT_ENA_ALL, P2A_INT_ENABLE);
+ altera_pcie_host_init(pcie);
+
+- list_splice_init(&pcie->resources, &bridge->windows);
+ bridge->dev.parent = dev;
+ bridge->sysdata = pcie;
+ bridge->busnr = pcie->root_bus_nr;
+@@ -884,7 +848,6 @@ static int altera_pcie_remove(struct platform_device *pdev)
+
+ pci_stop_root_bus(bridge->bus);
+ pci_remove_root_bus(bridge->bus);
+- pci_free_resource_list(&pcie->resources);
+ altera_pcie_irq_teardown(pcie);
+
+ return 0;
+
diff --git a/patches.suse/pci-brcmstb-add-broadcom-stb-pcie-host-controller-driver.patch b/patches.suse/pci-brcmstb-add-broadcom-stb-pcie-host-controller-driver.patch
new file mode 100644
index 0000000000..26610e87e5
--- /dev/null
+++ b/patches.suse/pci-brcmstb-add-broadcom-stb-pcie-host-controller-driver.patch
@@ -0,0 +1,843 @@
+From: Jim Quinlan <james.quinlan@broadcom.com>
+Date: Tue, 5 Nov 2019 15:02:55 +0100
+Subject: PCI: brcmstb: add Broadcom STB PCIe host controller driver
+Patch-mainline: Submitted, https://lkml.org/lkml/2019/11/26/131
+References: jsc#SLE-7772
+
+This adds a basic driver for Broadcom's STB PCIe controller, for now
+aimed at Raspberry Pi 4's SoC, bcm2711.
+
+Signed-off-by: Jim Quinlan <james.quinlan@broadcom.com>
+Co-developed-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+
+---
+
+Changes since v2:
+ - Correct rc_bar2_offset sign
+ - Invert IRQ clear and masking in setup code
+ - Use bitfield.h, redo all register ops while keeping the register
+ names intact
+ - Remove all SHIFT register definitions
+ - Get rid of all _RB writes
+ - Get rid of of_data
+ - Don't iterate over inexisting dma-ranges
+ - Add comment regarding dma-ranges validation
+ - Small cosmetic cleanups
+ - Fix license mismatch
+ - Set driver Kconfig tristate
+ - Didn't add any comment about the controller not being I/O coherent
+ for now as I wait for Jeremy's reply
+
+Changes since v1:
+ - Fix Kconfig
+ - Remove pci domain check
+ - Remove all MSI related code
+ - Remove supend/resume code
+ - Simplify link state wait routine
+ - Prefix all functions
+ - Use of_device_get_match_data()
+ - Use devm_clk_get_optional()
+ - Get rid of irq variable
+ - Use STB all over the driver
+ - Simplify map_bus() function
+ - Fix license mismatch
+ - Remove unused register definitions
+ - Small cleanups, spell errors
+
+This is based on Jim's original submission[1] but adapted and tailored
+specifically to bcm2711's needs (that's the Raspberry Pi 4). Support for
+the rest of the brcmstb family will soon follow once we get support for
+multiple dma-ranges in dma/direct.
+
+[1] https://patchwork.kernel.org/patch/10605959/
+---
+ drivers/pci/controller/Kconfig | 8
+ drivers/pci/controller/Makefile | 1
+ drivers/pci/controller/pcie-brcmstb.c | 754 ++++++++++++++++++++++++++++++++++
+ 3 files changed, 763 insertions(+)
+
+--- a/drivers/pci/controller/Kconfig
++++ b/drivers/pci/controller/Kconfig
+@@ -271,6 +271,14 @@ config VMD
+ To compile this driver as a module, choose M here: the
+ module will be called vmd.
+
++config PCIE_BRCMSTB
++ tristate "Broadcom Brcmstb PCIe host controller"
++ depends on ARCH_BCM2835 || COMPILE_TEST
++ depends on OF
++ help
++ Say Y here to enable PCIe host controller support for
++ Broadcom STB based SoCs, like the Raspberry Pi 4.
++
+ config PCI_HYPERV_INTERFACE
+ tristate "Hyper-V PCI Interface"
+ depends on X86 && HYPERV && PCI_MSI && PCI_MSI_IRQ_DOMAIN && X86_64
+--- a/drivers/pci/controller/Makefile
++++ b/drivers/pci/controller/Makefile
+@@ -29,6 +29,7 @@ obj-$(CONFIG_PCIE_ROCKCHIP_HOST) += pcie
+ obj-$(CONFIG_PCIE_MEDIATEK) += pcie-mediatek.o
+ obj-$(CONFIG_PCIE_TANGO_SMP8759) += pcie-tango.o
+ obj-$(CONFIG_VMD) += vmd.o
++obj-$(CONFIG_PCIE_BRCMSTB) += pcie-brcmstb.o
+ # pcie-hisi.o quirks are needed even without CONFIG_PCIE_DW
+ obj-y += dwc/
+ obj-y += mobiveil/
+--- /dev/null
++++ b/drivers/pci/controller/pcie-brcmstb.c
+@@ -0,0 +1,754 @@
++// SPDX-License-Identifier: GPL-2.0+
++/* Copyright (C) 2009 - 2019 Broadcom */
++
++#include <linux/bitfield.h>
++#include <linux/clk.h>
++#include <linux/compiler.h>
++#include <linux/delay.h>
++#include <linux/init.h>
++#include <linux/interrupt.h>
++#include <linux/io.h>
++#include <linux/ioport.h>
++#include <linux/irqdomain.h>
++#include <linux/kernel.h>
++#include <linux/list.h>
++#include <linux/log2.h>
++#include <linux/module.h>
++#include <linux/of_address.h>
++#include <linux/of_irq.h>
++#include <linux/of_pci.h>
++#include <linux/of_platform.h>
++#include <linux/pci.h>
++#include <linux/printk.h>
++#include <linux/sizes.h>
++#include <linux/slab.h>
++#include <linux/string.h>
++#include <linux/types.h>
++
++#include "../pci.h"
++
++/* BRCM_PCIE_CAP_REGS - Offset for the mandatory capability config regs */
++#define BRCM_PCIE_CAP_REGS 0x00ac
++
++/*
++ * Broadcom STB PCIe Register Offsets. The names are from the chip's RDB and we
++ * use them here so that a script can correlate this code and the RDB to
++ * prevent discrepancies.
++ */
++#define PCIE_RC_CFG_VENDOR_VENDOR_SPECIFIC_REG1 0x0188
++#define PCIE_RC_CFG_VENDOR_VENDOR_SPECIFIC_REG1_ENDIAN_MODE_BAR2_MASK 0xc
++#define PCIE_RC_CFG_VENDOR_SPCIFIC_REG1_LITTLE_ENDIAN 0x0
++
++#define PCIE_RC_CFG_PRIV1_ID_VAL3 0x043c
++#define PCIE_RC_CFG_PRIV1_ID_VAL3_CLASS_CODE_MASK 0xffffff
++
++#define PCIE_RC_DL_MDIO_ADDR 0x1100
++#define PCIE_RC_DL_MDIO_WR_DATA 0x1104
++#define PCIE_RC_DL_MDIO_RD_DATA 0x1108
++
++#define PCIE_MISC_MISC_CTRL 0x4008
++#define PCIE_MISC_MISC_CTRL_SCB_ACCESS_EN_MASK 0x1000
++#define PCIE_MISC_MISC_CTRL_CFG_READ_UR_MODE_MASK 0x2000
++#define PCIE_MISC_MISC_CTRL_MAX_BURST_SIZE_MASK 0x300000
++#define PCIE_MISC_MISC_CTRL_MAX_BURST_SIZE_128 0x0
++#define PCIE_MISC_MISC_CTRL_SCB0_SIZE_MASK 0xf8000000
++
++#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LO 0x400c
++#define PCIE_MEM_WIN0_LO(win) \
++ PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LO + ((win) * 4)
++
++#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_HI 0x4010
++#define PCIE_MEM_WIN0_HI(win) \
++ PCIE_MISC_CPU_2_PCIE_MEM_WIN0_HI + ((win) * 4)
++
++#define PCIE_MISC_RC_BAR1_CONFIG_LO 0x402c
++#define PCIE_MISC_RC_BAR1_CONFIG_LO_SIZE_MASK 0x1f
++
++#define PCIE_MISC_RC_BAR2_CONFIG_LO 0x4034
++#define PCIE_MISC_RC_BAR2_CONFIG_LO_SIZE_MASK 0x1f
++#define PCIE_MISC_RC_BAR2_CONFIG_HI 0x4038
++
++#define PCIE_MISC_RC_BAR3_CONFIG_LO 0x403c
++#define PCIE_MISC_RC_BAR3_CONFIG_LO_SIZE_MASK 0x1f
++
++#define PCIE_MISC_PCIE_CTRL 0x4064
++#define PCIE_MISC_PCIE_CTRL_PCIE_L23_REQUEST_MASK 0x1
++
++#define PCIE_MISC_PCIE_STATUS 0x4068
++#define PCIE_MISC_PCIE_STATUS_PCIE_PORT_MASK 0x80
++#define PCIE_MISC_PCIE_STATUS_PCIE_DL_ACTIVE_MASK 0x20
++#define PCIE_MISC_PCIE_STATUS_PCIE_PHYLINKUP_MASK 0x10
++#define PCIE_MISC_PCIE_STATUS_PCIE_LINK_IN_L23_MASK 0x40
++
++#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT 0x4070
++#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT_LIMIT_MASK 0xfff00000
++#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT_BASE_MASK 0xfff0
++#define PCIE_MEM_WIN0_BASE_LIMIT(win) \
++ PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT + ((win) * 4)
++
++#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_HI 0x4080
++#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_HI_BASE_MASK 0xff
++#define PCIE_MEM_WIN0_BASE_HI(win) \
++ PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_HI + ((win) * 8)
++
++#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LIMIT_HI 0x4084
++#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LIMIT_HI_LIMIT_MASK 0xff
++#define PCIE_MEM_WIN0_LIMIT_HI(win) \
++ PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LIMIT_HI + ((win) * 8)
++
++#define PCIE_MISC_HARD_PCIE_HARD_DEBUG 0x4204
++#define PCIE_MISC_HARD_PCIE_HARD_DEBUG_CLKREQ_DEBUG_ENABLE_MASK 0x2
++#define PCIE_MISC_HARD_PCIE_HARD_DEBUG_SERDES_IDDQ_MASK 0x08000000
++
++#define PCIE_MSI_INTR2_STATUS 0x4500
++#define PCIE_MSI_INTR2_CLR 0x4508
++#define PCIE_MSI_INTR2_MASK_SET 0x4510
++#define PCIE_MSI_INTR2_MASK_CLR 0x4514
++
++#define PCIE_EXT_CFG_DATA 0x8000
++
++#define PCIE_EXT_CFG_INDEX 0x9000
++#define PCIE_EXT_BUSNUM_SHIFT 20
++#define PCIE_EXT_SLOT_SHIFT 15
++#define PCIE_EXT_FUNC_SHIFT 12
++
++#define PCIE_RGR1_SW_INIT_1 0x9210
++#define PCIE_RGR1_SW_INIT_1_PERST_MASK 0x1
++#define PCIE_RGR1_SW_INIT_1_INIT_MASK 0x2
++
++/* PCIe parameters */
++#define BRCM_NUM_PCIE_OUT_WINS 0x4
++
++/* MDIO registers */
++#define MDIO_PORT0 0x0
++#define MDIO_DATA_MASK 0x7fffffff
++#define MDIO_PORT_MASK 0xf0000
++#define MDIO_REGAD_MASK 0xffff
++#define MDIO_CMD_MASK 0xfff00000
++#define MDIO_CMD_READ 0x1
++#define MDIO_CMD_WRITE 0x0
++#define MDIO_DATA_DONE_MASK 0x80000000
++#define MDIO_RD_DONE(x) (((x) & MDIO_DATA_DONE_MASK) ? 1 : 0)
++#define MDIO_WT_DONE(x) (((x) & MDIO_DATA_DONE_MASK) ? 0 : 1)
++#define SSC_REGS_ADDR 0x1100
++#define SET_ADDR_OFFSET 0x1f
++#define SSC_CNTL_OFFSET 0x2
++#define SSC_CNTL_OVRD_EN_MASK 0x8000
++#define SSC_CNTL_OVRD_VAL_MASK 0x4000
++#define SSC_STATUS_OFFSET 0x1
++#define SSC_STATUS_SSC_MASK 0x400
++#define SSC_STATUS_PLL_LOCK_MASK 0x800
++
++/* Internal PCIe Host Controller Information.*/
++struct brcm_pcie {
++ struct device *dev;
++ void __iomem *base;
++ struct clk *clk;
++ struct pci_bus *root_bus;
++ struct device_node *np;
++ bool ssc;
++ int gen;
++};
++
++/*
++ * This is to convert the size of the inbound "BAR" region to the
++ * non-linear values of PCIE_X_MISC_RC_BAR[123]_CONFIG_LO.SIZE
++ */
++static int brcm_pcie_encode_ibar_size(u64 size)
++{
++ int log2_in = ilog2(size);
++
++ if (log2_in >= 12 && log2_in <= 15)
++ /* Covers 4KB to 32KB (inclusive) */
++ return (log2_in - 12) + 0x1c;
++ else if (log2_in >= 16 && log2_in <= 35)
++ /* Covers 64KB to 32GB, (inclusive) */
++ return log2_in - 15;
++ /* Something is awry so disable */
++ return 0;
++}
++
++static u32 brcm_pcie_mdio_form_pkt(int port, int regad, int cmd)
++{
++ u32 pkt = 0;
++
++ pkt |= FIELD_PREP(MDIO_PORT_MASK, port);
++ pkt |= FIELD_PREP(MDIO_REGAD_MASK, regad);
++ pkt |= FIELD_PREP(MDIO_CMD_MASK, cmd);
++
++ return pkt;
++}
++
++/* negative return value indicates error */
++static int brcm_pcie_mdio_read(void __iomem *base, u8 port, u8 regad, u32 *val)
++{
++ int tries;
++ u32 data;
++
++ writel(brcm_pcie_mdio_form_pkt(port, regad, MDIO_CMD_READ),
++ base + PCIE_RC_DL_MDIO_ADDR);
++ readl(base + PCIE_RC_DL_MDIO_ADDR);
++
++ data = readl(base + PCIE_RC_DL_MDIO_RD_DATA);
++ for (tries = 0; !MDIO_RD_DONE(data) && tries < 10; tries++) {
++ udelay(10);
++ data = readl(base + PCIE_RC_DL_MDIO_RD_DATA);
++ }
++
++ *val = FIELD_GET(MDIO_DATA_MASK, data);
++ return MDIO_RD_DONE(data) ? 0 : -EIO;
++}
++
++/* negative return value indicates error */
++static int brcm_pcie_mdio_write(void __iomem *base, u8 port,
++ u8 regad, u16 wrdata)
++{
++ int tries;
++ u32 data;
++
++ writel(brcm_pcie_mdio_form_pkt(port, regad, MDIO_CMD_WRITE),
++ base + PCIE_RC_DL_MDIO_ADDR);
++ readl(base + PCIE_RC_DL_MDIO_ADDR);
++ writel(MDIO_DATA_DONE_MASK | wrdata, base + PCIE_RC_DL_MDIO_WR_DATA);
++
++ data = readl(base + PCIE_RC_DL_MDIO_WR_DATA);
++ for (tries = 0; !MDIO_WT_DONE(data) && tries < 10; tries++) {
++ udelay(10);
++ data = readl(base + PCIE_RC_DL_MDIO_WR_DATA);
++ }
++
++ return MDIO_WT_DONE(data) ? 0 : -EIO;
++}
++
++/*
++ * Configures device for Spread Spectrum Clocking (SSC) mode; a negative
++ * return value indicates error.
++ */
++static int brcm_pcie_set_ssc(struct brcm_pcie *pcie)
++{
++ int pll, ssc;
++ int ret;
++ u32 tmp;
++
++ ret = brcm_pcie_mdio_write(pcie->base, MDIO_PORT0, SET_ADDR_OFFSET,
++ SSC_REGS_ADDR);
++ if (ret < 0)
++ return ret;
++
++ ret = brcm_pcie_mdio_read(pcie->base, MDIO_PORT0,
++ SSC_CNTL_OFFSET, &tmp);
++ if (ret < 0)
++ return ret;
++
++ u32p_replace_bits(&tmp, 1, SSC_CNTL_OVRD_EN_MASK);
++ u32p_replace_bits(&tmp, 1, SSC_CNTL_OVRD_VAL_MASK);
++ ret = brcm_pcie_mdio_write(pcie->base, MDIO_PORT0,
++ SSC_CNTL_OFFSET, tmp);
++ if (ret < 0)
++ return ret;
++
++ usleep_range(1000, 2000);
++ ret = brcm_pcie_mdio_read(pcie->base, MDIO_PORT0,
++ SSC_STATUS_OFFSET, &tmp);
++ if (ret < 0)
++ return ret;
++
++ ssc = FIELD_GET(SSC_STATUS_SSC_MASK, tmp);
++ pll = FIELD_GET(SSC_STATUS_PLL_LOCK_MASK, tmp);
++
++ return ssc && pll ? 0 : -EIO;
++}
++
++/* Limits operation to a specific generation (1, 2, or 3) */
++static void brcm_pcie_set_gen(struct brcm_pcie *pcie, int gen)
++{
++ u16 lnkctl2 = readw(pcie->base + BRCM_PCIE_CAP_REGS + PCI_EXP_LNKCTL2);
++ u32 lnkcap = readl(pcie->base + BRCM_PCIE_CAP_REGS + PCI_EXP_LNKCAP);
++
++ lnkcap = (lnkcap & ~PCI_EXP_LNKCAP_SLS) | gen;
++ writel(lnkcap, pcie->base + BRCM_PCIE_CAP_REGS + PCI_EXP_LNKCAP);
++
++ lnkctl2 = (lnkctl2 & ~0xf) | gen;
++ writew(lnkctl2, pcie->base + BRCM_PCIE_CAP_REGS + PCI_EXP_LNKCTL2);
++}
++
++static void brcm_pcie_set_outbound_win(struct brcm_pcie *pcie,
++ unsigned int win, u64 cpu_addr,
++ u64 pcie_addr, u64 size)
++{
++ u32 cpu_addr_mb_high, limit_addr_mb_high;
++ phys_addr_t cpu_addr_mb, limit_addr_mb;
++ int high_addr_shift;
++ u32 tmp;
++
++ /* Set the base of the pcie_addr window */
++ writel(lower_32_bits(pcie_addr), pcie->base + PCIE_MEM_WIN0_LO(win));
++ writel(upper_32_bits(pcie_addr), pcie->base + PCIE_MEM_WIN0_HI(win));
++
++ /* Write the addr base & limit lower bits (in MBs) */
++ cpu_addr_mb = cpu_addr / SZ_1M;
++ limit_addr_mb = (cpu_addr + size - 1) / SZ_1M;
++
++ tmp = readl(pcie->base + PCIE_MEM_WIN0_BASE_LIMIT(win));
++ u32p_replace_bits(&tmp, cpu_addr_mb,
++ PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT_BASE_MASK);
++ u32p_replace_bits(&tmp, limit_addr_mb,
++ PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT_LIMIT_MASK);
++ writel(tmp, pcie->base + PCIE_MEM_WIN0_BASE_LIMIT(win));
++
++ /* Write the cpu & limit addr upper bits */
++ high_addr_shift =
++ HWEIGHT32(PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT_BASE_MASK);
++
++ cpu_addr_mb_high = cpu_addr_mb >> high_addr_shift;
++ tmp = readl(pcie->base + PCIE_MEM_WIN0_BASE_HI(win));
++ u32p_replace_bits(&tmp, cpu_addr_mb_high,
++ PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_HI_BASE_MASK);
++ writel(tmp, pcie->base + PCIE_MEM_WIN0_BASE_HI(win));
++
++ limit_addr_mb_high = limit_addr_mb >> high_addr_shift;
++ tmp = readl(pcie->base + PCIE_MEM_WIN0_LIMIT_HI(win));
++ u32p_replace_bits(&tmp, limit_addr_mb_high,
++ PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LIMIT_HI_LIMIT_MASK);
++ writel(tmp, pcie->base + PCIE_MEM_WIN0_LIMIT_HI(win));
++}
++
++/* The controller is capable of serving in both RC and EP roles */
++static bool brcm_pcie_rc_mode(struct brcm_pcie *pcie)
++{
++ void __iomem *base = pcie->base;
++ u32 val = readl(base + PCIE_MISC_PCIE_STATUS);
++
++ return !!FIELD_GET(PCIE_MISC_PCIE_STATUS_PCIE_PORT_MASK, val);
++}
++
++static bool brcm_pcie_link_up(struct brcm_pcie *pcie)
++{
++ u32 val = readl(pcie->base + PCIE_MISC_PCIE_STATUS);
++ u32 dla = FIELD_GET(PCIE_MISC_PCIE_STATUS_PCIE_DL_ACTIVE_MASK, val);
++ u32 plu = FIELD_GET(PCIE_MISC_PCIE_STATUS_PCIE_PHYLINKUP_MASK, val);
++
++ return dla && plu;
++}
++
++/* Configuration space read/write support */
++static inline int brcm_pcie_cfg_index(int busnr, int devfn, int reg)
++{
++ return ((PCI_SLOT(devfn) & 0x1f) << PCIE_EXT_SLOT_SHIFT)
++ | ((PCI_FUNC(devfn) & 0x07) << PCIE_EXT_FUNC_SHIFT)
++ | (busnr << PCIE_EXT_BUSNUM_SHIFT)
++ | (reg & ~3);
++}
++
++static void __iomem *brcm_pcie_map_conf(struct pci_bus *bus, unsigned int devfn,
++ int where)
++{
++ struct brcm_pcie *pcie = bus->sysdata;
++ void __iomem *base = pcie->base;
++ int idx;
++
++ /* Accesses to the RC go right to the RC registers if slot==0 */
++ if (pci_is_root_bus(bus))
++ return PCI_SLOT(devfn) ? NULL : base + where;
++
++ /* For devices, write to the config space index register */
++ idx = brcm_pcie_cfg_index(bus->number, devfn, 0);
++ writel(idx, pcie->base + PCIE_EXT_CFG_INDEX);
++ return base + PCIE_EXT_CFG_DATA + where;
++}
++
++static struct pci_ops brcm_pcie_ops = {
++ .map_bus = brcm_pcie_map_conf,
++ .read = pci_generic_config_read,
++ .write = pci_generic_config_write,
++};
++
++static inline void brcm_pcie_bridge_sw_init_set(struct brcm_pcie *pcie, u32 val)
++{
++ u32 tmp;
++
++ tmp = readl(pcie->base + PCIE_RGR1_SW_INIT_1);
++ u32p_replace_bits(&tmp, val, PCIE_RGR1_SW_INIT_1_INIT_MASK);
++ writel(tmp, pcie->base + PCIE_RGR1_SW_INIT_1);
++}
++
++static inline void brcm_pcie_perst_set(struct brcm_pcie *pcie, u32 val)
++{
++ u32 tmp;
++
++ tmp = readl(pcie->base + PCIE_RGR1_SW_INIT_1);
++ u32p_replace_bits(&tmp, val, PCIE_RGR1_SW_INIT_1_PERST_MASK);
++ writel(tmp, pcie->base + PCIE_RGR1_SW_INIT_1);
++}
++
++static inline int brcm_pcie_get_rc_bar2_size_and_offset(struct brcm_pcie *pcie,
++ u64 *rc_bar2_size,
++ u64 *rc_bar2_offset)
++{
++ struct pci_host_bridge *bridge = pci_host_bridge_from_priv(pcie);
++ struct device *dev = pcie->dev;
++ struct resource_entry *entry;
++
++ entry = resource_list_first_type(&bridge->dma_ranges, IORESOURCE_MEM);
++ if (!entry)
++ return -ENODEV;
++
++ *rc_bar2_offset = -entry->offset;
++ *rc_bar2_size = roundup_pow_of_two_u64(entry->res->end -
++ entry->res->start + 1);
++
++ /*
++ * We validate the inbound memory view even though we should trust
++ * whatever the device-tree provides. This is because of an HW issue on
++ * early Raspberry Pi 4's revisions (bcm2711). It turns out its
++ * firmware has to dynamically edit dma-ranges due to a bug on the
++ * PCIe controller integration, which prohibits any access above the
++ * lower 3GB of memory. Given this, we decided to keep the dma-ranges
++ * in check, avoiding hard to debug device-tree related issues in the
++ * future:
++ *
++ * The PCIe host controller by design must set the inbound viewport to
++ * be a contiguous arrangement of all of the system's memory. In
++ * addition, its size mut be a power of two. To further complicate
++ * matters, the viewport must start on a pcie-address that is aligned
++ * on a multiple of its size. If a portion of the viewport does not
++ * represent system memory -- e.g. 3GB of memory requires a 4GB
++ * viewport -- we can map the outbound memory in or after 3GB and even
++ * though the viewport will overlap the outbound memory the controller
++ * will know to send outbound memory downstream and everything else
++ * upstream.
++ *
++ * For example:
++ *
++ * - The best-case scenario, memory up to 3GB, is to place the inbound
++ * region in the first 4GB of pcie-space, as some legacy devices can
++ * only address 32bits. We would also like to put the MSI under 4GB
++ * as well, since some devices require a 32bit MSI target address.
++ *
++ * - If the system memory is 4GB or larger we cannot start the inbound
++ * region at location 0 (since we have to allow some space for
++ * outbound memory @ 3GB). So instead it will start at the 1x
++ * multiple of its size
++ */
++ if (!*rc_bar2_size || *rc_bar2_offset % *rc_bar2_size ||
++ (*rc_bar2_offset < SZ_4G && *rc_bar2_offset > SZ_2G)) {
++ dev_err(dev, "Invalid rc_bar2_offset/size: size 0x%llx, off 0x%llx\n",
++ *rc_bar2_size, *rc_bar2_offset);
++ return -EINVAL;
++ }
++
++ return 0;
++}
++
++static int brcm_pcie_setup(struct brcm_pcie *pcie)
++{
++ struct pci_host_bridge *bridge = pci_host_bridge_from_priv(pcie);
++ u64 rc_bar2_offset, rc_bar2_size;
++ void __iomem *base = pcie->base;
++ struct device *dev = pcie->dev;
++ struct resource_entry *entry;
++ unsigned int scb_size_val;
++ bool ssc_good = false;
++ struct resource *res;
++ int num_out_wins = 0;
++ u16 nlw, cls, lnksta;
++ int i, ret;
++ u32 tmp;
++
++ /* Reset the bridge */
++ brcm_pcie_bridge_sw_init_set(pcie, 1);
++
++ usleep_range(100, 200);
++
++ /* Take the bridge out of reset */
++ brcm_pcie_bridge_sw_init_set(pcie, 0);
++
++ tmp = readl(base + PCIE_MISC_HARD_PCIE_HARD_DEBUG);
++ tmp &= ~PCIE_MISC_HARD_PCIE_HARD_DEBUG_SERDES_IDDQ_MASK;
++ writel(tmp, base + PCIE_MISC_HARD_PCIE_HARD_DEBUG);
++ /* Wait for SerDes to be stable */
++ usleep_range(100, 200);
++
++ /* Set SCB_MAX_BURST_SIZE, CFG_READ_UR_MODE, SCB_ACCESS_EN */
++ u32p_replace_bits(&tmp, 1, PCIE_MISC_MISC_CTRL_SCB_ACCESS_EN_MASK);
++ u32p_replace_bits(&tmp, 1, PCIE_MISC_MISC_CTRL_CFG_READ_UR_MODE_MASK);
++ u32p_replace_bits(&tmp, PCIE_MISC_MISC_CTRL_MAX_BURST_SIZE_128,
++ PCIE_MISC_MISC_CTRL_MAX_BURST_SIZE_MASK);
++ writel(tmp, base + PCIE_MISC_MISC_CTRL);
++
++ ret = brcm_pcie_get_rc_bar2_size_and_offset(pcie, &rc_bar2_size,
++ &rc_bar2_offset);
++ if (ret)
++ return ret;
++
++ tmp = lower_32_bits(rc_bar2_offset);
++ u32p_replace_bits(&tmp, brcm_pcie_encode_ibar_size(rc_bar2_size),
++ PCIE_MISC_RC_BAR2_CONFIG_LO_SIZE_MASK);
++ writel(tmp, base + PCIE_MISC_RC_BAR2_CONFIG_LO);
++ writel(upper_32_bits(rc_bar2_offset),
++ base + PCIE_MISC_RC_BAR2_CONFIG_HI);
++
++ scb_size_val = rc_bar2_size ?
++ ilog2(rc_bar2_size) - 15 : 0xf; /* 0xf is 1GB */
++ tmp = readl(base + PCIE_MISC_MISC_CTRL);
++ u32p_replace_bits(&tmp, scb_size_val,
++ PCIE_MISC_MISC_CTRL_SCB0_SIZE_MASK);
++ writel(tmp, base + PCIE_MISC_MISC_CTRL);
++
++ /* disable the PCIe->GISB memory window (RC_BAR1) */
++ tmp = readl(base + PCIE_MISC_RC_BAR1_CONFIG_LO);
++ tmp &= ~PCIE_MISC_RC_BAR1_CONFIG_LO_SIZE_MASK;
++ writel(tmp, base + PCIE_MISC_RC_BAR1_CONFIG_LO);
++
++ /* disable the PCIe->SCB memory window (RC_BAR3) */
++ tmp = readl(base + PCIE_MISC_RC_BAR3_CONFIG_LO);
++ tmp &= ~PCIE_MISC_RC_BAR3_CONFIG_LO_SIZE_MASK;
++ writel(tmp, base + PCIE_MISC_RC_BAR3_CONFIG_LO);
++
++ /* Mask all interrupts since we are not handling any yet */
++ writel(0xffffffff, pcie->base + PCIE_MSI_INTR2_MASK_SET);
++
++ /* clear any interrupts we find on boot */
++ writel(0xffffffff, pcie->base + PCIE_MSI_INTR2_CLR);
++
++ if (pcie->gen)
++ brcm_pcie_set_gen(pcie, pcie->gen);
++
++ /* Unassert the fundamental reset */
++ brcm_pcie_perst_set(pcie, 0);
++
++ /*
++ * Give the RC/EP time to wake up, before trying to configure RC.
++ * Intermittently check status for link-up, up to a total of 100ms.
++ */
++ for (i = 0; i < 100 && !brcm_pcie_link_up(pcie); i += 5)
++ msleep(5);
++
++ if (!brcm_pcie_link_up(pcie)) {
++ dev_err(dev, "link down\n");
++ return -ENODEV;
++ }
++
++ if (!brcm_pcie_rc_mode(pcie)) {
++ dev_err(dev, "PCIe misconfigured; is in EP mode\n");
++ return -EINVAL;
++ }
++
++ resource_list_for_each_entry(entry, &bridge->windows) {
++ res = entry->res;
++
++ if (resource_type(res) != IORESOURCE_MEM)
++ continue;
++
++ if (num_out_wins >= BRCM_NUM_PCIE_OUT_WINS) {
++ dev_err(pcie->dev, "too many outbound wins\n");
++ return -EINVAL;
++ }
++
++ brcm_pcie_set_outbound_win(pcie, num_out_wins, res->start,
++ res->start - entry->offset,
++ res->end - res->start + 1);
++ num_out_wins++;
++ }
++
++ /*
++ * For config space accesses on the RC, show the right class for
++ * a PCIe-PCIe bridge (the default setting is to be EP mode).
++ */
++ tmp = readl(base + PCIE_RC_CFG_PRIV1_ID_VAL3);
++ u32p_replace_bits(&tmp, 0x060400,
++ PCIE_RC_CFG_PRIV1_ID_VAL3_CLASS_CODE_MASK);
++ writel(tmp, base + PCIE_RC_CFG_PRIV1_ID_VAL3);
++
++ if (pcie->ssc) {
++ ret = brcm_pcie_set_ssc(pcie);
++ if (ret == 0)
++ ssc_good = true;
++ else
++ dev_err(dev, "failed attempt to enter ssc mode\n");
++ }
++
++ lnksta = readw(base + BRCM_PCIE_CAP_REGS + PCI_EXP_LNKSTA);
++ cls = FIELD_GET(PCI_EXP_LNKSTA_CLS, lnksta);
++ nlw = FIELD_GET(PCI_EXP_LNKSTA_NLW, lnksta);
++ dev_info(dev, "link up, %s x%u %s\n",
++ PCIE_SPEED2STR(cls + PCI_SPEED_133MHz_PCIX_533),
++ nlw, ssc_good ? "(SSC)" : "(!SSC)");
++
++ /* PCIe->SCB endian mode for BAR */
++ tmp = readl(base + PCIE_RC_CFG_VENDOR_VENDOR_SPECIFIC_REG1);
++ u32p_replace_bits(&tmp, PCIE_RC_CFG_VENDOR_SPCIFIC_REG1_LITTLE_ENDIAN,
++ PCIE_RC_CFG_VENDOR_VENDOR_SPECIFIC_REG1_ENDIAN_MODE_BAR2_MASK);
++ writel(tmp, base + PCIE_RC_CFG_VENDOR_VENDOR_SPECIFIC_REG1);
++
++ /*
++ * Refclk from RC should be gated with CLKREQ# input when ASPM L0s,L1
++ * is enabled => setting the CLKREQ_DEBUG_ENABLE field to 1.
++ */
++ tmp = readl(base + PCIE_MISC_HARD_PCIE_HARD_DEBUG);
++ tmp |= PCIE_MISC_HARD_PCIE_HARD_DEBUG_CLKREQ_DEBUG_ENABLE_MASK;
++ writel(tmp, base + PCIE_MISC_HARD_PCIE_HARD_DEBUG);
++
++ return 0;
++}
++
++/* L23 is a low-power PCIe link state */
++static void brcm_pcie_enter_l23(struct brcm_pcie *pcie)
++{
++ void __iomem *base = pcie->base;
++ int l23, i;
++ u32 tmp;
++
++ /* Assert request for L23 */
++ tmp = readl(base + PCIE_MISC_PCIE_CTRL);
++ u32p_replace_bits(&tmp, 1, PCIE_MISC_PCIE_CTRL_PCIE_L23_REQUEST_MASK);
++ writel(tmp, base + PCIE_MISC_PCIE_CTRL);
++
++ /* Wait up to 36 msec for L23 */
++ tmp = readl(base + PCIE_MISC_PCIE_STATUS);
++ l23 = FIELD_GET(PCIE_MISC_PCIE_STATUS_PCIE_LINK_IN_L23_MASK, tmp);
++ for (i = 0; i < 15 && !l23; i++) {
++ usleep_range(2000, 2400);
++ tmp = readl(base + PCIE_MISC_PCIE_STATUS);
++ l23 = FIELD_GET(PCIE_MISC_PCIE_STATUS_PCIE_LINK_IN_L23_MASK,
++ tmp);
++ }
++
++ if (!l23)
++ dev_err(pcie->dev, "failed to enter low-power link state\n");
++}
++
++static void brcm_pcie_turn_off(struct brcm_pcie *pcie)
++{
++ void __iomem *base = pcie->base;
++ int tmp;
++
++ if (brcm_pcie_link_up(pcie))
++ brcm_pcie_enter_l23(pcie);
++ /* Assert fundamental reset */
++ brcm_pcie_perst_set(pcie, 1);
++
++ /* Deassert request for L23 in case it was asserted */
++ tmp = readl(base + PCIE_MISC_PCIE_CTRL);
++ u32p_replace_bits(&tmp, 0, PCIE_MISC_PCIE_CTRL_PCIE_L23_REQUEST_MASK);
++ writel(tmp, base + PCIE_MISC_PCIE_CTRL);
++
++ /* Turn off SerDes */
++ tmp = readl(base + PCIE_MISC_HARD_PCIE_HARD_DEBUG);
++ u32p_replace_bits(&tmp, 1, PCIE_MISC_HARD_PCIE_HARD_DEBUG_SERDES_IDDQ_MASK);
++ writel(tmp, base + PCIE_MISC_HARD_PCIE_HARD_DEBUG);
++
++ /* Shutdown PCIe bridge */
++ brcm_pcie_bridge_sw_init_set(pcie, 1);
++}
++
++static void __brcm_pcie_remove(struct brcm_pcie *pcie)
++{
++ brcm_pcie_turn_off(pcie);
++ clk_disable_unprepare(pcie->clk);
++ clk_put(pcie->clk);
++}
++
++static int brcm_pcie_remove(struct platform_device *pdev)
++{
++ struct brcm_pcie *pcie = platform_get_drvdata(pdev);
++
++ pci_stop_root_bus(pcie->root_bus);
++ pci_remove_root_bus(pcie->root_bus);
++ __brcm_pcie_remove(pcie);
++
++ return 0;
++}
++
++static int brcm_pcie_probe(struct platform_device *pdev)
++{
++ struct device_node *np = pdev->dev.of_node;
++ struct pci_host_bridge *bridge;
++ struct brcm_pcie *pcie;
++ struct pci_bus *child;
++ struct resource *res;
++ int ret;
++
++ bridge = devm_pci_alloc_host_bridge(&pdev->dev, sizeof(*pcie));
++ if (!bridge)
++ return -ENOMEM;
++
++ pcie = pci_host_bridge_priv(bridge);
++ pcie->dev = &pdev->dev;
++ pcie->np = np;
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ pcie->base = devm_ioremap_resource(&pdev->dev, res);
++ if (IS_ERR(pcie->base))
++ return PTR_ERR(pcie->base);
++
++ pcie->clk = devm_clk_get_optional(&pdev->dev, "sw_pcie");
++ if (IS_ERR(pcie->clk))
++ return PTR_ERR(pcie->clk);
++
++ ret = of_pci_get_max_link_speed(np);
++ pcie->gen = (ret < 0) ? 0 : ret;
++
++ pcie->ssc = of_property_read_bool(np, "brcm,enable-ssc");
++
++ ret = pci_parse_request_of_pci_ranges(pcie->dev, &bridge->windows,
++ &bridge->dma_ranges, NULL);
++ if (ret)
++ return ret;
++
++ ret = clk_prepare_enable(pcie->clk);
++ if (ret) {
++ dev_err(&pdev->dev, "could not enable clock\n");
++ return ret;
++ }
++
++ ret = brcm_pcie_setup(pcie);
++ if (ret)
++ goto fail;
++
++ bridge->dev.parent = &pdev->dev;
++ bridge->busnr = 0;
++ bridge->ops = &brcm_pcie_ops;
++ bridge->sysdata = pcie;
++ bridge->map_irq = of_irq_parse_and_map_pci;
++ bridge->swizzle_irq = pci_common_swizzle;
++
++ ret = pci_scan_root_bus_bridge(bridge);
++ if (ret < 0) {
++ dev_err(pcie->dev, "Scanning root bridge failed\n");
++ goto fail;
++ }
++
++ pci_assign_unassigned_bus_resources(bridge->bus);
++ list_for_each_entry(child, &bridge->bus->children, node)
++ pcie_bus_configure_settings(child);
++ pci_bus_add_devices(bridge->bus);
++ platform_set_drvdata(pdev, pcie);
++ pcie->root_bus = bridge->bus;
++
++ return 0;
++fail:
++ __brcm_pcie_remove(pcie);
++ return ret;
++}
++
++static const struct of_device_id brcm_pcie_match[] = {
++ { .compatible = "brcm,bcm2711-pcie" },
++ { .compatible = "brcm,bcm7445-pcie" },
++ {},
++};
++MODULE_DEVICE_TABLE(of, brcm_pcie_match);
++
++static struct platform_driver brcm_pcie_driver = {
++ .probe = brcm_pcie_probe,
++ .remove = brcm_pcie_remove,
++ .driver = {
++ .name = "brcm-pcie",
++ .of_match_table = brcm_pcie_match,
++ },
++};
++module_platform_driver(brcm_pcie_driver);
++
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("Broadcom STB PCIe RC driver");
++MODULE_AUTHOR("Broadcom");
diff --git a/patches.suse/pci-brcmstb-add-msi-capability.patch b/patches.suse/pci-brcmstb-add-msi-capability.patch
new file mode 100644
index 0000000000..256b543b79
--- /dev/null
+++ b/patches.suse/pci-brcmstb-add-msi-capability.patch
@@ -0,0 +1,409 @@
+From: Jim Quinlan <james.quinlan@broadcom.com>
+Date: Tue, 5 Nov 2019 15:03:24 +0100
+Subject: PCI: brcmstb: add MSI capability
+Patch-mainline: Submitted, https://lkml.org/lkml/2019/11/26/131
+References: jsc#SLE-7772
+
+This adds MSI support to the Broadcom STB PCIe host controller. The MSI
+controller is physically located within the PCIe block, however, there
+is no reason why the MSI controller could not be moved elsewhere in the
+future. MSIX is not supported by the HW.
+
+Since the internal Brcmstb MSI controller is intertwined with the PCIe
+controller, it is not its own platform device but rather part of the
+PCIe platform device.
+
+Signed-off-by: Jim Quinlan <james.quinlan@broadcom.com>
+Co-developed-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Reviewed-by: Marc Zyngier <maz@kernel.org>
+
+---
+
+Changes since v2 (kept Marc's reviewed by as changes seem small enough):
+ - Use standard APIs on register operations
+ - Get rid of revision code
+ - Update rules to msi_target_addr selection
+ - Remove unwarranted MSI_FLAG_PCI_MSIX
+ - Small cosmetic changes
+
+Changes since v1:
+ - Move revision code and some registers to this patch
+ - Use PCIE_MSI_IRQ_DOMAIN in Kconfig
+ - Remove redundant register read from ISR
+ - Fail probe on MSI init error
+ - Get rid of msi_internal
+ - Use bitmap family of functions
+ - Use edge triggered setup
+ - Add comment regarding MultiMSI
+ - Simplify compose_msi_msg to avoid reg read
+
+This is based on Jim's original submission[1] with some slight changes
+regarding how pcie->msi_target_addr is decided.
+
+[1] https://patchwork.kernel.org/patch/10605955/
+---
+ drivers/pci/controller/Kconfig | 1 +
+ drivers/pci/controller/pcie-brcmstb.c | 261 +++++++++++++++++++++++++++++++++-
+ 2 files changed, 261 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/pci/controller/Kconfig b/drivers/pci/controller/Kconfig
+index 27504f108ee5..918e283bbff1 100644
+--- a/drivers/pci/controller/Kconfig
++++ b/drivers/pci/controller/Kconfig
+@@ -257,6 +257,7 @@ config PCIE_BRCMSTB
+ tristate "Broadcom Brcmstb PCIe host controller"
+ depends on ARCH_BCM2835 || COMPILE_TEST
+ depends on OF
++ depends on PCI_MSI_IRQ_DOMAIN
+ help
+ Say Y here to enable PCIe host controller support for
+ Broadcom STB based SoCs, like the Raspberry Pi 4.
+diff --git a/drivers/pci/controller/pcie-brcmstb.c b/drivers/pci/controller/pcie-brcmstb.c
+index 28c1b9429d3d..eaf0119c08bf 100644
+--- a/drivers/pci/controller/pcie-brcmstb.c
++++ b/drivers/pci/controller/pcie-brcmstb.c
+@@ -2,6 +2,7 @@
+ /* Copyright (C) 2009 - 2019 Broadcom */
+
+ #include <linux/bitfield.h>
++#include <linux/bitops.h>
+ #include <linux/clk.h>
+ #include <linux/compiler.h>
+ #include <linux/delay.h>
+@@ -9,11 +10,13 @@
+ #include <linux/interrupt.h>
+ #include <linux/io.h>
+ #include <linux/ioport.h>
++#include <linux/irqchip/chained_irq.h>
+ #include <linux/irqdomain.h>
+ #include <linux/kernel.h>
+ #include <linux/list.h>
+ #include <linux/log2.h>
+ #include <linux/module.h>
++#include <linux/msi.h>
+ #include <linux/of_address.h>
+ #include <linux/of_irq.h>
+ #include <linux/of_pci.h>
+@@ -71,6 +74,12 @@
+ #define PCIE_MISC_RC_BAR3_CONFIG_LO 0x403c
+ #define PCIE_MISC_RC_BAR3_CONFIG_LO_SIZE_MASK 0x1f
+
++#define PCIE_MISC_MSI_BAR_CONFIG_LO 0x4044
++#define PCIE_MISC_MSI_BAR_CONFIG_HI 0x4048
++
++#define PCIE_MISC_MSI_DATA_CONFIG 0x404c
++#define PCIE_MISC_MSI_DATA_CONFIG_VAL 0xffe06540
++
+ #define PCIE_MISC_PCIE_CTRL 0x4064
+ #define PCIE_MISC_PCIE_CTRL_PCIE_L23_REQUEST_MASK 0x1
+
+@@ -118,6 +127,11 @@
+
+ /* PCIe parameters */
+ #define BRCM_NUM_PCIE_OUT_WINS 0x4
++#define BRCM_INT_PCI_MSI_NR 32
++
++/* MSI target adresses */
++#define BRCM_MSI_TARGET_ADDR_LT_4GB 0x0fffffffcULL
++#define BRCM_MSI_TARGET_ADDR_GT_4GB 0xffffffffcULL
+
+ /* MDIO registers */
+ #define MDIO_PORT0 0x0
+@@ -139,6 +153,19 @@
+ #define SSC_STATUS_SSC_MASK 0x400
+ #define SSC_STATUS_PLL_LOCK_MASK 0x800
+
++struct brcm_msi {
++ struct device *dev;
++ void __iomem *base;
++ struct device_node *np;
++ struct irq_domain *msi_domain;
++ struct irq_domain *inner_domain;
++ struct mutex lock; /* guards the alloc/free operations */
++ u64 target_addr;
++ int irq;
++ /* used indicates which MSI interrupts have been alloc'd */
++ unsigned long used;
++};
++
+ /* Internal PCIe Host Controller Information.*/
+ struct brcm_pcie {
+ struct device *dev;
+@@ -148,6 +175,8 @@ struct brcm_pcie {
+ struct device_node *np;
+ bool ssc;
+ int gen;
++ u64 msi_target_addr;
++ struct brcm_msi *msi;
+ };
+
+ /*
+@@ -313,6 +342,214 @@ static void brcm_pcie_set_outbound_win(struct brcm_pcie *pcie,
+ writel(tmp, pcie->base + PCIE_MEM_WIN0_LIMIT_HI(win));
+ }
+
++static struct irq_chip brcm_msi_irq_chip = {
++ .name = "BRCM STB PCIe MSI",
++ .irq_ack = irq_chip_ack_parent,
++ .irq_mask = pci_msi_mask_irq,
++ .irq_unmask = pci_msi_unmask_irq,
++};
++
++static struct msi_domain_info brcm_msi_domain_info = {
++ /* Multi MSI is supported by the controller, but not by this driver */
++ .flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS),
++ .chip = &brcm_msi_irq_chip,
++};
++
++static void brcm_pcie_msi_isr(struct irq_desc *desc)
++{
++ struct irq_chip *chip = irq_desc_get_chip(desc);
++ unsigned long status, virq;
++ struct brcm_msi *msi;
++ struct device *dev;
++ u32 bit;
++
++ chained_irq_enter(chip, desc);
++ msi = irq_desc_get_handler_data(desc);
++ dev = msi->dev;
++
++ status = readl(msi->base + PCIE_MSI_INTR2_STATUS);
++ for_each_set_bit(bit, &status, BRCM_INT_PCI_MSI_NR) {
++ virq = irq_find_mapping(msi->inner_domain, bit);
++ if (virq)
++ generic_handle_irq(virq);
++ else
++ dev_dbg(dev, "unexpected MSI\n");
++ }
++
++ chained_irq_exit(chip, desc);
++}
++
++static void brcm_msi_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
++{
++ struct brcm_msi *msi = irq_data_get_irq_chip_data(data);
++
++ msg->address_lo = lower_32_bits(msi->target_addr);
++ msg->address_hi = upper_32_bits(msi->target_addr);
++ msg->data = 0x6540 | data->hwirq;
++}
++
++static int brcm_msi_set_affinity(struct irq_data *irq_data,
++ const struct cpumask *mask, bool force)
++{
++ return -EINVAL;
++}
++
++static void brcm_msi_ack_irq(struct irq_data *data)
++{
++ struct brcm_msi *msi = irq_data_get_irq_chip_data(data);
++
++ writel(1 << data->hwirq, msi->base + PCIE_MSI_INTR2_CLR);
++}
++
++
++static struct irq_chip brcm_msi_bottom_irq_chip = {
++ .name = "BRCM STB MSI",
++ .irq_compose_msi_msg = brcm_msi_compose_msi_msg,
++ .irq_set_affinity = brcm_msi_set_affinity,
++ .irq_ack = brcm_msi_ack_irq,
++};
++
++static int brcm_msi_alloc(struct brcm_msi *msi)
++{
++ int hwirq;
++
++ mutex_lock(&msi->lock);
++ hwirq = bitmap_find_free_region(&msi->used, BRCM_INT_PCI_MSI_NR, 0);
++ mutex_unlock(&msi->lock);
++
++ return hwirq;
++}
++
++static void brcm_msi_free(struct brcm_msi *msi, unsigned long hwirq)
++{
++ mutex_lock(&msi->lock);
++ bitmap_release_region(&msi->used, hwirq, 0);
++ mutex_unlock(&msi->lock);
++}
++
++static int brcm_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
++ unsigned int nr_irqs, void *args)
++{
++ struct brcm_msi *msi = domain->host_data;
++ int hwirq;
++
++ hwirq = brcm_msi_alloc(msi);
++
++ if (hwirq < 0)
++ return hwirq;
++
++ irq_domain_set_info(domain, virq, (irq_hw_number_t)hwirq,
++ &brcm_msi_bottom_irq_chip, domain->host_data,
++ handle_edge_irq, NULL, NULL);
++ return 0;
++}
++
++static void brcm_irq_domain_free(struct irq_domain *domain,
++ unsigned int virq, unsigned int nr_irqs)
++{
++ struct irq_data *d = irq_domain_get_irq_data(domain, virq);
++ struct brcm_msi *msi = irq_data_get_irq_chip_data(d);
++
++ brcm_msi_free(msi, d->hwirq);
++}
++
++static const struct irq_domain_ops msi_domain_ops = {
++ .alloc = brcm_irq_domain_alloc,
++ .free = brcm_irq_domain_free,
++};
++
++static int brcm_allocate_domains(struct brcm_msi *msi)
++{
++ struct fwnode_handle *fwnode = of_node_to_fwnode(msi->np);
++ struct device *dev = msi->dev;
++
++ msi->inner_domain = irq_domain_add_linear(NULL, BRCM_INT_PCI_MSI_NR,
++ &msi_domain_ops, msi);
++ if (!msi->inner_domain) {
++ dev_err(dev, "failed to create IRQ domain\n");
++ return -ENOMEM;
++ }
++
++ msi->msi_domain = pci_msi_create_irq_domain(fwnode,
++ &brcm_msi_domain_info,
++ msi->inner_domain);
++ if (!msi->msi_domain) {
++ dev_err(dev, "failed to create MSI domain\n");
++ irq_domain_remove(msi->inner_domain);
++ return -ENOMEM;
++ }
++
++ return 0;
++}
++
++static void brcm_free_domains(struct brcm_msi *msi)
++{
++ irq_domain_remove(msi->msi_domain);
++ irq_domain_remove(msi->inner_domain);
++}
++
++static void brcm_msi_remove(struct brcm_pcie *pcie)
++{
++ struct brcm_msi *msi = pcie->msi;
++
++ if (!msi)
++ return;
++ irq_set_chained_handler(msi->irq, NULL);
++ irq_set_handler_data(msi->irq, NULL);
++ brcm_free_domains(msi);
++}
++
++static void brcm_msi_set_regs(struct brcm_msi *msi)
++{
++ writel(0xffffffff, msi->base + PCIE_MSI_INTR2_MASK_CLR);
++
++ /*
++ * The 0 bit of PCIE_MISC_MSI_BAR_CONFIG_LO is repurposed to MSI
++ * enable, which we set to 1.
++ */
++ writel(lower_32_bits(msi->target_addr) | 0x1,
++ msi->base + PCIE_MISC_MSI_BAR_CONFIG_LO);
++ writel(upper_32_bits(msi->target_addr),
++ msi->base + PCIE_MISC_MSI_BAR_CONFIG_HI);
++
++ writel(PCIE_MISC_MSI_DATA_CONFIG_VAL,
++ msi->base + PCIE_MISC_MSI_DATA_CONFIG);
++}
++
++static int brcm_pcie_enable_msi(struct brcm_pcie *pcie)
++{
++ struct brcm_msi *msi;
++ int irq, ret;
++ struct device *dev = pcie->dev;
++
++ irq = irq_of_parse_and_map(dev->of_node, 1);
++ if (irq <= 0) {
++ dev_err(dev, "cannot map MSI interrupt\n");
++ return -ENODEV;
++ }
++
++ msi = devm_kzalloc(dev, sizeof(struct brcm_msi), GFP_KERNEL);
++ if (!msi)
++ return -ENOMEM;
++
++ msi->dev = dev;
++ msi->base = pcie->base;
++ msi->np = pcie->np;
++ msi->target_addr = pcie->msi_target_addr;
++ msi->irq = irq;
++
++ ret = brcm_allocate_domains(msi);
++ if (ret)
++ return ret;
++
++ irq_set_chained_handler_and_data(msi->irq, brcm_pcie_msi_isr, msi);
++
++ brcm_msi_set_regs(msi);
++ pcie->msi = msi;
++
++ return 0;
++}
++
+ /* The controller is capable of serving in both RC and EP roles */
+ static bool brcm_pcie_rc_mode(struct brcm_pcie *pcie)
+ {
+@@ -495,6 +732,18 @@ static int brcm_pcie_setup(struct brcm_pcie *pcie)
+ PCIE_MISC_MISC_CTRL_SCB0_SIZE_MASK);
+ writel(tmp, base + PCIE_MISC_MISC_CTRL);
+
++ /*
++ * We ideally want the MSI target address to be located in the 32bit
++ * addressable memory area. Some devices might depend on it. This is
++ * possible either when the inbound window is located above the lower
++ * 4GB or when the inbound area is smaller than 4GB (taking into
++ * account the rounding-up we're forced to perform).
++ */
++ if (rc_bar2_offset >= SZ_4G || (rc_bar2_size + rc_bar2_offset) < SZ_4G)
++ pcie->msi_target_addr = BRCM_MSI_TARGET_ADDR_LT_4GB;
++ else
++ pcie->msi_target_addr = BRCM_MSI_TARGET_ADDR_GT_4GB;
++
+ /* disable the PCIe->GISB memory window (RC_BAR1) */
+ tmp = readl(base + PCIE_MISC_RC_BAR1_CONFIG_LO);
+ tmp &= ~PCIE_MISC_RC_BAR1_CONFIG_LO_SIZE_MASK;
+@@ -644,6 +893,7 @@ static void brcm_pcie_turn_off(struct brcm_pcie *pcie)
+
+ static void __brcm_pcie_remove(struct brcm_pcie *pcie)
+ {
++ brcm_msi_remove(pcie);
+ brcm_pcie_turn_off(pcie);
+ clk_disable_unprepare(pcie->clk);
+ clk_put(pcie->clk);
+@@ -662,7 +912,7 @@ static int brcm_pcie_remove(struct platform_device *pdev)
+
+ static int brcm_pcie_probe(struct platform_device *pdev)
+ {
+- struct device_node *np = pdev->dev.of_node;
++ struct device_node *np = pdev->dev.of_node, *msi_np;
+ struct pci_host_bridge *bridge;
+ struct brcm_pcie *pcie;
+ struct pci_bus *child;
+@@ -706,6 +956,15 @@ static int brcm_pcie_probe(struct platform_device *pdev)
+ if (ret)
+ goto fail;
+
++ msi_np = of_parse_phandle(pcie->np, "msi-parent", 0);
++ if (pci_msi_enabled() && msi_np == pcie->np) {
++ ret = brcm_pcie_enable_msi(pcie);
++ if (ret) {
++ dev_err(pcie->dev, "probe of internal MSI failed");
++ goto fail;
++ }
++ }
++
+ bridge->dev.parent = &pdev->dev;
+ bridge->busnr = 0;
+ bridge->ops = &brcm_pcie_ops;
+
diff --git a/patches.suse/pci-dwc-use-pci_parse_request_of_pci_ranges.patch b/patches.suse/pci-dwc-use-pci_parse_request_of_pci_ranges.patch
new file mode 100644
index 0000000000..68d7551581
--- /dev/null
+++ b/patches.suse/pci-dwc-use-pci_parse_request_of_pci_ranges.patch
@@ -0,0 +1,77 @@
+From: Rob Herring <robh@kernel.org>
+Date: Mon, 28 Oct 2019 11:32:36 -0500
+Subject: PCI: dwc: Use pci_parse_request_of_pci_ranges()
+Git-commit: 7fe71aa84b438d7830f812692f2e0fa55ecdf413
+Patch-mainline: Queued in subsystem maintainer repository
+Git-repo: https://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci.git
+References: jsc#SLE-7772
+
+Convert the Designware host bridge to use the common
+pci_parse_request_of_pci_ranges().
+
+Signed-off-by: Rob Herring <robh@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Cc: Jingoo Han <jingoohan1@gmail.com>
+Cc: Gustavo Pimentel <gustavo.pimentel@synopsys.com>
+Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Cc: Andrew Murray <andrew.murray@arm.com>
+Cc: Bjorn Helgaas <bhelgaas@google.com>
+
+Acked-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+---
+ drivers/pci/controller/dwc/pcie-designware-host.c | 28 +++++++----------------
+ 1 file changed, 8 insertions(+), 20 deletions(-)
+
+diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c
+index 0f36a926059a..aeec8b65eb97 100644
+--- a/drivers/pci/controller/dwc/pcie-designware-host.c
++++ b/drivers/pci/controller/dwc/pcie-designware-host.c
+@@ -319,7 +319,7 @@ int dw_pcie_host_init(struct pcie_port *pp)
+ struct device *dev = pci->dev;
+ struct device_node *np = dev->of_node;
+ struct platform_device *pdev = to_platform_device(dev);
+- struct resource_entry *win, *tmp;
++ struct resource_entry *win;
+ struct pci_bus *child;
+ struct pci_host_bridge *bridge;
+ struct resource *cfg_res;
+@@ -342,31 +342,19 @@ int dw_pcie_host_init(struct pcie_port *pp)
+ if (!bridge)
+ return -ENOMEM;
+
+- ret = devm_of_pci_get_host_bridge_resources(dev, 0, 0xff,
+- &bridge->windows, &pp->io_base);
+- if (ret)
+- return ret;
+-
+- ret = devm_request_pci_bus_resources(dev, &bridge->windows);
++ ret = pci_parse_request_of_pci_ranges(dev, &bridge->windows, NULL);
+ if (ret)
+ return ret;
+
+ /* Get the I/O and memory ranges from DT */
+- resource_list_for_each_entry_safe(win, tmp, &bridge->windows) {
++ resource_list_for_each_entry(win, &bridge->windows) {
+ switch (resource_type(win->res)) {
+ case IORESOURCE_IO:
+- ret = devm_pci_remap_iospace(dev, win->res,
+- pp->io_base);
+- if (ret) {
+- dev_warn(dev, "Error %d: failed to map resource %pR\n",
+- ret, win->res);
+- resource_list_destroy_entry(win);
+- } else {
+- pp->io = win->res;
+- pp->io->name = "I/O";
+- pp->io_size = resource_size(pp->io);
+- pp->io_bus_addr = pp->io->start - win->offset;
+- }
++ pp->io = win->res;
++ pp->io->name = "I/O";
++ pp->io_size = resource_size(pp->io);
++ pp->io_bus_addr = pp->io->start - win->offset;
++ pp->io_base = pci_pio_to_address(pp->io->start);
+ break;
+ case IORESOURCE_MEM:
+ pp->mem = win->res;
+
diff --git a/patches.suse/pci-export-pci_parse_request_of_pci_ranges.patch b/patches.suse/pci-export-pci_parse_request_of_pci_ranges.patch
new file mode 100644
index 0000000000..4958bf779b
--- /dev/null
+++ b/patches.suse/pci-export-pci_parse_request_of_pci_ranges.patch
@@ -0,0 +1,33 @@
+From: Rob Herring <robh@kernel.org>
+Date: Mon, 28 Oct 2019 11:32:33 -0500
+Subject: PCI: Export pci_parse_request_of_pci_ranges()
+Git-commit: 65991f43769941bea14158e0e731f9362051b618
+Patch-mainline: Queued in subsystem maintainer repository
+Git-repo: https://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci.git
+References: jsc#SLE-7772
+
+pci_parse_request_of_pci_ranges() is missing a module export, so add it.
+
+Signed-off-by: Rob Herring <robh@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Reviewed-by: Andrew Murray <andrew.murray@arm.com>
+Cc: Bjorn Helgaas <bhelgaas@google.com>
+
+Acked-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+---
+ drivers/pci/of.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/pci/of.c b/drivers/pci/of.c
+index 36891e7deee3..f3da49a31db4 100644
+--- a/drivers/pci/of.c
++++ b/drivers/pci/of.c
+@@ -530,6 +530,7 @@ int pci_parse_request_of_pci_ranges(struct device *dev,
+ pci_free_resource_list(resources);
+ return err;
+ }
++EXPORT_SYMBOL_GPL(pci_parse_request_of_pci_ranges);
+
+ #endif /* CONFIG_PCI */
+
+
diff --git a/patches.suse/pci-faraday-use-pci_parse_request_of_pci_ranges.patch b/patches.suse/pci-faraday-use-pci_parse_request_of_pci_ranges.patch
new file mode 100644
index 0000000000..4c3195c3aa
--- /dev/null
+++ b/patches.suse/pci-faraday-use-pci_parse_request_of_pci_ranges.patch
@@ -0,0 +1,121 @@
+From: Rob Herring <robh@kernel.org>
+Date: Mon, 28 Oct 2019 11:32:37 -0500
+Subject: PCI: faraday: Use pci_parse_request_of_pci_ranges()
+Git-commit: 783a862563f71e5a3253efa0653eb0ebf9188cf8
+Patch-mainline: Queued in subsystem maintainer repository
+Git-repo: https://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci.git
+References: jsc#SLE-7772
+
+Convert the Faraday host bridge to use the common
+pci_parse_request_of_pci_ranges().
+
+There's no need to assign the resources to a temporary list first. Just
+use bridge->windows directly and remove all the temporary list handling.
+
+Signed-off-by: Rob Herring <robh@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Reviewed-by: Andrew Murray <andrew.murray@arm.com>
+Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Cc: Bjorn Helgaas <bhelgaas@google.com>
+
+Acked-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+---
+ drivers/pci/controller/pci-ftpci100.c | 51 ++++++++---------------------------
+ 1 file changed, 11 insertions(+), 40 deletions(-)
+
+diff --git a/drivers/pci/controller/pci-ftpci100.c b/drivers/pci/controller/pci-ftpci100.c
+index bf5ece5d9291..75603348b88a 100644
+--- a/drivers/pci/controller/pci-ftpci100.c
++++ b/drivers/pci/controller/pci-ftpci100.c
+@@ -430,10 +430,8 @@ static int faraday_pci_probe(struct platform_device *pdev)
+ const struct faraday_pci_variant *variant =
+ of_device_get_match_data(dev);
+ struct resource *regs;
+- resource_size_t io_base;
+ struct resource_entry *win;
+ struct faraday_pci *p;
+- struct resource *mem;
+ struct resource *io;
+ struct pci_host_bridge *host;
+ struct clk *clk;
+@@ -441,7 +439,6 @@ static int faraday_pci_probe(struct platform_device *pdev)
+ unsigned char cur_bus_speed = PCI_SPEED_33MHz;
+ int ret;
+ u32 val;
+- LIST_HEAD(res);
+
+ host = devm_pci_alloc_host_bridge(dev, sizeof(*p));
+ if (!host)
+@@ -480,44 +477,20 @@ static int faraday_pci_probe(struct platform_device *pdev)
+ if (IS_ERR(p->base))
+ return PTR_ERR(p->base);
+
+- ret = devm_of_pci_get_host_bridge_resources(dev, 0, 0xff,
+- &res, &io_base);
++ ret = pci_parse_request_of_pci_ranges(dev, &host->windows, NULL);
+ if (ret)
+ return ret;
+
+- ret = devm_request_pci_bus_resources(dev, &res);
+- if (ret)
+- return ret;
+-
+- /* Get the I/O and memory ranges from DT */
+- resource_list_for_each_entry(win, &res) {
+- switch (resource_type(win->res)) {
+- case IORESOURCE_IO:
+- io = win->res;
+- io->name = "Gemini PCI I/O";
+- if (!faraday_res_to_memcfg(io->start - win->offset,
+- resource_size(io), &val)) {
+- /* setup I/O space size */
+- writel(val, p->base + PCI_IOSIZE);
+- } else {
+- dev_err(dev, "illegal IO mem size\n");
+- return -EINVAL;
+- }
+- ret = devm_pci_remap_iospace(dev, io, io_base);
+- if (ret) {
+- dev_warn(dev, "error %d: failed to map resource %pR\n",
+- ret, io);
+- continue;
+- }
+- break;
+- case IORESOURCE_MEM:
+- mem = win->res;
+- mem->name = "Gemini PCI MEM";
+- break;
+- case IORESOURCE_BUS:
+- break;
+- default:
+- break;
++ win = resource_list_first_type(&host->windows, IORESOURCE_IO);
++ if (win) {
++ io = win->res;
++ if (!faraday_res_to_memcfg(io->start - win->offset,
++ resource_size(io), &val)) {
++ /* setup I/O space size */
++ writel(val, p->base + PCI_IOSIZE);
++ } else {
++ dev_err(dev, "illegal IO mem size\n");
++ return -EINVAL;
+ }
+ }
+
+@@ -569,7 +542,6 @@ static int faraday_pci_probe(struct platform_device *pdev)
+ if (ret)
+ return ret;
+
+- list_splice_init(&res, &host->windows);
+ ret = pci_scan_root_bus_bridge(host);
+ if (ret) {
+ dev_err(dev, "failed to scan host: %d\n", ret);
+@@ -581,7 +553,6 @@ static int faraday_pci_probe(struct platform_device *pdev)
+
+ pci_bus_assign_resources(p->bus);
+ pci_bus_add_devices(p->bus);
+- pci_free_resource_list(&res);
+
+ return 0;
+ }
+
diff --git a/patches.suse/pci-ftpci100-use-inbound-resources-for-setup.patch b/patches.suse/pci-ftpci100-use-inbound-resources-for-setup.patch
new file mode 100644
index 0000000000..95fb908305
--- /dev/null
+++ b/patches.suse/pci-ftpci100-use-inbound-resources-for-setup.patch
@@ -0,0 +1,88 @@
+From: Rob Herring <robh@kernel.org>
+Date: Mon, 28 Oct 2019 11:32:51 -0500
+Subject: PCI: ftpci100: Use inbound resources for setup
+Git-commit: ea4f718e8455e8d94ec5fcf270b9d37988fc5bbd
+Patch-mainline: Queued in subsystem maintainer repository
+Git-repo: https://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci.git
+References: jsc#SLE-7772
+
+Now that the helpers provide the inbound resources in the host bridge
+'dma_ranges' resource list, convert Faraday ftpci100 host bridge to use
+the resource list to setup the inbound addresses.
+
+Signed-off-by: Rob Herring <robh@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Reviewed-by: Andrew Murray <andrew.murray@arm.com>
+Acked-by: Linus Walleij <linus.walleij@linaro.org>
+Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Cc: Bjorn Helgaas <bhelgaas@google.com>
+
+Acked-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+---
+ drivers/pci/controller/pci-ftpci100.c | 27 ++++++++++-----------------
+ 1 file changed, 10 insertions(+), 17 deletions(-)
+
+diff --git a/drivers/pci/controller/pci-ftpci100.c b/drivers/pci/controller/pci-ftpci100.c
+index 66288b94e92d..1b67564de7af 100644
+--- a/drivers/pci/controller/pci-ftpci100.c
++++ b/drivers/pci/controller/pci-ftpci100.c
+@@ -375,12 +375,11 @@ static int faraday_pci_setup_cascaded_irq(struct faraday_pci *p)
+ return 0;
+ }
+
+-static int faraday_pci_parse_map_dma_ranges(struct faraday_pci *p,
+- struct device_node *np)
++static int faraday_pci_parse_map_dma_ranges(struct faraday_pci *p)
+ {
+- struct of_pci_range range;
+- struct of_pci_range_parser parser;
+ struct device *dev = p->dev;
++ struct pci_host_bridge *bridge = pci_host_bridge_from_priv(p);
++ struct resource_entry *entry;
+ u32 confreg[3] = {
+ FARADAY_PCI_MEM1_BASE_SIZE,
+ FARADAY_PCI_MEM2_BASE_SIZE,
+@@ -389,19 +388,13 @@ static int faraday_pci_parse_map_dma_ranges(struct faraday_pci *p,
+ int i = 0;
+ u32 val;
+
+- if (of_pci_dma_range_parser_init(&parser, np)) {
+- dev_err(dev, "missing dma-ranges property\n");
+- return -EINVAL;
+- }
+-
+- /*
+- * Get the dma-ranges from the device tree
+- */
+- for_each_of_pci_range(&parser, &range) {
+- u64 end = range.pci_addr + range.size - 1;
++ resource_list_for_each_entry(entry, &bridge->dma_ranges) {
++ u64 pci_addr = entry->res->start - entry->offset;
++ u64 end = entry->res->end - entry->offset;
+ int ret;
+
+- ret = faraday_res_to_memcfg(range.pci_addr, range.size, &val);
++ ret = faraday_res_to_memcfg(pci_addr,
++ resource_size(entry->res), &val);
+ if (ret) {
+ dev_err(dev,
+ "DMA range %d: illegal MEM resource size\n", i);
+@@ -409,7 +402,7 @@ static int faraday_pci_parse_map_dma_ranges(struct faraday_pci *p,
+ }
+
+ dev_info(dev, "DMA MEM%d BASE: 0x%016llx -> 0x%016llx config %08x\n",
+- i + 1, range.pci_addr, end, val);
++ i + 1, pci_addr, end, val);
+ if (i <= 2) {
+ faraday_raw_pci_write_config(p, 0, 0, confreg[i],
+ 4, val);
+@@ -539,7 +532,7 @@ static int faraday_pci_probe(struct platform_device *pdev)
+ cur_bus_speed = PCI_SPEED_66MHz;
+ }
+
+- ret = faraday_pci_parse_map_dma_ranges(p, dev->of_node);
++ ret = faraday_pci_parse_map_dma_ranges(p);
+ if (ret)
+ return ret;
+
+
diff --git a/patches.suse/pci-iproc-use-inbound-resources-for-setup.patch b/patches.suse/pci-iproc-use-inbound-resources-for-setup.patch
new file mode 100644
index 0000000000..593753147f
--- /dev/null
+++ b/patches.suse/pci-iproc-use-inbound-resources-for-setup.patch
@@ -0,0 +1,145 @@
+From: Rob Herring <robh@kernel.org>
+Date: Mon, 28 Oct 2019 11:32:54 -0500
+Subject: PCI: iproc: Use inbound resources for setup
+Git-commit: b9ae59b30bcf62691aec4170ce4bafc20e968490
+Patch-mainline: Queued in subsystem maintainer repository
+Git-repo: https://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci.git
+References: jsc#SLE-7772
+
+Now that the helpers provide the inbound resources in the host bridge
+'dma_ranges' resource list, convert Broadcom iProc host bridge to use
+the resource list to setup the inbound addresses.
+
+Signed-off-by: Rob Herring <robh@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Reviewed-by: Andrew Murray <andrew.murray@arm.com>
+Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Cc: Bjorn Helgaas <bhelgaas@google.com>
+Cc: Ray Jui <rjui@broadcom.com>
+Cc: Scott Branden <sbranden@broadcom.com>
+Cc: bcm-kernel-feedback-list@broadcom.com
+
+Acked-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+---
+ drivers/pci/controller/pcie-iproc.c | 77 ++++++++-----------------------------
+ 1 file changed, 17 insertions(+), 60 deletions(-)
+
+diff --git a/drivers/pci/controller/pcie-iproc.c b/drivers/pci/controller/pcie-iproc.c
+index 223335ee791a..f4d78e66846e 100644
+--- a/drivers/pci/controller/pcie-iproc.c
++++ b/drivers/pci/controller/pcie-iproc.c
+@@ -1122,15 +1122,16 @@ static int iproc_pcie_ib_write(struct iproc_pcie *pcie, int region_idx,
+ }
+
+ static int iproc_pcie_setup_ib(struct iproc_pcie *pcie,
+- struct of_pci_range *range,
++ struct resource_entry *entry,
+ enum iproc_pcie_ib_map_type type)
+ {
+ struct device *dev = pcie->dev;
+ struct iproc_pcie_ib *ib = &pcie->ib;
+ int ret;
+ unsigned int region_idx, size_idx;
+- u64 axi_addr = range->cpu_addr, pci_addr = range->pci_addr;
+- resource_size_t size = range->size;
++ u64 axi_addr = entry->res->start;
++ u64 pci_addr = entry->res->start - entry->offset;
++ resource_size_t size = resource_size(entry->res);
+
+ /* iterate through all IARR mapping regions */
+ for (region_idx = 0; region_idx < ib->nr_regions; region_idx++) {
+@@ -1182,66 +1183,19 @@ static int iproc_pcie_setup_ib(struct iproc_pcie *pcie,
+ return ret;
+ }
+
+-static int iproc_pcie_add_dma_range(struct device *dev,
+- struct list_head *resources,
+- struct of_pci_range *range)
+-{
+- struct resource *res;
+- struct resource_entry *entry, *tmp;
+- struct list_head *head = resources;
+-
+- res = devm_kzalloc(dev, sizeof(struct resource), GFP_KERNEL);
+- if (!res)
+- return -ENOMEM;
+-
+- resource_list_for_each_entry(tmp, resources) {
+- if (tmp->res->start < range->cpu_addr)
+- head = &tmp->node;
+- }
+-
+- res->start = range->cpu_addr;
+- res->end = res->start + range->size - 1;
+-
+- entry = resource_list_create_entry(res, 0);
+- if (!entry)
+- return -ENOMEM;
+-
+- entry->offset = res->start - range->cpu_addr;
+- resource_list_add(entry, head);
+-
+- return 0;
+-}
+-
+ static int iproc_pcie_map_dma_ranges(struct iproc_pcie *pcie)
+ {
+ struct pci_host_bridge *host = pci_host_bridge_from_priv(pcie);
+- struct of_pci_range range;
+- struct of_pci_range_parser parser;
+- int ret;
+- LIST_HEAD(resources);
+-
+- /* Get the dma-ranges from DT */
+- ret = of_pci_dma_range_parser_init(&parser, pcie->dev->of_node);
+- if (ret)
+- return ret;
++ struct resource_entry *entry;
++ int ret = 0;
+
+- for_each_of_pci_range(&parser, &range) {
+- ret = iproc_pcie_add_dma_range(pcie->dev,
+- &resources,
+- &range);
+- if (ret)
+- goto out;
++ resource_list_for_each_entry(entry, &host->dma_ranges) {
+ /* Each range entry corresponds to an inbound mapping region */
+- ret = iproc_pcie_setup_ib(pcie, &range, IPROC_PCIE_IB_MAP_MEM);
++ ret = iproc_pcie_setup_ib(pcie, entry, IPROC_PCIE_IB_MAP_MEM);
+ if (ret)
+- goto out;
++ break;
+ }
+
+- list_splice_init(&resources, &host->dma_ranges);
+-
+- return 0;
+-out:
+- pci_free_resource_list(&resources);
+ return ret;
+ }
+
+@@ -1276,13 +1230,16 @@ static int iproce_pcie_get_msi(struct iproc_pcie *pcie,
+ static int iproc_pcie_paxb_v2_msi_steer(struct iproc_pcie *pcie, u64 msi_addr)
+ {
+ int ret;
+- struct of_pci_range range;
++ struct resource_entry entry;
++
++ memset(&entry, 0, sizeof(entry));
++ entry.res = &entry.__res;
+
+- memset(&range, 0, sizeof(range));
+- range.size = SZ_32K;
+- range.pci_addr = range.cpu_addr = msi_addr & ~(range.size - 1);
++ msi_addr &= ~(SZ_32K - 1);
++ entry.res->start = msi_addr;
++ entry.res->end = msi_addr + SZ_32K - 1;
+
+- ret = iproc_pcie_setup_ib(pcie, &range, IPROC_PCIE_IB_MAP_IO);
++ ret = iproc_pcie_setup_ib(pcie, &entry, IPROC_PCIE_IB_MAP_IO);
+ return ret;
+ }
+
+
diff --git a/patches.suse/pci-iproc-use-pci_parse_request_of_pci_ranges.patch b/patches.suse/pci-iproc-use-pci_parse_request_of_pci_ranges.patch
new file mode 100644
index 0000000000..ace63c208f
--- /dev/null
+++ b/patches.suse/pci-iproc-use-pci_parse_request_of_pci_ranges.patch
@@ -0,0 +1,83 @@
+From: Rob Herring <robh@kernel.org>
+Date: Mon, 28 Oct 2019 11:32:38 -0500
+Subject: PCI: iproc: Use pci_parse_request_of_pci_ranges()
+Git-commit: 7ef1c871da16125ae58db13716fe82795dcbe3e8
+Patch-mainline: Queued in subsystem maintainer repository
+Git-repo: https://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci.git
+References: jsc#SLE-7772
+
+Convert the iProc host bridge to use the common
+pci_parse_request_of_pci_ranges().
+
+There's no need to assign the resources to a temporary list, so just use
+bridge->windows directly.
+
+Signed-off-by: Rob Herring <robh@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Reviewed-by: Andrew Murray <andrew.murray@arm.com>
+Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Cc: Bjorn Helgaas <bhelgaas@google.com>
+Cc: Ray Jui <rjui@broadcom.com>
+Cc: Scott Branden <sbranden@broadcom.com>
+Cc: bcm-kernel-feedback-list@broadcom.com
+
+Acked-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+---
+ drivers/pci/controller/pcie-iproc-platform.c | 8 ++------
+ drivers/pci/controller/pcie-iproc.c | 5 -----
+ 2 files changed, 2 insertions(+), 11 deletions(-)
+
+--- a/drivers/pci/controller/pcie-iproc-platform.c
++++ b/drivers/pci/controller/pcie-iproc-platform.c
+@@ -43,8 +43,6 @@ static int iproc_pcie_pltfm_probe(struct
+ struct iproc_pcie *pcie;
+ struct device_node *np = dev->of_node;
+ struct resource reg;
+- resource_size_t iobase = 0;
+- LIST_HEAD(resources);
+ struct pci_host_bridge *bridge;
+ int ret;
+
+@@ -100,8 +98,7 @@ static int iproc_pcie_pltfm_probe(struct
+ pcie->phy = NULL;
+ }
+
+- ret = devm_of_pci_get_host_bridge_resources(dev, 0, 0xff, &resources,
+- &iobase);
++ ret = pci_parse_request_of_pci_ranges(dev, &bridge->windows, NULL);
+ if (ret) {
+ dev_err(dev, "unable to get PCI host bridge resources\n");
+ return ret;
+@@ -116,10 +113,9 @@ static int iproc_pcie_pltfm_probe(struct
+ pcie->map_irq = of_irq_parse_and_map_pci;
+ }
+
+- ret = iproc_pcie_setup(pcie, &resources);
++ ret = iproc_pcie_setup(pcie, &bridge->windows);
+ if (ret) {
+ dev_err(dev, "PCIe controller setup failed\n");
+- pci_free_resource_list(&resources);
+ return ret;
+ }
+
+--- a/drivers/pci/controller/pcie-iproc.c
++++ b/drivers/pci/controller/pcie-iproc.c
+@@ -1498,10 +1498,6 @@ int iproc_pcie_setup(struct iproc_pcie *
+ return ret;
+ }
+
+- ret = devm_request_pci_bus_resources(dev, res);
+- if (ret)
+- return ret;
+-
+ ret = phy_init(pcie->phy);
+ if (ret) {
+ dev_err(dev, "unable to initialize PCIe PHY\n");
+@@ -1543,7 +1539,6 @@ int iproc_pcie_setup(struct iproc_pcie *
+ if (iproc_pcie_msi_enable(pcie))
+ dev_info(dev, "not using iProc MSI\n");
+
+- list_splice_init(res, &host->windows);
+ host->busnr = 0;
+ host->dev.parent = dev;
+ host->ops = &iproc_pcie_ops;
diff --git a/patches.suse/pci-mediatek-use-pci_parse_request_of_pci_ranges.patch b/patches.suse/pci-mediatek-use-pci_parse_request_of_pci_ranges.patch
new file mode 100644
index 0000000000..a0d71149d3
--- /dev/null
+++ b/patches.suse/pci-mediatek-use-pci_parse_request_of_pci_ranges.patch
@@ -0,0 +1,103 @@
+From: Rob Herring <robh@kernel.org>
+Date: Mon, 28 Oct 2019 11:32:39 -0500
+Subject: PCI: mediatek: Use pci_parse_request_of_pci_ranges()
+Git-commit: 8a26f861b815c997dd85cc2f6210020e7a700a62
+Patch-mainline: Queued in subsystem maintainer repository
+Git-repo: https://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci.git
+References: jsc#SLE-7772
+
+Convert Mediatek host bridge to use the common
+pci_parse_request_of_pci_ranges().
+
+Signed-off-by: Rob Herring <robh@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Reviewed-by: Andrew Murray <andrew.murray@arm.com>
+Cc: Ryder Lee <ryder.lee@mediatek.com>
+Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Cc: Bjorn Helgaas <bhelgaas@google.com>
+Cc: Matthias Brugger <matthias.bgg@gmail.com>
+Cc: linux-mediatek@lists.infradead.org
+
+Acked-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+---
+ drivers/pci/controller/pcie-mediatek.c | 43 ++++++++++------------------------
+ 1 file changed, 13 insertions(+), 30 deletions(-)
+
+diff --git a/drivers/pci/controller/pcie-mediatek.c b/drivers/pci/controller/pcie-mediatek.c
+index 626a7c352dfd..d9206a3cd56b 100644
+--- a/drivers/pci/controller/pcie-mediatek.c
++++ b/drivers/pci/controller/pcie-mediatek.c
+@@ -216,7 +216,6 @@ struct mtk_pcie {
+ void __iomem *base;
+ struct clk *free_ck;
+
+- struct resource mem;
+ struct list_head ports;
+ const struct mtk_pcie_soc *soc;
+ unsigned int busnr;
+@@ -661,11 +660,19 @@ static int mtk_pcie_setup_irq(struct mtk_pcie_port *port,
+ static int mtk_pcie_startup_port_v2(struct mtk_pcie_port *port)
+ {
+ struct mtk_pcie *pcie = port->pcie;
+- struct resource *mem = &pcie->mem;
++ struct pci_host_bridge *host = pci_host_bridge_from_priv(pcie);
++ struct resource *mem = NULL;
++ struct resource_entry *entry;
+ const struct mtk_pcie_soc *soc = port->pcie->soc;
+ u32 val;
+ int err;
+
++ entry = resource_list_first_type(&host->windows, IORESOURCE_MEM);
++ if (entry)
++ mem = entry->res;
++ if (!mem)
++ return -EINVAL;
++
+ /* MT7622 platforms need to enable LTSSM and ASPM from PCIe subsys */
+ if (pcie->base) {
+ val = readl(pcie->base + PCIE_SYS_CFG_V2);
+@@ -1023,39 +1030,15 @@ static int mtk_pcie_setup(struct mtk_pcie *pcie)
+ struct mtk_pcie_port *port, *tmp;
+ struct pci_host_bridge *host = pci_host_bridge_from_priv(pcie);
+ struct list_head *windows = &host->windows;
+- struct resource_entry *win, *tmp_win;
+- resource_size_t io_base;
++ struct resource *bus;
+ int err;
+
+- err = devm_of_pci_get_host_bridge_resources(dev, 0, 0xff,
+- windows, &io_base);
++ err = pci_parse_request_of_pci_ranges(dev, windows,
++ &bus);
+ if (err)
+ return err;
+
+- err = devm_request_pci_bus_resources(dev, windows);
+- if (err < 0)
+- return err;
+-
+- /* Get the I/O and memory ranges from DT */
+- resource_list_for_each_entry_safe(win, tmp_win, windows) {
+- switch (resource_type(win->res)) {
+- case IORESOURCE_IO:
+- err = devm_pci_remap_iospace(dev, win->res, io_base);
+- if (err) {
+- dev_warn(dev, "error %d: failed to map resource %pR\n",
+- err, win->res);
+- resource_list_destroy_entry(win);
+- }
+- break;
+- case IORESOURCE_MEM:
+- memcpy(&pcie->mem, win->res, sizeof(*win->res));
+- pcie->mem.name = "non-prefetchable";
+- break;
+- case IORESOURCE_BUS:
+- pcie->busnr = win->res->start;
+- break;
+- }
+- }
++ pcie->busnr = bus->start;
+
+ for_each_available_child_of_node(node, child) {
+ int slot;
+
diff --git a/patches.suse/pci-mobiveil-use-pci_parse_request_of_pci_ranges.patch b/patches.suse/pci-mobiveil-use-pci_parse_request_of_pci_ranges.patch
new file mode 100644
index 0000000000..d19da4c524
--- /dev/null
+++ b/patches.suse/pci-mobiveil-use-pci_parse_request_of_pci_ranges.patch
@@ -0,0 +1,132 @@
+From: Rob Herring <robh@kernel.org>
+Date: Mon, 28 Oct 2019 11:32:40 -0500
+Subject: PCI: mobiveil: Use pci_parse_request_of_pci_ranges()
+Git-commit: 6c6a0dff064176a5a0c6b1a9ee32f868ecd5e0f1
+Patch-mainline: Queued in subsystem maintainer repository
+Git-repo: https://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci.git
+References: jsc#SLE-7772
+
+Convert the Mobiveil host bridge to use the common
+pci_parse_request_of_pci_ranges().
+
+There's no need to assign the resources to a temporary list first. Just
+use bridge->windows directly and remove all the temporary list handling.
+
+Signed-off-by: Rob Herring <robh@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Reviewed-by: Andrew Murray <andrew.murray@arm.com>
+Reviewed-by: Hou Zhiqiang <Zhiqiang.Hou@nxp.com>
+Cc: Karthikeyan Mitran <m.karthikeyan@mobiveil.co.in>
+Cc: Hou Zhiqiang <Zhiqiang.Hou@nxp.com>
+Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Cc: Bjorn Helgaas <bhelgaas@google.com>
+
+Acked-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+---
+ drivers/pci/controller/pcie-mobiveil.c | 26 +++++++-------------------
+ 1 file changed, 7 insertions(+), 19 deletions(-)
+
+diff --git a/drivers/pci/controller/pcie-mobiveil.c b/drivers/pci/controller/pcie-mobiveil.c
+index a45a6447b01d..4eab8624ce4d 100644
+--- a/drivers/pci/controller/pcie-mobiveil.c
++++ b/drivers/pci/controller/pcie-mobiveil.c
+@@ -140,7 +140,6 @@ struct mobiveil_msi { /* MSI information */
+
+ struct mobiveil_pcie {
+ struct platform_device *pdev;
+- struct list_head resources;
+ void __iomem *config_axi_slave_base; /* endpoint config base */
+ void __iomem *csr_axi_slave_base; /* root port config base */
+ void __iomem *apb_csr_base; /* MSI register base */
+@@ -575,6 +574,7 @@ static void mobiveil_pcie_enable_msi(struct mobiveil_pcie *pcie)
+
+ static int mobiveil_host_init(struct mobiveil_pcie *pcie)
+ {
++ struct pci_host_bridge *bridge = pci_host_bridge_from_priv(pcie);
+ u32 value, pab_ctrl, type;
+ struct resource_entry *win;
+
+@@ -631,7 +631,7 @@ static int mobiveil_host_init(struct mobiveil_pcie *pcie)
+ program_ib_windows(pcie, WIN_NUM_0, 0, 0, MEM_WINDOW_TYPE, IB_WIN_SIZE);
+
+ /* Get the I/O and memory ranges from DT */
+- resource_list_for_each_entry(win, &pcie->resources) {
++ resource_list_for_each_entry(win, &bridge->windows) {
+ if (resource_type(win->res) == IORESOURCE_MEM)
+ type = MEM_WINDOW_TYPE;
+ else if (resource_type(win->res) == IORESOURCE_IO)
+@@ -857,7 +857,6 @@ static int mobiveil_pcie_probe(struct platform_device *pdev)
+ struct pci_bus *child;
+ struct pci_host_bridge *bridge;
+ struct device *dev = &pdev->dev;
+- resource_size_t iobase;
+ int ret;
+
+ /* allocate the PCIe port */
+@@ -875,11 +874,8 @@ static int mobiveil_pcie_probe(struct platform_device *pdev)
+ return ret;
+ }
+
+- INIT_LIST_HEAD(&pcie->resources);
+-
+ /* parse the host bridge base addresses from the device tree file */
+- ret = devm_of_pci_get_host_bridge_resources(dev, 0, 0xff,
+- &pcie->resources, &iobase);
++ ret = pci_parse_request_of_pci_ranges(dev, &bridge->windows, NULL);
+ if (ret) {
+ dev_err(dev, "Getting bridge resources failed\n");
+ return ret;
+@@ -892,24 +888,19 @@ static int mobiveil_pcie_probe(struct platform_device *pdev)
+ ret = mobiveil_host_init(pcie);
+ if (ret) {
+ dev_err(dev, "Failed to initialize host\n");
+- goto error;
++ return ret;
+ }
+
+ /* initialize the IRQ domains */
+ ret = mobiveil_pcie_init_irq_domain(pcie);
+ if (ret) {
+ dev_err(dev, "Failed creating IRQ Domain\n");
+- goto error;
++ return ret;
+ }
+
+ irq_set_chained_handler_and_data(pcie->irq, mobiveil_pcie_isr, pcie);
+
+- ret = devm_request_pci_bus_resources(dev, &pcie->resources);
+- if (ret)
+- goto error;
+-
+ /* Initialize bridge */
+- list_splice_init(&pcie->resources, &bridge->windows);
+ bridge->dev.parent = dev;
+ bridge->sysdata = pcie;
+ bridge->busnr = pcie->root_bus_nr;
+@@ -920,13 +911,13 @@ static int mobiveil_pcie_probe(struct platform_device *pdev)
+ ret = mobiveil_bringup_link(pcie);
+ if (ret) {
+ dev_info(dev, "link bring-up failed\n");
+- goto error;
++ return ret;
+ }
+
+ /* setup the kernel resources for the newly added PCIe root bus */
+ ret = pci_scan_root_bus_bridge(bridge);
+ if (ret)
+- goto error;
++ return ret;
+
+ bus = bridge->bus;
+
+@@ -936,9 +927,6 @@ static int mobiveil_pcie_probe(struct platform_device *pdev)
+ pci_bus_add_devices(bus);
+
+ return 0;
+-error:
+- pci_free_resource_list(&pcie->resources);
+- return ret;
+ }
+
+ static const struct of_device_id mobiveil_pcie_of_match[] = {
+
diff --git a/patches.suse/pci-of-add-inbound-resource-parsing-to-helpers.patch b/patches.suse/pci-of-add-inbound-resource-parsing-to-helpers.patch
new file mode 100644
index 0000000000..3b8e6abc8e
--- /dev/null
+++ b/patches.suse/pci-of-add-inbound-resource-parsing-to-helpers.patch
@@ -0,0 +1,408 @@
+From: Rob Herring <robh@kernel.org>
+Date: Wed, 30 Oct 2019 17:30:57 -0500
+Subject: PCI: of: Add inbound resource parsing to helpers
+Git-commit: 331f63457165a30c708280de2c77f1742c6351dc
+Patch-mainline: Queued in subsystem maintainer repository
+Git-repo: https://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci.git
+References: jsc#SLE-7772
+
+Extend devm_of_pci_get_host_bridge_resources() and
+pci_parse_request_of_pci_ranges() helpers to also parse the inbound
+addresses from DT 'dma-ranges' and populate a resource list with the
+translated addresses. This will help ensure 'dma-ranges' is always
+parsed in a consistent way.
+
+Tested-by: Srinath Mannam <srinath.mannam@broadcom.com>
+Tested-by: Thomas Petazzoni <thomas.petazzoni@bootlin.com> # for AArdvark
+Signed-off-by: Rob Herring <robh@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Reviewed-by: Srinath Mannam <srinath.mannam@broadcom.com>
+Reviewed-by: Andrew Murray <andrew.murray@arm.com>
+Acked-by: Gustavo Pimentel <gustavo.pimentel@synopsys.com>
+Cc: Jingoo Han <jingoohan1@gmail.com>
+Cc: Gustavo Pimentel <gustavo.pimentel@synopsys.com>
+Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Cc: Bjorn Helgaas <bhelgaas@google.com>
+Cc: Thomas Petazzoni <thomas.petazzoni@bootlin.com>
+Cc: Will Deacon <will@kernel.org>
+Cc: Linus Walleij <linus.walleij@linaro.org>
+Cc: Toan Le <toan@os.amperecomputing.com>
+Cc: Ley Foon Tan <lftan@altera.com>
+Cc: Tom Joseph <tjoseph@cadence.com>
+Cc: Ray Jui <rjui@broadcom.com>
+Cc: Scott Branden <sbranden@broadcom.com>
+Cc: bcm-kernel-feedback-list@broadcom.com
+Cc: Ryder Lee <ryder.lee@mediatek.com>
+Cc: Karthikeyan Mitran <m.karthikeyan@mobiveil.co.in>
+Cc: Hou Zhiqiang <Zhiqiang.Hou@nxp.com>
+Cc: Simon Horman <horms@verge.net.au>
+Cc: Shawn Lin <shawn.lin@rock-chips.com>
+Cc: Heiko Stuebner <heiko@sntech.de>
+Cc: Michal Simek <michal.simek@xilinx.com>
+Cc: rfi@lists.rocketboards.org
+Cc: linux-mediatek@lists.infradead.org
+Cc: linux-renesas-soc@vger.kernel.org
+Cc: linux-rockchip@lists.infradead.org
+
+Acked-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+---
+ drivers/pci/controller/dwc/pcie-designware-host.c | 3 -
+ drivers/pci/controller/pci-aardvark.c | 2
+ drivers/pci/controller/pci-ftpci100.c | 3 -
+ drivers/pci/controller/pci-host-common.c | 2
+ drivers/pci/controller/pci-v3-semi.c | 3 -
+ drivers/pci/controller/pci-versatile.c | 3 -
+ drivers/pci/controller/pci-xgene.c | 3 -
+ drivers/pci/controller/pcie-altera.c | 2
+ drivers/pci/controller/pcie-cadence-host.c | 2
+ drivers/pci/controller/pcie-iproc-platform.c | 3 -
+ drivers/pci/controller/pcie-mediatek.c | 2
+ drivers/pci/controller/pcie-mobiveil.c | 3 -
+ drivers/pci/controller/pcie-rcar.c | 3 -
+ drivers/pci/controller/pcie-rockchip-host.c | 3 -
+ drivers/pci/controller/pcie-xilinx-nwl.c | 3 -
+ drivers/pci/controller/pcie-xilinx.c | 3 -
+ drivers/pci/of.c | 61 +++++++++++++++++++---
+ drivers/pci/pci.h | 8 ++
+ include/linux/pci.h | 9 ++-
+ 19 files changed, 93 insertions(+), 28 deletions(-)
+
+--- a/drivers/pci/controller/dwc/pcie-designware-host.c
++++ b/drivers/pci/controller/dwc/pcie-designware-host.c
+@@ -341,7 +341,8 @@ int dw_pcie_host_init(struct pcie_port *
+ if (!bridge)
+ return -ENOMEM;
+
+- ret = pci_parse_request_of_pci_ranges(dev, &bridge->windows, NULL);
++ ret = pci_parse_request_of_pci_ranges(dev, &bridge->windows,
++ &bridge->dma_ranges, NULL);
+ if (ret)
+ return ret;
+
+--- a/drivers/pci/controller/pci-aardvark.c
++++ b/drivers/pci/controller/pci-aardvark.c
+@@ -939,7 +939,7 @@ static int advk_pcie_probe(struct platfo
+ }
+
+ ret = pci_parse_request_of_pci_ranges(dev, &bridge->windows,
+- &bus);
++ &bridge->dma_ranges, &bus);
+ if (ret) {
+ dev_err(dev, "Failed to parse resources\n");
+ return ret;
+--- a/drivers/pci/controller/pci-ftpci100.c
++++ b/drivers/pci/controller/pci-ftpci100.c
+@@ -477,7 +477,8 @@ static int faraday_pci_probe(struct plat
+ if (IS_ERR(p->base))
+ return PTR_ERR(p->base);
+
+- ret = pci_parse_request_of_pci_ranges(dev, &host->windows, NULL);
++ ret = pci_parse_request_of_pci_ranges(dev, &host->windows,
++ &host->dma_ranges, NULL);
+ if (ret)
+ return ret;
+
+--- a/drivers/pci/controller/pci-host-common.c
++++ b/drivers/pci/controller/pci-host-common.c
+@@ -27,7 +27,7 @@ static struct pci_config_window *gen_pci
+ struct pci_config_window *cfg;
+
+ /* Parse our PCI ranges and request their resources */
+- err = pci_parse_request_of_pci_ranges(dev, resources, &bus_range);
++ err = pci_parse_request_of_pci_ranges(dev, resources, NULL, &bus_range);
+ if (err)
+ return ERR_PTR(err);
+
+--- a/drivers/pci/controller/pci-v3-semi.c
++++ b/drivers/pci/controller/pci-v3-semi.c
+@@ -776,7 +776,8 @@ static int v3_pci_probe(struct platform_
+ if (IS_ERR(v3->config_base))
+ return PTR_ERR(v3->config_base);
+
+- ret = pci_parse_request_of_pci_ranges(dev, &host->windows, NULL);
++ ret = pci_parse_request_of_pci_ranges(dev, &host->windows,
++ &host->dma_ranges, NULL);
+ if (ret)
+ return ret;
+
+--- a/drivers/pci/controller/pci-versatile.c
++++ b/drivers/pci/controller/pci-versatile.c
+@@ -92,7 +92,8 @@ static int versatile_pci_probe(struct pl
+ if (IS_ERR(versatile_cfg_base[1]))
+ return PTR_ERR(versatile_cfg_base[1]);
+
+- ret = pci_parse_request_of_pci_ranges(dev, &bridge->windows, NULL);
++ ret = pci_parse_request_of_pci_ranges(dev, &bridge->windows,
++ NULL, NULL);
+ if (ret)
+ return ret;
+
+--- a/drivers/pci/controller/pci-xgene.c
++++ b/drivers/pci/controller/pci-xgene.c
+@@ -627,7 +627,8 @@ static int xgene_pcie_probe(struct platf
+ if (ret)
+ return ret;
+
+- ret = pci_parse_request_of_pci_ranges(dev, &bridge->windows, NULL);
++ ret = pci_parse_request_of_pci_ranges(dev, &bridge->windows,
++ &bridge->dma_ranges, NULL);
+ if (ret)
+ return ret;
+
+--- a/drivers/pci/controller/pcie-altera.c
++++ b/drivers/pci/controller/pcie-altera.c
+@@ -800,7 +800,7 @@ static int altera_pcie_probe(struct plat
+ }
+
+ ret = pci_parse_request_of_pci_ranges(dev, &bridge->windows,
+- NULL);
++ &bridge->dma_ranges, NULL);
+ if (ret) {
+ dev_err(dev, "Failed add resources\n");
+ return ret;
+--- a/drivers/pci/controller/pcie-cadence-host.c
++++ b/drivers/pci/controller/pcie-cadence-host.c
+@@ -211,7 +211,7 @@ static int cdns_pcie_host_init(struct de
+ int err;
+
+ /* Parse our PCI ranges and request their resources */
+- err = pci_parse_request_of_pci_ranges(dev, resources, &bus_range);
++ err = pci_parse_request_of_pci_ranges(dev, resources, NULL, &bus_range);
+ if (err)
+ return err;
+
+--- a/drivers/pci/controller/pcie-iproc-platform.c
++++ b/drivers/pci/controller/pcie-iproc-platform.c
+@@ -98,7 +98,8 @@ static int iproc_pcie_pltfm_probe(struct
+ pcie->phy = NULL;
+ }
+
+- ret = pci_parse_request_of_pci_ranges(dev, &bridge->windows, NULL);
++ ret = pci_parse_request_of_pci_ranges(dev, &bridge->windows,
++ &bridge->dma_ranges, NULL);
+ if (ret) {
+ dev_err(dev, "unable to get PCI host bridge resources\n");
+ return ret;
+--- a/drivers/pci/controller/pcie-mediatek.c
++++ b/drivers/pci/controller/pcie-mediatek.c
+@@ -1028,7 +1028,7 @@ static int mtk_pcie_setup(struct mtk_pci
+ int err;
+
+ err = pci_parse_request_of_pci_ranges(dev, windows,
+- &bus);
++ &host->dma_ranges, &bus);
+ if (err)
+ return err;
+
+--- a/drivers/pci/controller/pcie-mobiveil.c
++++ b/drivers/pci/controller/pcie-mobiveil.c
+@@ -875,7 +875,8 @@ static int mobiveil_pcie_probe(struct pl
+ }
+
+ /* parse the host bridge base addresses from the device tree file */
+- ret = pci_parse_request_of_pci_ranges(dev, &bridge->windows, NULL);
++ ret = pci_parse_request_of_pci_ranges(dev, &bridge->windows,
++ &bridge->dma_ranges, NULL);
+ if (ret) {
+ dev_err(dev, "Getting bridge resources failed\n");
+ return ret;
+--- a/drivers/pci/controller/pcie-rcar.c
++++ b/drivers/pci/controller/pcie-rcar.c
+@@ -1138,7 +1138,8 @@ static int rcar_pcie_probe(struct platfo
+ pcie->dev = dev;
+ platform_set_drvdata(pdev, pcie);
+
+- err = pci_parse_request_of_pci_ranges(dev, &pcie->resources, NULL);
++ err = pci_parse_request_of_pci_ranges(dev, &pcie->resources,
++ &bridge->dma_ranges, NULL);
+ if (err)
+ goto err_free_bridge;
+
+--- a/drivers/pci/controller/pcie-rockchip-host.c
++++ b/drivers/pci/controller/pcie-rockchip-host.c
+@@ -1004,7 +1004,8 @@ static int rockchip_pcie_probe(struct pl
+ if (err < 0)
+ goto err_deinit_port;
+
+- err = pci_parse_request_of_pci_ranges(dev, &bridge->windows, &bus_res);
++ err = pci_parse_request_of_pci_ranges(dev, &bridge->windows,
++ &bridge->dma_ranges, &bus_res);
+ if (err)
+ goto err_remove_irq_domain;
+
+--- a/drivers/pci/controller/pcie-xilinx-nwl.c
++++ b/drivers/pci/controller/pcie-xilinx-nwl.c
+@@ -843,7 +843,8 @@ static int nwl_pcie_probe(struct platfor
+ return err;
+ }
+
+- err = pci_parse_request_of_pci_ranges(dev, &bridge->windows, NULL);
++ err = pci_parse_request_of_pci_ranges(dev, &bridge->windows,
++ &bridge->dma_ranges, NULL);
+ if (err) {
+ dev_err(dev, "Getting bridge resources failed\n");
+ return err;
+--- a/drivers/pci/controller/pcie-xilinx.c
++++ b/drivers/pci/controller/pcie-xilinx.c
+@@ -645,7 +645,8 @@ static int xilinx_pcie_probe(struct plat
+ return err;
+ }
+
+- err = pci_parse_request_of_pci_ranges(dev, &bridge->windows, NULL);
++ err = pci_parse_request_of_pci_ranges(dev, &bridge->windows,
++ &bridge->dma_ranges, NULL);
+ if (err) {
+ dev_err(dev, "Getting bridge resources failed\n");
+ return err;
+--- a/drivers/pci/of.c
++++ b/drivers/pci/of.c
+@@ -257,14 +257,16 @@ EXPORT_SYMBOL_GPL(of_pci_check_probe_onl
+ */
+ int devm_of_pci_get_host_bridge_resources(struct device *dev,
+ unsigned char busno, unsigned char bus_max,
+- struct list_head *resources, resource_size_t *io_base)
++ struct list_head *resources,
++ struct list_head *ib_resources,
++ resource_size_t *io_base)
+ {
+ struct device_node *dev_node = dev->of_node;
+ struct resource *res, tmp_res;
+ struct resource *bus_range;
+ struct of_pci_range range;
+ struct of_pci_range_parser parser;
+- char range_type[4];
++ const char *range_type;
+ int err;
+
+ if (io_base)
+@@ -298,12 +300,12 @@ int devm_of_pci_get_host_bridge_resource
+ for_each_of_pci_range(&parser, &range) {
+ /* Read next ranges element */
+ if ((range.flags & IORESOURCE_TYPE_BITS) == IORESOURCE_IO)
+- snprintf(range_type, 4, " IO");
++ range_type = "IO";
+ else if ((range.flags & IORESOURCE_TYPE_BITS) == IORESOURCE_MEM)
+- snprintf(range_type, 4, "MEM");
++ range_type = "MEM";
+ else
+- snprintf(range_type, 4, "err");
+- dev_info(dev, " %s %#010llx..%#010llx -> %#010llx\n",
++ range_type = "err";
++ dev_info(dev, " %6s %#012llx..%#012llx -> %#012llx\n",
+ range_type, range.cpu_addr,
+ range.cpu_addr + range.size - 1, range.pci_addr);
+
+@@ -340,6 +342,48 @@ int devm_of_pci_get_host_bridge_resource
+ pci_add_resource_offset(resources, res, res->start - range.pci_addr);
+ }
+
++ /* Check for dma-ranges property */
++ if (!ib_resources)
++ return 0;
++ err = of_pci_dma_range_parser_init(&parser, dev_node);
++ if (err)
++ return 0;
++
++ dev_dbg(dev, "Parsing dma-ranges property...\n");
++ for_each_of_pci_range(&parser, &range) {
++ struct resource_entry *entry;
++ /*
++ * If we failed translation or got a zero-sized region
++ * then skip this range
++ */
++ if (((range.flags & IORESOURCE_TYPE_BITS) != IORESOURCE_MEM) ||
++ range.cpu_addr == OF_BAD_ADDR || range.size == 0)
++ continue;
++
++ dev_info(dev, " %6s %#012llx..%#012llx -> %#012llx\n",
++ "IB MEM", range.cpu_addr,
++ range.cpu_addr + range.size - 1, range.pci_addr);
++
++
++ err = of_pci_range_to_resource(&range, dev_node, &tmp_res);
++ if (err)
++ continue;
++
++ res = devm_kmemdup(dev, &tmp_res, sizeof(tmp_res), GFP_KERNEL);
++ if (!res) {
++ err = -ENOMEM;
++ goto failed;
++ }
++
++ /* Keep the resource list sorted */
++ resource_list_for_each_entry(entry, ib_resources)
++ if (entry->res->start > res->start)
++ break;
++
++ pci_add_resource_offset(&entry->node, res,
++ res->start - range.pci_addr);
++ }
++
+ return 0;
+
+ failed:
+@@ -482,6 +526,7 @@ EXPORT_SYMBOL_GPL(of_irq_parse_and_map_p
+
+ int pci_parse_request_of_pci_ranges(struct device *dev,
+ struct list_head *resources,
++ struct list_head *ib_resources,
+ struct resource **bus_range)
+ {
+ int err, res_valid = 0;
+@@ -489,8 +534,10 @@ int pci_parse_request_of_pci_ranges(stru
+ struct resource_entry *win, *tmp;
+
+ INIT_LIST_HEAD(resources);
++ if (ib_resources)
++ INIT_LIST_HEAD(ib_resources);
+ err = devm_of_pci_get_host_bridge_resources(dev, 0, 0xff, resources,
+- &iobase);
++ ib_resources, &iobase);
+ if (err)
+ return err;
+
+--- a/drivers/pci/pci.h
++++ b/drivers/pci/pci.h
+@@ -582,11 +582,15 @@ of_pci_get_max_link_speed(struct device_
+ #if defined(CONFIG_OF_ADDRESS)
+ int devm_of_pci_get_host_bridge_resources(struct device *dev,
+ unsigned char busno, unsigned char bus_max,
+- struct list_head *resources, resource_size_t *io_base);
++ struct list_head *resources,
++ struct list_head *ib_resources,
++ resource_size_t *io_base);
+ #else
+ static inline int devm_of_pci_get_host_bridge_resources(struct device *dev,
+ unsigned char busno, unsigned char bus_max,
+- struct list_head *resources, resource_size_t *io_base)
++ struct list_head *resources,
++ struct list_head *ib_resources,
++ resource_size_t *io_base)
+ {
+ return -EINVAL;
+ }
+--- a/include/linux/pci.h
++++ b/include/linux/pci.h
+@@ -2312,6 +2312,7 @@ void pci_release_bus_of_node(struct pci_
+ struct irq_domain *pci_host_bridge_of_msi_domain(struct pci_bus *bus);
+ int pci_parse_request_of_pci_ranges(struct device *dev,
+ struct list_head *resources,
++ struct list_head *ib_resources,
+ struct resource **bus_range);
+
+ /* Arch may override this (weak) */
+@@ -2324,9 +2325,11 @@ static inline void pci_set_bus_of_node(s
+ static inline void pci_release_bus_of_node(struct pci_bus *bus) { }
+ static inline struct irq_domain *
+ pci_host_bridge_of_msi_domain(struct pci_bus *bus) { return NULL; }
+-static inline int pci_parse_request_of_pci_ranges(struct device *dev,
+- struct list_head *resources,
+- struct resource **bus_range)
++static inline int
++pci_parse_request_of_pci_ranges(struct device *dev,
++ struct list_head *resources,
++ struct list_head *ib_resources,
++ struct resource **bus_range)
+ {
+ return -EINVAL;
+ }
diff --git a/patches.suse/pci-rcar-use-inbound-resources-for-setup.patch b/patches.suse/pci-rcar-use-inbound-resources-for-setup.patch
new file mode 100644
index 0000000000..0f60aa8fae
--- /dev/null
+++ b/patches.suse/pci-rcar-use-inbound-resources-for-setup.patch
@@ -0,0 +1,110 @@
+From: Rob Herring <robh@kernel.org>
+Date: Mon, 28 Oct 2019 11:32:55 -0500
+Subject: PCI: rcar: Use inbound resources for setup
+Git-commit: 085f793984adcbf3966176bac088c32e0b66235a
+Patch-mainline: Queued in subsystem maintainer repository
+Git-repo: https://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci.git
+References: jsc#SLE-7772
+
+Now that the helpers provide the inbound resources in the host bridge
+'dma_ranges' resource list, convert Renesas R-Car PCIe host bridge to
+use the resource list to setup the inbound addresses.
+
+Signed-off-by: Rob Herring <robh@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Cc: Simon Horman <horms@verge.net.au>
+Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Cc: Bjorn Helgaas <bhelgaas@google.com>
+
+Acked-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+---
+ drivers/pci/controller/pcie-rcar.c | 45 ++++++++++++++------------------------
+ 1 file changed, 16 insertions(+), 29 deletions(-)
+
+diff --git a/drivers/pci/controller/pcie-rcar.c b/drivers/pci/controller/pcie-rcar.c
+index b8d6e86a5539..453c931aaf77 100644
+--- a/drivers/pci/controller/pcie-rcar.c
++++ b/drivers/pci/controller/pcie-rcar.c
+@@ -1014,16 +1014,16 @@ static int rcar_pcie_get_resources(struct rcar_pcie *pcie)
+ }
+
+ static int rcar_pcie_inbound_ranges(struct rcar_pcie *pcie,
+- struct of_pci_range *range,
++ struct resource_entry *entry,
+ int *index)
+ {
+- u64 restype = range->flags;
+- u64 cpu_addr = range->cpu_addr;
+- u64 cpu_end = range->cpu_addr + range->size;
+- u64 pci_addr = range->pci_addr;
++ u64 restype = entry->res->flags;
++ u64 cpu_addr = entry->res->start;
++ u64 cpu_end = entry->res->end;
++ u64 pci_addr = entry->res->start - entry->offset;
+ u32 flags = LAM_64BIT | LAR_ENABLE;
+ u64 mask;
+- u64 size;
++ u64 size = resource_size(entry->res);
+ int idx = *index;
+
+ if (restype & IORESOURCE_PREFETCH)
+@@ -1037,9 +1037,7 @@ static int rcar_pcie_inbound_ranges(struct rcar_pcie *pcie,
+ unsigned long nr_zeros = __ffs64(cpu_addr);
+ u64 alignment = 1ULL << nr_zeros;
+
+- size = min(range->size, alignment);
+- } else {
+- size = range->size;
++ size = min(size, alignment);
+ }
+ /* Hardware supports max 4GiB inbound region */
+ size = min(size, 1ULL << 32);
+@@ -1078,30 +1076,19 @@ static int rcar_pcie_inbound_ranges(struct rcar_pcie *pcie,
+ return 0;
+ }
+
+-static int rcar_pcie_parse_map_dma_ranges(struct rcar_pcie *pcie,
+- struct device_node *np)
++static int rcar_pcie_parse_map_dma_ranges(struct rcar_pcie *pcie)
+ {
+- struct of_pci_range range;
+- struct of_pci_range_parser parser;
+- int index = 0;
+- int err;
+-
+- if (of_pci_dma_range_parser_init(&parser, np))
+- return -EINVAL;
+-
+- /* Get the dma-ranges from DT */
+- for_each_of_pci_range(&parser, &range) {
+- u64 end = range.cpu_addr + range.size - 1;
+-
+- dev_dbg(pcie->dev, "0x%08x 0x%016llx..0x%016llx -> 0x%016llx\n",
+- range.flags, range.cpu_addr, end, range.pci_addr);
++ struct pci_host_bridge *bridge = pci_host_bridge_from_priv(pcie);
++ struct resource_entry *entry;
++ int index = 0, err = 0;
+
+- err = rcar_pcie_inbound_ranges(pcie, &range, &index);
++ resource_list_for_each_entry(entry, &bridge->dma_ranges) {
++ err = rcar_pcie_inbound_ranges(pcie, entry, &index);
+ if (err)
+- return err;
++ break;
+ }
+
+- return 0;
++ return err;
+ }
+
+ static const struct of_device_id rcar_pcie_of_match[] = {
+@@ -1162,7 +1149,7 @@ static int rcar_pcie_probe(struct platform_device *pdev)
+ goto err_unmap_msi_irqs;
+ }
+
+- err = rcar_pcie_parse_map_dma_ranges(pcie, dev->of_node);
++ err = rcar_pcie_parse_map_dma_ranges(pcie);
+ if (err)
+ goto err_clk_disable;
+
+
diff --git a/patches.suse/pci-rockchip-drop-storing-driver-private-outbound-resource-data.patch b/patches.suse/pci-rockchip-drop-storing-driver-private-outbound-resource-data.patch
new file mode 100644
index 0000000000..b7c7e31b62
--- /dev/null
+++ b/patches.suse/pci-rockchip-drop-storing-driver-private-outbound-resource-data.patch
@@ -0,0 +1,153 @@
+From: Rob Herring <robh@kernel.org>
+Date: Mon, 28 Oct 2019 11:32:42 -0500
+Subject: PCI: rockchip: Drop storing driver private outbound resource data
+Git-commit: 62240a88004b0205beb0c1faca1c875c392b53f0
+Patch-mainline: Queued in subsystem maintainer repository
+Git-repo: https://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci.git
+References: jsc#SLE-7772
+
+The Rockchip host bridge driver doesn't need to store outboard resources
+in its private struct as they are already stored in struct
+pci_host_bridge.
+
+Signed-off-by: Rob Herring <robh@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Cc: Shawn Lin <shawn.lin@rock-chips.com>
+Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Cc: Andrew Murray <andrew.murray@arm.com>
+Cc: Bjorn Helgaas <bhelgaas@google.com>
+Cc: Heiko Stuebner <heiko@sntech.de>
+Cc: linux-rockchip@lists.infradead.org
+
+Acked-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+---
+ drivers/pci/controller/pcie-rockchip-host.c | 54 ++++++++++++-----------------
+ drivers/pci/controller/pcie-rockchip.h | 5 ---
+ 2 files changed, 23 insertions(+), 36 deletions(-)
+
+diff --git a/drivers/pci/controller/pcie-rockchip-host.c b/drivers/pci/controller/pcie-rockchip-host.c
+index 8d2e6f2e141e..f375e55ea02e 100644
+--- a/drivers/pci/controller/pcie-rockchip-host.c
++++ b/drivers/pci/controller/pcie-rockchip-host.c
+@@ -806,19 +806,28 @@ static int rockchip_pcie_prog_ib_atu(struct rockchip_pcie *rockchip,
+ static int rockchip_pcie_cfg_atu(struct rockchip_pcie *rockchip)
+ {
+ struct device *dev = rockchip->dev;
++ struct pci_host_bridge *bridge = pci_host_bridge_from_priv(rockchip);
++ struct resource_entry *entry;
++ u64 pci_addr, size;
+ int offset;
+ int err;
+ int reg_no;
+
+ rockchip_pcie_cfg_configuration_accesses(rockchip,
+ AXI_WRAPPER_TYPE0_CFG);
++ entry = resource_list_first_type(&bridge->windows, IORESOURCE_MEM);
++ if (!entry)
++ return -ENODEV;
++
++ size = resource_size(entry->res);
++ pci_addr = entry->res->start - entry->offset;
++ rockchip->msg_bus_addr = pci_addr;
+
+- for (reg_no = 0; reg_no < (rockchip->mem_size >> 20); reg_no++) {
++ for (reg_no = 0; reg_no < (size >> 20); reg_no++) {
+ err = rockchip_pcie_prog_ob_atu(rockchip, reg_no + 1,
+ AXI_WRAPPER_MEM_WRITE,
+ 20 - 1,
+- rockchip->mem_bus_addr +
+- (reg_no << 20),
++ pci_addr + (reg_no << 20),
+ 0);
+ if (err) {
+ dev_err(dev, "program RC mem outbound ATU failed\n");
+@@ -832,14 +841,20 @@ static int rockchip_pcie_cfg_atu(struct rockchip_pcie *rockchip)
+ return err;
+ }
+
+- offset = rockchip->mem_size >> 20;
+- for (reg_no = 0; reg_no < (rockchip->io_size >> 20); reg_no++) {
++ entry = resource_list_first_type(&bridge->windows, IORESOURCE_IO);
++ if (!entry)
++ return -ENODEV;
++
++ size = resource_size(entry->res);
++ pci_addr = entry->res->start - entry->offset;
++
++ offset = size >> 20;
++ for (reg_no = 0; reg_no < (size >> 20); reg_no++) {
+ err = rockchip_pcie_prog_ob_atu(rockchip,
+ reg_no + 1 + offset,
+ AXI_WRAPPER_IO_WRITE,
+ 20 - 1,
+- rockchip->io_bus_addr +
+- (reg_no << 20),
++ pci_addr + (reg_no << 20),
+ 0);
+ if (err) {
+ dev_err(dev, "program RC io outbound ATU failed\n");
+@@ -852,8 +867,7 @@ static int rockchip_pcie_cfg_atu(struct rockchip_pcie *rockchip)
+ AXI_WRAPPER_NOR_MSG,
+ 20 - 1, 0, 0);
+
+- rockchip->msg_bus_addr = rockchip->mem_bus_addr +
+- ((reg_no + offset) << 20);
++ rockchip->msg_bus_addr += ((reg_no + offset) << 20);
+ return err;
+ }
+
+@@ -951,7 +965,6 @@ static int rockchip_pcie_probe(struct platform_device *pdev)
+ struct pci_bus *bus, *child;
+ struct pci_host_bridge *bridge;
+ struct resource *bus_res;
+- struct resource_entry *win;
+ int err;
+
+ if (!dev->of_node)
+@@ -997,27 +1010,6 @@ static int rockchip_pcie_probe(struct platform_device *pdev)
+
+ rockchip->root_bus_nr = bus_res->start;
+
+- /* Get the I/O and memory ranges from DT */
+- resource_list_for_each_entry(win, &bridge->windows) {
+- switch (resource_type(win->res)) {
+- case IORESOURCE_IO:
+- io = win->res;
+- io->name = "I/O";
+- rockchip->io_size = resource_size(io);
+- rockchip->io_bus_addr = io->start - win->offset;
+- rockchip->io = io;
+- break;
+- case IORESOURCE_MEM:
+- mem = win->res;
+- mem->name = "MEM";
+- rockchip->mem_size = resource_size(mem);
+- rockchip->mem_bus_addr = mem->start - win->offset;
+- break;
+- default:
+- continue;
+- }
+- }
+-
+ err = rockchip_pcie_cfg_atu(rockchip);
+ if (err)
+ goto err_remove_irq_domain;
+diff --git a/drivers/pci/controller/pcie-rockchip.h b/drivers/pci/controller/pcie-rockchip.h
+index 8e87a059ce73..bef42a803b56 100644
+--- a/drivers/pci/controller/pcie-rockchip.h
++++ b/drivers/pci/controller/pcie-rockchip.h
+@@ -304,13 +304,8 @@ struct rockchip_pcie {
+ struct irq_domain *irq_domain;
+ int offset;
+ struct pci_bus *root_bus;
+- struct resource *io;
+- phys_addr_t io_bus_addr;
+- u32 io_size;
+ void __iomem *msg_region;
+- u32 mem_size;
+ phys_addr_t msg_bus_addr;
+- phys_addr_t mem_bus_addr;
+ bool is_rc;
+ struct resource *mem_res;
+ };
+
diff --git a/patches.suse/pci-rockchip-use-pci_parse_request_of_pci_ranges.patch b/patches.suse/pci-rockchip-use-pci_parse_request_of_pci_ranges.patch
new file mode 100644
index 0000000000..c964e7dce0
--- /dev/null
+++ b/patches.suse/pci-rockchip-use-pci_parse_request_of_pci_ranges.patch
@@ -0,0 +1,138 @@
+From: Rob Herring <robh@kernel.org>
+Date: Mon, 28 Oct 2019 11:32:41 -0500
+Subject: PCI: rockchip: Use pci_parse_request_of_pci_ranges()
+Git-commit: 5c1306a0fde67e5a39bef79932a0cb5cec5fd629
+Patch-mainline: Queued in subsystem maintainer repository
+Git-repo: https://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci.git
+References: jsc#SLE-7772
+
+Convert the Rockchip host bridge to use the common
+pci_parse_request_of_pci_ranges().
+
+There's no need to assign the resources to a temporary list first. Just
+use bridge->windows directly and remove all the temporary list handling.
+
+Signed-off-by: Rob Herring <robh@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Cc: Shawn Lin <shawn.lin@rock-chips.com>
+Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Cc: Andrew Murray <andrew.murray@arm.com>
+Cc: Bjorn Helgaas <bhelgaas@google.com>
+Cc: Heiko Stuebner <heiko@sntech.de>
+Cc: linux-rockchip@lists.infradead.org
+
+Acked-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+---
+ drivers/pci/controller/pcie-rockchip-host.c | 36 ++++++-----------------------
+ 1 file changed, 7 insertions(+), 29 deletions(-)
+
+diff --git a/drivers/pci/controller/pcie-rockchip-host.c b/drivers/pci/controller/pcie-rockchip-host.c
+index ef8e677ce9d1..8d2e6f2e141e 100644
+--- a/drivers/pci/controller/pcie-rockchip-host.c
++++ b/drivers/pci/controller/pcie-rockchip-host.c
+@@ -950,14 +950,10 @@ static int rockchip_pcie_probe(struct platform_device *pdev)
+ struct device *dev = &pdev->dev;
+ struct pci_bus *bus, *child;
+ struct pci_host_bridge *bridge;
++ struct resource *bus_res;
+ struct resource_entry *win;
+- resource_size_t io_base;
+- struct resource *mem;
+- struct resource *io;
+ int err;
+
+- LIST_HEAD(res);
+-
+ if (!dev->of_node)
+ return -ENODEV;
+
+@@ -995,29 +991,20 @@ static int rockchip_pcie_probe(struct platform_device *pdev)
+ if (err < 0)
+ goto err_deinit_port;
+
+- err = devm_of_pci_get_host_bridge_resources(dev, 0, 0xff,
+- &res, &io_base);
++ err = pci_parse_request_of_pci_ranges(dev, &bridge->windows, &bus_res);
+ if (err)
+ goto err_remove_irq_domain;
+
+- err = devm_request_pci_bus_resources(dev, &res);
+- if (err)
+- goto err_free_res;
++ rockchip->root_bus_nr = bus_res->start;
+
+ /* Get the I/O and memory ranges from DT */
+- resource_list_for_each_entry(win, &res) {
++ resource_list_for_each_entry(win, &bridge->windows) {
+ switch (resource_type(win->res)) {
+ case IORESOURCE_IO:
+ io = win->res;
+ io->name = "I/O";
+ rockchip->io_size = resource_size(io);
+ rockchip->io_bus_addr = io->start - win->offset;
+- err = pci_remap_iospace(io, io_base);
+- if (err) {
+- dev_warn(dev, "error %d: failed to map resource %pR\n",
+- err, io);
+- continue;
+- }
+ rockchip->io = io;
+ break;
+ case IORESOURCE_MEM:
+@@ -1026,9 +1013,6 @@ static int rockchip_pcie_probe(struct platform_device *pdev)
+ rockchip->mem_size = resource_size(mem);
+ rockchip->mem_bus_addr = mem->start - win->offset;
+ break;
+- case IORESOURCE_BUS:
+- rockchip->root_bus_nr = win->res->start;
+- break;
+ default:
+ continue;
+ }
+@@ -1036,15 +1020,14 @@ static int rockchip_pcie_probe(struct platform_device *pdev)
+
+ err = rockchip_pcie_cfg_atu(rockchip);
+ if (err)
+- goto err_unmap_iospace;
++ goto err_remove_irq_domain;
+
+ rockchip->msg_region = devm_ioremap(dev, rockchip->msg_bus_addr, SZ_1M);
+ if (!rockchip->msg_region) {
+ err = -ENOMEM;
+- goto err_unmap_iospace;
++ goto err_remove_irq_domain;
+ }
+
+- list_splice_init(&res, &bridge->windows);
+ bridge->dev.parent = dev;
+ bridge->sysdata = rockchip;
+ bridge->busnr = 0;
+@@ -1054,7 +1037,7 @@ static int rockchip_pcie_probe(struct platform_device *pdev)
+
+ err = pci_scan_root_bus_bridge(bridge);
+ if (err < 0)
+- goto err_unmap_iospace;
++ goto err_remove_irq_domain;
+
+ bus = bridge->bus;
+
+@@ -1068,10 +1051,6 @@ static int rockchip_pcie_probe(struct platform_device *pdev)
+ pci_bus_add_devices(bus);
+ return 0;
+
+-err_unmap_iospace:
+- pci_unmap_iospace(rockchip->io);
+-err_free_res:
+- pci_free_resource_list(&res);
+ err_remove_irq_domain:
+ irq_domain_remove(rockchip->irq_domain);
+ err_deinit_port:
+@@ -1097,7 +1076,6 @@ static int rockchip_pcie_remove(struct platform_device *pdev)
+
+ pci_stop_root_bus(rockchip->root_bus);
+ pci_remove_root_bus(rockchip->root_bus);
+- pci_unmap_iospace(rockchip->io);
+ irq_domain_remove(rockchip->irq_domain);
+
+ rockchip_pcie_deinit_phys(rockchip);
+
diff --git a/patches.suse/pci-v3-semi-use-inbound-resources-for-setup.patch b/patches.suse/pci-v3-semi-use-inbound-resources-for-setup.patch
new file mode 100644
index 0000000000..4c640b07ba
--- /dev/null
+++ b/patches.suse/pci-v3-semi-use-inbound-resources-for-setup.patch
@@ -0,0 +1,108 @@
+From: Rob Herring <robh@kernel.org>
+Date: Mon, 28 Oct 2019 11:32:52 -0500
+Subject: PCI: v3-semi: Use inbound resources for setup
+Git-commit: 070d7d70291c3a6b61fb10f0e9cf5874df91e214
+Patch-mainline: Queued in subsystem maintainer repository
+Git-repo: https://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci.git
+References: jsc#SLE-7772
+
+Now that the helpers provide the inbound resources in the host bridge
+'dma_ranges' resource list, convert the v3-semi host bridge to use
+the resource list to setup the inbound addresses.
+
+Signed-off-by: Rob Herring <robh@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Reviewed-by: Andrew Murray <andrew.murray@arm.com>
+Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
+Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Cc: Bjorn Helgaas <bhelgaas@google.com>
+
+Acked-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+---
+ drivers/pci/controller/pci-v3-semi.c | 38 +++++++++++++++---------------------
+ 1 file changed, 16 insertions(+), 22 deletions(-)
+
+diff --git a/drivers/pci/controller/pci-v3-semi.c b/drivers/pci/controller/pci-v3-semi.c
+index 2209c7671115..bd05221f5a22 100644
+--- a/drivers/pci/controller/pci-v3-semi.c
++++ b/drivers/pci/controller/pci-v3-semi.c
+@@ -598,28 +598,30 @@ static int v3_pci_setup_resource(struct v3_pci *v3,
+ }
+
+ static int v3_get_dma_range_config(struct v3_pci *v3,
+- struct of_pci_range *range,
++ struct resource_entry *entry,
+ u32 *pci_base, u32 *pci_map)
+ {
+ struct device *dev = v3->dev;
+- u64 cpu_end = range->cpu_addr + range->size - 1;
+- u64 pci_end = range->pci_addr + range->size - 1;
++ u64 cpu_addr = entry->res->start;
++ u64 cpu_end = entry->res->end;
++ u64 pci_end = cpu_end - entry->offset;
++ u64 pci_addr = entry->res->start - entry->offset;
+ u32 val;
+
+- if (range->pci_addr & ~V3_PCI_BASE_M_ADR_BASE) {
++ if (pci_addr & ~V3_PCI_BASE_M_ADR_BASE) {
+ dev_err(dev, "illegal range, only PCI bits 31..20 allowed\n");
+ return -EINVAL;
+ }
+- val = ((u32)range->pci_addr) & V3_PCI_BASE_M_ADR_BASE;
++ val = ((u32)pci_addr) & V3_PCI_BASE_M_ADR_BASE;
+ *pci_base = val;
+
+- if (range->cpu_addr & ~V3_PCI_MAP_M_MAP_ADR) {
++ if (cpu_addr & ~V3_PCI_MAP_M_MAP_ADR) {
+ dev_err(dev, "illegal range, only CPU bits 31..20 allowed\n");
+ return -EINVAL;
+ }
+- val = ((u32)range->cpu_addr) & V3_PCI_MAP_M_MAP_ADR;
++ val = ((u32)cpu_addr) & V3_PCI_MAP_M_MAP_ADR;
+
+- switch (range->size) {
++ switch (resource_size(entry->res)) {
+ case SZ_1M:
+ val |= V3_LB_BASE_ADR_SIZE_1MB;
+ break;
+@@ -667,8 +669,8 @@ static int v3_get_dma_range_config(struct v3_pci *v3,
+ dev_dbg(dev,
+ "DMA MEM CPU: 0x%016llx -> 0x%016llx => "
+ "PCI: 0x%016llx -> 0x%016llx base %08x map %08x\n",
+- range->cpu_addr, cpu_end,
+- range->pci_addr, pci_end,
++ cpu_addr, cpu_end,
++ pci_addr, pci_end,
+ *pci_base, *pci_map);
+
+ return 0;
+@@ -677,24 +679,16 @@ static int v3_get_dma_range_config(struct v3_pci *v3,
+ static int v3_pci_parse_map_dma_ranges(struct v3_pci *v3,
+ struct device_node *np)
+ {
+- struct of_pci_range range;
+- struct of_pci_range_parser parser;
++ struct pci_host_bridge *bridge = pci_host_bridge_from_priv(v3);
+ struct device *dev = v3->dev;
++ struct resource_entry *entry;
+ int i = 0;
+
+- if (of_pci_dma_range_parser_init(&parser, np)) {
+- dev_err(dev, "missing dma-ranges property\n");
+- return -EINVAL;
+- }
+-
+- /*
+- * Get the dma-ranges from the device tree
+- */
+- for_each_of_pci_range(&parser, &range) {
++ resource_list_for_each_entry(entry, &bridge->dma_ranges) {
+ int ret;
+ u32 pci_base, pci_map;
+
+- ret = v3_get_dma_range_config(v3, &range, &pci_base, &pci_map);
++ ret = v3_get_dma_range_config(v3, entry, &pci_base, &pci_map);
+ if (ret)
+ return ret;
+
+
diff --git a/patches.suse/pci-v3-semi-use-pci_parse_request_of_pci_ranges.patch b/patches.suse/pci-v3-semi-use-pci_parse_request_of_pci_ranges.patch
new file mode 100644
index 0000000000..1ecd12bbd5
--- /dev/null
+++ b/patches.suse/pci-v3-semi-use-pci_parse_request_of_pci_ranges.patch
@@ -0,0 +1,127 @@
+From: Rob Herring <robh@kernel.org>
+Date: Mon, 28 Oct 2019 11:32:43 -0500
+Subject: PCI: v3-semi: Use pci_parse_request_of_pci_ranges()
+Git-commit: e0aebfe84a2fb02ca1f195054595af9c3c01f12e
+Patch-mainline: Queued in subsystem maintainer repository
+Git-repo: https://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci.git
+References: jsc#SLE-7772
+
+Convert V3 host bridge to use the common
+pci_parse_request_of_pci_ranges().
+
+Signed-off-by: Rob Herring <robh@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Acked-by: Linus Walleij <linus.walleij@linaro.org>
+Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Cc: Andrew Murray <andrew.murray@arm.com>
+Cc: Bjorn Helgaas <bhelgaas@google.com>
+
+Acked-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+---
+ drivers/pci/controller/pci-v3-semi.c | 35 ++++++-----------------------------
+ 1 file changed, 6 insertions(+), 29 deletions(-)
+
+diff --git a/drivers/pci/controller/pci-v3-semi.c b/drivers/pci/controller/pci-v3-semi.c
+index d219404bad92..96677520f6c1 100644
+--- a/drivers/pci/controller/pci-v3-semi.c
++++ b/drivers/pci/controller/pci-v3-semi.c
+@@ -241,10 +241,8 @@ struct v3_pci {
+ void __iomem *config_base;
+ struct pci_bus *bus;
+ u32 config_mem;
+- u32 io_mem;
+ u32 non_pre_mem;
+ u32 pre_mem;
+- phys_addr_t io_bus_addr;
+ phys_addr_t non_pre_bus_addr;
+ phys_addr_t pre_bus_addr;
+ struct regmap *map;
+@@ -520,35 +518,22 @@ static int v3_integrator_init(struct v3_pci *v3)
+ }
+
+ static int v3_pci_setup_resource(struct v3_pci *v3,
+- resource_size_t io_base,
+ struct pci_host_bridge *host,
+ struct resource_entry *win)
+ {
+ struct device *dev = v3->dev;
+ struct resource *mem;
+ struct resource *io;
+- int ret;
+
+ switch (resource_type(win->res)) {
+ case IORESOURCE_IO:
+ io = win->res;
+- io->name = "V3 PCI I/O";
+- v3->io_mem = io_base;
+- v3->io_bus_addr = io->start - win->offset;
+- dev_dbg(dev, "I/O window %pR, bus addr %pap\n",
+- io, &v3->io_bus_addr);
+- ret = devm_pci_remap_iospace(dev, io, io_base);
+- if (ret) {
+- dev_warn(dev,
+- "error %d: failed to map resource %pR\n",
+- ret, io);
+- return ret;
+- }
++
+ /* Setup window 2 - PCI I/O */
+- writel(v3_addr_to_lb_base2(v3->io_mem) |
++ writel(v3_addr_to_lb_base2(pci_pio_to_address(io->start)) |
+ V3_LB_BASE2_ENABLE,
+ v3->base + V3_LB_BASE2);
+- writew(v3_addr_to_lb_map2(v3->io_bus_addr),
++ writew(v3_addr_to_lb_map2(io->start - win->offset),
+ v3->base + V3_LB_MAP2);
+ break;
+ case IORESOURCE_MEM:
+@@ -732,7 +717,6 @@ static int v3_pci_probe(struct platform_device *pdev)
+ {
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+- resource_size_t io_base;
+ struct resource *regs;
+ struct resource_entry *win;
+ struct v3_pci *v3;
+@@ -741,7 +725,6 @@ static int v3_pci_probe(struct platform_device *pdev)
+ u16 val;
+ int irq;
+ int ret;
+- LIST_HEAD(res);
+
+ host = pci_alloc_host_bridge(sizeof(*v3));
+ if (!host)
+@@ -793,12 +776,7 @@ static int v3_pci_probe(struct platform_device *pdev)
+ if (IS_ERR(v3->config_base))
+ return PTR_ERR(v3->config_base);
+
+- ret = devm_of_pci_get_host_bridge_resources(dev, 0, 0xff, &res,
+- &io_base);
+- if (ret)
+- return ret;
+-
+- ret = devm_request_pci_bus_resources(dev, &res);
++ ret = pci_parse_request_of_pci_ranges(dev, &host->windows, NULL);
+ if (ret)
+ return ret;
+
+@@ -852,8 +830,8 @@ static int v3_pci_probe(struct platform_device *pdev)
+ writew(val, v3->base + V3_PCI_CMD);
+
+ /* Get the I/O and memory ranges from DT */
+- resource_list_for_each_entry(win, &res) {
+- ret = v3_pci_setup_resource(v3, io_base, host, win);
++ resource_list_for_each_entry(win, &host->windows) {
++ ret = v3_pci_setup_resource(v3, host, win);
+ if (ret) {
+ dev_err(dev, "error setting up resources\n");
+ return ret;
+@@ -931,7 +909,6 @@ static int v3_pci_probe(struct platform_device *pdev)
+ val |= V3_SYSTEM_M_LOCK;
+ writew(val, v3->base + V3_SYSTEM);
+
+- list_splice_init(&res, &host->windows);
+ ret = pci_scan_root_bus_bridge(host);
+ if (ret) {
+ dev_err(dev, "failed to register host: %d\n", ret);
+
diff --git a/patches.suse/pci-versatile-enable-compile_test.patch b/patches.suse/pci-versatile-enable-compile_test.patch
new file mode 100644
index 0000000000..046c37ecde
--- /dev/null
+++ b/patches.suse/pci-versatile-enable-compile_test.patch
@@ -0,0 +1,38 @@
+From: Rob Herring <robh@kernel.org>
+Date: Mon, 28 Oct 2019 11:32:49 -0500
+Subject: PCI: versatile: Enable COMPILE_TEST
+Git-commit: ecf8fd6d917dca1065e1021ff7fc6b6c282373f9
+Patch-mainline: Queued in subsystem maintainer repository
+Git-repo: https://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci.git
+References: jsc#SLE-7772
+
+Since commit a574795bc383 ("PCI: generic,versatile: Remove unused
+pci_sys_data structures") the build dependency on ARM is gone, so let's
+enable COMPILE_TEST for versatile.
+
+Signed-off-by: Rob Herring <robh@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Reviewed-by: Andrew Murray <andrew.murray@arm.com>
+Acked-by: Linus Walleij <linus.walleij@linaro.org>
+Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Cc: Bjorn Helgaas <bhelgaas@google.com>
+
+Acked-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+---
+ drivers/pci/controller/Kconfig | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/pci/controller/Kconfig b/drivers/pci/controller/Kconfig
+index 70e078238899..f5de9119e8d3 100644
+--- a/drivers/pci/controller/Kconfig
++++ b/drivers/pci/controller/Kconfig
+@@ -135,7 +135,7 @@ config PCI_V3_SEMI
+
+ config PCI_VERSATILE
+ bool "ARM Versatile PB PCI controller"
+- depends on ARCH_VERSATILE
++ depends on ARCH_VERSATILE || COMPILE_TEST
+
+ config PCIE_IPROC
+ tristate
+
diff --git a/patches.suse/pci-versatile-remove-usage-of-phys_offset.patch b/patches.suse/pci-versatile-remove-usage-of-phys_offset.patch
new file mode 100644
index 0000000000..11fc74aa9e
--- /dev/null
+++ b/patches.suse/pci-versatile-remove-usage-of-phys_offset.patch
@@ -0,0 +1,55 @@
+From: Rob Herring <robh@kernel.org>
+Date: Mon, 28 Oct 2019 11:32:48 -0500
+Subject: PCI: versatile: Remove usage of PHYS_OFFSET
+Git-commit: 2999dea8e94a8e32dadfe17970aa29eba46985b9
+Patch-mainline: Queued in subsystem maintainer repository
+Git-repo: https://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci.git
+References: jsc#SLE-7772
+
+PHYS_OFFSET is not universally defined on all arches and using it prevents
+enabling COMPILE_TEST. PAGE_OFFSET and __pa() are always available, so use
+them to get the physical start of memory address.
+
+This should have probably used 'dma-ranges' to get the address, but we
+don't want to force a DT update to do that. At least in QEMU, the SMAP
+registers have no effect (or perhaps the only value that is handled is 0).
+
+Signed-off-by: Rob Herring <robh@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Acked-by: Linus Walleij <linus.walleij@linaro.org>
+Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Cc: Andrew Murray <andrew.murray@arm.com>
+Cc: Bjorn Helgaas <bhelgaas@google.com>
+
+Acked-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+---
+ drivers/pci/controller/pci-versatile.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/pci/controller/pci-versatile.c b/drivers/pci/controller/pci-versatile.c
+index 18697f2ea345..eae1b859990b 100644
+--- a/drivers/pci/controller/pci-versatile.c
++++ b/drivers/pci/controller/pci-versatile.c
+@@ -99,7 +99,7 @@ static int versatile_pci_probe(struct platform_device *pdev)
+ resource_list_for_each_entry(entry, &bridge->windows) {
+ if (resource_type(entry->res) == IORESOURCE_MEM) {
+ writel(entry->res->start >> 28, PCI_IMAP(mem));
+- writel(PHYS_OFFSET >> 28, PCI_SMAP(mem));
++ writel(__pa(PAGE_OFFSET) >> 28, PCI_SMAP(mem));
+ mem++;
+ }
+ }
+@@ -136,9 +136,9 @@ static int versatile_pci_probe(struct platform_device *pdev)
+ /*
+ * Configure the PCI inbound memory windows to be 1:1 mapped to SDRAM
+ */
+- writel(PHYS_OFFSET, local_pci_cfg_base + PCI_BASE_ADDRESS_0);
+- writel(PHYS_OFFSET, local_pci_cfg_base + PCI_BASE_ADDRESS_1);
+- writel(PHYS_OFFSET, local_pci_cfg_base + PCI_BASE_ADDRESS_2);
++ writel(__pa(PAGE_OFFSET), local_pci_cfg_base + PCI_BASE_ADDRESS_0);
++ writel(__pa(PAGE_OFFSET), local_pci_cfg_base + PCI_BASE_ADDRESS_1);
++ writel(__pa(PAGE_OFFSET), local_pci_cfg_base + PCI_BASE_ADDRESS_2);
+
+ /*
+ * For many years the kernel and QEMU were symbiotically buggy
+
diff --git a/patches.suse/pci-versatile-use-pci_parse_request_of_pci_ranges.patch b/patches.suse/pci-versatile-use-pci_parse_request_of_pci_ranges.patch
new file mode 100644
index 0000000000..bfd2ee74a8
--- /dev/null
+++ b/patches.suse/pci-versatile-use-pci_parse_request_of_pci_ranges.patch
@@ -0,0 +1,126 @@
+From: Rob Herring <robh@kernel.org>
+Date: Mon, 28 Oct 2019 11:32:47 -0500
+Subject: PCI: versatile: Use pci_parse_request_of_pci_ranges()
+Git-commit: f9f4fdaa3509b804410b4742bcad9469151f4ee0
+Patch-mainline: Queued in subsystem maintainer repository
+Git-repo: https://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci.git
+References: jsc#SLE-7772
+
+Convert ARM Versatile host bridge to use the common
+pci_parse_request_of_pci_ranges().
+
+There's no need to assign the resources to a temporary list first. Just
+use bridge->windows directly and remove all the temporary list handling.
+
+Signed-off-by: Rob Herring <robh@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Acked-by: Linus Walleij <linus.walleij@linaro.org>
+Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Cc: Bjorn Helgaas <bhelgaas@google.com>
+
+Acked-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+---
+ drivers/pci/controller/pci-versatile.c | 64 ++++++----------------------------
+ 1 file changed, 11 insertions(+), 53 deletions(-)
+
+diff --git a/drivers/pci/controller/pci-versatile.c b/drivers/pci/controller/pci-versatile.c
+index f59ad2728c0b..18697f2ea345 100644
+--- a/drivers/pci/controller/pci-versatile.c
++++ b/drivers/pci/controller/pci-versatile.c
+@@ -62,65 +62,16 @@ static struct pci_ops pci_versatile_ops = {
+ .write = pci_generic_config_write,
+ };
+
+-static int versatile_pci_parse_request_of_pci_ranges(struct device *dev,
+- struct list_head *res)
+-{
+- int err, mem = 1, res_valid = 0;
+- resource_size_t iobase;
+- struct resource_entry *win, *tmp;
+-
+- err = devm_of_pci_get_host_bridge_resources(dev, 0, 0xff, res, &iobase);
+- if (err)
+- return err;
+-
+- err = devm_request_pci_bus_resources(dev, res);
+- if (err)
+- goto out_release_res;
+-
+- resource_list_for_each_entry_safe(win, tmp, res) {
+- struct resource *res = win->res;
+-
+- switch (resource_type(res)) {
+- case IORESOURCE_IO:
+- err = devm_pci_remap_iospace(dev, res, iobase);
+- if (err) {
+- dev_warn(dev, "error %d: failed to map resource %pR\n",
+- err, res);
+- resource_list_destroy_entry(win);
+- }
+- break;
+- case IORESOURCE_MEM:
+- res_valid |= !(res->flags & IORESOURCE_PREFETCH);
+-
+- writel(res->start >> 28, PCI_IMAP(mem));
+- writel(PHYS_OFFSET >> 28, PCI_SMAP(mem));
+- mem++;
+-
+- break;
+- }
+- }
+-
+- if (res_valid)
+- return 0;
+-
+- dev_err(dev, "non-prefetchable memory resource required\n");
+- err = -EINVAL;
+-
+-out_release_res:
+- pci_free_resource_list(res);
+- return err;
+-}
+-
+ static int versatile_pci_probe(struct platform_device *pdev)
+ {
+ struct device *dev = &pdev->dev;
+ struct resource *res;
+- int ret, i, myslot = -1;
++ struct resource_entry *entry;
++ int ret, i, myslot = -1, mem = 1;
+ u32 val;
+ void __iomem *local_pci_cfg_base;
+ struct pci_bus *bus, *child;
+ struct pci_host_bridge *bridge;
+- LIST_HEAD(pci_res);
+
+ bridge = devm_pci_alloc_host_bridge(dev, 0);
+ if (!bridge)
+@@ -141,10 +92,18 @@ static int versatile_pci_probe(struct platform_device *pdev)
+ if (IS_ERR(versatile_cfg_base[1]))
+ return PTR_ERR(versatile_cfg_base[1]);
+
+- ret = versatile_pci_parse_request_of_pci_ranges(dev, &pci_res);
++ ret = pci_parse_request_of_pci_ranges(dev, &bridge->windows, NULL);
+ if (ret)
+ return ret;
+
++ resource_list_for_each_entry(entry, &bridge->windows) {
++ if (resource_type(entry->res) == IORESOURCE_MEM) {
++ writel(entry->res->start >> 28, PCI_IMAP(mem));
++ writel(PHYS_OFFSET >> 28, PCI_SMAP(mem));
++ mem++;
++ }
++ }
++
+ /*
+ * We need to discover the PCI core first to configure itself
+ * before the main PCI probing is performed
+@@ -197,7 +156,6 @@ static int versatile_pci_probe(struct platform_device *pdev)
+ pci_add_flags(PCI_ENABLE_PROC_DOMAINS);
+ pci_add_flags(PCI_REASSIGN_ALL_BUS);
+
+- list_splice_init(&pci_res, &bridge->windows);
+ bridge->dev.parent = dev;
+ bridge->sysdata = NULL;
+ bridge->busnr = 0;
+
diff --git a/patches.suse/pci-xgene-use-inbound-resources-for-setup.patch b/patches.suse/pci-xgene-use-inbound-resources-for-setup.patch
new file mode 100644
index 0000000000..d95913ae99
--- /dev/null
+++ b/patches.suse/pci-xgene-use-inbound-resources-for-setup.patch
@@ -0,0 +1,94 @@
+From: Rob Herring <robh@kernel.org>
+Date: Mon, 28 Oct 2019 11:32:53 -0500
+Subject: PCI: xgene: Use inbound resources for setup
+Git-commit: 6dce5aa59e0bf2430733d7a8b11c205ec10f408e
+Patch-mainline: Queued in subsystem maintainer repository
+Git-repo: https://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci.git
+References: jsc#SLE-7772
+
+Now that the helpers provide the inbound resources in the host bridge
+'dma_ranges' resource list, convert the Xgene host bridge to use the
+resource list to setup the inbound addresses.
+
+Signed-off-by: Rob Herring <robh@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Reviewed-by: Andrew Murray <andrew.murray@arm.com>
+Cc: Toan Le <toan@os.amperecomputing.com>
+Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Cc: Bjorn Helgaas <bhelgaas@google.com>
+
+Acked-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+---
+ drivers/pci/controller/pci-xgene.c | 33 +++++++++++----------------------
+ 1 file changed, 11 insertions(+), 22 deletions(-)
+
+diff --git a/drivers/pci/controller/pci-xgene.c b/drivers/pci/controller/pci-xgene.c
+index 9408269d943d..de195fd430dc 100644
+--- a/drivers/pci/controller/pci-xgene.c
++++ b/drivers/pci/controller/pci-xgene.c
+@@ -481,27 +481,28 @@ static int xgene_pcie_select_ib_reg(u8 *ib_reg_mask, u64 size)
+ }
+
+ static void xgene_pcie_setup_ib_reg(struct xgene_pcie_port *port,
+- struct of_pci_range *range, u8 *ib_reg_mask)
++ struct resource_entry *entry,
++ u8 *ib_reg_mask)
+ {
+ void __iomem *cfg_base = port->cfg_base;
+ struct device *dev = port->dev;
+ void *bar_addr;
+ u32 pim_reg;
+- u64 cpu_addr = range->cpu_addr;
+- u64 pci_addr = range->pci_addr;
+- u64 size = range->size;
++ u64 cpu_addr = entry->res->start;
++ u64 pci_addr = cpu_addr - entry->offset;
++ u64 size = resource_size(entry->res);
+ u64 mask = ~(size - 1) | EN_REG;
+ u32 flags = PCI_BASE_ADDRESS_MEM_TYPE_64;
+ u32 bar_low;
+ int region;
+
+- region = xgene_pcie_select_ib_reg(ib_reg_mask, range->size);
++ region = xgene_pcie_select_ib_reg(ib_reg_mask, size);
+ if (region < 0) {
+ dev_warn(dev, "invalid pcie dma-range config\n");
+ return;
+ }
+
+- if (range->flags & IORESOURCE_PREFETCH)
++ if (entry->res->flags & IORESOURCE_PREFETCH)
+ flags |= PCI_BASE_ADDRESS_MEM_PREFETCH;
+
+ bar_low = pcie_bar_low_val((u32)cpu_addr, flags);
+@@ -532,25 +533,13 @@ static void xgene_pcie_setup_ib_reg(struct xgene_pcie_port *port,
+
+ static int xgene_pcie_parse_map_dma_ranges(struct xgene_pcie_port *port)
+ {
+- struct device_node *np = port->node;
+- struct of_pci_range range;
+- struct of_pci_range_parser parser;
+- struct device *dev = port->dev;
++ struct pci_host_bridge *bridge = pci_host_bridge_from_priv(port);
++ struct resource_entry *entry;
+ u8 ib_reg_mask = 0;
+
+- if (of_pci_dma_range_parser_init(&parser, np)) {
+- dev_err(dev, "missing dma-ranges property\n");
+- return -EINVAL;
+- }
+-
+- /* Get the dma-ranges from DT */
+- for_each_of_pci_range(&parser, &range) {
+- u64 end = range.cpu_addr + range.size - 1;
++ resource_list_for_each_entry(entry, &bridge->dma_ranges)
++ xgene_pcie_setup_ib_reg(port, entry, &ib_reg_mask);
+
+- dev_dbg(dev, "0x%08x 0x%016llx..0x%016llx -> 0x%016llx\n",
+- range.flags, range.cpu_addr, end, range.pci_addr);
+- xgene_pcie_setup_ib_reg(port, &range, &ib_reg_mask);
+- }
+ return 0;
+ }
+
+
diff --git a/patches.suse/pci-xgene-use-pci_parse_request_of_pci_ranges.patch b/patches.suse/pci-xgene-use-pci_parse_request_of_pci_ranges.patch
new file mode 100644
index 0000000000..7e5fa492e0
--- /dev/null
+++ b/patches.suse/pci-xgene-use-pci_parse_request_of_pci_ranges.patch
@@ -0,0 +1,139 @@
+From: Rob Herring <robh@kernel.org>
+Date: Mon, 28 Oct 2019 11:32:44 -0500
+Subject: PCI: xgene: Use pci_parse_request_of_pci_ranges()
+Git-commit: 83083e241d48aba4d0b92c3f5e274351c1560c97
+Patch-mainline: Queued in subsystem maintainer repository
+Git-repo: https://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci.git
+References: jsc#SLE-7772
+
+Convert the xgene host bridge to use the common
+pci_parse_request_of_pci_ranges().
+
+There's no need to assign the resources to a temporary list first. Just
+use bridge->windows directly and remove all the temporary list handling.
+
+Signed-off-by: Rob Herring <robh@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Cc: Toan Le <toan@os.amperecomputing.com>
+Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Cc: Andrew Murray <andrew.murray@arm.com>
+Cc: Bjorn Helgaas <bhelgaas@google.com>
+
+Acked-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+---
+ drivers/pci/controller/pci-xgene.c | 39 +++++++++++---------------------------
+ 1 file changed, 11 insertions(+), 28 deletions(-)
+
+diff --git a/drivers/pci/controller/pci-xgene.c b/drivers/pci/controller/pci-xgene.c
+index ffda3e8b4742..7d0f0395a479 100644
+--- a/drivers/pci/controller/pci-xgene.c
++++ b/drivers/pci/controller/pci-xgene.c
+@@ -405,15 +405,13 @@ static void xgene_pcie_setup_cfg_reg(struct xgene_pcie_port *port)
+ xgene_pcie_writel(port, CFGCTL, EN_REG);
+ }
+
+-static int xgene_pcie_map_ranges(struct xgene_pcie_port *port,
+- struct list_head *res,
+- resource_size_t io_base)
++static int xgene_pcie_map_ranges(struct xgene_pcie_port *port)
+ {
++ struct pci_host_bridge *bridge = pci_host_bridge_from_priv(port);
+ struct resource_entry *window;
+ struct device *dev = port->dev;
+- int ret;
+
+- resource_list_for_each_entry(window, res) {
++ resource_list_for_each_entry(window, &bridge->windows) {
+ struct resource *res = window->res;
+ u64 restype = resource_type(res);
+
+@@ -421,11 +419,9 @@ static int xgene_pcie_map_ranges(struct xgene_pcie_port *port,
+
+ switch (restype) {
+ case IORESOURCE_IO:
+- xgene_pcie_setup_ob_reg(port, res, OMR3BARL, io_base,
++ xgene_pcie_setup_ob_reg(port, res, OMR3BARL,
++ pci_pio_to_address(res->start),
+ res->start - window->offset);
+- ret = devm_pci_remap_iospace(dev, res, io_base);
+- if (ret < 0)
+- return ret;
+ break;
+ case IORESOURCE_MEM:
+ if (res->flags & IORESOURCE_PREFETCH)
+@@ -567,8 +563,7 @@ static void xgene_pcie_clear_config(struct xgene_pcie_port *port)
+ xgene_pcie_writel(port, i, 0);
+ }
+
+-static int xgene_pcie_setup(struct xgene_pcie_port *port, struct list_head *res,
+- resource_size_t io_base)
++static int xgene_pcie_setup(struct xgene_pcie_port *port)
+ {
+ struct device *dev = port->dev;
+ u32 val, lanes = 0, speed = 0;
+@@ -580,7 +575,7 @@ static int xgene_pcie_setup(struct xgene_pcie_port *port, struct list_head *res,
+ val = (XGENE_PCIE_DEVICEID << 16) | XGENE_PCIE_VENDORID;
+ xgene_pcie_writel(port, BRIDGE_CFG_0, val);
+
+- ret = xgene_pcie_map_ranges(port, res, io_base);
++ ret = xgene_pcie_map_ranges(port);
+ if (ret)
+ return ret;
+
+@@ -607,11 +602,9 @@ static int xgene_pcie_probe(struct platform_device *pdev)
+ struct device *dev = &pdev->dev;
+ struct device_node *dn = dev->of_node;
+ struct xgene_pcie_port *port;
+- resource_size_t iobase = 0;
+ struct pci_bus *bus, *child;
+ struct pci_host_bridge *bridge;
+ int ret;
+- LIST_HEAD(res);
+
+ bridge = devm_pci_alloc_host_bridge(dev, sizeof(*port));
+ if (!bridge)
+@@ -634,20 +627,14 @@ static int xgene_pcie_probe(struct platform_device *pdev)
+ if (ret)
+ return ret;
+
+- ret = devm_of_pci_get_host_bridge_resources(dev, 0, 0xff, &res,
+- &iobase);
++ ret = pci_parse_request_of_pci_ranges(dev, &bridge->windows, NULL);
+ if (ret)
+ return ret;
+
+- ret = devm_request_pci_bus_resources(dev, &res);
+- if (ret)
+- goto error;
+-
+- ret = xgene_pcie_setup(port, &res, iobase);
++ ret = xgene_pcie_setup(port);
+ if (ret)
+- goto error;
++ return ret;
+
+- list_splice_init(&res, &bridge->windows);
+ bridge->dev.parent = dev;
+ bridge->sysdata = port;
+ bridge->busnr = 0;
+@@ -657,7 +644,7 @@ static int xgene_pcie_probe(struct platform_device *pdev)
+
+ ret = pci_scan_root_bus_bridge(bridge);
+ if (ret < 0)
+- goto error;
++ return ret;
+
+ bus = bridge->bus;
+
+@@ -666,10 +653,6 @@ static int xgene_pcie_probe(struct platform_device *pdev)
+ pcie_bus_configure_settings(child);
+ pci_bus_add_devices(bus);
+ return 0;
+-
+-error:
+- pci_free_resource_list(&res);
+- return ret;
+ }
+
+ static const struct of_device_id xgene_pcie_match_table[] = {
+
diff --git a/patches.suse/pci-xilinx-nwl-use-pci_parse_request_of_pci_ranges.patch b/patches.suse/pci-xilinx-nwl-use-pci_parse_request_of_pci_ranges.patch
new file mode 100644
index 0000000000..a487f2f7d9
--- /dev/null
+++ b/patches.suse/pci-xilinx-nwl-use-pci_parse_request_of_pci_ranges.patch
@@ -0,0 +1,94 @@
+From: Rob Herring <robh@kernel.org>
+Date: Mon, 28 Oct 2019 11:32:46 -0500
+Subject: PCI: xilinx-nwl: Use pci_parse_request_of_pci_ranges()
+Git-commit: 3c65ebff8faedfc3386e6e1ad91adf2bdb8eeaa7
+Patch-mainline: Queued in subsystem maintainer repository
+Git-repo: https://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci.git
+References: jsc#SLE-7772
+
+Convert the xilinx-nwl host bridge to use the common
+pci_parse_request_of_pci_ranges().
+
+There's no need to assign the resources to a temporary list first. Just
+use bridge->windows directly and remove all the temporary list handling.
+
+Signed-off-by: Rob Herring <robh@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Cc: Andrew Murray <andrew.murray@arm.com>
+Cc: Bjorn Helgaas <bhelgaas@google.com>
+Cc: Michal Simek <michal.simek@xilinx.com>
+
+Acked-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+---
+ drivers/pci/controller/pcie-xilinx-nwl.c | 20 ++++----------------
+ 1 file changed, 4 insertions(+), 16 deletions(-)
+
+diff --git a/drivers/pci/controller/pcie-xilinx-nwl.c b/drivers/pci/controller/pcie-xilinx-nwl.c
+index 45c0f344ccd1..e135a4b60489 100644
+--- a/drivers/pci/controller/pcie-xilinx-nwl.c
++++ b/drivers/pci/controller/pcie-xilinx-nwl.c
+@@ -821,8 +821,6 @@ static int nwl_pcie_probe(struct platform_device *pdev)
+ struct pci_bus *child;
+ struct pci_host_bridge *bridge;
+ int err;
+- resource_size_t iobase = 0;
+- LIST_HEAD(res);
+
+ bridge = devm_pci_alloc_host_bridge(dev, sizeof(*pcie));
+ if (!bridge)
+@@ -845,24 +843,18 @@ static int nwl_pcie_probe(struct platform_device *pdev)
+ return err;
+ }
+
+- err = devm_of_pci_get_host_bridge_resources(dev, 0, 0xff, &res,
+- &iobase);
++ err = pci_parse_request_of_pci_ranges(dev, &bridge->windows, NULL);
+ if (err) {
+ dev_err(dev, "Getting bridge resources failed\n");
+ return err;
+ }
+
+- err = devm_request_pci_bus_resources(dev, &res);
+- if (err)
+- goto error;
+-
+ err = nwl_pcie_init_irq_domain(pcie);
+ if (err) {
+ dev_err(dev, "Failed creating IRQ Domain\n");
+- goto error;
++ return err;
+ }
+
+- list_splice_init(&res, &bridge->windows);
+ bridge->dev.parent = dev;
+ bridge->sysdata = pcie;
+ bridge->busnr = pcie->root_busno;
+@@ -874,13 +866,13 @@ static int nwl_pcie_probe(struct platform_device *pdev)
+ err = nwl_pcie_enable_msi(pcie);
+ if (err < 0) {
+ dev_err(dev, "failed to enable MSI support: %d\n", err);
+- goto error;
++ return err;
+ }
+ }
+
+ err = pci_scan_root_bus_bridge(bridge);
+ if (err)
+- goto error;
++ return err;
+
+ bus = bridge->bus;
+
+@@ -889,10 +881,6 @@ static int nwl_pcie_probe(struct platform_device *pdev)
+ pcie_bus_configure_settings(child);
+ pci_bus_add_devices(bus);
+ return 0;
+-
+-error:
+- pci_free_resource_list(&res);
+- return err;
+ }
+
+ static struct platform_driver nwl_pcie_driver = {
+
diff --git a/patches.suse/pci-xilinx-use-pci_parse_request_of_pci_ranges.patch b/patches.suse/pci-xilinx-use-pci_parse_request_of_pci_ranges.patch
new file mode 100644
index 0000000000..61be77a849
--- /dev/null
+++ b/patches.suse/pci-xilinx-use-pci_parse_request_of_pci_ranges.patch
@@ -0,0 +1,81 @@
+From: Rob Herring <robh@kernel.org>
+Date: Mon, 28 Oct 2019 11:32:45 -0500
+Subject: PCI: xilinx: Use pci_parse_request_of_pci_ranges()
+Git-commit: ee352c272e41c67aac887cbfd8c6aa71e5721997
+Patch-mainline: Queued in subsystem maintainer repository
+Git-repo: https://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci.git
+References: jsc#SLE-7772
+
+Convert the Xilinx host bridge to use the common
+pci_parse_request_of_pci_ranges().
+
+There's no need to assign the resources to a temporary list first. Just
+use bridge->windows directly and remove all the temporary list handling.
+
+Signed-off-by: Rob Herring <robh@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Cc: Andrew Murray <andrew.murray@arm.com>
+Cc: Bjorn Helgaas <bhelgaas@google.com>
+Cc: Michal Simek <michal.simek@xilinx.com>
+
+Acked-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+---
+ drivers/pci/controller/pcie-xilinx.c | 17 ++---------------
+ 1 file changed, 2 insertions(+), 15 deletions(-)
+
+diff --git a/drivers/pci/controller/pcie-xilinx.c b/drivers/pci/controller/pcie-xilinx.c
+index 5bf3af3b28e6..257702288787 100644
+--- a/drivers/pci/controller/pcie-xilinx.c
++++ b/drivers/pci/controller/pcie-xilinx.c
+@@ -619,8 +619,6 @@ static int xilinx_pcie_probe(struct platform_device *pdev)
+ struct pci_bus *bus, *child;
+ struct pci_host_bridge *bridge;
+ int err;
+- resource_size_t iobase = 0;
+- LIST_HEAD(res);
+
+ if (!dev->of_node)
+ return -ENODEV;
+@@ -647,19 +645,12 @@ static int xilinx_pcie_probe(struct platform_device *pdev)
+ return err;
+ }
+
+- err = devm_of_pci_get_host_bridge_resources(dev, 0, 0xff, &res,
+- &iobase);
++ err = pci_parse_request_of_pci_ranges(dev, &bridge->windows, NULL);
+ if (err) {
+ dev_err(dev, "Getting bridge resources failed\n");
+ return err;
+ }
+
+- err = devm_request_pci_bus_resources(dev, &res);
+- if (err)
+- goto error;
+-
+-
+- list_splice_init(&res, &bridge->windows);
+ bridge->dev.parent = dev;
+ bridge->sysdata = port;
+ bridge->busnr = 0;
+@@ -673,7 +664,7 @@ static int xilinx_pcie_probe(struct platform_device *pdev)
+ #endif
+ err = pci_scan_root_bus_bridge(bridge);
+ if (err < 0)
+- goto error;
++ return err;
+
+ bus = bridge->bus;
+
+@@ -682,10 +673,6 @@ static int xilinx_pcie_probe(struct platform_device *pdev)
+ pcie_bus_configure_settings(child);
+ pci_bus_add_devices(bus);
+ return 0;
+-
+-error:
+- pci_free_resource_list(&res);
+- return err;
+ }
+
+ static const struct of_device_id xilinx_pcie_of_match[] = {
+
diff --git a/patches.suse/resource-add-a-resource_list_first_type-helper.patch b/patches.suse/resource-add-a-resource_list_first_type-helper.patch
new file mode 100644
index 0000000000..07868753b5
--- /dev/null
+++ b/patches.suse/resource-add-a-resource_list_first_type-helper.patch
@@ -0,0 +1,41 @@
+From: Rob Herring <robh@kernel.org>
+Date: Mon, 28 Oct 2019 11:32:32 -0500
+Subject: resource: Add a resource_list_first_type helper
+Git-commit: 494f8b10d832456a96be4ee7317425f6936cabc8
+Patch-mainline: Queued in subsystem maintainer repository
+Git-repo: https://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci.git
+References: jsc#SLE-7772
+
+A common pattern is looping over a resource_list just to get a matching
+entry with a specific type. Add resource_list_first_type() helper which
+implements this.
+
+Signed-off-by: Rob Herring <robh@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Acked-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+---
+ include/linux/resource_ext.h | 12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+
+diff --git a/include/linux/resource_ext.h b/include/linux/resource_ext.h
+index 06da59b23b79..ff0339df56af 100644
+--- a/include/linux/resource_ext.h
++++ b/include/linux/resource_ext.h
+@@ -66,4 +66,16 @@ resource_list_destroy_entry(struct resource_entry *entry)
+ #define resource_list_for_each_entry_safe(entry, tmp, list) \
+ list_for_each_entry_safe((entry), (tmp), (list), node)
+
++static inline struct resource_entry *
++resource_list_first_type(struct list_head *list, unsigned long type)
++{
++ struct resource_entry *entry;
++
++ resource_list_for_each_entry(entry, list) {
++ if (resource_type(entry->res) == type)
++ return entry;
++ }
++ return NULL;
++}
++
+ #endif /* _LINUX_RESOURCE_EXT_H */
+
diff --git a/patches.suse/x86-pci-sta2x11-use-default-dma-address-translation.patch b/patches.suse/x86-pci-sta2x11-use-default-dma-address-translation.patch
new file mode 100644
index 0000000000..7b7fa8c638
--- /dev/null
+++ b/patches.suse/x86-pci-sta2x11-use-default-dma-address-translation.patch
@@ -0,0 +1,268 @@
+From: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Date: Thu, 7 Nov 2019 16:06:45 +0100
+Subject: x86/PCI: sta2x11: use default DMA address translation
+Git-commit: e380a0394c36a3a878c858418d5dd7f5f195b6fc
+Patch-mainline: Queued in subsystem maintainer repo
+Git-repo: git://git.infradead.org/users/hch/dma-mapping.git
+References: jsc#SLE-7772
+
+The devices found behind this PCIe chip have unusual DMA mapping
+constraints as there is an AMBA interconnect placed in between them and
+the different PCI endpoints. The offset between physical memory
+addresses and AMBA's view is provided by reading a PCI config register,
+which is saved and used whenever DMA mapping is needed.
+
+It turns out that this DMA setup can be represented by properly setting
+'dma_pfn_offset', 'dma_bus_mask' and 'dma_mask' during the PCI device
+enable fixup. And ultimately allows us to get rid of this device's
+custom DMA functions.
+
+Aside from the code deletion and DMA setup, sta2x11_pdev_to_mapping() is
+moved to avoid warnings whenever CONFIG_PM is not enabled.
+
+Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Signed-off-by: Christoph Hellwig <hch@lst.de>
+---
+ arch/x86/Kconfig | 1 -
+ arch/x86/include/asm/device.h | 3 -
+ arch/x86/include/asm/dma-direct.h | 9 ---
+ arch/x86/pci/sta2x11-fixup.c | 135 ++++++++------------------------------
+ 4 files changed, 26 insertions(+), 122 deletions(-)
+
+diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
+index d6e1faa28c58..35dd8f147f99 100644
+--- a/arch/x86/Kconfig
++++ b/arch/x86/Kconfig
+@@ -708,7 +708,6 @@ config X86_SUPPORTS_MEMORY_FAILURE
+ config STA2X11
+ bool "STA2X11 Companion Chip Support"
+ depends on X86_32_NON_STANDARD && PCI
+- select ARCH_HAS_PHYS_TO_DMA
+ select SWIOTLB
+ select MFD_STA2X11
+ select GPIOLIB
+diff --git a/arch/x86/include/asm/device.h b/arch/x86/include/asm/device.h
+index a8f6c809d9b1..5e12c63b47aa 100644
+--- a/arch/x86/include/asm/device.h
++++ b/arch/x86/include/asm/device.h
+@@ -6,9 +6,6 @@ struct dev_archdata {
+ #if defined(CONFIG_INTEL_IOMMU) || defined(CONFIG_AMD_IOMMU)
+ void *iommu; /* hook for IOMMU specific extension */
+ #endif
+-#ifdef CONFIG_STA2X11
+- bool is_sta2x11;
+-#endif
+ };
+
+ #if defined(CONFIG_X86_DEV_DMA_OPS) && defined(CONFIG_PCI_DOMAINS)
+diff --git a/arch/x86/include/asm/dma-direct.h b/arch/x86/include/asm/dma-direct.h
+deleted file mode 100644
+index 1a19251eaac9..000000000000
+--- a/arch/x86/include/asm/dma-direct.h
++++ /dev/null
+@@ -1,9 +0,0 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
+-#ifndef ASM_X86_DMA_DIRECT_H
+-#define ASM_X86_DMA_DIRECT_H 1
+-
+-bool dma_capable(struct device *dev, dma_addr_t addr, size_t size);
+-dma_addr_t __phys_to_dma(struct device *dev, phys_addr_t paddr);
+-phys_addr_t __dma_to_phys(struct device *dev, dma_addr_t daddr);
+-
+-#endif /* ASM_X86_DMA_DIRECT_H */
+diff --git a/arch/x86/pci/sta2x11-fixup.c b/arch/x86/pci/sta2x11-fixup.c
+index 6269a175385d..4a631264b809 100644
+--- a/arch/x86/pci/sta2x11-fixup.c
++++ b/arch/x86/pci/sta2x11-fixup.c
+@@ -30,7 +30,6 @@ struct sta2x11_ahb_regs { /* saved during suspend */
+ };
+
+ struct sta2x11_mapping {
+- u32 amba_base;
+ int is_suspended;
+ struct sta2x11_ahb_regs regs[STA2X11_NR_FUNCS];
+ };
+@@ -92,18 +91,6 @@ static int sta2x11_pdev_to_ep(struct pci_dev *pdev)
+ return pdev->bus->number - instance->bus0;
+ }
+
+-static struct sta2x11_mapping *sta2x11_pdev_to_mapping(struct pci_dev *pdev)
+-{
+- struct sta2x11_instance *instance;
+- int ep;
+-
+- instance = sta2x11_pdev_to_instance(pdev);
+- if (!instance)
+- return NULL;
+- ep = sta2x11_pdev_to_ep(pdev);
+- return instance->map + ep;
+-}
+-
+ /* This is exported, as some devices need to access the MFD registers */
+ struct sta2x11_instance *sta2x11_get_instance(struct pci_dev *pdev)
+ {
+@@ -111,39 +98,6 @@ struct sta2x11_instance *sta2x11_get_instance(struct pci_dev *pdev)
+ }
+ EXPORT_SYMBOL(sta2x11_get_instance);
+
+-
+-/**
+- * p2a - Translate physical address to STA2x11 AMBA address,
+- * used for DMA transfers to STA2x11
+- * @p: Physical address
+- * @pdev: PCI device (must be hosted within the connext)
+- */
+-static dma_addr_t p2a(dma_addr_t p, struct pci_dev *pdev)
+-{
+- struct sta2x11_mapping *map;
+- dma_addr_t a;
+-
+- map = sta2x11_pdev_to_mapping(pdev);
+- a = p + map->amba_base;
+- return a;
+-}
+-
+-/**
+- * a2p - Translate STA2x11 AMBA address to physical address
+- * used for DMA transfers from STA2x11
+- * @a: STA2x11 AMBA address
+- * @pdev: PCI device (must be hosted within the connext)
+- */
+-static dma_addr_t a2p(dma_addr_t a, struct pci_dev *pdev)
+-{
+- struct sta2x11_mapping *map;
+- dma_addr_t p;
+-
+- map = sta2x11_pdev_to_mapping(pdev);
+- p = a - map->amba_base;
+- return p;
+-}
+-
+ /* At setup time, we use our own ops if the device is a ConneXt one */
+ static void sta2x11_setup_pdev(struct pci_dev *pdev)
+ {
+@@ -151,70 +105,12 @@ static void sta2x11_setup_pdev(struct pci_dev *pdev)
+
+ if (!instance) /* either a sta2x11 bridge or another ST device */
+ return;
+- pci_set_consistent_dma_mask(pdev, STA2X11_AMBA_SIZE - 1);
+- pci_set_dma_mask(pdev, STA2X11_AMBA_SIZE - 1);
+- pdev->dev.archdata.is_sta2x11 = true;
+
+ /* We must enable all devices as master, for audio DMA to work */
+ pci_set_master(pdev);
+ }
+ DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_STMICRO, PCI_ANY_ID, sta2x11_setup_pdev);
+
+-/*
+- * The following three functions are exported (used in swiotlb: FIXME)
+- */
+-/**
+- * dma_capable - Check if device can manage DMA transfers (FIXME: kill it)
+- * @dev: device for a PCI device
+- * @addr: DMA address
+- * @size: DMA size
+- */
+-bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
+-{
+- struct sta2x11_mapping *map;
+-
+- if (!dev->archdata.is_sta2x11) {
+- if (!dev->dma_mask)
+- return false;
+- return addr + size - 1 <= *dev->dma_mask;
+- }
+-
+- map = sta2x11_pdev_to_mapping(to_pci_dev(dev));
+-
+- if (!map || (addr < map->amba_base))
+- return false;
+- if (addr + size >= map->amba_base + STA2X11_AMBA_SIZE) {
+- return false;
+- }
+-
+- return true;
+-}
+-
+-/**
+- * __phys_to_dma - Return the DMA AMBA address used for this STA2x11 device
+- * @dev: device for a PCI device
+- * @paddr: Physical address
+- */
+-dma_addr_t __phys_to_dma(struct device *dev, phys_addr_t paddr)
+-{
+- if (!dev->archdata.is_sta2x11)
+- return paddr;
+- return p2a(paddr, to_pci_dev(dev));
+-}
+-
+-/**
+- * dma_to_phys - Return the physical address used for this STA2x11 DMA address
+- * @dev: device for a PCI device
+- * @daddr: STA2x11 AMBA DMA address
+- */
+-phys_addr_t __dma_to_phys(struct device *dev, dma_addr_t daddr)
+-{
+- if (!dev->archdata.is_sta2x11)
+- return daddr;
+- return a2p(daddr, to_pci_dev(dev));
+-}
+-
+-
+ /*
+ * At boot we must set up the mappings for the pcie-to-amba bridge.
+ * It involves device access, and the same happens at suspend/resume time
+@@ -234,12 +130,22 @@ phys_addr_t __dma_to_phys(struct device *dev, dma_addr_t daddr)
+ /* At probe time, enable mapping for each endpoint, using the pdev */
+ static void sta2x11_map_ep(struct pci_dev *pdev)
+ {
+- struct sta2x11_mapping *map = sta2x11_pdev_to_mapping(pdev);
++ struct sta2x11_instance *instance = sta2x11_pdev_to_instance(pdev);
++ struct device *dev = &pdev->dev;
++ u32 amba_base, max_amba_addr;
+ int i;
+
+- if (!map)
++ if (!instance)
+ return;
+- pci_read_config_dword(pdev, AHB_BASE(0), &map->amba_base);
++
++ pci_read_config_dword(pdev, AHB_BASE(0), &amba_base);
++ max_amba_addr = amba_base + STA2X11_AMBA_SIZE - 1;
++
++ dev->dma_pfn_offset = PFN_DOWN(-amba_base);
++
++ dev->bus_dma_mask = max_amba_addr;
++ pci_set_consistent_dma_mask(pdev, max_amba_addr);
++ pci_set_dma_mask(pdev, max_amba_addr);
+
+ /* Configure AHB mapping */
+ pci_write_config_dword(pdev, AHB_PEXLBASE(0), 0);
+@@ -253,13 +159,24 @@ static void sta2x11_map_ep(struct pci_dev *pdev)
+
+ dev_info(&pdev->dev,
+ "sta2x11: Map EP %i: AMBA address %#8x-%#8x\n",
+- sta2x11_pdev_to_ep(pdev), map->amba_base,
+- map->amba_base + STA2X11_AMBA_SIZE - 1);
++ sta2x11_pdev_to_ep(pdev), amba_base, max_amba_addr);
+ }
+ DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_STMICRO, PCI_ANY_ID, sta2x11_map_ep);
+
+ #ifdef CONFIG_PM /* Some register values must be saved and restored */
+
++static struct sta2x11_mapping *sta2x11_pdev_to_mapping(struct pci_dev *pdev)
++{
++ struct sta2x11_instance *instance;
++ int ep;
++
++ instance = sta2x11_pdev_to_instance(pdev);
++ if (!instance)
++ return NULL;
++ ep = sta2x11_pdev_to_ep(pdev);
++ return instance->map + ep;
++}
++
+ static void suspend_mapping(struct pci_dev *pdev)
+ {
+ struct sta2x11_mapping *map = sta2x11_pdev_to_mapping(pdev);
+
diff --git a/series.conf b/series.conf
index be072efd14..b16f1b8020 100644
--- a/series.conf
+++ b/series.conf
@@ -3824,6 +3824,8 @@
patches.suse/0002-arm64-rename-variables-used-to-calculate-ZONE_DMA32-.patch
patches.suse/0003-arm64-use-both-ZONE_DMA-and-ZONE_DMA32.patch
patches.suse/0004-mm-refresh-ZONE_DMA-and-ZONE_DMA32-comments-in-enum-.patch
+ patches.suse/arm64-mm-fix-unused-variable-warning-in-zone_sizes_init.patch
+ patches.suse/arm64-mm-reserve-cma-and-crashkernel-in-zone_dma32.patch
patches.suse/0001-crypto-algif_skcipher-Use-chunksize-instead-of-block.patch
patches.suse/0001-crypto-af_alg-cast-ki_complete-ternary-op-to-int.patch
patches.suse/crypto-user-fix-memory-leak-in-crypto_report.patch
@@ -4060,6 +4062,47 @@
patches.suse/scsi-lpfc-revise-nvme-max-queues-to-be-hdwq-count.patch
patches.suse/scsi-lpfc-Update-lpfc-version-to-12.6.0.2.patch
+ # helgaas/pci next
+ patches.suse/resource-add-a-resource_list_first_type-helper.patch
+ patches.suse/pci-export-pci_parse_request_of_pci_ranges.patch
+ patches.suse/pci-aardvark-use-pci_parse_request_of_pci_ranges.patch
+ patches.suse/pci-altera-use-pci_parse_request_of_pci_ranges.patch
+ patches.suse/pci-dwc-use-pci_parse_request_of_pci_ranges.patch
+ patches.suse/pci-faraday-use-pci_parse_request_of_pci_ranges.patch
+ patches.suse/pci-iproc-use-pci_parse_request_of_pci_ranges.patch
+ patches.suse/pci-mediatek-use-pci_parse_request_of_pci_ranges.patch
+ patches.suse/pci-mobiveil-use-pci_parse_request_of_pci_ranges.patch
+ patches.suse/pci-rockchip-use-pci_parse_request_of_pci_ranges.patch
+ patches.suse/pci-rockchip-drop-storing-driver-private-outbound-resource-data.patch
+ patches.suse/pci-v3-semi-use-pci_parse_request_of_pci_ranges.patch
+ patches.suse/pci-xgene-use-pci_parse_request_of_pci_ranges.patch
+ patches.suse/pci-xilinx-use-pci_parse_request_of_pci_ranges.patch
+ patches.suse/pci-xilinx-nwl-use-pci_parse_request_of_pci_ranges.patch
+ patches.suse/pci-versatile-use-pci_parse_request_of_pci_ranges.patch
+ patches.suse/pci-versatile-remove-usage-of-phys_offset.patch
+ patches.suse/pci-versatile-enable-compile_test.patch
+ patches.suse/pci-of-add-inbound-resource-parsing-to-helpers.patch
+ patches.suse/pci-ftpci100-use-inbound-resources-for-setup.patch
+ patches.suse/pci-v3-semi-use-inbound-resources-for-setup.patch
+ patches.suse/pci-xgene-use-inbound-resources-for-setup.patch
+ patches.suse/pci-iproc-use-inbound-resources-for-setup.patch
+ patches.suse/pci-rcar-use-inbound-resources-for-setup.patch
+
+ # robh/linux for-next
+ patches.suse/of-address-introduce-of_get_next_dma_parent-helper.patch
+ patches.suse/of-address-follow-dma-parent-for-dma-coherent.patch
+ patches.suse/of-factor-out-addr-size-cells-parsing.patch
+ patches.suse/of-address-translate-dma-ranges-for-parent-nodes-missing-dma-ranges.patch
+ patches.suse/of-address-fix-of_pci_range_parser_one-translation-of-dma-addresses.patch
+ patches.suse/of-make-of_dma_get_range-work-on-bus-nodes.patch
+
+ # git://git.infradead.org/users/hch/dma-mapping.git for-next
+ patches.suse/dma-direct-check-for-overflows-on-32-bit-dma-addresses.patch
+ patches.suse/x86-pci-sta2x11-use-default-dma-address-translation.patch
+ patches.suse/dma-direct-unify-the-dma_capable-definitions.patch
+ patches.suse/dma-direct-avoid-a-forward-declaration-for-phys_to_dma.patch
+ patches.suse/dma-direct-exclude-dma_direct_map_resource-from-the-min_low_pfn-check.patch
+ patches.suse/dma-mapping-treat-dev-bus_dma_mask-as-a-dma-limit.patch
########################################################
# end of sorted patches
########################################################
@@ -4348,6 +4391,11 @@
#Jetson TX2
patches.suse/cpufreq-tegra186-add-CPUFREQ_NEED_INITIAL_FREQ_CHECK.patch
+ #Raspberry Pi 4 PCIe controller
+ patches.suse/linux-log2-h-add-roundup-rounddown_pow_two64-family-of-functions.patch
+ patches.suse/pci-brcmstb-add-broadcom-stb-pcie-host-controller-driver.patch
+ patches.suse/pci-brcmstb-add-msi-capability.patch
+
########################################################
# Debugging
########################################################
diff --git a/supported.conf b/supported.conf
index c2b4d1223c..4b057f9a85 100644
--- a/supported.conf
+++ b/supported.conf
@@ -1950,6 +1950,7 @@
drivers/pci/controller/pcie-iproc
drivers/pci/controller/pcie-iproc-platform
- drivers/pci/controller/pcie-rockchip-host
+ drivers/pci/controller/pcie-brcmstb
drivers/pci/controller/vmd # FATE#326872
- drivers/pci/endpoint/functions/pci-epf-test
drivers/pci/hotplug/acpiphp_ibm # ACPI Hot Plug PCI Controller Driver IBM extension