summaryrefslogtreecommitdiff
path: root/target/linux/ipq806x/patches/0138-PCI-qcom-Add-support-for-pcie-controllers-on-IPQ8064.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/ipq806x/patches/0138-PCI-qcom-Add-support-for-pcie-controllers-on-IPQ8064.patch')
-rw-r--r--target/linux/ipq806x/patches/0138-PCI-qcom-Add-support-for-pcie-controllers-on-IPQ8064.patch716
1 files changed, 0 insertions, 716 deletions
diff --git a/target/linux/ipq806x/patches/0138-PCI-qcom-Add-support-for-pcie-controllers-on-IPQ8064.patch b/target/linux/ipq806x/patches/0138-PCI-qcom-Add-support-for-pcie-controllers-on-IPQ8064.patch
deleted file mode 100644
index 8aaa766..0000000
--- a/target/linux/ipq806x/patches/0138-PCI-qcom-Add-support-for-pcie-controllers-on-IPQ8064.patch
+++ /dev/null
@@ -1,716 +0,0 @@
-From 98567c99b4dcd80fc9e5dd97229ebb9a7f6dab03 Mon Sep 17 00:00:00 2001
-From: Kumar Gala <galak@codeaurora.org>
-Date: Fri, 16 May 2014 11:53:23 -0500
-Subject: [PATCH 138/182] PCI: qcom: Add support for pcie controllers on
- IPQ8064
-
----
- arch/arm/mach-qcom/Kconfig | 2 +
- drivers/pci/host/Makefile | 1 +
- drivers/pci/host/pci-qcom.c | 682 +++++++++++++++++++++++++++++++++++++++++++
- 3 files changed, 685 insertions(+)
- create mode 100644 drivers/pci/host/pci-qcom.c
-
---- a/arch/arm/mach-qcom/Kconfig
-+++ b/arch/arm/mach-qcom/Kconfig
-@@ -7,6 +7,8 @@ config ARCH_QCOM
- select GENERIC_CLOCKEVENTS
- select HAVE_SMP
- select PINCTRL
-+ select MIGHT_HAVE_PCI
-+ select PCI_DOMAINS if PCI
- select QCOM_SCM if SMP
- help
- Support for Qualcomm's devicetree based systems.
---- a/drivers/pci/host/Makefile
-+++ b/drivers/pci/host/Makefile
-@@ -4,3 +4,4 @@ obj-$(CONFIG_PCI_IMX6) += pci-imx6.o
- obj-$(CONFIG_PCI_MVEBU) += pci-mvebu.o
- obj-$(CONFIG_PCI_TEGRA) += pci-tegra.o
- obj-$(CONFIG_PCI_RCAR_GEN2) += pci-rcar-gen2.o
-+obj-$(CONFIG_ARCH_QCOM) += pci-qcom.o
---- /dev/null
-+++ b/drivers/pci/host/pci-qcom.c
-@@ -0,0 +1,682 @@
-+/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 and
-+ * only version 2 as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+/*
-+ * QCOM MSM PCIe controller driver.
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/pci.h>
-+#include <linux/gpio.h>
-+#include <linux/of_gpio.h>
-+#include <linux/platform_device.h>
-+#include <linux/of_address.h>
-+#include <linux/clk.h>
-+#include <linux/reset.h>
-+#include <linux/delay.h>
-+
-+/* Root Complex Port vendor/device IDs */
-+#define PCIE_VENDOR_ID_RCP 0x17cb
-+#define PCIE_DEVICE_ID_RCP 0x0101
-+
-+#define __set(v, a, b) (((v) << (b)) & GENMASK(a, b))
-+
-+#define PCIE20_PARF_PCS_DEEMPH 0x34
-+#define PCIE20_PARF_PCS_DEEMPH_TX_DEEMPH_GEN1(x) __set(x, 21, 16)
-+#define PCIE20_PARF_PCS_DEEMPH_TX_DEEMPH_GEN2_3_5DB(x) __set(x, 13, 8)
-+#define PCIE20_PARF_PCS_DEEMPH_TX_DEEMPH_GEN2_6DB(x) __set(x, 5, 0)
-+
-+#define PCIE20_PARF_PCS_SWING 0x38
-+#define PCIE20_PARF_PCS_SWING_TX_SWING_FULL(x) __set(x, 14, 8)
-+#define PCIE20_PARF_PCS_SWING_TX_SWING_LOW(x) __set(x, 6, 0)
-+
-+#define PCIE20_PARF_PHY_CTRL 0x40
-+#define PCIE20_PARF_PHY_CTRL_PHY_TX0_TERM_OFFST(x) __set(x, 20, 16)
-+#define PCIE20_PARF_PHY_CTRL_PHY_LOS_LEVEL(x) __set(x, 12, 8)
-+#define PCIE20_PARF_PHY_CTRL_PHY_RTUNE_REQ (1 << 4)
-+#define PCIE20_PARF_PHY_CTRL_PHY_TEST_BURNIN (1 << 2)
-+#define PCIE20_PARF_PHY_CTRL_PHY_TEST_BYPASS (1 << 1)
-+#define PCIE20_PARF_PHY_CTRL_PHY_TEST_PWR_DOWN (1 << 0)
-+
-+#define PCIE20_PARF_PHY_REFCLK 0x4C
-+#define PCIE20_PARF_CONFIG_BITS 0x50
-+
-+#define PCIE20_ELBI_SYS_CTRL 0x04
-+#define PCIE20_ELBI_SYS_CTRL_LTSSM_EN 0x01
-+
-+#define PCIE20_CAP 0x70
-+#define PCIE20_CAP_LINKCTRLSTATUS (PCIE20_CAP + 0x10)
-+
-+#define PCIE20_COMMAND_STATUS 0x04
-+#define PCIE20_BUSNUMBERS 0x18
-+#define PCIE20_MEMORY_BASE_LIMIT 0x20
-+
-+#define PCIE20_AXI_MSTR_RESP_COMP_CTRL0 0x818
-+#define PCIE20_AXI_MSTR_RESP_COMP_CTRL1 0x81c
-+#define PCIE20_PLR_IATU_VIEWPORT 0x900
-+#define PCIE20_PLR_IATU_CTRL1 0x904
-+#define PCIE20_PLR_IATU_CTRL2 0x908
-+#define PCIE20_PLR_IATU_LBAR 0x90C
-+#define PCIE20_PLR_IATU_UBAR 0x910
-+#define PCIE20_PLR_IATU_LAR 0x914
-+#define PCIE20_PLR_IATU_LTAR 0x918
-+#define PCIE20_PLR_IATU_UTAR 0x91c
-+
-+#define MSM_PCIE_DEV_CFG_ADDR 0x01000000
-+
-+#define RD 0
-+#define WR 1
-+
-+#define MAX_RC_NUM 3
-+#define PCIE_BUS_PRIV_DATA(pdev) \
-+ (((struct pci_sys_data *)pdev->bus->sysdata)->private_data)
-+
-+/* PCIe TLP types that we are interested in */
-+#define PCI_CFG0_RDWR 0x4
-+#define PCI_CFG1_RDWR 0x5
-+
-+#define readl_poll_timeout(addr, val, cond, sleep_us, timeout_us) \
-+({ \
-+ unsigned long timeout = jiffies + usecs_to_jiffies(timeout_us); \
-+ might_sleep_if(timeout_us); \
-+ for (;;) { \
-+ (val) = readl(addr); \
-+ if (cond) \
-+ break; \
-+ if (timeout_us && time_after(jiffies, timeout)) { \
-+ (val) = readl(addr); \
-+ break; \
-+ } \
-+ if (sleep_us) \
-+ usleep_range(DIV_ROUND_UP(sleep_us, 4), sleep_us); \
-+ } \
-+ (cond) ? 0 : -ETIMEDOUT; \
-+})
-+
-+struct qcom_pcie {
-+ void __iomem *elbi_base;
-+ void __iomem *parf_base;
-+ void __iomem *dwc_base;
-+ void __iomem *cfg_base;
-+ int reset_gpio;
-+ struct clk *iface_clk;
-+ struct clk *bus_clk;
-+ struct clk *phy_clk;
-+ int irq_int[4];
-+ struct reset_control *axi_reset;
-+ struct reset_control *ahb_reset;
-+ struct reset_control *por_reset;
-+ struct reset_control *pci_reset;
-+ struct reset_control *phy_reset;
-+
-+ struct resource conf;
-+ struct resource io;
-+ struct resource mem;
-+};
-+
-+static int qcom_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin);
-+static int qcom_pcie_setup(int nr, struct pci_sys_data *sys);
-+static int msm_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
-+ int size, u32 *val);
-+static int msm_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
-+ int where, int size, u32 val);
-+
-+static struct pci_ops qcom_pcie_ops = {
-+ .read = msm_pcie_rd_conf,
-+ .write = msm_pcie_wr_conf,
-+};
-+
-+static struct hw_pci qcom_hw_pci[MAX_RC_NUM] = {
-+ {
-+#ifdef CONFIG_PCI_DOMAINS
-+ .domain = 0,
-+#endif
-+ .ops = &qcom_pcie_ops,
-+ .nr_controllers = 1,
-+ .swizzle = pci_common_swizzle,
-+ .setup = qcom_pcie_setup,
-+ .map_irq = qcom_pcie_map_irq,
-+ },
-+ {
-+#ifdef CONFIG_PCI_DOMAINS
-+ .domain = 1,
-+#endif
-+ .ops = &qcom_pcie_ops,
-+ .nr_controllers = 1,
-+ .swizzle = pci_common_swizzle,
-+ .setup = qcom_pcie_setup,
-+ .map_irq = qcom_pcie_map_irq,
-+ },
-+ {
-+#ifdef CONFIG_PCI_DOMAINS
-+ .domain = 2,
-+#endif
-+ .ops = &qcom_pcie_ops,
-+ .nr_controllers = 1,
-+ .swizzle = pci_common_swizzle,
-+ .setup = qcom_pcie_setup,
-+ .map_irq = qcom_pcie_map_irq,
-+ },
-+};
-+
-+static int nr_controllers;
-+static DEFINE_SPINLOCK(qcom_hw_pci_lock);
-+
-+static inline struct qcom_pcie *sys_to_pcie(struct pci_sys_data *sys)
-+{
-+ return sys->private_data;
-+}
-+
-+inline int is_msm_pcie_rc(struct pci_bus *bus)
-+{
-+ return (bus->number == 0);
-+}
-+
-+static int qcom_pcie_is_link_up(struct qcom_pcie *dev)
-+{
-+ return readl_relaxed(dev->dwc_base + PCIE20_CAP_LINKCTRLSTATUS) & BIT(29);
-+}
-+
-+inline int msm_pcie_get_cfgtype(struct pci_bus *bus)
-+{
-+ /*
-+ * http://www.tldp.org/LDP/tlk/dd/pci.html
-+ * Pass it onto the secondary bus interface unchanged if the
-+ * bus number specified is greater than the secondary bus
-+ * number and less than or equal to the subordinate bus
-+ * number.
-+ *
-+ * Read/Write to the RC and Device/Switch connected to the RC
-+ * are CFG0 type transactions. Rest have to be forwarded
-+ * down stream as CFG1 transactions.
-+ *
-+ */
-+ if (bus->number == 0)
-+ return PCI_CFG0_RDWR;
-+
-+ return PCI_CFG0_RDWR;
-+}
-+
-+void msm_pcie_config_cfgtype(struct pci_bus *bus, u32 devfn)
-+{
-+ uint32_t bdf, cfgtype;
-+ struct qcom_pcie *dev = sys_to_pcie(bus->sysdata);
-+
-+ cfgtype = msm_pcie_get_cfgtype(bus);
-+
-+ if (cfgtype == PCI_CFG0_RDWR) {
-+ bdf = MSM_PCIE_DEV_CFG_ADDR;
-+ } else {
-+ /*
-+ * iATU Lower Target Address Register
-+ * Bits Description
-+ * *-1:0 Forms bits [*:0] of the
-+ * start address of the new
-+ * address of the translated
-+ * region. The start address
-+ * must be aligned to a
-+ * CX_ATU_MIN_REGION_SIZE kB
-+ * boundary, so these bits are
-+ * always 0. A write to this
-+ * location is ignored by the
-+ * PCIe core.
-+ * 31:*1 Forms bits [31:*] of the of
-+ * the new address of the
-+ * translated region.
-+ *
-+ * * is log2(CX_ATU_MIN_REGION_SIZE)
-+ */
-+ bdf = (((bus->number & 0xff) << 24) & 0xff000000) |
-+ (((devfn & 0xff) << 16) & 0x00ff0000);
-+ }
-+
-+ writel_relaxed(0, dev->dwc_base + PCIE20_PLR_IATU_VIEWPORT);
-+ wmb();
-+
-+ /* Program Bdf Address */
-+ writel_relaxed(bdf, dev->dwc_base + PCIE20_PLR_IATU_LTAR);
-+ wmb();
-+
-+ /* Write Config Request Type */
-+ writel_relaxed(cfgtype, dev->dwc_base + PCIE20_PLR_IATU_CTRL1);
-+ wmb();
-+}
-+
-+static inline int msm_pcie_oper_conf(struct pci_bus *bus, u32 devfn, int oper,
-+ int where, int size, u32 *val)
-+{
-+ uint32_t word_offset, byte_offset, mask;
-+ uint32_t rd_val, wr_val;
-+ struct qcom_pcie *dev = sys_to_pcie(bus->sysdata);
-+ void __iomem *config_base;
-+ int rc;
-+
-+ rc = is_msm_pcie_rc(bus);
-+
-+ /*
-+ * For downstream bus, make sure link is up
-+ */
-+ if (rc && (devfn != 0)) {
-+ *val = ~0;
-+ return PCIBIOS_DEVICE_NOT_FOUND;
-+ } else if ((!rc) && (!qcom_pcie_is_link_up(dev))) {
-+ *val = ~0;
-+ return PCIBIOS_DEVICE_NOT_FOUND;
-+ }
-+
-+ msm_pcie_config_cfgtype(bus, devfn);
-+
-+ word_offset = where & ~0x3;
-+ byte_offset = where & 0x3;
-+ mask = (~0 >> (8 * (4 - size))) << (8 * byte_offset);
-+
-+ config_base = (rc) ? dev->dwc_base : dev->cfg_base;
-+ rd_val = readl_relaxed(config_base + word_offset);
-+
-+ if (oper == RD) {
-+ *val = ((rd_val & mask) >> (8 * byte_offset));
-+ } else {
-+ wr_val = (rd_val & ~mask) |
-+ ((*val << (8 * byte_offset)) & mask);
-+ writel_relaxed(wr_val, config_base + word_offset);
-+ wmb(); /* ensure config data is written to hardware register */
-+ }
-+
-+ return 0;
-+}
-+
-+static int msm_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
-+ int size, u32 *val)
-+{
-+ return msm_pcie_oper_conf(bus, devfn, RD, where, size, val);
-+}
-+
-+static int msm_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
-+ int where, int size, u32 val)
-+{
-+ /*
-+ *Attempt to reset secondary bus is causing PCIE core to reset.
-+ *Disable secondary bus reset functionality.
-+ */
-+ if ((bus->number == 0) && (where == PCI_BRIDGE_CONTROL) &&
-+ (val & PCI_BRIDGE_CTL_BUS_RESET)) {
-+ pr_info("PCIE secondary bus reset not supported\n");
-+ val &= ~PCI_BRIDGE_CTL_BUS_RESET;
-+ }
-+
-+ return msm_pcie_oper_conf(bus, devfn, WR, where, size, &val);
-+}
-+
-+static int qcom_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
-+{
-+ struct qcom_pcie *pcie_dev = PCIE_BUS_PRIV_DATA(dev);
-+
-+ return pcie_dev->irq_int[pin-1];
-+}
-+
-+static int qcom_pcie_setup(int nr, struct pci_sys_data *sys)
-+{
-+ struct qcom_pcie *qcom_pcie = sys->private_data;
-+
-+ /*
-+ * specify linux PCI framework to allocate device memory (BARs)
-+ * from msm_pcie_dev.dev_mem_res resource.
-+ */
-+ sys->mem_offset = 0;
-+ sys->io_offset = 0;
-+
-+ pci_add_resource(&sys->resources, &qcom_pcie->mem);
-+ pci_add_resource(&sys->resources, &qcom_pcie->io);
-+
-+ return 1;
-+}
-+
-+static inline void qcom_elbi_writel_relaxed(struct qcom_pcie *pcie, u32 val, u32 reg)
-+{
-+ writel_relaxed(val, pcie->elbi_base + reg);
-+}
-+
-+static inline u32 qcom_elbi_readl_relaxed(struct qcom_pcie *pcie, u32 reg)
-+{
-+ return readl_relaxed(pcie->elbi_base + reg);
-+}
-+
-+static inline void qcom_parf_writel_relaxed(struct qcom_pcie *pcie, u32 val, u32 reg)
-+{
-+ writel_relaxed(val, pcie->parf_base + reg);
-+}
-+
-+static inline u32 qcom_parf_readl_relaxed(struct qcom_pcie *pcie, u32 reg)
-+{
-+ return readl_relaxed(pcie->parf_base + reg);
-+}
-+
-+static void msm_pcie_write_mask(void __iomem *addr,
-+ uint32_t clear_mask, uint32_t set_mask)
-+{
-+ uint32_t val;
-+
-+ val = (readl_relaxed(addr) & ~clear_mask) | set_mask;
-+ writel_relaxed(val, addr);
-+ wmb(); /* ensure data is written to hardware register */
-+}
-+
-+static void qcom_pcie_config_controller(struct qcom_pcie *dev)
-+{
-+ /*
-+ * program and enable address translation region 0 (device config
-+ * address space); region type config;
-+ * axi config address range to device config address range
-+ */
-+ writel_relaxed(0, dev->dwc_base + PCIE20_PLR_IATU_VIEWPORT);
-+ /* ensure that hardware locks the region before programming it */
-+ wmb();
-+
-+ writel_relaxed(4, dev->dwc_base + PCIE20_PLR_IATU_CTRL1);
-+ writel_relaxed(BIT(31), dev->dwc_base + PCIE20_PLR_IATU_CTRL2);
-+ writel_relaxed(dev->conf.start, dev->dwc_base + PCIE20_PLR_IATU_LBAR);
-+ writel_relaxed(0, dev->dwc_base + PCIE20_PLR_IATU_UBAR);
-+ writel_relaxed(dev->conf.end, dev->dwc_base + PCIE20_PLR_IATU_LAR);
-+ writel_relaxed(MSM_PCIE_DEV_CFG_ADDR,
-+ dev->dwc_base + PCIE20_PLR_IATU_LTAR);
-+ writel_relaxed(0, dev->dwc_base + PCIE20_PLR_IATU_UTAR);
-+ /* ensure that hardware registers the configuration */
-+ wmb();
-+
-+ /*
-+ * program and enable address translation region 2 (device resource
-+ * address space); region type memory;
-+ * axi device bar address range to device bar address range
-+ */
-+ writel_relaxed(2, dev->dwc_base + PCIE20_PLR_IATU_VIEWPORT);
-+ /* ensure that hardware locks the region before programming it */
-+ wmb();
-+
-+ writel_relaxed(0, dev->dwc_base + PCIE20_PLR_IATU_CTRL1);
-+ writel_relaxed(BIT(31), dev->dwc_base + PCIE20_PLR_IATU_CTRL2);
-+ writel_relaxed(dev->mem.start, dev->dwc_base + PCIE20_PLR_IATU_LBAR);
-+ writel_relaxed(0, dev->dwc_base + PCIE20_PLR_IATU_UBAR);
-+ writel_relaxed(dev->mem.end, dev->dwc_base + PCIE20_PLR_IATU_LAR);
-+ writel_relaxed(dev->mem.start,
-+ dev->dwc_base + PCIE20_PLR_IATU_LTAR);
-+ writel_relaxed(0, dev->dwc_base + PCIE20_PLR_IATU_UTAR);
-+ /* ensure that hardware registers the configuration */
-+ wmb();
-+
-+ /* 1K PCIE buffer setting */
-+ writel_relaxed(0x3, dev->dwc_base + PCIE20_AXI_MSTR_RESP_COMP_CTRL0);
-+ writel_relaxed(0x1, dev->dwc_base + PCIE20_AXI_MSTR_RESP_COMP_CTRL1);
-+ /* ensure that hardware registers the configuration */
-+ wmb();
-+}
-+
-+static int qcom_pcie_probe(struct platform_device *pdev)
-+{
-+ unsigned long flags;
-+ struct qcom_pcie *qcom_pcie;
-+ struct device_node *np = pdev->dev.of_node;
-+ struct resource *elbi_base, *parf_base, *dwc_base;
-+ struct hw_pci *hw;
-+ struct of_pci_range range;
-+ struct of_pci_range_parser parser;
-+ int ret, i;
-+ u32 val;
-+
-+ qcom_pcie = devm_kzalloc(&pdev->dev, sizeof(*qcom_pcie), GFP_KERNEL);
-+ if (!qcom_pcie) {
-+ dev_err(&pdev->dev, "no memory for qcom_pcie\n");
-+ return -ENOMEM;
-+ }
-+
-+ elbi_base = platform_get_resource_byname(pdev, IORESOURCE_MEM, "elbi");
-+ qcom_pcie->elbi_base = devm_ioremap_resource(&pdev->dev, elbi_base);
-+ if (IS_ERR(qcom_pcie->elbi_base)) {
-+ dev_err(&pdev->dev, "Failed to ioremap elbi space\n");
-+ return PTR_ERR(qcom_pcie->elbi_base);
-+ }
-+
-+ parf_base = platform_get_resource_byname(pdev, IORESOURCE_MEM, "parf");
-+ qcom_pcie->parf_base = devm_ioremap_resource(&pdev->dev, parf_base);
-+ if (IS_ERR(qcom_pcie->parf_base)) {
-+ dev_err(&pdev->dev, "Failed to ioremap parf space\n");
-+ return PTR_ERR(qcom_pcie->parf_base);
-+ }
-+
-+ dwc_base = platform_get_resource_byname(pdev, IORESOURCE_MEM, "base");
-+ qcom_pcie->dwc_base = devm_ioremap_resource(&pdev->dev, dwc_base);
-+ if (IS_ERR(qcom_pcie->dwc_base)) {
-+ dev_err(&pdev->dev, "Failed to ioremap dwc_base space\n");
-+ return PTR_ERR(qcom_pcie->dwc_base);
-+ }
-+
-+ if (of_pci_range_parser_init(&parser, np)) {
-+ dev_err(&pdev->dev, "missing ranges property\n");
-+ return -EINVAL;
-+ }
-+
-+ /* Get the I/O and memory ranges from DT */
-+ for_each_of_pci_range(&parser, &range) {
-+ switch (range.pci_space & 0x3) {
-+ case 0: /* cfg */
-+ of_pci_range_to_resource(&range, np, &qcom_pcie->conf);
-+ qcom_pcie->conf.flags = IORESOURCE_MEM;
-+ break;
-+ case 1: /* io */
-+ of_pci_range_to_resource(&range, np, &qcom_pcie->io);
-+ break;
-+ default: /* mem */
-+ of_pci_range_to_resource(&range, np, &qcom_pcie->mem);
-+ break;
-+ }
-+ }
-+
-+ qcom_pcie->cfg_base = devm_ioremap_resource(&pdev->dev, &qcom_pcie->conf);
-+ if (IS_ERR(qcom_pcie->cfg_base)) {
-+ dev_err(&pdev->dev, "Failed to ioremap PCIe cfg space\n");
-+ return PTR_ERR(qcom_pcie->cfg_base);
-+ }
-+
-+ qcom_pcie->reset_gpio = of_get_named_gpio(np, "reset-gpio", 0);
-+ if (!gpio_is_valid(qcom_pcie->reset_gpio)) {
-+ dev_err(&pdev->dev, "pcie reset gpio is not valid\n");
-+ return -EINVAL;
-+ }
-+
-+ ret = devm_gpio_request_one(&pdev->dev, qcom_pcie->reset_gpio,
-+ GPIOF_DIR_OUT, "pcie_reset");
-+ if (ret) {
-+ dev_err(&pdev->dev, "Failed to request pcie reset gpio\n");
-+ return ret;
-+ }
-+
-+ qcom_pcie->iface_clk = devm_clk_get(&pdev->dev, "iface");
-+ if (IS_ERR(qcom_pcie->iface_clk)) {
-+ dev_err(&pdev->dev, "Failed to get pcie iface clock\n");
-+ return PTR_ERR(qcom_pcie->iface_clk);
-+ }
-+
-+ qcom_pcie->phy_clk = devm_clk_get(&pdev->dev, "phy");
-+ if (IS_ERR(qcom_pcie->phy_clk)) {
-+ dev_err(&pdev->dev, "Failed to get pcie phy clock\n");
-+ return PTR_ERR(qcom_pcie->phy_clk);
-+ }
-+
-+ qcom_pcie->bus_clk = devm_clk_get(&pdev->dev, "core");
-+ if (IS_ERR(qcom_pcie->bus_clk)) {
-+ dev_err(&pdev->dev, "Failed to get pcie core clock\n");
-+ return PTR_ERR(qcom_pcie->bus_clk);
-+ }
-+
-+ qcom_pcie->axi_reset = devm_reset_control_get(&pdev->dev, "axi");
-+ if (IS_ERR(qcom_pcie->axi_reset)) {
-+ dev_err(&pdev->dev, "Failed to get axi reset\n");
-+ return PTR_ERR(qcom_pcie->axi_reset);
-+ }
-+
-+ qcom_pcie->ahb_reset = devm_reset_control_get(&pdev->dev, "ahb");
-+ if (IS_ERR(qcom_pcie->ahb_reset)) {
-+ dev_err(&pdev->dev, "Failed to get ahb reset\n");
-+ return PTR_ERR(qcom_pcie->ahb_reset);
-+ }
-+
-+ qcom_pcie->por_reset = devm_reset_control_get(&pdev->dev, "por");
-+ if (IS_ERR(qcom_pcie->por_reset)) {
-+ dev_err(&pdev->dev, "Failed to get por reset\n");
-+ return PTR_ERR(qcom_pcie->por_reset);
-+ }
-+
-+ qcom_pcie->pci_reset = devm_reset_control_get(&pdev->dev, "pci");
-+ if (IS_ERR(qcom_pcie->pci_reset)) {
-+ dev_err(&pdev->dev, "Failed to get pci reset\n");
-+ return PTR_ERR(qcom_pcie->pci_reset);
-+ }
-+
-+ qcom_pcie->phy_reset = devm_reset_control_get(&pdev->dev, "phy");
-+ if (IS_ERR(qcom_pcie->phy_reset)) {
-+ dev_err(&pdev->dev, "Failed to get phy reset\n");
-+ return PTR_ERR(qcom_pcie->phy_reset);
-+ }
-+
-+ for (i = 0; i < 4; i++) {
-+ qcom_pcie->irq_int[i] = platform_get_irq(pdev, i+1);
-+ if (qcom_pcie->irq_int[i] < 0) {
-+ dev_err(&pdev->dev, "failed to get irq resource\n");
-+ return qcom_pcie->irq_int[i];
-+ }
-+ }
-+
-+ gpio_set_value(qcom_pcie->reset_gpio, 0);
-+ usleep_range(10000, 15000);
-+
-+ /* assert PCIe PARF reset while powering the core */
-+ reset_control_assert(qcom_pcie->ahb_reset);
-+
-+ /* enable clocks */
-+ ret = clk_prepare_enable(qcom_pcie->iface_clk);
-+ if (ret)
-+ return ret;
-+ ret = clk_prepare_enable(qcom_pcie->phy_clk);
-+ if (ret)
-+ return ret;
-+ ret = clk_prepare_enable(qcom_pcie->bus_clk);
-+ if (ret)
-+ return ret;
-+
-+ /*
-+ * de-assert PCIe PARF reset;
-+ * wait 1us before accessing PARF registers
-+ */
-+ reset_control_deassert(qcom_pcie->ahb_reset);
-+ udelay(1);
-+
-+ /* enable PCIe clocks and resets */
-+ msm_pcie_write_mask(qcom_pcie->parf_base + PCIE20_PARF_PHY_CTRL, BIT(0), 0);
-+
-+ /* Set Tx Termination Offset */
-+ val = qcom_parf_readl_relaxed(qcom_pcie, PCIE20_PARF_PHY_CTRL);
-+ val |= PCIE20_PARF_PHY_CTRL_PHY_TX0_TERM_OFFST(7);
-+ qcom_parf_writel_relaxed(qcom_pcie, val, PCIE20_PARF_PHY_CTRL);
-+
-+ /* PARF programming */
-+ qcom_parf_writel_relaxed(qcom_pcie, PCIE20_PARF_PCS_DEEMPH_TX_DEEMPH_GEN1(0x18) |
-+ PCIE20_PARF_PCS_DEEMPH_TX_DEEMPH_GEN2_3_5DB(0x18) |
-+ PCIE20_PARF_PCS_DEEMPH_TX_DEEMPH_GEN2_6DB(0x22),
-+ PCIE20_PARF_PCS_DEEMPH);
-+ qcom_parf_writel_relaxed(qcom_pcie, PCIE20_PARF_PCS_SWING_TX_SWING_FULL(0x78) |
-+ PCIE20_PARF_PCS_SWING_TX_SWING_LOW(0x78),
-+ PCIE20_PARF_PCS_SWING);
-+ qcom_parf_writel_relaxed(qcom_pcie, (4<<24), PCIE20_PARF_CONFIG_BITS);
-+ /* ensure that hardware registers the PARF configuration */
-+ wmb();
-+
-+ /* enable reference clock */
-+ msm_pcie_write_mask(qcom_pcie->parf_base + PCIE20_PARF_PHY_REFCLK, BIT(12), BIT(16));
-+
-+ /* ensure that access is enabled before proceeding */
-+ wmb();
-+
-+ /* de-assert PICe PHY, Core, POR and AXI clk domain resets */
-+ reset_control_deassert(qcom_pcie->phy_reset);
-+ reset_control_deassert(qcom_pcie->pci_reset);
-+ reset_control_deassert(qcom_pcie->por_reset);
-+ reset_control_deassert(qcom_pcie->axi_reset);
-+
-+ /* wait 150ms for clock acquisition */
-+ usleep_range(10000, 15000);
-+
-+ /* de-assert PCIe reset link to bring EP out of reset */
-+ gpio_set_value(qcom_pcie->reset_gpio, 1 - 0);
-+ usleep_range(10000, 15000);
-+
-+ /* enable link training */
-+ val = qcom_elbi_readl_relaxed(qcom_pcie, PCIE20_ELBI_SYS_CTRL);
-+ val |= PCIE20_ELBI_SYS_CTRL_LTSSM_EN;
-+ qcom_elbi_writel_relaxed(qcom_pcie, val, PCIE20_ELBI_SYS_CTRL);
-+ wmb();
-+
-+ /* poll for link to come up for upto 100ms */
-+ ret = readl_poll_timeout(
-+ (qcom_pcie->dwc_base + PCIE20_CAP_LINKCTRLSTATUS),
-+ val, (val & BIT(29)), 10000, 100000);
-+
-+ printk("link initialized %d\n", ret);
-+
-+ qcom_pcie_config_controller(qcom_pcie);
-+
-+ platform_set_drvdata(pdev, qcom_pcie);
-+
-+ spin_lock_irqsave(&qcom_hw_pci_lock, flags);
-+ qcom_hw_pci[nr_controllers].private_data = (void **)&qcom_pcie;
-+ hw = &qcom_hw_pci[nr_controllers];
-+ nr_controllers++;
-+ spin_unlock_irqrestore(&qcom_hw_pci_lock, flags);
-+
-+ pci_common_init(hw);
-+
-+ return 0;
-+}
-+
-+static int __exit qcom_pcie_remove(struct platform_device *pdev)
-+{
-+ struct qcom_pcie *qcom_pcie = platform_get_drvdata(pdev);
-+
-+ return 0;
-+}
-+
-+static struct of_device_id qcom_pcie_match[] = {
-+ { .compatible = "qcom,pcie-ipq8064", },
-+ {}
-+};
-+
-+static struct platform_driver qcom_pcie_driver = {
-+ .probe = qcom_pcie_probe,
-+ .remove = qcom_pcie_remove,
-+ .driver = {
-+ .name = "qcom_pcie",
-+ .owner = THIS_MODULE,
-+ .of_match_table = qcom_pcie_match,
-+ },
-+};
-+
-+static int qcom_pcie_init(void)
-+{
-+ return platform_driver_register(&qcom_pcie_driver);
-+}
-+subsys_initcall(qcom_pcie_init);
-+
-+/* RC do not represent the right class; set it to PCI_CLASS_BRIDGE_PCI */
-+static void msm_pcie_fixup_early(struct pci_dev *dev)
-+{
-+ if (dev->hdr_type == 1)
-+ dev->class = (dev->class & 0xff) | (PCI_CLASS_BRIDGE_PCI << 8);
-+}
-+DECLARE_PCI_FIXUP_EARLY(PCIE_VENDOR_ID_RCP, PCIE_DEVICE_ID_RCP, msm_pcie_fixup_early);