16e0832faSShawn Lin // SPDX-License-Identifier: GPL-2.0
26e0832faSShawn Lin /*
36e0832faSShawn Lin  * Qualcomm PCIe root complex driver
46e0832faSShawn Lin  *
56e0832faSShawn Lin  * Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
66e0832faSShawn Lin  * Copyright 2015 Linaro Limited.
76e0832faSShawn Lin  *
86e0832faSShawn Lin  * Author: Stanimir Varbanov <svarbanov@mm-sol.com>
96e0832faSShawn Lin  */
106e0832faSShawn Lin 
116e0832faSShawn Lin #include <linux/clk.h>
124c939882SManivannan Sadhasivam #include <linux/crc8.h>
136e0832faSShawn Lin #include <linux/delay.h>
146e0832faSShawn Lin #include <linux/gpio/consumer.h>
156e0832faSShawn Lin #include <linux/interrupt.h>
166e0832faSShawn Lin #include <linux/io.h>
176e0832faSShawn Lin #include <linux/iopoll.h>
186e0832faSShawn Lin #include <linux/kernel.h>
196e0832faSShawn Lin #include <linux/init.h>
206e0832faSShawn Lin #include <linux/of_device.h>
216e0832faSShawn Lin #include <linux/of_gpio.h>
226e0832faSShawn Lin #include <linux/pci.h>
236e0832faSShawn Lin #include <linux/pm_runtime.h>
246e0832faSShawn Lin #include <linux/platform_device.h>
256e0832faSShawn Lin #include <linux/phy/phy.h>
266e0832faSShawn Lin #include <linux/regulator/consumer.h>
276e0832faSShawn Lin #include <linux/reset.h>
286e0832faSShawn Lin #include <linux/slab.h>
296e0832faSShawn Lin #include <linux/types.h>
306e0832faSShawn Lin 
3151ed2c2bSSham Muthayyan #include "../../pci.h"
326e0832faSShawn Lin #include "pcie-designware.h"
336e0832faSShawn Lin 
346e0832faSShawn Lin #define PCIE20_PARF_SYS_CTRL			0x00
356e0832faSShawn Lin #define MST_WAKEUP_EN				BIT(13)
366e0832faSShawn Lin #define SLV_WAKEUP_EN				BIT(12)
376e0832faSShawn Lin #define MSTR_ACLK_CGC_DIS			BIT(10)
386e0832faSShawn Lin #define SLV_ACLK_CGC_DIS			BIT(9)
396e0832faSShawn Lin #define CORE_CLK_CGC_DIS			BIT(6)
406e0832faSShawn Lin #define AUX_PWR_DET				BIT(4)
416e0832faSShawn Lin #define L23_CLK_RMV_DIS				BIT(2)
426e0832faSShawn Lin #define L1_CLK_RMV_DIS				BIT(1)
436e0832faSShawn Lin 
446e0832faSShawn Lin #define PCIE20_PARF_PHY_CTRL			0x40
45de3c4bf6SAnsuel Smith #define PHY_CTRL_PHY_TX0_TERM_OFFSET_MASK	GENMASK(20, 16)
46de3c4bf6SAnsuel Smith #define PHY_CTRL_PHY_TX0_TERM_OFFSET(x)		((x) << 16)
47de3c4bf6SAnsuel Smith 
486e0832faSShawn Lin #define PCIE20_PARF_PHY_REFCLK			0x4C
49de3c4bf6SAnsuel Smith #define PHY_REFCLK_SSP_EN			BIT(16)
50de3c4bf6SAnsuel Smith #define PHY_REFCLK_USE_PAD			BIT(12)
51de3c4bf6SAnsuel Smith 
526e0832faSShawn Lin #define PCIE20_PARF_DBI_BASE_ADDR		0x168
536e0832faSShawn Lin #define PCIE20_PARF_SLV_ADDR_SPACE_SIZE		0x16C
546e0832faSShawn Lin #define PCIE20_PARF_MHI_CLOCK_RESET_CTRL	0x174
556e0832faSShawn Lin #define PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT	0x178
566e0832faSShawn Lin #define PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT_V2	0x1A8
576e0832faSShawn Lin #define PCIE20_PARF_LTSSM			0x1B0
586e0832faSShawn Lin #define PCIE20_PARF_SID_OFFSET			0x234
596e0832faSShawn Lin #define PCIE20_PARF_BDF_TRANSLATE_CFG		0x24C
60ed8cc3b1SBjorn Andersson #define PCIE20_PARF_DEVICE_TYPE			0x1000
614c939882SManivannan Sadhasivam #define PCIE20_PARF_BDF_TO_SID_TABLE_N		0x2000
626e0832faSShawn Lin 
636e0832faSShawn Lin #define PCIE20_ELBI_SYS_CTRL			0x04
646e0832faSShawn Lin #define PCIE20_ELBI_SYS_CTRL_LT_ENABLE		BIT(0)
656e0832faSShawn Lin 
666e0832faSShawn Lin #define PCIE20_AXI_MSTR_RESP_COMP_CTRL0		0x818
676e0832faSShawn Lin #define CFG_REMOTE_RD_REQ_BRIDGE_SIZE_2K	0x4
686e0832faSShawn Lin #define CFG_REMOTE_RD_REQ_BRIDGE_SIZE_4K	0x5
696e0832faSShawn Lin #define PCIE20_AXI_MSTR_RESP_COMP_CTRL1		0x81c
706e0832faSShawn Lin #define CFG_BRIDGE_SB_INIT			BIT(0)
716e0832faSShawn Lin 
726e0832faSShawn Lin #define PCIE_CAP_LINK1_VAL			0x2FD7F
736e0832faSShawn Lin 
746e0832faSShawn Lin #define PCIE20_PARF_Q2A_FLUSH			0x1AC
756e0832faSShawn Lin 
766e0832faSShawn Lin #define PCIE20_MISC_CONTROL_1_REG		0x8BC
776e0832faSShawn Lin #define DBI_RO_WR_EN				1
786e0832faSShawn Lin 
796e0832faSShawn Lin #define PERST_DELAY_US				1000
805149901eSAnsuel Smith /* PARF registers */
815149901eSAnsuel Smith #define PCIE20_PARF_PCS_DEEMPH			0x34
825149901eSAnsuel Smith #define PCS_DEEMPH_TX_DEEMPH_GEN1(x)		((x) << 16)
835149901eSAnsuel Smith #define PCS_DEEMPH_TX_DEEMPH_GEN2_3_5DB(x)	((x) << 8)
845149901eSAnsuel Smith #define PCS_DEEMPH_TX_DEEMPH_GEN2_6DB(x)	((x) << 0)
855149901eSAnsuel Smith 
865149901eSAnsuel Smith #define PCIE20_PARF_PCS_SWING			0x38
875149901eSAnsuel Smith #define PCS_SWING_TX_SWING_FULL(x)		((x) << 8)
885149901eSAnsuel Smith #define PCS_SWING_TX_SWING_LOW(x)		((x) << 0)
895149901eSAnsuel Smith 
905149901eSAnsuel Smith #define PCIE20_PARF_CONFIG_BITS		0x50
915149901eSAnsuel Smith #define PHY_RX0_EQ(x)				((x) << 24)
926e0832faSShawn Lin 
936e0832faSShawn Lin #define PCIE20_v3_PARF_SLV_ADDR_SPACE_SIZE	0x358
946e0832faSShawn Lin #define SLV_ADDR_SPACE_SZ			0x10000000
956e0832faSShawn Lin 
9651ed2c2bSSham Muthayyan #define PCIE20_LNK_CONTROL2_LINK_STATUS2	0xa0
9751ed2c2bSSham Muthayyan 
98ed8cc3b1SBjorn Andersson #define DEVICE_TYPE_RC				0x4
99ed8cc3b1SBjorn Andersson 
1006e0832faSShawn Lin #define QCOM_PCIE_2_1_0_MAX_SUPPLY	3
1016a114526SAnsuel Smith #define QCOM_PCIE_2_1_0_MAX_CLOCKS	5
1024c939882SManivannan Sadhasivam 
1034c939882SManivannan Sadhasivam #define QCOM_PCIE_CRC8_POLYNOMIAL (BIT(2) | BIT(1) | BIT(0))
1044c939882SManivannan Sadhasivam 
1056e0832faSShawn Lin struct qcom_pcie_resources_2_1_0 {
1066a114526SAnsuel Smith 	struct clk_bulk_data clks[QCOM_PCIE_2_1_0_MAX_CLOCKS];
1076e0832faSShawn Lin 	struct reset_control *pci_reset;
1086e0832faSShawn Lin 	struct reset_control *axi_reset;
1096e0832faSShawn Lin 	struct reset_control *ahb_reset;
1106e0832faSShawn Lin 	struct reset_control *por_reset;
1116e0832faSShawn Lin 	struct reset_control *phy_reset;
112ee367e2cSAnsuel Smith 	struct reset_control *ext_reset;
1136e0832faSShawn Lin 	struct regulator_bulk_data supplies[QCOM_PCIE_2_1_0_MAX_SUPPLY];
1146e0832faSShawn Lin };
1156e0832faSShawn Lin 
1166e0832faSShawn Lin struct qcom_pcie_resources_1_0_0 {
1176e0832faSShawn Lin 	struct clk *iface;
1186e0832faSShawn Lin 	struct clk *aux;
1196e0832faSShawn Lin 	struct clk *master_bus;
1206e0832faSShawn Lin 	struct clk *slave_bus;
1216e0832faSShawn Lin 	struct reset_control *core;
1226e0832faSShawn Lin 	struct regulator *vdda;
1236e0832faSShawn Lin };
1246e0832faSShawn Lin 
1256e0832faSShawn Lin #define QCOM_PCIE_2_3_2_MAX_SUPPLY	2
1266e0832faSShawn Lin struct qcom_pcie_resources_2_3_2 {
1276e0832faSShawn Lin 	struct clk *aux_clk;
1286e0832faSShawn Lin 	struct clk *master_clk;
1296e0832faSShawn Lin 	struct clk *slave_clk;
1306e0832faSShawn Lin 	struct clk *cfg_clk;
1316e0832faSShawn Lin 	struct regulator_bulk_data supplies[QCOM_PCIE_2_3_2_MAX_SUPPLY];
1326e0832faSShawn Lin };
1336e0832faSShawn Lin 
13467021ae0SBjorn Andersson #define QCOM_PCIE_2_4_0_MAX_CLOCKS	4
1356e0832faSShawn Lin struct qcom_pcie_resources_2_4_0 {
1365aa18097SBjorn Andersson 	struct clk_bulk_data clks[QCOM_PCIE_2_4_0_MAX_CLOCKS];
1375aa18097SBjorn Andersson 	int num_clks;
1386e0832faSShawn Lin 	struct reset_control *axi_m_reset;
1396e0832faSShawn Lin 	struct reset_control *axi_s_reset;
1406e0832faSShawn Lin 	struct reset_control *pipe_reset;
1416e0832faSShawn Lin 	struct reset_control *axi_m_vmid_reset;
1426e0832faSShawn Lin 	struct reset_control *axi_s_xpu_reset;
1436e0832faSShawn Lin 	struct reset_control *parf_reset;
1446e0832faSShawn Lin 	struct reset_control *phy_reset;
1456e0832faSShawn Lin 	struct reset_control *axi_m_sticky_reset;
1466e0832faSShawn Lin 	struct reset_control *pipe_sticky_reset;
1476e0832faSShawn Lin 	struct reset_control *pwr_reset;
1486e0832faSShawn Lin 	struct reset_control *ahb_reset;
1496e0832faSShawn Lin 	struct reset_control *phy_ahb_reset;
1506e0832faSShawn Lin };
1516e0832faSShawn Lin 
1526e0832faSShawn Lin struct qcom_pcie_resources_2_3_3 {
1536e0832faSShawn Lin 	struct clk *iface;
1546e0832faSShawn Lin 	struct clk *axi_m_clk;
1556e0832faSShawn Lin 	struct clk *axi_s_clk;
1566e0832faSShawn Lin 	struct clk *ahb_clk;
1576e0832faSShawn Lin 	struct clk *aux_clk;
1586e0832faSShawn Lin 	struct reset_control *rst[7];
1596e0832faSShawn Lin };
1606e0832faSShawn Lin 
1617081556fSDmitry Baryshkov /* 6 clocks typically, 7 for sm8250 */
162ed8cc3b1SBjorn Andersson struct qcom_pcie_resources_2_7_0 {
1631c5aa037SDmitry Baryshkov 	struct clk_bulk_data clks[9];
1647081556fSDmitry Baryshkov 	int num_clks;
165ed8cc3b1SBjorn Andersson 	struct regulator_bulk_data supplies[2];
166ed8cc3b1SBjorn Andersson 	struct reset_control *pci_reset;
167aa9c0df9SPrasad Malisetty 	struct clk *pipe_clk_src;
168aa9c0df9SPrasad Malisetty 	struct clk *phy_pipe_clk;
169aa9c0df9SPrasad Malisetty 	struct clk *ref_clk_src;
170ed8cc3b1SBjorn Andersson };
171ed8cc3b1SBjorn Andersson 
1726e0832faSShawn Lin union qcom_pcie_resources {
1736e0832faSShawn Lin 	struct qcom_pcie_resources_1_0_0 v1_0_0;
1746e0832faSShawn Lin 	struct qcom_pcie_resources_2_1_0 v2_1_0;
1756e0832faSShawn Lin 	struct qcom_pcie_resources_2_3_2 v2_3_2;
1766e0832faSShawn Lin 	struct qcom_pcie_resources_2_3_3 v2_3_3;
1776e0832faSShawn Lin 	struct qcom_pcie_resources_2_4_0 v2_4_0;
178ed8cc3b1SBjorn Andersson 	struct qcom_pcie_resources_2_7_0 v2_7_0;
1796e0832faSShawn Lin };
1806e0832faSShawn Lin 
1816e0832faSShawn Lin struct qcom_pcie;
1826e0832faSShawn Lin 
1836e0832faSShawn Lin struct qcom_pcie_ops {
1846e0832faSShawn Lin 	int (*get_resources)(struct qcom_pcie *pcie);
1856e0832faSShawn Lin 	int (*init)(struct qcom_pcie *pcie);
1866e0832faSShawn Lin 	int (*post_init)(struct qcom_pcie *pcie);
1876e0832faSShawn Lin 	void (*deinit)(struct qcom_pcie *pcie);
1886e0832faSShawn Lin 	void (*post_deinit)(struct qcom_pcie *pcie);
1896e0832faSShawn Lin 	void (*ltssm_enable)(struct qcom_pcie *pcie);
1904c939882SManivannan Sadhasivam 	int (*config_sid)(struct qcom_pcie *pcie);
1916e0832faSShawn Lin };
1926e0832faSShawn Lin 
193b89ff410SPrasad Malisetty struct qcom_pcie_cfg {
194b89ff410SPrasad Malisetty 	const struct qcom_pcie_ops *ops;
195aa9c0df9SPrasad Malisetty 	unsigned int pipe_clk_need_muxing:1;
1961c5aa037SDmitry Baryshkov 	unsigned int has_tbu_clk:1;
1970614f98bSDmitry Baryshkov 	unsigned int has_ddrss_sf_tbu_clk:1;
1981c5aa037SDmitry Baryshkov 	unsigned int has_aggre0_clk:1;
1991c5aa037SDmitry Baryshkov 	unsigned int has_aggre1_clk:1;
200b89ff410SPrasad Malisetty };
201b89ff410SPrasad Malisetty 
2026e0832faSShawn Lin struct qcom_pcie {
2036e0832faSShawn Lin 	struct dw_pcie *pci;
2046e0832faSShawn Lin 	void __iomem *parf;			/* DT parf */
2056e0832faSShawn Lin 	void __iomem *elbi;			/* DT elbi */
2066e0832faSShawn Lin 	union qcom_pcie_resources res;
2076e0832faSShawn Lin 	struct phy *phy;
2086e0832faSShawn Lin 	struct gpio_desc *reset;
209f94c35e0SDmitry Baryshkov 	const struct qcom_pcie_cfg *cfg;
2106e0832faSShawn Lin };
2116e0832faSShawn Lin 
2126e0832faSShawn Lin #define to_qcom_pcie(x)		dev_get_drvdata((x)->dev)
2136e0832faSShawn Lin 
2146e0832faSShawn Lin static void qcom_ep_reset_assert(struct qcom_pcie *pcie)
2156e0832faSShawn Lin {
2166e0832faSShawn Lin 	gpiod_set_value_cansleep(pcie->reset, 1);
2176e0832faSShawn Lin 	usleep_range(PERST_DELAY_US, PERST_DELAY_US + 500);
2186e0832faSShawn Lin }
2196e0832faSShawn Lin 
2206e0832faSShawn Lin static void qcom_ep_reset_deassert(struct qcom_pcie *pcie)
2216e0832faSShawn Lin {
22264adde31SNiklas Cassel 	/* Ensure that PERST has been asserted for at least 100 ms */
22364adde31SNiklas Cassel 	msleep(100);
2246e0832faSShawn Lin 	gpiod_set_value_cansleep(pcie->reset, 0);
2256e0832faSShawn Lin 	usleep_range(PERST_DELAY_US, PERST_DELAY_US + 500);
2266e0832faSShawn Lin }
2276e0832faSShawn Lin 
228886a9c13SRob Herring static int qcom_pcie_start_link(struct dw_pcie *pci)
2296e0832faSShawn Lin {
230886a9c13SRob Herring 	struct qcom_pcie *pcie = to_qcom_pcie(pci);
2316e0832faSShawn Lin 
2326e0832faSShawn Lin 	/* Enable Link Training state machine */
233f94c35e0SDmitry Baryshkov 	if (pcie->cfg->ops->ltssm_enable)
234f94c35e0SDmitry Baryshkov 		pcie->cfg->ops->ltssm_enable(pcie);
2356e0832faSShawn Lin 
236886a9c13SRob Herring 	return 0;
2376e0832faSShawn Lin }
2386e0832faSShawn Lin 
2396e0832faSShawn Lin static void qcom_pcie_2_1_0_ltssm_enable(struct qcom_pcie *pcie)
2406e0832faSShawn Lin {
2416e0832faSShawn Lin 	u32 val;
2426e0832faSShawn Lin 
2436e0832faSShawn Lin 	/* enable link training */
2446e0832faSShawn Lin 	val = readl(pcie->elbi + PCIE20_ELBI_SYS_CTRL);
2456e0832faSShawn Lin 	val |= PCIE20_ELBI_SYS_CTRL_LT_ENABLE;
2466e0832faSShawn Lin 	writel(val, pcie->elbi + PCIE20_ELBI_SYS_CTRL);
2476e0832faSShawn Lin }
2486e0832faSShawn Lin 
2496e0832faSShawn Lin static int qcom_pcie_get_resources_2_1_0(struct qcom_pcie *pcie)
2506e0832faSShawn Lin {
2516e0832faSShawn Lin 	struct qcom_pcie_resources_2_1_0 *res = &pcie->res.v2_1_0;
2526e0832faSShawn Lin 	struct dw_pcie *pci = pcie->pci;
2536e0832faSShawn Lin 	struct device *dev = pci->dev;
2546e0832faSShawn Lin 	int ret;
2556e0832faSShawn Lin 
2566e0832faSShawn Lin 	res->supplies[0].supply = "vdda";
2576e0832faSShawn Lin 	res->supplies[1].supply = "vdda_phy";
2586e0832faSShawn Lin 	res->supplies[2].supply = "vdda_refclk";
2596e0832faSShawn Lin 	ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(res->supplies),
2606e0832faSShawn Lin 				      res->supplies);
2616e0832faSShawn Lin 	if (ret)
2626e0832faSShawn Lin 		return ret;
2636e0832faSShawn Lin 
2646a114526SAnsuel Smith 	res->clks[0].id = "iface";
2656a114526SAnsuel Smith 	res->clks[1].id = "core";
2666a114526SAnsuel Smith 	res->clks[2].id = "phy";
2676a114526SAnsuel Smith 	res->clks[3].id = "aux";
2686a114526SAnsuel Smith 	res->clks[4].id = "ref";
2696e0832faSShawn Lin 
2706a114526SAnsuel Smith 	/* iface, core, phy are required */
2716a114526SAnsuel Smith 	ret = devm_clk_bulk_get(dev, 3, res->clks);
2726a114526SAnsuel Smith 	if (ret < 0)
2736a114526SAnsuel Smith 		return ret;
2746e0832faSShawn Lin 
2756a114526SAnsuel Smith 	/* aux, ref are optional */
2766a114526SAnsuel Smith 	ret = devm_clk_bulk_get_optional(dev, 2, res->clks + 3);
2776a114526SAnsuel Smith 	if (ret < 0)
2786a114526SAnsuel Smith 		return ret;
2798b6f0330SAnsuel Smith 
2806e0832faSShawn Lin 	res->pci_reset = devm_reset_control_get_exclusive(dev, "pci");
2816e0832faSShawn Lin 	if (IS_ERR(res->pci_reset))
2826e0832faSShawn Lin 		return PTR_ERR(res->pci_reset);
2836e0832faSShawn Lin 
2846e0832faSShawn Lin 	res->axi_reset = devm_reset_control_get_exclusive(dev, "axi");
2856e0832faSShawn Lin 	if (IS_ERR(res->axi_reset))
2866e0832faSShawn Lin 		return PTR_ERR(res->axi_reset);
2876e0832faSShawn Lin 
2886e0832faSShawn Lin 	res->ahb_reset = devm_reset_control_get_exclusive(dev, "ahb");
2896e0832faSShawn Lin 	if (IS_ERR(res->ahb_reset))
2906e0832faSShawn Lin 		return PTR_ERR(res->ahb_reset);
2916e0832faSShawn Lin 
2926e0832faSShawn Lin 	res->por_reset = devm_reset_control_get_exclusive(dev, "por");
2936e0832faSShawn Lin 	if (IS_ERR(res->por_reset))
2946e0832faSShawn Lin 		return PTR_ERR(res->por_reset);
2956e0832faSShawn Lin 
296ee367e2cSAnsuel Smith 	res->ext_reset = devm_reset_control_get_optional_exclusive(dev, "ext");
297ee367e2cSAnsuel Smith 	if (IS_ERR(res->ext_reset))
298ee367e2cSAnsuel Smith 		return PTR_ERR(res->ext_reset);
299ee367e2cSAnsuel Smith 
3006e0832faSShawn Lin 	res->phy_reset = devm_reset_control_get_exclusive(dev, "phy");
3016e0832faSShawn Lin 	return PTR_ERR_OR_ZERO(res->phy_reset);
3026e0832faSShawn Lin }
3036e0832faSShawn Lin 
3046e0832faSShawn Lin static void qcom_pcie_deinit_2_1_0(struct qcom_pcie *pcie)
3056e0832faSShawn Lin {
3066e0832faSShawn Lin 	struct qcom_pcie_resources_2_1_0 *res = &pcie->res.v2_1_0;
3076e0832faSShawn Lin 
3086a114526SAnsuel Smith 	clk_bulk_disable_unprepare(ARRAY_SIZE(res->clks), res->clks);
3096e0832faSShawn Lin 	reset_control_assert(res->pci_reset);
3106e0832faSShawn Lin 	reset_control_assert(res->axi_reset);
3116e0832faSShawn Lin 	reset_control_assert(res->ahb_reset);
3126e0832faSShawn Lin 	reset_control_assert(res->por_reset);
313ee367e2cSAnsuel Smith 	reset_control_assert(res->ext_reset);
314dd58318cSAbhishek Sahu 	reset_control_assert(res->phy_reset);
315d3d4d028SAnsuel Smith 
316d3d4d028SAnsuel Smith 	writel(1, pcie->parf + PCIE20_PARF_PHY_CTRL);
317d3d4d028SAnsuel Smith 
3186e0832faSShawn Lin 	regulator_bulk_disable(ARRAY_SIZE(res->supplies), res->supplies);
3196e0832faSShawn Lin }
3206e0832faSShawn Lin 
3216e0832faSShawn Lin static int qcom_pcie_init_2_1_0(struct qcom_pcie *pcie)
3226e0832faSShawn Lin {
3236e0832faSShawn Lin 	struct qcom_pcie_resources_2_1_0 *res = &pcie->res.v2_1_0;
3246e0832faSShawn Lin 	struct dw_pcie *pci = pcie->pci;
3256e0832faSShawn Lin 	struct device *dev = pci->dev;
3266e0832faSShawn Lin 	int ret;
3276e0832faSShawn Lin 
328d3d4d028SAnsuel Smith 	/* reset the PCIe interface as uboot can leave it undefined state */
329d3d4d028SAnsuel Smith 	reset_control_assert(res->pci_reset);
330d3d4d028SAnsuel Smith 	reset_control_assert(res->axi_reset);
331d3d4d028SAnsuel Smith 	reset_control_assert(res->ahb_reset);
332d3d4d028SAnsuel Smith 	reset_control_assert(res->por_reset);
333d3d4d028SAnsuel Smith 	reset_control_assert(res->ext_reset);
334d3d4d028SAnsuel Smith 	reset_control_assert(res->phy_reset);
335d3d4d028SAnsuel Smith 
3366e0832faSShawn Lin 	ret = regulator_bulk_enable(ARRAY_SIZE(res->supplies), res->supplies);
3376e0832faSShawn Lin 	if (ret < 0) {
3386e0832faSShawn Lin 		dev_err(dev, "cannot enable regulators\n");
3396e0832faSShawn Lin 		return ret;
3406e0832faSShawn Lin 	}
3416e0832faSShawn Lin 
3426e0832faSShawn Lin 	ret = reset_control_deassert(res->ahb_reset);
3436e0832faSShawn Lin 	if (ret) {
3446e0832faSShawn Lin 		dev_err(dev, "cannot deassert ahb reset\n");
3456e0832faSShawn Lin 		goto err_deassert_ahb;
3466e0832faSShawn Lin 	}
3476e0832faSShawn Lin 
348ee367e2cSAnsuel Smith 	ret = reset_control_deassert(res->ext_reset);
349ee367e2cSAnsuel Smith 	if (ret) {
350ee367e2cSAnsuel Smith 		dev_err(dev, "cannot deassert ext reset\n");
3516a114526SAnsuel Smith 		goto err_deassert_ext;
352ee367e2cSAnsuel Smith 	}
353ee367e2cSAnsuel Smith 
3546a114526SAnsuel Smith 	ret = reset_control_deassert(res->phy_reset);
3556a114526SAnsuel Smith 	if (ret) {
3566a114526SAnsuel Smith 		dev_err(dev, "cannot deassert phy reset\n");
3576a114526SAnsuel Smith 		goto err_deassert_phy;
3586a114526SAnsuel Smith 	}
3596a114526SAnsuel Smith 
3606a114526SAnsuel Smith 	ret = reset_control_deassert(res->pci_reset);
3616a114526SAnsuel Smith 	if (ret) {
3626a114526SAnsuel Smith 		dev_err(dev, "cannot deassert pci reset\n");
3636a114526SAnsuel Smith 		goto err_deassert_pci;
3646a114526SAnsuel Smith 	}
3656a114526SAnsuel Smith 
3666a114526SAnsuel Smith 	ret = reset_control_deassert(res->por_reset);
3676a114526SAnsuel Smith 	if (ret) {
3686a114526SAnsuel Smith 		dev_err(dev, "cannot deassert por reset\n");
3696a114526SAnsuel Smith 		goto err_deassert_por;
3706a114526SAnsuel Smith 	}
3716a114526SAnsuel Smith 
3726a114526SAnsuel Smith 	ret = reset_control_deassert(res->axi_reset);
3736a114526SAnsuel Smith 	if (ret) {
3746a114526SAnsuel Smith 		dev_err(dev, "cannot deassert axi reset\n");
3756a114526SAnsuel Smith 		goto err_deassert_axi;
3766a114526SAnsuel Smith 	}
3776a114526SAnsuel Smith 
37836d9018dSRobert Marko 	return 0;
37936d9018dSRobert Marko 
38036d9018dSRobert Marko err_deassert_axi:
38136d9018dSRobert Marko 	reset_control_assert(res->por_reset);
38236d9018dSRobert Marko err_deassert_por:
38336d9018dSRobert Marko 	reset_control_assert(res->pci_reset);
38436d9018dSRobert Marko err_deassert_pci:
38536d9018dSRobert Marko 	reset_control_assert(res->phy_reset);
38636d9018dSRobert Marko err_deassert_phy:
38736d9018dSRobert Marko 	reset_control_assert(res->ext_reset);
38836d9018dSRobert Marko err_deassert_ext:
38936d9018dSRobert Marko 	reset_control_assert(res->ahb_reset);
39036d9018dSRobert Marko err_deassert_ahb:
39136d9018dSRobert Marko 	regulator_bulk_disable(ARRAY_SIZE(res->supplies), res->supplies);
39236d9018dSRobert Marko 
39336d9018dSRobert Marko 	return ret;
39436d9018dSRobert Marko }
39536d9018dSRobert Marko 
39636d9018dSRobert Marko static int qcom_pcie_post_init_2_1_0(struct qcom_pcie *pcie)
39736d9018dSRobert Marko {
39836d9018dSRobert Marko 	struct qcom_pcie_resources_2_1_0 *res = &pcie->res.v2_1_0;
39936d9018dSRobert Marko 	struct dw_pcie *pci = pcie->pci;
40036d9018dSRobert Marko 	struct device *dev = pci->dev;
40136d9018dSRobert Marko 	struct device_node *node = dev->of_node;
40236d9018dSRobert Marko 	u32 val;
40336d9018dSRobert Marko 	int ret;
40436d9018dSRobert Marko 
4056e0832faSShawn Lin 	/* enable PCIe clocks and resets */
4066e0832faSShawn Lin 	val = readl(pcie->parf + PCIE20_PARF_PHY_CTRL);
4076e0832faSShawn Lin 	val &= ~BIT(0);
4086e0832faSShawn Lin 	writel(val, pcie->parf + PCIE20_PARF_PHY_CTRL);
4096e0832faSShawn Lin 
41038f897aeSChristian Marangi 	ret = clk_bulk_prepare_enable(ARRAY_SIZE(res->clks), res->clks);
41138f897aeSChristian Marangi 	if (ret)
41236d9018dSRobert Marko 		return ret;
41338f897aeSChristian Marangi 
4148df093feSAnsuel Smith 	if (of_device_is_compatible(node, "qcom,pcie-ipq8064") ||
4158df093feSAnsuel Smith 	    of_device_is_compatible(node, "qcom,pcie-ipq8064-v2")) {
4165149901eSAnsuel Smith 		writel(PCS_DEEMPH_TX_DEEMPH_GEN1(24) |
4175149901eSAnsuel Smith 			       PCS_DEEMPH_TX_DEEMPH_GEN2_3_5DB(24) |
4185149901eSAnsuel Smith 			       PCS_DEEMPH_TX_DEEMPH_GEN2_6DB(34),
4195149901eSAnsuel Smith 		       pcie->parf + PCIE20_PARF_PCS_DEEMPH);
4205149901eSAnsuel Smith 		writel(PCS_SWING_TX_SWING_FULL(120) |
4215149901eSAnsuel Smith 			       PCS_SWING_TX_SWING_LOW(120),
4225149901eSAnsuel Smith 		       pcie->parf + PCIE20_PARF_PCS_SWING);
4235149901eSAnsuel Smith 		writel(PHY_RX0_EQ(4), pcie->parf + PCIE20_PARF_CONFIG_BITS);
4245149901eSAnsuel Smith 	}
4255149901eSAnsuel Smith 
426de3c4bf6SAnsuel Smith 	if (of_device_is_compatible(node, "qcom,pcie-ipq8064")) {
427de3c4bf6SAnsuel Smith 		/* set TX termination offset */
428de3c4bf6SAnsuel Smith 		val = readl(pcie->parf + PCIE20_PARF_PHY_CTRL);
429de3c4bf6SAnsuel Smith 		val &= ~PHY_CTRL_PHY_TX0_TERM_OFFSET_MASK;
430de3c4bf6SAnsuel Smith 		val |= PHY_CTRL_PHY_TX0_TERM_OFFSET(7);
431de3c4bf6SAnsuel Smith 		writel(val, pcie->parf + PCIE20_PARF_PHY_CTRL);
432de3c4bf6SAnsuel Smith 	}
433de3c4bf6SAnsuel Smith 
4346e0832faSShawn Lin 	/* enable external reference clock */
4356e0832faSShawn Lin 	val = readl(pcie->parf + PCIE20_PARF_PHY_REFCLK);
4362cfef197SAnsuel Smith 	/* USE_PAD is required only for ipq806x */
4372cfef197SAnsuel Smith 	if (!of_device_is_compatible(node, "qcom,pcie-apq8064"))
438de3c4bf6SAnsuel Smith 		val &= ~PHY_REFCLK_USE_PAD;
439de3c4bf6SAnsuel Smith 	val |= PHY_REFCLK_SSP_EN;
4406e0832faSShawn Lin 	writel(val, pcie->parf + PCIE20_PARF_PHY_REFCLK);
4416e0832faSShawn Lin 
4426e0832faSShawn Lin 	/* wait for clock acquisition */
4436e0832faSShawn Lin 	usleep_range(1000, 1500);
4446e0832faSShawn Lin 
4456e0832faSShawn Lin 	/* Set the Max TLP size to 2K, instead of using default of 4K */
4466e0832faSShawn Lin 	writel(CFG_REMOTE_RD_REQ_BRIDGE_SIZE_2K,
4476e0832faSShawn Lin 	       pci->dbi_base + PCIE20_AXI_MSTR_RESP_COMP_CTRL0);
4486e0832faSShawn Lin 	writel(CFG_BRIDGE_SB_INIT,
4496e0832faSShawn Lin 	       pci->dbi_base + PCIE20_AXI_MSTR_RESP_COMP_CTRL1);
4506e0832faSShawn Lin 
4516e0832faSShawn Lin 	return 0;
4526e0832faSShawn Lin }
4536e0832faSShawn Lin 
4546e0832faSShawn Lin static int qcom_pcie_get_resources_1_0_0(struct qcom_pcie *pcie)
4556e0832faSShawn Lin {
4566e0832faSShawn Lin 	struct qcom_pcie_resources_1_0_0 *res = &pcie->res.v1_0_0;
4576e0832faSShawn Lin 	struct dw_pcie *pci = pcie->pci;
4586e0832faSShawn Lin 	struct device *dev = pci->dev;
4596e0832faSShawn Lin 
4606e0832faSShawn Lin 	res->vdda = devm_regulator_get(dev, "vdda");
4616e0832faSShawn Lin 	if (IS_ERR(res->vdda))
4626e0832faSShawn Lin 		return PTR_ERR(res->vdda);
4636e0832faSShawn Lin 
4646e0832faSShawn Lin 	res->iface = devm_clk_get(dev, "iface");
4656e0832faSShawn Lin 	if (IS_ERR(res->iface))
4666e0832faSShawn Lin 		return PTR_ERR(res->iface);
4676e0832faSShawn Lin 
4686e0832faSShawn Lin 	res->aux = devm_clk_get(dev, "aux");
4696e0832faSShawn Lin 	if (IS_ERR(res->aux))
4706e0832faSShawn Lin 		return PTR_ERR(res->aux);
4716e0832faSShawn Lin 
4726e0832faSShawn Lin 	res->master_bus = devm_clk_get(dev, "master_bus");
4736e0832faSShawn Lin 	if (IS_ERR(res->master_bus))
4746e0832faSShawn Lin 		return PTR_ERR(res->master_bus);
4756e0832faSShawn Lin 
4766e0832faSShawn Lin 	res->slave_bus = devm_clk_get(dev, "slave_bus");
4776e0832faSShawn Lin 	if (IS_ERR(res->slave_bus))
4786e0832faSShawn Lin 		return PTR_ERR(res->slave_bus);
4796e0832faSShawn Lin 
4806e0832faSShawn Lin 	res->core = devm_reset_control_get_exclusive(dev, "core");
4816e0832faSShawn Lin 	return PTR_ERR_OR_ZERO(res->core);
4826e0832faSShawn Lin }
4836e0832faSShawn Lin 
4846e0832faSShawn Lin static void qcom_pcie_deinit_1_0_0(struct qcom_pcie *pcie)
4856e0832faSShawn Lin {
4866e0832faSShawn Lin 	struct qcom_pcie_resources_1_0_0 *res = &pcie->res.v1_0_0;
4876e0832faSShawn Lin 
4886e0832faSShawn Lin 	reset_control_assert(res->core);
4896e0832faSShawn Lin 	clk_disable_unprepare(res->slave_bus);
4906e0832faSShawn Lin 	clk_disable_unprepare(res->master_bus);
4916e0832faSShawn Lin 	clk_disable_unprepare(res->iface);
4926e0832faSShawn Lin 	clk_disable_unprepare(res->aux);
4936e0832faSShawn Lin 	regulator_disable(res->vdda);
4946e0832faSShawn Lin }
4956e0832faSShawn Lin 
4966e0832faSShawn Lin static int qcom_pcie_init_1_0_0(struct qcom_pcie *pcie)
4976e0832faSShawn Lin {
4986e0832faSShawn Lin 	struct qcom_pcie_resources_1_0_0 *res = &pcie->res.v1_0_0;
4996e0832faSShawn Lin 	struct dw_pcie *pci = pcie->pci;
5006e0832faSShawn Lin 	struct device *dev = pci->dev;
5016e0832faSShawn Lin 	int ret;
5026e0832faSShawn Lin 
5036e0832faSShawn Lin 	ret = reset_control_deassert(res->core);
5046e0832faSShawn Lin 	if (ret) {
5056e0832faSShawn Lin 		dev_err(dev, "cannot deassert core reset\n");
5066e0832faSShawn Lin 		return ret;
5076e0832faSShawn Lin 	}
5086e0832faSShawn Lin 
5096e0832faSShawn Lin 	ret = clk_prepare_enable(res->aux);
5106e0832faSShawn Lin 	if (ret) {
5116e0832faSShawn Lin 		dev_err(dev, "cannot prepare/enable aux clock\n");
5126e0832faSShawn Lin 		goto err_res;
5136e0832faSShawn Lin 	}
5146e0832faSShawn Lin 
5156e0832faSShawn Lin 	ret = clk_prepare_enable(res->iface);
5166e0832faSShawn Lin 	if (ret) {
5176e0832faSShawn Lin 		dev_err(dev, "cannot prepare/enable iface clock\n");
5186e0832faSShawn Lin 		goto err_aux;
5196e0832faSShawn Lin 	}
5206e0832faSShawn Lin 
5216e0832faSShawn Lin 	ret = clk_prepare_enable(res->master_bus);
5226e0832faSShawn Lin 	if (ret) {
5236e0832faSShawn Lin 		dev_err(dev, "cannot prepare/enable master_bus clock\n");
5246e0832faSShawn Lin 		goto err_iface;
5256e0832faSShawn Lin 	}
5266e0832faSShawn Lin 
5276e0832faSShawn Lin 	ret = clk_prepare_enable(res->slave_bus);
5286e0832faSShawn Lin 	if (ret) {
5296e0832faSShawn Lin 		dev_err(dev, "cannot prepare/enable slave_bus clock\n");
5306e0832faSShawn Lin 		goto err_master;
5316e0832faSShawn Lin 	}
5326e0832faSShawn Lin 
5336e0832faSShawn Lin 	ret = regulator_enable(res->vdda);
5346e0832faSShawn Lin 	if (ret) {
5356e0832faSShawn Lin 		dev_err(dev, "cannot enable vdda regulator\n");
5366e0832faSShawn Lin 		goto err_slave;
5376e0832faSShawn Lin 	}
5386e0832faSShawn Lin 
5396e0832faSShawn Lin 	return 0;
5406e0832faSShawn Lin err_slave:
5416e0832faSShawn Lin 	clk_disable_unprepare(res->slave_bus);
5426e0832faSShawn Lin err_master:
5436e0832faSShawn Lin 	clk_disable_unprepare(res->master_bus);
5446e0832faSShawn Lin err_iface:
5456e0832faSShawn Lin 	clk_disable_unprepare(res->iface);
5466e0832faSShawn Lin err_aux:
5476e0832faSShawn Lin 	clk_disable_unprepare(res->aux);
5486e0832faSShawn Lin err_res:
5496e0832faSShawn Lin 	reset_control_assert(res->core);
5506e0832faSShawn Lin 
5516e0832faSShawn Lin 	return ret;
5526e0832faSShawn Lin }
5536e0832faSShawn Lin 
55436d9018dSRobert Marko static int qcom_pcie_post_init_1_0_0(struct qcom_pcie *pcie)
55536d9018dSRobert Marko {
55636d9018dSRobert Marko 	/* change DBI base address */
55736d9018dSRobert Marko 	writel(0, pcie->parf + PCIE20_PARF_DBI_BASE_ADDR);
55836d9018dSRobert Marko 
55936d9018dSRobert Marko 	if (IS_ENABLED(CONFIG_PCI_MSI)) {
56036d9018dSRobert Marko 		u32 val = readl(pcie->parf + PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT);
56136d9018dSRobert Marko 
56236d9018dSRobert Marko 		val |= BIT(31);
56336d9018dSRobert Marko 		writel(val, pcie->parf + PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT);
56436d9018dSRobert Marko 	}
56536d9018dSRobert Marko 
56636d9018dSRobert Marko 	return 0;
56736d9018dSRobert Marko }
56836d9018dSRobert Marko 
5696e0832faSShawn Lin static void qcom_pcie_2_3_2_ltssm_enable(struct qcom_pcie *pcie)
5706e0832faSShawn Lin {
5716e0832faSShawn Lin 	u32 val;
5726e0832faSShawn Lin 
5736e0832faSShawn Lin 	/* enable link training */
5746e0832faSShawn Lin 	val = readl(pcie->parf + PCIE20_PARF_LTSSM);
5756e0832faSShawn Lin 	val |= BIT(8);
5766e0832faSShawn Lin 	writel(val, pcie->parf + PCIE20_PARF_LTSSM);
5776e0832faSShawn Lin }
5786e0832faSShawn Lin 
5796e0832faSShawn Lin static int qcom_pcie_get_resources_2_3_2(struct qcom_pcie *pcie)
5806e0832faSShawn Lin {
5816e0832faSShawn Lin 	struct qcom_pcie_resources_2_3_2 *res = &pcie->res.v2_3_2;
5826e0832faSShawn Lin 	struct dw_pcie *pci = pcie->pci;
5836e0832faSShawn Lin 	struct device *dev = pci->dev;
5846e0832faSShawn Lin 	int ret;
5856e0832faSShawn Lin 
5866e0832faSShawn Lin 	res->supplies[0].supply = "vdda";
5876e0832faSShawn Lin 	res->supplies[1].supply = "vddpe-3v3";
5886e0832faSShawn Lin 	ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(res->supplies),
5896e0832faSShawn Lin 				      res->supplies);
5906e0832faSShawn Lin 	if (ret)
5916e0832faSShawn Lin 		return ret;
5926e0832faSShawn Lin 
5936e0832faSShawn Lin 	res->aux_clk = devm_clk_get(dev, "aux");
5946e0832faSShawn Lin 	if (IS_ERR(res->aux_clk))
5956e0832faSShawn Lin 		return PTR_ERR(res->aux_clk);
5966e0832faSShawn Lin 
5976e0832faSShawn Lin 	res->cfg_clk = devm_clk_get(dev, "cfg");
5986e0832faSShawn Lin 	if (IS_ERR(res->cfg_clk))
5996e0832faSShawn Lin 		return PTR_ERR(res->cfg_clk);
6006e0832faSShawn Lin 
6016e0832faSShawn Lin 	res->master_clk = devm_clk_get(dev, "bus_master");
6026e0832faSShawn Lin 	if (IS_ERR(res->master_clk))
6036e0832faSShawn Lin 		return PTR_ERR(res->master_clk);
6046e0832faSShawn Lin 
6056e0832faSShawn Lin 	res->slave_clk = devm_clk_get(dev, "bus_slave");
6066e0832faSShawn Lin 	if (IS_ERR(res->slave_clk))
6076e0832faSShawn Lin 		return PTR_ERR(res->slave_clk);
6086e0832faSShawn Lin 
609*affac98aSDmitry Baryshkov 	return 0;
6106e0832faSShawn Lin }
6116e0832faSShawn Lin 
6126e0832faSShawn Lin static void qcom_pcie_deinit_2_3_2(struct qcom_pcie *pcie)
6136e0832faSShawn Lin {
6146e0832faSShawn Lin 	struct qcom_pcie_resources_2_3_2 *res = &pcie->res.v2_3_2;
6156e0832faSShawn Lin 
6166e0832faSShawn Lin 	clk_disable_unprepare(res->slave_clk);
6176e0832faSShawn Lin 	clk_disable_unprepare(res->master_clk);
6186e0832faSShawn Lin 	clk_disable_unprepare(res->cfg_clk);
6196e0832faSShawn Lin 	clk_disable_unprepare(res->aux_clk);
6206e0832faSShawn Lin 
6216e0832faSShawn Lin 	regulator_bulk_disable(ARRAY_SIZE(res->supplies), res->supplies);
6226e0832faSShawn Lin }
6236e0832faSShawn Lin 
6246e0832faSShawn Lin static int qcom_pcie_init_2_3_2(struct qcom_pcie *pcie)
6256e0832faSShawn Lin {
6266e0832faSShawn Lin 	struct qcom_pcie_resources_2_3_2 *res = &pcie->res.v2_3_2;
6276e0832faSShawn Lin 	struct dw_pcie *pci = pcie->pci;
6286e0832faSShawn Lin 	struct device *dev = pci->dev;
6296e0832faSShawn Lin 	int ret;
6306e0832faSShawn Lin 
6316e0832faSShawn Lin 	ret = regulator_bulk_enable(ARRAY_SIZE(res->supplies), res->supplies);
6326e0832faSShawn Lin 	if (ret < 0) {
6336e0832faSShawn Lin 		dev_err(dev, "cannot enable regulators\n");
6346e0832faSShawn Lin 		return ret;
6356e0832faSShawn Lin 	}
6366e0832faSShawn Lin 
6376e0832faSShawn Lin 	ret = clk_prepare_enable(res->aux_clk);
6386e0832faSShawn Lin 	if (ret) {
6396e0832faSShawn Lin 		dev_err(dev, "cannot prepare/enable aux clock\n");
6406e0832faSShawn Lin 		goto err_aux_clk;
6416e0832faSShawn Lin 	}
6426e0832faSShawn Lin 
6436e0832faSShawn Lin 	ret = clk_prepare_enable(res->cfg_clk);
6446e0832faSShawn Lin 	if (ret) {
6456e0832faSShawn Lin 		dev_err(dev, "cannot prepare/enable cfg clock\n");
6466e0832faSShawn Lin 		goto err_cfg_clk;
6476e0832faSShawn Lin 	}
6486e0832faSShawn Lin 
6496e0832faSShawn Lin 	ret = clk_prepare_enable(res->master_clk);
6506e0832faSShawn Lin 	if (ret) {
6516e0832faSShawn Lin 		dev_err(dev, "cannot prepare/enable master clock\n");
6526e0832faSShawn Lin 		goto err_master_clk;
6536e0832faSShawn Lin 	}
6546e0832faSShawn Lin 
6556e0832faSShawn Lin 	ret = clk_prepare_enable(res->slave_clk);
6566e0832faSShawn Lin 	if (ret) {
6576e0832faSShawn Lin 		dev_err(dev, "cannot prepare/enable slave clock\n");
6586e0832faSShawn Lin 		goto err_slave_clk;
6596e0832faSShawn Lin 	}
6606e0832faSShawn Lin 
6616e0832faSShawn Lin 	return 0;
6626e0832faSShawn Lin 
6636e0832faSShawn Lin err_slave_clk:
6646e0832faSShawn Lin 	clk_disable_unprepare(res->master_clk);
6656e0832faSShawn Lin err_master_clk:
6666e0832faSShawn Lin 	clk_disable_unprepare(res->cfg_clk);
6676e0832faSShawn Lin err_cfg_clk:
6686e0832faSShawn Lin 	clk_disable_unprepare(res->aux_clk);
6696e0832faSShawn Lin 
6706e0832faSShawn Lin err_aux_clk:
6716e0832faSShawn Lin 	regulator_bulk_disable(ARRAY_SIZE(res->supplies), res->supplies);
6726e0832faSShawn Lin 
6736e0832faSShawn Lin 	return ret;
6746e0832faSShawn Lin }
6756e0832faSShawn Lin 
6766e0832faSShawn Lin static int qcom_pcie_post_init_2_3_2(struct qcom_pcie *pcie)
6776e0832faSShawn Lin {
67836d9018dSRobert Marko 	u32 val;
6796e0832faSShawn Lin 
68036d9018dSRobert Marko 	/* enable PCIe clocks and resets */
68136d9018dSRobert Marko 	val = readl(pcie->parf + PCIE20_PARF_PHY_CTRL);
68236d9018dSRobert Marko 	val &= ~BIT(0);
68336d9018dSRobert Marko 	writel(val, pcie->parf + PCIE20_PARF_PHY_CTRL);
68436d9018dSRobert Marko 
68536d9018dSRobert Marko 	/* change DBI base address */
68636d9018dSRobert Marko 	writel(0, pcie->parf + PCIE20_PARF_DBI_BASE_ADDR);
68736d9018dSRobert Marko 
68836d9018dSRobert Marko 	/* MAC PHY_POWERDOWN MUX DISABLE  */
68936d9018dSRobert Marko 	val = readl(pcie->parf + PCIE20_PARF_SYS_CTRL);
69036d9018dSRobert Marko 	val &= ~BIT(29);
69136d9018dSRobert Marko 	writel(val, pcie->parf + PCIE20_PARF_SYS_CTRL);
69236d9018dSRobert Marko 
69336d9018dSRobert Marko 	val = readl(pcie->parf + PCIE20_PARF_MHI_CLOCK_RESET_CTRL);
69436d9018dSRobert Marko 	val |= BIT(4);
69536d9018dSRobert Marko 	writel(val, pcie->parf + PCIE20_PARF_MHI_CLOCK_RESET_CTRL);
69636d9018dSRobert Marko 
69736d9018dSRobert Marko 	val = readl(pcie->parf + PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT_V2);
69836d9018dSRobert Marko 	val |= BIT(31);
69936d9018dSRobert Marko 	writel(val, pcie->parf + PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT_V2);
70036d9018dSRobert Marko 
7016e0832faSShawn Lin 	return 0;
7026e0832faSShawn Lin }
7036e0832faSShawn Lin 
7046e0832faSShawn Lin static int qcom_pcie_get_resources_2_4_0(struct qcom_pcie *pcie)
7056e0832faSShawn Lin {
7066e0832faSShawn Lin 	struct qcom_pcie_resources_2_4_0 *res = &pcie->res.v2_4_0;
7076e0832faSShawn Lin 	struct dw_pcie *pci = pcie->pci;
7086e0832faSShawn Lin 	struct device *dev = pci->dev;
70967021ae0SBjorn Andersson 	bool is_ipq = of_device_is_compatible(dev->of_node, "qcom,pcie-ipq4019");
7105aa18097SBjorn Andersson 	int ret;
7116e0832faSShawn Lin 
7125aa18097SBjorn Andersson 	res->clks[0].id = "aux";
7135aa18097SBjorn Andersson 	res->clks[1].id = "master_bus";
7145aa18097SBjorn Andersson 	res->clks[2].id = "slave_bus";
71567021ae0SBjorn Andersson 	res->clks[3].id = "iface";
7166e0832faSShawn Lin 
71767021ae0SBjorn Andersson 	/* qcom,pcie-ipq4019 is defined without "iface" */
71867021ae0SBjorn Andersson 	res->num_clks = is_ipq ? 3 : 4;
7196e0832faSShawn Lin 
7205aa18097SBjorn Andersson 	ret = devm_clk_bulk_get(dev, res->num_clks, res->clks);
7215aa18097SBjorn Andersson 	if (ret < 0)
7225aa18097SBjorn Andersson 		return ret;
7236e0832faSShawn Lin 
7246e0832faSShawn Lin 	res->axi_m_reset = devm_reset_control_get_exclusive(dev, "axi_m");
7256e0832faSShawn Lin 	if (IS_ERR(res->axi_m_reset))
7266e0832faSShawn Lin 		return PTR_ERR(res->axi_m_reset);
7276e0832faSShawn Lin 
7286e0832faSShawn Lin 	res->axi_s_reset = devm_reset_control_get_exclusive(dev, "axi_s");
7296e0832faSShawn Lin 	if (IS_ERR(res->axi_s_reset))
7306e0832faSShawn Lin 		return PTR_ERR(res->axi_s_reset);
7316e0832faSShawn Lin 
73267021ae0SBjorn Andersson 	if (is_ipq) {
73367021ae0SBjorn Andersson 		/*
73467021ae0SBjorn Andersson 		 * These resources relates to the PHY or are secure clocks, but
73567021ae0SBjorn Andersson 		 * are controlled here for IPQ4019
73667021ae0SBjorn Andersson 		 */
7376e0832faSShawn Lin 		res->pipe_reset = devm_reset_control_get_exclusive(dev, "pipe");
7386e0832faSShawn Lin 		if (IS_ERR(res->pipe_reset))
7396e0832faSShawn Lin 			return PTR_ERR(res->pipe_reset);
7406e0832faSShawn Lin 
7416e0832faSShawn Lin 		res->axi_m_vmid_reset = devm_reset_control_get_exclusive(dev,
7426e0832faSShawn Lin 									 "axi_m_vmid");
7436e0832faSShawn Lin 		if (IS_ERR(res->axi_m_vmid_reset))
7446e0832faSShawn Lin 			return PTR_ERR(res->axi_m_vmid_reset);
7456e0832faSShawn Lin 
7466e0832faSShawn Lin 		res->axi_s_xpu_reset = devm_reset_control_get_exclusive(dev,
7476e0832faSShawn Lin 									"axi_s_xpu");
7486e0832faSShawn Lin 		if (IS_ERR(res->axi_s_xpu_reset))
7496e0832faSShawn Lin 			return PTR_ERR(res->axi_s_xpu_reset);
7506e0832faSShawn Lin 
7516e0832faSShawn Lin 		res->parf_reset = devm_reset_control_get_exclusive(dev, "parf");
7526e0832faSShawn Lin 		if (IS_ERR(res->parf_reset))
7536e0832faSShawn Lin 			return PTR_ERR(res->parf_reset);
7546e0832faSShawn Lin 
7556e0832faSShawn Lin 		res->phy_reset = devm_reset_control_get_exclusive(dev, "phy");
7566e0832faSShawn Lin 		if (IS_ERR(res->phy_reset))
7576e0832faSShawn Lin 			return PTR_ERR(res->phy_reset);
75867021ae0SBjorn Andersson 	}
7596e0832faSShawn Lin 
7606e0832faSShawn Lin 	res->axi_m_sticky_reset = devm_reset_control_get_exclusive(dev,
7616e0832faSShawn Lin 								   "axi_m_sticky");
7626e0832faSShawn Lin 	if (IS_ERR(res->axi_m_sticky_reset))
7636e0832faSShawn Lin 		return PTR_ERR(res->axi_m_sticky_reset);
7646e0832faSShawn Lin 
7656e0832faSShawn Lin 	res->pipe_sticky_reset = devm_reset_control_get_exclusive(dev,
7666e0832faSShawn Lin 								  "pipe_sticky");
7676e0832faSShawn Lin 	if (IS_ERR(res->pipe_sticky_reset))
7686e0832faSShawn Lin 		return PTR_ERR(res->pipe_sticky_reset);
7696e0832faSShawn Lin 
7706e0832faSShawn Lin 	res->pwr_reset = devm_reset_control_get_exclusive(dev, "pwr");
7716e0832faSShawn Lin 	if (IS_ERR(res->pwr_reset))
7726e0832faSShawn Lin 		return PTR_ERR(res->pwr_reset);
7736e0832faSShawn Lin 
7746e0832faSShawn Lin 	res->ahb_reset = devm_reset_control_get_exclusive(dev, "ahb");
7756e0832faSShawn Lin 	if (IS_ERR(res->ahb_reset))
7766e0832faSShawn Lin 		return PTR_ERR(res->ahb_reset);
7776e0832faSShawn Lin 
77867021ae0SBjorn Andersson 	if (is_ipq) {
7796e0832faSShawn Lin 		res->phy_ahb_reset = devm_reset_control_get_exclusive(dev, "phy_ahb");
7806e0832faSShawn Lin 		if (IS_ERR(res->phy_ahb_reset))
7816e0832faSShawn Lin 			return PTR_ERR(res->phy_ahb_reset);
78267021ae0SBjorn Andersson 	}
7836e0832faSShawn Lin 
7846e0832faSShawn Lin 	return 0;
7856e0832faSShawn Lin }
7866e0832faSShawn Lin 
7876e0832faSShawn Lin static void qcom_pcie_deinit_2_4_0(struct qcom_pcie *pcie)
7886e0832faSShawn Lin {
7896e0832faSShawn Lin 	struct qcom_pcie_resources_2_4_0 *res = &pcie->res.v2_4_0;
7906e0832faSShawn Lin 
7916e0832faSShawn Lin 	reset_control_assert(res->axi_m_reset);
7926e0832faSShawn Lin 	reset_control_assert(res->axi_s_reset);
7936e0832faSShawn Lin 	reset_control_assert(res->pipe_reset);
7946e0832faSShawn Lin 	reset_control_assert(res->pipe_sticky_reset);
7956e0832faSShawn Lin 	reset_control_assert(res->phy_reset);
7966e0832faSShawn Lin 	reset_control_assert(res->phy_ahb_reset);
7976e0832faSShawn Lin 	reset_control_assert(res->axi_m_sticky_reset);
7986e0832faSShawn Lin 	reset_control_assert(res->pwr_reset);
7996e0832faSShawn Lin 	reset_control_assert(res->ahb_reset);
8005aa18097SBjorn Andersson 	clk_bulk_disable_unprepare(res->num_clks, res->clks);
8016e0832faSShawn Lin }
8026e0832faSShawn Lin 
8036e0832faSShawn Lin static int qcom_pcie_init_2_4_0(struct qcom_pcie *pcie)
8046e0832faSShawn Lin {
8056e0832faSShawn Lin 	struct qcom_pcie_resources_2_4_0 *res = &pcie->res.v2_4_0;
8066e0832faSShawn Lin 	struct dw_pcie *pci = pcie->pci;
8076e0832faSShawn Lin 	struct device *dev = pci->dev;
8086e0832faSShawn Lin 	int ret;
8096e0832faSShawn Lin 
8106e0832faSShawn Lin 	ret = reset_control_assert(res->axi_m_reset);
8116e0832faSShawn Lin 	if (ret) {
8126e0832faSShawn Lin 		dev_err(dev, "cannot assert axi master reset\n");
8136e0832faSShawn Lin 		return ret;
8146e0832faSShawn Lin 	}
8156e0832faSShawn Lin 
8166e0832faSShawn Lin 	ret = reset_control_assert(res->axi_s_reset);
8176e0832faSShawn Lin 	if (ret) {
8186e0832faSShawn Lin 		dev_err(dev, "cannot assert axi slave reset\n");
8196e0832faSShawn Lin 		return ret;
8206e0832faSShawn Lin 	}
8216e0832faSShawn Lin 
8226e0832faSShawn Lin 	usleep_range(10000, 12000);
8236e0832faSShawn Lin 
8246e0832faSShawn Lin 	ret = reset_control_assert(res->pipe_reset);
8256e0832faSShawn Lin 	if (ret) {
8266e0832faSShawn Lin 		dev_err(dev, "cannot assert pipe reset\n");
8276e0832faSShawn Lin 		return ret;
8286e0832faSShawn Lin 	}
8296e0832faSShawn Lin 
8306e0832faSShawn Lin 	ret = reset_control_assert(res->pipe_sticky_reset);
8316e0832faSShawn Lin 	if (ret) {
8326e0832faSShawn Lin 		dev_err(dev, "cannot assert pipe sticky reset\n");
8336e0832faSShawn Lin 		return ret;
8346e0832faSShawn Lin 	}
8356e0832faSShawn Lin 
8366e0832faSShawn Lin 	ret = reset_control_assert(res->phy_reset);
8376e0832faSShawn Lin 	if (ret) {
8386e0832faSShawn Lin 		dev_err(dev, "cannot assert phy reset\n");
8396e0832faSShawn Lin 		return ret;
8406e0832faSShawn Lin 	}
8416e0832faSShawn Lin 
8426e0832faSShawn Lin 	ret = reset_control_assert(res->phy_ahb_reset);
8436e0832faSShawn Lin 	if (ret) {
8446e0832faSShawn Lin 		dev_err(dev, "cannot assert phy ahb reset\n");
8456e0832faSShawn Lin 		return ret;
8466e0832faSShawn Lin 	}
8476e0832faSShawn Lin 
8486e0832faSShawn Lin 	usleep_range(10000, 12000);
8496e0832faSShawn Lin 
8506e0832faSShawn Lin 	ret = reset_control_assert(res->axi_m_sticky_reset);
8516e0832faSShawn Lin 	if (ret) {
8526e0832faSShawn Lin 		dev_err(dev, "cannot assert axi master sticky reset\n");
8536e0832faSShawn Lin 		return ret;
8546e0832faSShawn Lin 	}
8556e0832faSShawn Lin 
8566e0832faSShawn Lin 	ret = reset_control_assert(res->pwr_reset);
8576e0832faSShawn Lin 	if (ret) {
8586e0832faSShawn Lin 		dev_err(dev, "cannot assert power reset\n");
8596e0832faSShawn Lin 		return ret;
8606e0832faSShawn Lin 	}
8616e0832faSShawn Lin 
8626e0832faSShawn Lin 	ret = reset_control_assert(res->ahb_reset);
8636e0832faSShawn Lin 	if (ret) {
8646e0832faSShawn Lin 		dev_err(dev, "cannot assert ahb reset\n");
8656e0832faSShawn Lin 		return ret;
8666e0832faSShawn Lin 	}
8676e0832faSShawn Lin 
8686e0832faSShawn Lin 	usleep_range(10000, 12000);
8696e0832faSShawn Lin 
8706e0832faSShawn Lin 	ret = reset_control_deassert(res->phy_ahb_reset);
8716e0832faSShawn Lin 	if (ret) {
8726e0832faSShawn Lin 		dev_err(dev, "cannot deassert phy ahb reset\n");
8736e0832faSShawn Lin 		return ret;
8746e0832faSShawn Lin 	}
8756e0832faSShawn Lin 
8766e0832faSShawn Lin 	ret = reset_control_deassert(res->phy_reset);
8776e0832faSShawn Lin 	if (ret) {
8786e0832faSShawn Lin 		dev_err(dev, "cannot deassert phy reset\n");
8796e0832faSShawn Lin 		goto err_rst_phy;
8806e0832faSShawn Lin 	}
8816e0832faSShawn Lin 
8826e0832faSShawn Lin 	ret = reset_control_deassert(res->pipe_reset);
8836e0832faSShawn Lin 	if (ret) {
8846e0832faSShawn Lin 		dev_err(dev, "cannot deassert pipe reset\n");
8856e0832faSShawn Lin 		goto err_rst_pipe;
8866e0832faSShawn Lin 	}
8876e0832faSShawn Lin 
8886e0832faSShawn Lin 	ret = reset_control_deassert(res->pipe_sticky_reset);
8896e0832faSShawn Lin 	if (ret) {
8906e0832faSShawn Lin 		dev_err(dev, "cannot deassert pipe sticky reset\n");
8916e0832faSShawn Lin 		goto err_rst_pipe_sticky;
8926e0832faSShawn Lin 	}
8936e0832faSShawn Lin 
8946e0832faSShawn Lin 	usleep_range(10000, 12000);
8956e0832faSShawn Lin 
8966e0832faSShawn Lin 	ret = reset_control_deassert(res->axi_m_reset);
8976e0832faSShawn Lin 	if (ret) {
8986e0832faSShawn Lin 		dev_err(dev, "cannot deassert axi master reset\n");
8996e0832faSShawn Lin 		goto err_rst_axi_m;
9006e0832faSShawn Lin 	}
9016e0832faSShawn Lin 
9026e0832faSShawn Lin 	ret = reset_control_deassert(res->axi_m_sticky_reset);
9036e0832faSShawn Lin 	if (ret) {
9046e0832faSShawn Lin 		dev_err(dev, "cannot deassert axi master sticky reset\n");
9056e0832faSShawn Lin 		goto err_rst_axi_m_sticky;
9066e0832faSShawn Lin 	}
9076e0832faSShawn Lin 
9086e0832faSShawn Lin 	ret = reset_control_deassert(res->axi_s_reset);
9096e0832faSShawn Lin 	if (ret) {
9106e0832faSShawn Lin 		dev_err(dev, "cannot deassert axi slave reset\n");
9116e0832faSShawn Lin 		goto err_rst_axi_s;
9126e0832faSShawn Lin 	}
9136e0832faSShawn Lin 
9146e0832faSShawn Lin 	ret = reset_control_deassert(res->pwr_reset);
9156e0832faSShawn Lin 	if (ret) {
9166e0832faSShawn Lin 		dev_err(dev, "cannot deassert power reset\n");
9176e0832faSShawn Lin 		goto err_rst_pwr;
9186e0832faSShawn Lin 	}
9196e0832faSShawn Lin 
9206e0832faSShawn Lin 	ret = reset_control_deassert(res->ahb_reset);
9216e0832faSShawn Lin 	if (ret) {
9226e0832faSShawn Lin 		dev_err(dev, "cannot deassert ahb reset\n");
9236e0832faSShawn Lin 		goto err_rst_ahb;
9246e0832faSShawn Lin 	}
9256e0832faSShawn Lin 
9266e0832faSShawn Lin 	usleep_range(10000, 12000);
9276e0832faSShawn Lin 
9285aa18097SBjorn Andersson 	ret = clk_bulk_prepare_enable(res->num_clks, res->clks);
9295aa18097SBjorn Andersson 	if (ret)
9305aa18097SBjorn Andersson 		goto err_clks;
9316e0832faSShawn Lin 
93236d9018dSRobert Marko 	return 0;
93336d9018dSRobert Marko 
93436d9018dSRobert Marko err_clks:
93536d9018dSRobert Marko 	reset_control_assert(res->ahb_reset);
93636d9018dSRobert Marko err_rst_ahb:
93736d9018dSRobert Marko 	reset_control_assert(res->pwr_reset);
93836d9018dSRobert Marko err_rst_pwr:
93936d9018dSRobert Marko 	reset_control_assert(res->axi_s_reset);
94036d9018dSRobert Marko err_rst_axi_s:
94136d9018dSRobert Marko 	reset_control_assert(res->axi_m_sticky_reset);
94236d9018dSRobert Marko err_rst_axi_m_sticky:
94336d9018dSRobert Marko 	reset_control_assert(res->axi_m_reset);
94436d9018dSRobert Marko err_rst_axi_m:
94536d9018dSRobert Marko 	reset_control_assert(res->pipe_sticky_reset);
94636d9018dSRobert Marko err_rst_pipe_sticky:
94736d9018dSRobert Marko 	reset_control_assert(res->pipe_reset);
94836d9018dSRobert Marko err_rst_pipe:
94936d9018dSRobert Marko 	reset_control_assert(res->phy_reset);
95036d9018dSRobert Marko err_rst_phy:
95136d9018dSRobert Marko 	reset_control_assert(res->phy_ahb_reset);
95236d9018dSRobert Marko 	return ret;
95336d9018dSRobert Marko }
95436d9018dSRobert Marko 
95536d9018dSRobert Marko static int qcom_pcie_post_init_2_4_0(struct qcom_pcie *pcie)
95636d9018dSRobert Marko {
95736d9018dSRobert Marko 	u32 val;
95836d9018dSRobert Marko 
9596e0832faSShawn Lin 	/* enable PCIe clocks and resets */
9606e0832faSShawn Lin 	val = readl(pcie->parf + PCIE20_PARF_PHY_CTRL);
9616e0832faSShawn Lin 	val &= ~BIT(0);
9626e0832faSShawn Lin 	writel(val, pcie->parf + PCIE20_PARF_PHY_CTRL);
9636e0832faSShawn Lin 
9646e0832faSShawn Lin 	/* change DBI base address */
9656e0832faSShawn Lin 	writel(0, pcie->parf + PCIE20_PARF_DBI_BASE_ADDR);
9666e0832faSShawn Lin 
9676e0832faSShawn Lin 	/* MAC PHY_POWERDOWN MUX DISABLE  */
9686e0832faSShawn Lin 	val = readl(pcie->parf + PCIE20_PARF_SYS_CTRL);
9696e0832faSShawn Lin 	val &= ~BIT(29);
9706e0832faSShawn Lin 	writel(val, pcie->parf + PCIE20_PARF_SYS_CTRL);
9716e0832faSShawn Lin 
9726e0832faSShawn Lin 	val = readl(pcie->parf + PCIE20_PARF_MHI_CLOCK_RESET_CTRL);
9736e0832faSShawn Lin 	val |= BIT(4);
9746e0832faSShawn Lin 	writel(val, pcie->parf + PCIE20_PARF_MHI_CLOCK_RESET_CTRL);
9756e0832faSShawn Lin 
9766e0832faSShawn Lin 	val = readl(pcie->parf + PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT_V2);
9776e0832faSShawn Lin 	val |= BIT(31);
9786e0832faSShawn Lin 	writel(val, pcie->parf + PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT_V2);
9796e0832faSShawn Lin 
9806e0832faSShawn Lin 	return 0;
9816e0832faSShawn Lin }
9826e0832faSShawn Lin 
9836e0832faSShawn Lin static int qcom_pcie_get_resources_2_3_3(struct qcom_pcie *pcie)
9846e0832faSShawn Lin {
9856e0832faSShawn Lin 	struct qcom_pcie_resources_2_3_3 *res = &pcie->res.v2_3_3;
9866e0832faSShawn Lin 	struct dw_pcie *pci = pcie->pci;
9876e0832faSShawn Lin 	struct device *dev = pci->dev;
9886e0832faSShawn Lin 	int i;
9896e0832faSShawn Lin 	const char *rst_names[] = { "axi_m", "axi_s", "pipe",
9906e0832faSShawn Lin 				    "axi_m_sticky", "sticky",
9916e0832faSShawn Lin 				    "ahb", "sleep", };
9926e0832faSShawn Lin 
9936e0832faSShawn Lin 	res->iface = devm_clk_get(dev, "iface");
9946e0832faSShawn Lin 	if (IS_ERR(res->iface))
9956e0832faSShawn Lin 		return PTR_ERR(res->iface);
9966e0832faSShawn Lin 
9976e0832faSShawn Lin 	res->axi_m_clk = devm_clk_get(dev, "axi_m");
9986e0832faSShawn Lin 	if (IS_ERR(res->axi_m_clk))
9996e0832faSShawn Lin 		return PTR_ERR(res->axi_m_clk);
10006e0832faSShawn Lin 
10016e0832faSShawn Lin 	res->axi_s_clk = devm_clk_get(dev, "axi_s");
10026e0832faSShawn Lin 	if (IS_ERR(res->axi_s_clk))
10036e0832faSShawn Lin 		return PTR_ERR(res->axi_s_clk);
10046e0832faSShawn Lin 
10056e0832faSShawn Lin 	res->ahb_clk = devm_clk_get(dev, "ahb");
10066e0832faSShawn Lin 	if (IS_ERR(res->ahb_clk))
10076e0832faSShawn Lin 		return PTR_ERR(res->ahb_clk);
10086e0832faSShawn Lin 
10096e0832faSShawn Lin 	res->aux_clk = devm_clk_get(dev, "aux");
10106e0832faSShawn Lin 	if (IS_ERR(res->aux_clk))
10116e0832faSShawn Lin 		return PTR_ERR(res->aux_clk);
10126e0832faSShawn Lin 
10136e0832faSShawn Lin 	for (i = 0; i < ARRAY_SIZE(rst_names); i++) {
10146e0832faSShawn Lin 		res->rst[i] = devm_reset_control_get(dev, rst_names[i]);
10156e0832faSShawn Lin 		if (IS_ERR(res->rst[i]))
10166e0832faSShawn Lin 			return PTR_ERR(res->rst[i]);
10176e0832faSShawn Lin 	}
10186e0832faSShawn Lin 
10196e0832faSShawn Lin 	return 0;
10206e0832faSShawn Lin }
10216e0832faSShawn Lin 
10226e0832faSShawn Lin static void qcom_pcie_deinit_2_3_3(struct qcom_pcie *pcie)
10236e0832faSShawn Lin {
10246e0832faSShawn Lin 	struct qcom_pcie_resources_2_3_3 *res = &pcie->res.v2_3_3;
10256e0832faSShawn Lin 
10266e0832faSShawn Lin 	clk_disable_unprepare(res->iface);
10276e0832faSShawn Lin 	clk_disable_unprepare(res->axi_m_clk);
10286e0832faSShawn Lin 	clk_disable_unprepare(res->axi_s_clk);
10296e0832faSShawn Lin 	clk_disable_unprepare(res->ahb_clk);
10306e0832faSShawn Lin 	clk_disable_unprepare(res->aux_clk);
10316e0832faSShawn Lin }
10326e0832faSShawn Lin 
10336e0832faSShawn Lin static int qcom_pcie_init_2_3_3(struct qcom_pcie *pcie)
10346e0832faSShawn Lin {
10356e0832faSShawn Lin 	struct qcom_pcie_resources_2_3_3 *res = &pcie->res.v2_3_3;
10366e0832faSShawn Lin 	struct dw_pcie *pci = pcie->pci;
10376e0832faSShawn Lin 	struct device *dev = pci->dev;
10386e0832faSShawn Lin 	int i, ret;
10396e0832faSShawn Lin 
10406e0832faSShawn Lin 	for (i = 0; i < ARRAY_SIZE(res->rst); i++) {
10416e0832faSShawn Lin 		ret = reset_control_assert(res->rst[i]);
10426e0832faSShawn Lin 		if (ret) {
10436e0832faSShawn Lin 			dev_err(dev, "reset #%d assert failed (%d)\n", i, ret);
10446e0832faSShawn Lin 			return ret;
10456e0832faSShawn Lin 		}
10466e0832faSShawn Lin 	}
10476e0832faSShawn Lin 
10486e0832faSShawn Lin 	usleep_range(2000, 2500);
10496e0832faSShawn Lin 
10506e0832faSShawn Lin 	for (i = 0; i < ARRAY_SIZE(res->rst); i++) {
10516e0832faSShawn Lin 		ret = reset_control_deassert(res->rst[i]);
10526e0832faSShawn Lin 		if (ret) {
10536e0832faSShawn Lin 			dev_err(dev, "reset #%d deassert failed (%d)\n", i,
10546e0832faSShawn Lin 				ret);
10556e0832faSShawn Lin 			return ret;
10566e0832faSShawn Lin 		}
10576e0832faSShawn Lin 	}
10586e0832faSShawn Lin 
10596e0832faSShawn Lin 	/*
10606e0832faSShawn Lin 	 * Don't have a way to see if the reset has completed.
10616e0832faSShawn Lin 	 * Wait for some time.
10626e0832faSShawn Lin 	 */
10636e0832faSShawn Lin 	usleep_range(2000, 2500);
10646e0832faSShawn Lin 
10656e0832faSShawn Lin 	ret = clk_prepare_enable(res->iface);
10666e0832faSShawn Lin 	if (ret) {
10676e0832faSShawn Lin 		dev_err(dev, "cannot prepare/enable core clock\n");
10686e0832faSShawn Lin 		goto err_clk_iface;
10696e0832faSShawn Lin 	}
10706e0832faSShawn Lin 
10716e0832faSShawn Lin 	ret = clk_prepare_enable(res->axi_m_clk);
10726e0832faSShawn Lin 	if (ret) {
10736e0832faSShawn Lin 		dev_err(dev, "cannot prepare/enable core clock\n");
10746e0832faSShawn Lin 		goto err_clk_axi_m;
10756e0832faSShawn Lin 	}
10766e0832faSShawn Lin 
10776e0832faSShawn Lin 	ret = clk_prepare_enable(res->axi_s_clk);
10786e0832faSShawn Lin 	if (ret) {
10796e0832faSShawn Lin 		dev_err(dev, "cannot prepare/enable axi slave clock\n");
10806e0832faSShawn Lin 		goto err_clk_axi_s;
10816e0832faSShawn Lin 	}
10826e0832faSShawn Lin 
10836e0832faSShawn Lin 	ret = clk_prepare_enable(res->ahb_clk);
10846e0832faSShawn Lin 	if (ret) {
10856e0832faSShawn Lin 		dev_err(dev, "cannot prepare/enable ahb clock\n");
10866e0832faSShawn Lin 		goto err_clk_ahb;
10876e0832faSShawn Lin 	}
10886e0832faSShawn Lin 
10896e0832faSShawn Lin 	ret = clk_prepare_enable(res->aux_clk);
10906e0832faSShawn Lin 	if (ret) {
10916e0832faSShawn Lin 		dev_err(dev, "cannot prepare/enable aux clock\n");
10926e0832faSShawn Lin 		goto err_clk_aux;
10936e0832faSShawn Lin 	}
10946e0832faSShawn Lin 
1095a0e43bb9SRobert Marko 	return 0;
1096a0e43bb9SRobert Marko 
1097a0e43bb9SRobert Marko err_clk_aux:
1098a0e43bb9SRobert Marko 	clk_disable_unprepare(res->ahb_clk);
1099a0e43bb9SRobert Marko err_clk_ahb:
1100a0e43bb9SRobert Marko 	clk_disable_unprepare(res->axi_s_clk);
1101a0e43bb9SRobert Marko err_clk_axi_s:
1102a0e43bb9SRobert Marko 	clk_disable_unprepare(res->axi_m_clk);
1103a0e43bb9SRobert Marko err_clk_axi_m:
1104a0e43bb9SRobert Marko 	clk_disable_unprepare(res->iface);
1105a0e43bb9SRobert Marko err_clk_iface:
1106a0e43bb9SRobert Marko 	/*
1107a0e43bb9SRobert Marko 	 * Not checking for failure, will anyway return
1108a0e43bb9SRobert Marko 	 * the original failure in 'ret'.
1109a0e43bb9SRobert Marko 	 */
1110a0e43bb9SRobert Marko 	for (i = 0; i < ARRAY_SIZE(res->rst); i++)
1111a0e43bb9SRobert Marko 		reset_control_assert(res->rst[i]);
1112a0e43bb9SRobert Marko 
1113a0e43bb9SRobert Marko 	return ret;
1114a0e43bb9SRobert Marko }
1115a0e43bb9SRobert Marko 
1116a0e43bb9SRobert Marko static int qcom_pcie_post_init_2_3_3(struct qcom_pcie *pcie)
1117a0e43bb9SRobert Marko {
1118a0e43bb9SRobert Marko 	struct dw_pcie *pci = pcie->pci;
1119a0e43bb9SRobert Marko 	u16 offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
1120a0e43bb9SRobert Marko 	u32 val;
1121a0e43bb9SRobert Marko 
11226e0832faSShawn Lin 	writel(SLV_ADDR_SPACE_SZ,
11236e0832faSShawn Lin 		pcie->parf + PCIE20_v3_PARF_SLV_ADDR_SPACE_SIZE);
11246e0832faSShawn Lin 
11256e0832faSShawn Lin 	val = readl(pcie->parf + PCIE20_PARF_PHY_CTRL);
11266e0832faSShawn Lin 	val &= ~BIT(0);
11276e0832faSShawn Lin 	writel(val, pcie->parf + PCIE20_PARF_PHY_CTRL);
11286e0832faSShawn Lin 
11296e0832faSShawn Lin 	writel(0, pcie->parf + PCIE20_PARF_DBI_BASE_ADDR);
11306e0832faSShawn Lin 
11316e0832faSShawn Lin 	writel(MST_WAKEUP_EN | SLV_WAKEUP_EN | MSTR_ACLK_CGC_DIS
11326e0832faSShawn Lin 		| SLV_ACLK_CGC_DIS | CORE_CLK_CGC_DIS |
11336e0832faSShawn Lin 		AUX_PWR_DET | L23_CLK_RMV_DIS | L1_CLK_RMV_DIS,
11346e0832faSShawn Lin 		pcie->parf + PCIE20_PARF_SYS_CTRL);
11356e0832faSShawn Lin 	writel(0, pcie->parf + PCIE20_PARF_Q2A_FLUSH);
11366e0832faSShawn Lin 
1137824001cbSAnsuel Smith 	writel(PCI_COMMAND_MASTER, pci->dbi_base + PCI_COMMAND);
11386e0832faSShawn Lin 	writel(DBI_RO_WR_EN, pci->dbi_base + PCIE20_MISC_CONTROL_1_REG);
11397b87ddc0SRob Herring 	writel(PCIE_CAP_LINK1_VAL, pci->dbi_base + offset + PCI_EXP_SLTCAP);
11406e0832faSShawn Lin 
11417b87ddc0SRob Herring 	val = readl(pci->dbi_base + offset + PCI_EXP_LNKCAP);
1142824001cbSAnsuel Smith 	val &= ~PCI_EXP_LNKCAP_ASPMS;
11437b87ddc0SRob Herring 	writel(val, pci->dbi_base + offset + PCI_EXP_LNKCAP);
11446e0832faSShawn Lin 
11457b87ddc0SRob Herring 	writel(PCI_EXP_DEVCTL2_COMP_TMOUT_DIS, pci->dbi_base + offset +
11467b87ddc0SRob Herring 		PCI_EXP_DEVCTL2);
11476e0832faSShawn Lin 
11486e0832faSShawn Lin 	return 0;
11496e0832faSShawn Lin }
11506e0832faSShawn Lin 
1151ed8cc3b1SBjorn Andersson static int qcom_pcie_get_resources_2_7_0(struct qcom_pcie *pcie)
1152ed8cc3b1SBjorn Andersson {
1153ed8cc3b1SBjorn Andersson 	struct qcom_pcie_resources_2_7_0 *res = &pcie->res.v2_7_0;
1154ed8cc3b1SBjorn Andersson 	struct dw_pcie *pci = pcie->pci;
1155ed8cc3b1SBjorn Andersson 	struct device *dev = pci->dev;
11561c5aa037SDmitry Baryshkov 	unsigned int idx;
1157ed8cc3b1SBjorn Andersson 	int ret;
1158ed8cc3b1SBjorn Andersson 
1159ed8cc3b1SBjorn Andersson 	res->pci_reset = devm_reset_control_get_exclusive(dev, "pci");
1160ed8cc3b1SBjorn Andersson 	if (IS_ERR(res->pci_reset))
1161ed8cc3b1SBjorn Andersson 		return PTR_ERR(res->pci_reset);
1162ed8cc3b1SBjorn Andersson 
1163ed8cc3b1SBjorn Andersson 	res->supplies[0].supply = "vdda";
1164ed8cc3b1SBjorn Andersson 	res->supplies[1].supply = "vddpe-3v3";
1165ed8cc3b1SBjorn Andersson 	ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(res->supplies),
1166ed8cc3b1SBjorn Andersson 				      res->supplies);
1167ed8cc3b1SBjorn Andersson 	if (ret)
1168ed8cc3b1SBjorn Andersson 		return ret;
1169ed8cc3b1SBjorn Andersson 
11701c5aa037SDmitry Baryshkov 	idx = 0;
11711c5aa037SDmitry Baryshkov 	res->clks[idx++].id = "aux";
11721c5aa037SDmitry Baryshkov 	res->clks[idx++].id = "cfg";
11731c5aa037SDmitry Baryshkov 	res->clks[idx++].id = "bus_master";
11741c5aa037SDmitry Baryshkov 	res->clks[idx++].id = "bus_slave";
11751c5aa037SDmitry Baryshkov 	res->clks[idx++].id = "slave_q2a";
11761c5aa037SDmitry Baryshkov 	if (pcie->cfg->has_tbu_clk)
11771c5aa037SDmitry Baryshkov 		res->clks[idx++].id = "tbu";
11781c5aa037SDmitry Baryshkov 	if (pcie->cfg->has_ddrss_sf_tbu_clk)
11791c5aa037SDmitry Baryshkov 		res->clks[idx++].id = "ddrss_sf_tbu";
11801c5aa037SDmitry Baryshkov 	if (pcie->cfg->has_aggre0_clk)
11811c5aa037SDmitry Baryshkov 		res->clks[idx++].id = "aggre0";
11821c5aa037SDmitry Baryshkov 	if (pcie->cfg->has_aggre1_clk)
11831c5aa037SDmitry Baryshkov 		res->clks[idx++].id = "aggre1";
11841c5aa037SDmitry Baryshkov 
11851c5aa037SDmitry Baryshkov 	res->num_clks = idx;
1186ed8cc3b1SBjorn Andersson 
11877081556fSDmitry Baryshkov 	ret = devm_clk_bulk_get(dev, res->num_clks, res->clks);
1188ed8cc3b1SBjorn Andersson 	if (ret < 0)
1189ed8cc3b1SBjorn Andersson 		return ret;
1190ed8cc3b1SBjorn Andersson 
1191f94c35e0SDmitry Baryshkov 	if (pcie->cfg->pipe_clk_need_muxing) {
1192aa9c0df9SPrasad Malisetty 		res->pipe_clk_src = devm_clk_get(dev, "pipe_mux");
1193aa9c0df9SPrasad Malisetty 		if (IS_ERR(res->pipe_clk_src))
1194aa9c0df9SPrasad Malisetty 			return PTR_ERR(res->pipe_clk_src);
1195aa9c0df9SPrasad Malisetty 
1196aa9c0df9SPrasad Malisetty 		res->phy_pipe_clk = devm_clk_get(dev, "phy_pipe");
1197aa9c0df9SPrasad Malisetty 		if (IS_ERR(res->phy_pipe_clk))
1198aa9c0df9SPrasad Malisetty 			return PTR_ERR(res->phy_pipe_clk);
1199aa9c0df9SPrasad Malisetty 
1200aa9c0df9SPrasad Malisetty 		res->ref_clk_src = devm_clk_get(dev, "ref");
1201aa9c0df9SPrasad Malisetty 		if (IS_ERR(res->ref_clk_src))
1202aa9c0df9SPrasad Malisetty 			return PTR_ERR(res->ref_clk_src);
1203aa9c0df9SPrasad Malisetty 	}
1204aa9c0df9SPrasad Malisetty 
1205*affac98aSDmitry Baryshkov 	return 0;
1206ed8cc3b1SBjorn Andersson }
1207ed8cc3b1SBjorn Andersson 
1208ed8cc3b1SBjorn Andersson static int qcom_pcie_init_2_7_0(struct qcom_pcie *pcie)
1209ed8cc3b1SBjorn Andersson {
1210ed8cc3b1SBjorn Andersson 	struct qcom_pcie_resources_2_7_0 *res = &pcie->res.v2_7_0;
1211ed8cc3b1SBjorn Andersson 	struct dw_pcie *pci = pcie->pci;
1212ed8cc3b1SBjorn Andersson 	struct device *dev = pci->dev;
1213ed8cc3b1SBjorn Andersson 	u32 val;
1214ed8cc3b1SBjorn Andersson 	int ret;
1215ed8cc3b1SBjorn Andersson 
1216ed8cc3b1SBjorn Andersson 	ret = regulator_bulk_enable(ARRAY_SIZE(res->supplies), res->supplies);
1217ed8cc3b1SBjorn Andersson 	if (ret < 0) {
1218ed8cc3b1SBjorn Andersson 		dev_err(dev, "cannot enable regulators\n");
1219ed8cc3b1SBjorn Andersson 		return ret;
1220ed8cc3b1SBjorn Andersson 	}
1221ed8cc3b1SBjorn Andersson 
1222aa9c0df9SPrasad Malisetty 	/* Set TCXO as clock source for pcie_pipe_clk_src */
1223f94c35e0SDmitry Baryshkov 	if (pcie->cfg->pipe_clk_need_muxing)
1224aa9c0df9SPrasad Malisetty 		clk_set_parent(res->pipe_clk_src, res->ref_clk_src);
1225aa9c0df9SPrasad Malisetty 
12267081556fSDmitry Baryshkov 	ret = clk_bulk_prepare_enable(res->num_clks, res->clks);
1227ed8cc3b1SBjorn Andersson 	if (ret < 0)
1228ed8cc3b1SBjorn Andersson 		goto err_disable_regulators;
1229ed8cc3b1SBjorn Andersson 
1230ed8cc3b1SBjorn Andersson 	ret = reset_control_assert(res->pci_reset);
1231ed8cc3b1SBjorn Andersson 	if (ret < 0) {
1232ed8cc3b1SBjorn Andersson 		dev_err(dev, "cannot deassert pci reset\n");
1233ed8cc3b1SBjorn Andersson 		goto err_disable_clocks;
1234ed8cc3b1SBjorn Andersson 	}
1235ed8cc3b1SBjorn Andersson 
1236ed8cc3b1SBjorn Andersson 	usleep_range(1000, 1500);
1237ed8cc3b1SBjorn Andersson 
1238ed8cc3b1SBjorn Andersson 	ret = reset_control_deassert(res->pci_reset);
1239ed8cc3b1SBjorn Andersson 	if (ret < 0) {
1240ed8cc3b1SBjorn Andersson 		dev_err(dev, "cannot deassert pci reset\n");
1241ed8cc3b1SBjorn Andersson 		goto err_disable_clocks;
1242ed8cc3b1SBjorn Andersson 	}
1243ed8cc3b1SBjorn Andersson 
12441c5aa037SDmitry Baryshkov 	/* Wait for reset to complete, required on SM8450 */
12451c5aa037SDmitry Baryshkov 	usleep_range(1000, 1500);
12461c5aa037SDmitry Baryshkov 
1247ed8cc3b1SBjorn Andersson 	/* configure PCIe to RC mode */
1248ed8cc3b1SBjorn Andersson 	writel(DEVICE_TYPE_RC, pcie->parf + PCIE20_PARF_DEVICE_TYPE);
1249ed8cc3b1SBjorn Andersson 
1250ed8cc3b1SBjorn Andersson 	/* enable PCIe clocks and resets */
1251ed8cc3b1SBjorn Andersson 	val = readl(pcie->parf + PCIE20_PARF_PHY_CTRL);
1252ed8cc3b1SBjorn Andersson 	val &= ~BIT(0);
1253ed8cc3b1SBjorn Andersson 	writel(val, pcie->parf + PCIE20_PARF_PHY_CTRL);
1254ed8cc3b1SBjorn Andersson 
1255ed8cc3b1SBjorn Andersson 	/* change DBI base address */
1256ed8cc3b1SBjorn Andersson 	writel(0, pcie->parf + PCIE20_PARF_DBI_BASE_ADDR);
1257ed8cc3b1SBjorn Andersson 
1258ed8cc3b1SBjorn Andersson 	/* MAC PHY_POWERDOWN MUX DISABLE  */
1259ed8cc3b1SBjorn Andersson 	val = readl(pcie->parf + PCIE20_PARF_SYS_CTRL);
1260ed8cc3b1SBjorn Andersson 	val &= ~BIT(29);
1261ed8cc3b1SBjorn Andersson 	writel(val, pcie->parf + PCIE20_PARF_SYS_CTRL);
1262ed8cc3b1SBjorn Andersson 
1263ed8cc3b1SBjorn Andersson 	val = readl(pcie->parf + PCIE20_PARF_MHI_CLOCK_RESET_CTRL);
1264ed8cc3b1SBjorn Andersson 	val |= BIT(4);
1265ed8cc3b1SBjorn Andersson 	writel(val, pcie->parf + PCIE20_PARF_MHI_CLOCK_RESET_CTRL);
1266ed8cc3b1SBjorn Andersson 
1267ed8cc3b1SBjorn Andersson 	if (IS_ENABLED(CONFIG_PCI_MSI)) {
1268ed8cc3b1SBjorn Andersson 		val = readl(pcie->parf + PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT);
1269ed8cc3b1SBjorn Andersson 		val |= BIT(31);
1270ed8cc3b1SBjorn Andersson 		writel(val, pcie->parf + PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT);
1271ed8cc3b1SBjorn Andersson 	}
1272ed8cc3b1SBjorn Andersson 
1273ed8cc3b1SBjorn Andersson 	return 0;
1274ed8cc3b1SBjorn Andersson err_disable_clocks:
12757081556fSDmitry Baryshkov 	clk_bulk_disable_unprepare(res->num_clks, res->clks);
1276ed8cc3b1SBjorn Andersson err_disable_regulators:
1277ed8cc3b1SBjorn Andersson 	regulator_bulk_disable(ARRAY_SIZE(res->supplies), res->supplies);
1278ed8cc3b1SBjorn Andersson 
1279ed8cc3b1SBjorn Andersson 	return ret;
1280ed8cc3b1SBjorn Andersson }
1281ed8cc3b1SBjorn Andersson 
1282ed8cc3b1SBjorn Andersson static void qcom_pcie_deinit_2_7_0(struct qcom_pcie *pcie)
1283ed8cc3b1SBjorn Andersson {
1284ed8cc3b1SBjorn Andersson 	struct qcom_pcie_resources_2_7_0 *res = &pcie->res.v2_7_0;
1285ed8cc3b1SBjorn Andersson 
12867081556fSDmitry Baryshkov 	clk_bulk_disable_unprepare(res->num_clks, res->clks);
1287ed8cc3b1SBjorn Andersson 	regulator_bulk_disable(ARRAY_SIZE(res->supplies), res->supplies);
1288ed8cc3b1SBjorn Andersson }
1289ed8cc3b1SBjorn Andersson 
1290ed8cc3b1SBjorn Andersson static int qcom_pcie_post_init_2_7_0(struct qcom_pcie *pcie)
1291ed8cc3b1SBjorn Andersson {
1292ed8cc3b1SBjorn Andersson 	struct qcom_pcie_resources_2_7_0 *res = &pcie->res.v2_7_0;
1293ed8cc3b1SBjorn Andersson 
1294aa9c0df9SPrasad Malisetty 	/* Set pipe clock as clock source for pcie_pipe_clk_src */
1295f94c35e0SDmitry Baryshkov 	if (pcie->cfg->pipe_clk_need_muxing)
1296aa9c0df9SPrasad Malisetty 		clk_set_parent(res->pipe_clk_src, res->phy_pipe_clk);
1297aa9c0df9SPrasad Malisetty 
1298*affac98aSDmitry Baryshkov 	return 0;
1299ed8cc3b1SBjorn Andersson }
1300ed8cc3b1SBjorn Andersson 
13016e0832faSShawn Lin static int qcom_pcie_link_up(struct dw_pcie *pci)
13026e0832faSShawn Lin {
13037b87ddc0SRob Herring 	u16 offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
13047b87ddc0SRob Herring 	u16 val = readw(pci->dbi_base + offset + PCI_EXP_LNKSTA);
13056e0832faSShawn Lin 
13066e0832faSShawn Lin 	return !!(val & PCI_EXP_LNKSTA_DLLLA);
13076e0832faSShawn Lin }
13086e0832faSShawn Lin 
13094c939882SManivannan Sadhasivam static int qcom_pcie_config_sid_sm8250(struct qcom_pcie *pcie)
13104c939882SManivannan Sadhasivam {
13114c939882SManivannan Sadhasivam 	/* iommu map structure */
13124c939882SManivannan Sadhasivam 	struct {
13134c939882SManivannan Sadhasivam 		u32 bdf;
13144c939882SManivannan Sadhasivam 		u32 phandle;
13154c939882SManivannan Sadhasivam 		u32 smmu_sid;
13164c939882SManivannan Sadhasivam 		u32 smmu_sid_len;
13174c939882SManivannan Sadhasivam 	} *map;
13184c939882SManivannan Sadhasivam 	void __iomem *bdf_to_sid_base = pcie->parf + PCIE20_PARF_BDF_TO_SID_TABLE_N;
13194c939882SManivannan Sadhasivam 	struct device *dev = pcie->pci->dev;
13204c939882SManivannan Sadhasivam 	u8 qcom_pcie_crc8_table[CRC8_TABLE_SIZE];
13214c939882SManivannan Sadhasivam 	int i, nr_map, size = 0;
13224c939882SManivannan Sadhasivam 	u32 smmu_sid_base;
13234c939882SManivannan Sadhasivam 
13244c939882SManivannan Sadhasivam 	of_get_property(dev->of_node, "iommu-map", &size);
13254c939882SManivannan Sadhasivam 	if (!size)
13264c939882SManivannan Sadhasivam 		return 0;
13274c939882SManivannan Sadhasivam 
13284c939882SManivannan Sadhasivam 	map = kzalloc(size, GFP_KERNEL);
13294c939882SManivannan Sadhasivam 	if (!map)
13304c939882SManivannan Sadhasivam 		return -ENOMEM;
13314c939882SManivannan Sadhasivam 
13324c939882SManivannan Sadhasivam 	of_property_read_u32_array(dev->of_node,
13334c939882SManivannan Sadhasivam 		"iommu-map", (u32 *)map, size / sizeof(u32));
13344c939882SManivannan Sadhasivam 
13354c939882SManivannan Sadhasivam 	nr_map = size / (sizeof(*map));
13364c939882SManivannan Sadhasivam 
13374c939882SManivannan Sadhasivam 	crc8_populate_msb(qcom_pcie_crc8_table, QCOM_PCIE_CRC8_POLYNOMIAL);
13384c939882SManivannan Sadhasivam 
13394c939882SManivannan Sadhasivam 	/* Registers need to be zero out first */
13404c939882SManivannan Sadhasivam 	memset_io(bdf_to_sid_base, 0, CRC8_TABLE_SIZE * sizeof(u32));
13414c939882SManivannan Sadhasivam 
13424c939882SManivannan Sadhasivam 	/* Extract the SMMU SID base from the first entry of iommu-map */
13434c939882SManivannan Sadhasivam 	smmu_sid_base = map[0].smmu_sid;
13444c939882SManivannan Sadhasivam 
13454c939882SManivannan Sadhasivam 	/* Look for an available entry to hold the mapping */
13464c939882SManivannan Sadhasivam 	for (i = 0; i < nr_map; i++) {
13473f13d611SManivannan Sadhasivam 		__be16 bdf_be = cpu_to_be16(map[i].bdf);
13484c939882SManivannan Sadhasivam 		u32 val;
13494c939882SManivannan Sadhasivam 		u8 hash;
13504c939882SManivannan Sadhasivam 
13514c939882SManivannan Sadhasivam 		hash = crc8(qcom_pcie_crc8_table, (u8 *)&bdf_be, sizeof(bdf_be),
13524c939882SManivannan Sadhasivam 			0);
13534c939882SManivannan Sadhasivam 
13544c939882SManivannan Sadhasivam 		val = readl(bdf_to_sid_base + hash * sizeof(u32));
13554c939882SManivannan Sadhasivam 
13564c939882SManivannan Sadhasivam 		/* If the register is already populated, look for next available entry */
13574c939882SManivannan Sadhasivam 		while (val) {
13584c939882SManivannan Sadhasivam 			u8 current_hash = hash++;
13594c939882SManivannan Sadhasivam 			u8 next_mask = 0xff;
13604c939882SManivannan Sadhasivam 
13614c939882SManivannan Sadhasivam 			/* If NEXT field is NULL then update it with next hash */
13624c939882SManivannan Sadhasivam 			if (!(val & next_mask)) {
13634c939882SManivannan Sadhasivam 				val |= (u32)hash;
13644c939882SManivannan Sadhasivam 				writel(val, bdf_to_sid_base + current_hash * sizeof(u32));
13654c939882SManivannan Sadhasivam 			}
13664c939882SManivannan Sadhasivam 
13674c939882SManivannan Sadhasivam 			val = readl(bdf_to_sid_base + hash * sizeof(u32));
13684c939882SManivannan Sadhasivam 		}
13694c939882SManivannan Sadhasivam 
13704c939882SManivannan Sadhasivam 		/* BDF [31:16] | SID [15:8] | NEXT [7:0] */
13714c939882SManivannan Sadhasivam 		val = map[i].bdf << 16 | (map[i].smmu_sid - smmu_sid_base) << 8 | 0;
13724c939882SManivannan Sadhasivam 		writel(val, bdf_to_sid_base + hash * sizeof(u32));
13734c939882SManivannan Sadhasivam 	}
13744c939882SManivannan Sadhasivam 
13754c939882SManivannan Sadhasivam 	kfree(map);
13764c939882SManivannan Sadhasivam 
13774c939882SManivannan Sadhasivam 	return 0;
13784c939882SManivannan Sadhasivam }
13794c939882SManivannan Sadhasivam 
13806e0832faSShawn Lin static int qcom_pcie_host_init(struct pcie_port *pp)
13816e0832faSShawn Lin {
13826e0832faSShawn Lin 	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
13836e0832faSShawn Lin 	struct qcom_pcie *pcie = to_qcom_pcie(pci);
13846e0832faSShawn Lin 	int ret;
13856e0832faSShawn Lin 
13866e0832faSShawn Lin 	qcom_ep_reset_assert(pcie);
13876e0832faSShawn Lin 
1388f94c35e0SDmitry Baryshkov 	ret = pcie->cfg->ops->init(pcie);
13896e0832faSShawn Lin 	if (ret)
13906e0832faSShawn Lin 		return ret;
13916e0832faSShawn Lin 
13926e0832faSShawn Lin 	ret = phy_power_on(pcie->phy);
13936e0832faSShawn Lin 	if (ret)
13946e0832faSShawn Lin 		goto err_deinit;
13956e0832faSShawn Lin 
1396f94c35e0SDmitry Baryshkov 	if (pcie->cfg->ops->post_init) {
1397f94c35e0SDmitry Baryshkov 		ret = pcie->cfg->ops->post_init(pcie);
13986e0832faSShawn Lin 		if (ret)
13996e0832faSShawn Lin 			goto err_disable_phy;
14006e0832faSShawn Lin 	}
14016e0832faSShawn Lin 
14026e0832faSShawn Lin 	qcom_ep_reset_deassert(pcie);
14036e0832faSShawn Lin 
1404f94c35e0SDmitry Baryshkov 	if (pcie->cfg->ops->config_sid) {
1405f94c35e0SDmitry Baryshkov 		ret = pcie->cfg->ops->config_sid(pcie);
14064c939882SManivannan Sadhasivam 		if (ret)
14074c939882SManivannan Sadhasivam 			goto err;
14084c939882SManivannan Sadhasivam 	}
14094c939882SManivannan Sadhasivam 
14106e0832faSShawn Lin 	return 0;
1411886a9c13SRob Herring 
14124c939882SManivannan Sadhasivam err:
14134c939882SManivannan Sadhasivam 	qcom_ep_reset_assert(pcie);
1414f94c35e0SDmitry Baryshkov 	if (pcie->cfg->ops->post_deinit)
1415f94c35e0SDmitry Baryshkov 		pcie->cfg->ops->post_deinit(pcie);
14166e0832faSShawn Lin err_disable_phy:
14176e0832faSShawn Lin 	phy_power_off(pcie->phy);
14186e0832faSShawn Lin err_deinit:
1419f94c35e0SDmitry Baryshkov 	pcie->cfg->ops->deinit(pcie);
14206e0832faSShawn Lin 
14216e0832faSShawn Lin 	return ret;
14226e0832faSShawn Lin }
14236e0832faSShawn Lin 
14246e0832faSShawn Lin static const struct dw_pcie_host_ops qcom_pcie_dw_ops = {
14256e0832faSShawn Lin 	.host_init = qcom_pcie_host_init,
14266e0832faSShawn Lin };
14276e0832faSShawn Lin 
14286e0832faSShawn Lin /* Qcom IP rev.: 2.1.0	Synopsys IP rev.: 4.01a */
14296e0832faSShawn Lin static const struct qcom_pcie_ops ops_2_1_0 = {
14306e0832faSShawn Lin 	.get_resources = qcom_pcie_get_resources_2_1_0,
14316e0832faSShawn Lin 	.init = qcom_pcie_init_2_1_0,
143236d9018dSRobert Marko 	.post_init = qcom_pcie_post_init_2_1_0,
14336e0832faSShawn Lin 	.deinit = qcom_pcie_deinit_2_1_0,
14346e0832faSShawn Lin 	.ltssm_enable = qcom_pcie_2_1_0_ltssm_enable,
14356e0832faSShawn Lin };
14366e0832faSShawn Lin 
14376e0832faSShawn Lin /* Qcom IP rev.: 1.0.0	Synopsys IP rev.: 4.11a */
14386e0832faSShawn Lin static const struct qcom_pcie_ops ops_1_0_0 = {
14396e0832faSShawn Lin 	.get_resources = qcom_pcie_get_resources_1_0_0,
14406e0832faSShawn Lin 	.init = qcom_pcie_init_1_0_0,
144136d9018dSRobert Marko 	.post_init = qcom_pcie_post_init_1_0_0,
14426e0832faSShawn Lin 	.deinit = qcom_pcie_deinit_1_0_0,
14436e0832faSShawn Lin 	.ltssm_enable = qcom_pcie_2_1_0_ltssm_enable,
14446e0832faSShawn Lin };
14456e0832faSShawn Lin 
14466e0832faSShawn Lin /* Qcom IP rev.: 2.3.2	Synopsys IP rev.: 4.21a */
14476e0832faSShawn Lin static const struct qcom_pcie_ops ops_2_3_2 = {
14486e0832faSShawn Lin 	.get_resources = qcom_pcie_get_resources_2_3_2,
14496e0832faSShawn Lin 	.init = qcom_pcie_init_2_3_2,
14506e0832faSShawn Lin 	.post_init = qcom_pcie_post_init_2_3_2,
14516e0832faSShawn Lin 	.deinit = qcom_pcie_deinit_2_3_2,
14526e0832faSShawn Lin 	.ltssm_enable = qcom_pcie_2_3_2_ltssm_enable,
14536e0832faSShawn Lin };
14546e0832faSShawn Lin 
14556e0832faSShawn Lin /* Qcom IP rev.: 2.4.0	Synopsys IP rev.: 4.20a */
14566e0832faSShawn Lin static const struct qcom_pcie_ops ops_2_4_0 = {
14576e0832faSShawn Lin 	.get_resources = qcom_pcie_get_resources_2_4_0,
14586e0832faSShawn Lin 	.init = qcom_pcie_init_2_4_0,
145936d9018dSRobert Marko 	.post_init = qcom_pcie_post_init_2_4_0,
14606e0832faSShawn Lin 	.deinit = qcom_pcie_deinit_2_4_0,
14616e0832faSShawn Lin 	.ltssm_enable = qcom_pcie_2_3_2_ltssm_enable,
14626e0832faSShawn Lin };
14636e0832faSShawn Lin 
14646e0832faSShawn Lin /* Qcom IP rev.: 2.3.3	Synopsys IP rev.: 4.30a */
14656e0832faSShawn Lin static const struct qcom_pcie_ops ops_2_3_3 = {
14666e0832faSShawn Lin 	.get_resources = qcom_pcie_get_resources_2_3_3,
14676e0832faSShawn Lin 	.init = qcom_pcie_init_2_3_3,
1468a0e43bb9SRobert Marko 	.post_init = qcom_pcie_post_init_2_3_3,
14696e0832faSShawn Lin 	.deinit = qcom_pcie_deinit_2_3_3,
14706e0832faSShawn Lin 	.ltssm_enable = qcom_pcie_2_3_2_ltssm_enable,
14716e0832faSShawn Lin };
14726e0832faSShawn Lin 
1473ed8cc3b1SBjorn Andersson /* Qcom IP rev.: 2.7.0	Synopsys IP rev.: 4.30a */
1474ed8cc3b1SBjorn Andersson static const struct qcom_pcie_ops ops_2_7_0 = {
1475ed8cc3b1SBjorn Andersson 	.get_resources = qcom_pcie_get_resources_2_7_0,
1476ed8cc3b1SBjorn Andersson 	.init = qcom_pcie_init_2_7_0,
1477ed8cc3b1SBjorn Andersson 	.deinit = qcom_pcie_deinit_2_7_0,
1478ed8cc3b1SBjorn Andersson 	.ltssm_enable = qcom_pcie_2_3_2_ltssm_enable,
1479ed8cc3b1SBjorn Andersson 	.post_init = qcom_pcie_post_init_2_7_0,
1480ed8cc3b1SBjorn Andersson };
1481ed8cc3b1SBjorn Andersson 
1482e1dd639eSManivannan Sadhasivam /* Qcom IP rev.: 1.9.0 */
1483e1dd639eSManivannan Sadhasivam static const struct qcom_pcie_ops ops_1_9_0 = {
1484e1dd639eSManivannan Sadhasivam 	.get_resources = qcom_pcie_get_resources_2_7_0,
1485e1dd639eSManivannan Sadhasivam 	.init = qcom_pcie_init_2_7_0,
1486e1dd639eSManivannan Sadhasivam 	.deinit = qcom_pcie_deinit_2_7_0,
1487e1dd639eSManivannan Sadhasivam 	.ltssm_enable = qcom_pcie_2_3_2_ltssm_enable,
1488e1dd639eSManivannan Sadhasivam 	.post_init = qcom_pcie_post_init_2_7_0,
14894c939882SManivannan Sadhasivam 	.config_sid = qcom_pcie_config_sid_sm8250,
1490e1dd639eSManivannan Sadhasivam };
1491e1dd639eSManivannan Sadhasivam 
1492b89ff410SPrasad Malisetty static const struct qcom_pcie_cfg apq8084_cfg = {
1493b89ff410SPrasad Malisetty 	.ops = &ops_1_0_0,
1494b89ff410SPrasad Malisetty };
1495b89ff410SPrasad Malisetty 
1496b89ff410SPrasad Malisetty static const struct qcom_pcie_cfg ipq8064_cfg = {
1497b89ff410SPrasad Malisetty 	.ops = &ops_2_1_0,
1498b89ff410SPrasad Malisetty };
1499b89ff410SPrasad Malisetty 
1500b89ff410SPrasad Malisetty static const struct qcom_pcie_cfg msm8996_cfg = {
1501b89ff410SPrasad Malisetty 	.ops = &ops_2_3_2,
1502b89ff410SPrasad Malisetty };
1503b89ff410SPrasad Malisetty 
1504b89ff410SPrasad Malisetty static const struct qcom_pcie_cfg ipq8074_cfg = {
1505b89ff410SPrasad Malisetty 	.ops = &ops_2_3_3,
1506b89ff410SPrasad Malisetty };
1507b89ff410SPrasad Malisetty 
1508b89ff410SPrasad Malisetty static const struct qcom_pcie_cfg ipq4019_cfg = {
1509b89ff410SPrasad Malisetty 	.ops = &ops_2_4_0,
1510b89ff410SPrasad Malisetty };
1511b89ff410SPrasad Malisetty 
1512b89ff410SPrasad Malisetty static const struct qcom_pcie_cfg sdm845_cfg = {
1513b89ff410SPrasad Malisetty 	.ops = &ops_2_7_0,
15141c5aa037SDmitry Baryshkov 	.has_tbu_clk = true,
1515b89ff410SPrasad Malisetty };
1516b89ff410SPrasad Malisetty 
1517a935601eSBhupesh Sharma static const struct qcom_pcie_cfg sm8150_cfg = {
1518a935601eSBhupesh Sharma 	/* sm8150 has qcom IP rev 1.5.0. However 1.5.0 ops are same as
1519a935601eSBhupesh Sharma 	 * 1.9.0, so reuse the same.
1520a935601eSBhupesh Sharma 	 */
1521a935601eSBhupesh Sharma 	.ops = &ops_1_9_0,
1522a935601eSBhupesh Sharma };
1523a935601eSBhupesh Sharma 
1524b89ff410SPrasad Malisetty static const struct qcom_pcie_cfg sm8250_cfg = {
1525b89ff410SPrasad Malisetty 	.ops = &ops_1_9_0,
15261c5aa037SDmitry Baryshkov 	.has_tbu_clk = true,
15270614f98bSDmitry Baryshkov 	.has_ddrss_sf_tbu_clk = true,
1528b89ff410SPrasad Malisetty };
1529b89ff410SPrasad Malisetty 
15301c5aa037SDmitry Baryshkov static const struct qcom_pcie_cfg sm8450_pcie0_cfg = {
15311c5aa037SDmitry Baryshkov 	.ops = &ops_1_9_0,
15321c5aa037SDmitry Baryshkov 	.has_ddrss_sf_tbu_clk = true,
15331c5aa037SDmitry Baryshkov 	.pipe_clk_need_muxing = true,
15341c5aa037SDmitry Baryshkov 	.has_aggre0_clk = true,
15351c5aa037SDmitry Baryshkov 	.has_aggre1_clk = true,
15361c5aa037SDmitry Baryshkov };
15371c5aa037SDmitry Baryshkov 
15381c5aa037SDmitry Baryshkov static const struct qcom_pcie_cfg sm8450_pcie1_cfg = {
15391c5aa037SDmitry Baryshkov 	.ops = &ops_1_9_0,
15401c5aa037SDmitry Baryshkov 	.has_ddrss_sf_tbu_clk = true,
15411c5aa037SDmitry Baryshkov 	.pipe_clk_need_muxing = true,
15421c5aa037SDmitry Baryshkov 	.has_aggre1_clk = true,
1543b89ff410SPrasad Malisetty };
1544b89ff410SPrasad Malisetty 
1545b89ff410SPrasad Malisetty static const struct qcom_pcie_cfg sc7280_cfg = {
1546b89ff410SPrasad Malisetty 	.ops = &ops_1_9_0,
15471c5aa037SDmitry Baryshkov 	.has_tbu_clk = true,
1548aa9c0df9SPrasad Malisetty 	.pipe_clk_need_muxing = true,
1549b89ff410SPrasad Malisetty };
1550b89ff410SPrasad Malisetty 
1551134b5ce3SBjorn Andersson static const struct qcom_pcie_cfg sc8180x_cfg = {
1552134b5ce3SBjorn Andersson 	.ops = &ops_1_9_0,
1553134b5ce3SBjorn Andersson 	.has_tbu_clk = true,
1554134b5ce3SBjorn Andersson };
1555134b5ce3SBjorn Andersson 
15566e0832faSShawn Lin static const struct dw_pcie_ops dw_pcie_ops = {
15576e0832faSShawn Lin 	.link_up = qcom_pcie_link_up,
1558886a9c13SRob Herring 	.start_link = qcom_pcie_start_link,
15596e0832faSShawn Lin };
15606e0832faSShawn Lin 
15616e0832faSShawn Lin static int qcom_pcie_probe(struct platform_device *pdev)
15626e0832faSShawn Lin {
15636e0832faSShawn Lin 	struct device *dev = &pdev->dev;
15646e0832faSShawn Lin 	struct pcie_port *pp;
15656e0832faSShawn Lin 	struct dw_pcie *pci;
15666e0832faSShawn Lin 	struct qcom_pcie *pcie;
1567b89ff410SPrasad Malisetty 	const struct qcom_pcie_cfg *pcie_cfg;
15686e0832faSShawn Lin 	int ret;
15696e0832faSShawn Lin 
15704e0e9053SChristophe JAILLET 	pcie_cfg = of_device_get_match_data(dev);
15714e0e9053SChristophe JAILLET 	if (!pcie_cfg || !pcie_cfg->ops) {
15724e0e9053SChristophe JAILLET 		dev_err(dev, "Invalid platform data\n");
15734e0e9053SChristophe JAILLET 		return -EINVAL;
15744e0e9053SChristophe JAILLET 	}
15754e0e9053SChristophe JAILLET 
15766e0832faSShawn Lin 	pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL);
15776e0832faSShawn Lin 	if (!pcie)
15786e0832faSShawn Lin 		return -ENOMEM;
15796e0832faSShawn Lin 
15806e0832faSShawn Lin 	pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL);
15816e0832faSShawn Lin 	if (!pci)
15826e0832faSShawn Lin 		return -ENOMEM;
15836e0832faSShawn Lin 
15846e0832faSShawn Lin 	pm_runtime_enable(dev);
15856e5da6f7SBjorn Andersson 	ret = pm_runtime_get_sync(dev);
1586cb52a402SDinghao Liu 	if (ret < 0)
1587cb52a402SDinghao Liu 		goto err_pm_runtime_put;
15886e5da6f7SBjorn Andersson 
15896e0832faSShawn Lin 	pci->dev = dev;
15906e0832faSShawn Lin 	pci->ops = &dw_pcie_ops;
15916e0832faSShawn Lin 	pp = &pci->pp;
15926e0832faSShawn Lin 
15936e0832faSShawn Lin 	pcie->pci = pci;
15946e0832faSShawn Lin 
1595f94c35e0SDmitry Baryshkov 	pcie->cfg = pcie_cfg;
15966e0832faSShawn Lin 
159702b485e3SBjorn Andersson 	pcie->reset = devm_gpiod_get_optional(dev, "perst", GPIOD_OUT_HIGH);
15986e5da6f7SBjorn Andersson 	if (IS_ERR(pcie->reset)) {
15996e5da6f7SBjorn Andersson 		ret = PTR_ERR(pcie->reset);
16006e5da6f7SBjorn Andersson 		goto err_pm_runtime_put;
16016e5da6f7SBjorn Andersson 	}
16026e0832faSShawn Lin 
1603936fa5cdSDejin Zheng 	pcie->parf = devm_platform_ioremap_resource_byname(pdev, "parf");
16046e5da6f7SBjorn Andersson 	if (IS_ERR(pcie->parf)) {
16056e5da6f7SBjorn Andersson 		ret = PTR_ERR(pcie->parf);
16066e5da6f7SBjorn Andersson 		goto err_pm_runtime_put;
16076e5da6f7SBjorn Andersson 	}
16086e0832faSShawn Lin 
1609936fa5cdSDejin Zheng 	pcie->elbi = devm_platform_ioremap_resource_byname(pdev, "elbi");
16106e5da6f7SBjorn Andersson 	if (IS_ERR(pcie->elbi)) {
16116e5da6f7SBjorn Andersson 		ret = PTR_ERR(pcie->elbi);
16126e5da6f7SBjorn Andersson 		goto err_pm_runtime_put;
16136e5da6f7SBjorn Andersson 	}
16146e0832faSShawn Lin 
16156e0832faSShawn Lin 	pcie->phy = devm_phy_optional_get(dev, "pciephy");
16166e5da6f7SBjorn Andersson 	if (IS_ERR(pcie->phy)) {
16176e5da6f7SBjorn Andersson 		ret = PTR_ERR(pcie->phy);
16186e5da6f7SBjorn Andersson 		goto err_pm_runtime_put;
16196e5da6f7SBjorn Andersson 	}
16206e0832faSShawn Lin 
1621f94c35e0SDmitry Baryshkov 	ret = pcie->cfg->ops->get_resources(pcie);
16226e0832faSShawn Lin 	if (ret)
16236e5da6f7SBjorn Andersson 		goto err_pm_runtime_put;
16246e0832faSShawn Lin 
16256e0832faSShawn Lin 	pp->ops = &qcom_pcie_dw_ops;
16266e0832faSShawn Lin 
16276e0832faSShawn Lin 	ret = phy_init(pcie->phy);
162887d83b96SJohan Hovold 	if (ret)
16296e5da6f7SBjorn Andersson 		goto err_pm_runtime_put;
16306e0832faSShawn Lin 
16316e0832faSShawn Lin 	platform_set_drvdata(pdev, pcie);
16326e0832faSShawn Lin 
16336e0832faSShawn Lin 	ret = dw_pcie_host_init(pp);
16346e0832faSShawn Lin 	if (ret) {
16356e0832faSShawn Lin 		dev_err(dev, "cannot initialize host\n");
163683013631SJohan Hovold 		goto err_phy_exit;
16376e0832faSShawn Lin 	}
16386e0832faSShawn Lin 
16396e0832faSShawn Lin 	return 0;
16406e5da6f7SBjorn Andersson 
164183013631SJohan Hovold err_phy_exit:
164283013631SJohan Hovold 	phy_exit(pcie->phy);
16436e5da6f7SBjorn Andersson err_pm_runtime_put:
16446e5da6f7SBjorn Andersson 	pm_runtime_put(dev);
16456e5da6f7SBjorn Andersson 	pm_runtime_disable(dev);
16466e5da6f7SBjorn Andersson 
16476e5da6f7SBjorn Andersson 	return ret;
16486e0832faSShawn Lin }
16496e0832faSShawn Lin 
16506e0832faSShawn Lin static const struct of_device_id qcom_pcie_match[] = {
1651b89ff410SPrasad Malisetty 	{ .compatible = "qcom,pcie-apq8084", .data = &apq8084_cfg },
1652b89ff410SPrasad Malisetty 	{ .compatible = "qcom,pcie-ipq8064", .data = &ipq8064_cfg },
1653b89ff410SPrasad Malisetty 	{ .compatible = "qcom,pcie-ipq8064-v2", .data = &ipq8064_cfg },
1654b89ff410SPrasad Malisetty 	{ .compatible = "qcom,pcie-apq8064", .data = &ipq8064_cfg },
1655b89ff410SPrasad Malisetty 	{ .compatible = "qcom,pcie-msm8996", .data = &msm8996_cfg },
1656b89ff410SPrasad Malisetty 	{ .compatible = "qcom,pcie-ipq8074", .data = &ipq8074_cfg },
1657b89ff410SPrasad Malisetty 	{ .compatible = "qcom,pcie-ipq4019", .data = &ipq4019_cfg },
1658b89ff410SPrasad Malisetty 	{ .compatible = "qcom,pcie-qcs404", .data = &ipq4019_cfg },
1659b89ff410SPrasad Malisetty 	{ .compatible = "qcom,pcie-sdm845", .data = &sdm845_cfg },
1660a935601eSBhupesh Sharma 	{ .compatible = "qcom,pcie-sm8150", .data = &sm8150_cfg },
1661b89ff410SPrasad Malisetty 	{ .compatible = "qcom,pcie-sm8250", .data = &sm8250_cfg },
1662134b5ce3SBjorn Andersson 	{ .compatible = "qcom,pcie-sc8180x", .data = &sc8180x_cfg },
16631c5aa037SDmitry Baryshkov 	{ .compatible = "qcom,pcie-sm8450-pcie0", .data = &sm8450_pcie0_cfg },
16641c5aa037SDmitry Baryshkov 	{ .compatible = "qcom,pcie-sm8450-pcie1", .data = &sm8450_pcie1_cfg },
1665b89ff410SPrasad Malisetty 	{ .compatible = "qcom,pcie-sc7280", .data = &sc7280_cfg },
16666e0832faSShawn Lin 	{ }
16676e0832faSShawn Lin };
16686e0832faSShawn Lin 
1669322f0343SMarc Gonzalez static void qcom_fixup_class(struct pci_dev *dev)
1670322f0343SMarc Gonzalez {
1671904b10fbSPali Rohár 	dev->class = PCI_CLASS_BRIDGE_PCI_NORMAL;
1672322f0343SMarc Gonzalez }
1673604f3956SBjorn Andersson DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_QCOM, 0x0101, qcom_fixup_class);
1674604f3956SBjorn Andersson DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_QCOM, 0x0104, qcom_fixup_class);
1675604f3956SBjorn Andersson DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_QCOM, 0x0106, qcom_fixup_class);
1676604f3956SBjorn Andersson DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_QCOM, 0x0107, qcom_fixup_class);
1677604f3956SBjorn Andersson DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_QCOM, 0x0302, qcom_fixup_class);
1678604f3956SBjorn Andersson DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_QCOM, 0x1000, qcom_fixup_class);
1679604f3956SBjorn Andersson DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_QCOM, 0x1001, qcom_fixup_class);
1680322f0343SMarc Gonzalez 
16816e0832faSShawn Lin static struct platform_driver qcom_pcie_driver = {
16826e0832faSShawn Lin 	.probe = qcom_pcie_probe,
16836e0832faSShawn Lin 	.driver = {
16846e0832faSShawn Lin 		.name = "qcom-pcie",
16856e0832faSShawn Lin 		.suppress_bind_attrs = true,
16866e0832faSShawn Lin 		.of_match_table = qcom_pcie_match,
16876e0832faSShawn Lin 	},
16886e0832faSShawn Lin };
16896e0832faSShawn Lin builtin_platform_driver(qcom_pcie_driver);
1690