diff options
Diffstat (limited to 'target/linux/bcm53xx/patches-4.3/146-PCI-iproc-Add-outbound-mapping-support.patch')
-rw-r--r-- | target/linux/bcm53xx/patches-4.3/146-PCI-iproc-Add-outbound-mapping-support.patch | 236 |
1 files changed, 0 insertions, 236 deletions
diff --git a/target/linux/bcm53xx/patches-4.3/146-PCI-iproc-Add-outbound-mapping-support.patch b/target/linux/bcm53xx/patches-4.3/146-PCI-iproc-Add-outbound-mapping-support.patch deleted file mode 100644 index b65d3057bc..0000000000 --- a/target/linux/bcm53xx/patches-4.3/146-PCI-iproc-Add-outbound-mapping-support.patch +++ /dev/null @@ -1,236 +0,0 @@ -From e99a187b5c5f60fe55ca586f82ac1a3557fb166a Mon Sep 17 00:00:00 2001 -From: Ray Jui <rjui@broadcom.com> -Date: Fri, 16 Oct 2015 08:18:24 -0500 -Subject: [PATCH 146/147] PCI: iproc: Add outbound mapping support - -Certain SoCs require the PCIe outbound mapping to be configured in -software. Add support for those chips. - -[jonmason: Use %pap format when printing size_t to avoid warnings in 32-bit -build.] -[arnd: Use div64_u64() instead of "%" to avoid __aeabi_uldivmod link error -in 32-bit build.] -Signed-off-by: Ray Jui <rjui@broadcom.com> -Signed-off-by: Jon Mason <jonmason@broadcom.com> -Signed-off-by: Arnd Bergmann <arnd@arndb.de> -Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> ---- - drivers/pci/host/pcie-iproc-platform.c | 27 ++++++++ - drivers/pci/host/pcie-iproc.c | 115 +++++++++++++++++++++++++++++++++ - drivers/pci/host/pcie-iproc.h | 17 +++++ - 3 files changed, 159 insertions(+) - ---- a/drivers/pci/host/pcie-iproc-platform.c -+++ b/drivers/pci/host/pcie-iproc-platform.c -@@ -54,6 +54,33 @@ static int iproc_pcie_pltfm_probe(struct - return -ENOMEM; - } - -+ if (of_property_read_bool(np, "brcm,pcie-ob")) { -+ u32 val; -+ -+ ret = of_property_read_u32(np, "brcm,pcie-ob-axi-offset", -+ &val); -+ if (ret) { -+ dev_err(pcie->dev, -+ "missing brcm,pcie-ob-axi-offset property\n"); -+ return ret; -+ } -+ pcie->ob.axi_offset = val; -+ -+ ret = of_property_read_u32(np, "brcm,pcie-ob-window-size", -+ &val); -+ if (ret) { -+ dev_err(pcie->dev, -+ "missing brcm,pcie-ob-window-size property\n"); -+ return ret; -+ } -+ pcie->ob.window_size = (resource_size_t)val * SZ_1M; -+ -+ if (of_property_read_bool(np, "brcm,pcie-ob-oarr-size")) -+ pcie->ob.set_oarr_size = true; -+ -+ pcie->need_ob_cfg = true; -+ } -+ - /* PHY use is optional */ - pcie->phy = devm_phy_get(&pdev->dev, "pcie-phy"); - if (IS_ERR(pcie->phy)) { ---- a/drivers/pci/host/pcie-iproc.c -+++ b/drivers/pci/host/pcie-iproc.c -@@ -66,6 +66,18 @@ - #define PCIE_DL_ACTIVE_SHIFT 2 - #define PCIE_DL_ACTIVE BIT(PCIE_DL_ACTIVE_SHIFT) - -+#define OARR_VALID_SHIFT 0 -+#define OARR_VALID BIT(OARR_VALID_SHIFT) -+#define OARR_SIZE_CFG_SHIFT 1 -+#define OARR_SIZE_CFG BIT(OARR_SIZE_CFG_SHIFT) -+ -+#define OARR_LO(window) (0xd20 + (window) * 8) -+#define OARR_HI(window) (0xd24 + (window) * 8) -+#define OMAP_LO(window) (0xd40 + (window) * 8) -+#define OMAP_HI(window) (0xd44 + (window) * 8) -+ -+#define MAX_NUM_OB_WINDOWS 2 -+ - static inline struct iproc_pcie *iproc_data(struct pci_bus *bus) - { - struct iproc_pcie *pcie; -@@ -212,6 +224,101 @@ static void iproc_pcie_enable(struct ipr - writel(SYS_RC_INTX_MASK, pcie->base + SYS_RC_INTX_EN); - } - -+/** -+ * Some iProc SoCs require the SW to configure the outbound address mapping -+ * -+ * Outbound address translation: -+ * -+ * iproc_pcie_address = axi_address - axi_offset -+ * OARR = iproc_pcie_address -+ * OMAP = pci_addr -+ * -+ * axi_addr -> iproc_pcie_address -> OARR -> OMAP -> pci_address -+ */ -+static int iproc_pcie_setup_ob(struct iproc_pcie *pcie, u64 axi_addr, -+ u64 pci_addr, resource_size_t size) -+{ -+ struct iproc_pcie_ob *ob = &pcie->ob; -+ unsigned i; -+ u64 max_size = (u64)ob->window_size * MAX_NUM_OB_WINDOWS; -+ u64 remainder; -+ -+ if (size > max_size) { -+ dev_err(pcie->dev, -+ "res size 0x%pap exceeds max supported size 0x%llx\n", -+ &size, max_size); -+ return -EINVAL; -+ } -+ -+ div64_u64_rem(size, ob->window_size, &remainder); -+ if (remainder) { -+ dev_err(pcie->dev, -+ "res size %pap needs to be multiple of window size %pap\n", -+ &size, &ob->window_size); -+ return -EINVAL; -+ } -+ -+ if (axi_addr < ob->axi_offset) { -+ dev_err(pcie->dev, -+ "axi address %pap less than offset %pap\n", -+ &axi_addr, &ob->axi_offset); -+ return -EINVAL; -+ } -+ -+ /* -+ * Translate the AXI address to the internal address used by the iProc -+ * PCIe core before programming the OARR -+ */ -+ axi_addr -= ob->axi_offset; -+ -+ for (i = 0; i < MAX_NUM_OB_WINDOWS; i++) { -+ writel(lower_32_bits(axi_addr) | OARR_VALID | -+ (ob->set_oarr_size ? 1 : 0), pcie->base + OARR_LO(i)); -+ writel(upper_32_bits(axi_addr), pcie->base + OARR_HI(i)); -+ writel(lower_32_bits(pci_addr), pcie->base + OMAP_LO(i)); -+ writel(upper_32_bits(pci_addr), pcie->base + OMAP_HI(i)); -+ -+ size -= ob->window_size; -+ if (size == 0) -+ break; -+ -+ axi_addr += ob->window_size; -+ pci_addr += ob->window_size; -+ } -+ -+ return 0; -+} -+ -+static int iproc_pcie_map_ranges(struct iproc_pcie *pcie, -+ struct list_head *resources) -+{ -+ struct resource_entry *window; -+ int ret; -+ -+ resource_list_for_each_entry(window, resources) { -+ struct resource *res = window->res; -+ u64 res_type = resource_type(res); -+ -+ switch (res_type) { -+ case IORESOURCE_IO: -+ case IORESOURCE_BUS: -+ break; -+ case IORESOURCE_MEM: -+ ret = iproc_pcie_setup_ob(pcie, res->start, -+ res->start - window->offset, -+ resource_size(res)); -+ if (ret) -+ return ret; -+ break; -+ default: -+ dev_err(pcie->dev, "invalid resource %pR\n", res); -+ return -EINVAL; -+ } -+ } -+ -+ return 0; -+} -+ - int iproc_pcie_setup(struct iproc_pcie *pcie, struct list_head *res) - { - int ret; -@@ -235,6 +342,14 @@ int iproc_pcie_setup(struct iproc_pcie * - - iproc_pcie_reset(pcie); - -+ if (pcie->need_ob_cfg) { -+ ret = iproc_pcie_map_ranges(pcie, res); -+ if (ret) { -+ dev_err(pcie->dev, "map failed\n"); -+ goto err_power_off_phy; -+ } -+ } -+ - #ifdef CONFIG_ARM - pcie->sysdata.private_data = pcie; - sysdata = &pcie->sysdata; ---- a/drivers/pci/host/pcie-iproc.h -+++ b/drivers/pci/host/pcie-iproc.h -@@ -15,6 +15,19 @@ - #define _PCIE_IPROC_H - - /** -+ * iProc PCIe outbound mapping -+ * @set_oarr_size: indicates the OARR size bit needs to be set -+ * @axi_offset: offset from the AXI address to the internal address used by -+ * the iProc PCIe core -+ * @window_size: outbound window size -+ */ -+struct iproc_pcie_ob { -+ bool set_oarr_size; -+ resource_size_t axi_offset; -+ resource_size_t window_size; -+}; -+ -+/** - * iProc PCIe device - * @dev: pointer to device data structure - * @base: PCIe host controller I/O register base -@@ -23,6 +36,8 @@ - * @phy: optional PHY device that controls the Serdes - * @irqs: interrupt IDs - * @map_irq: function callback to map interrupts -+ * @need_ob_cfg: indidates SW needs to configure the outbound mapping window -+ * @ob: outbound mapping parameters - */ - struct iproc_pcie { - struct device *dev; -@@ -33,6 +48,8 @@ struct iproc_pcie { - struct pci_bus *root_bus; - struct phy *phy; - int (*map_irq)(const struct pci_dev *, u8, u8); -+ bool need_ob_cfg; -+ struct iproc_pcie_ob ob; - }; - - int iproc_pcie_setup(struct iproc_pcie *pcie, struct list_head *res); |