16e0832faSShawn Lin // SPDX-License-Identifier: GPL-2.0+
26e0832faSShawn Lin /*
36e0832faSShawn Lin  * Rockchip AXI PCIe host controller driver
46e0832faSShawn Lin  *
56e0832faSShawn Lin  * Copyright (c) 2016 Rockchip, Inc.
66e0832faSShawn Lin  *
76e0832faSShawn Lin  * Author: Shawn Lin <shawn.lin@rock-chips.com>
86e0832faSShawn Lin  *         Wenrui Li <wenrui.li@rock-chips.com>
96e0832faSShawn Lin  *
106e0832faSShawn Lin  * Bits taken from Synopsys DesignWare Host controller driver and
116e0832faSShawn Lin  * ARM PCI Host generic driver.
126e0832faSShawn Lin  */
136e0832faSShawn Lin 
146e0832faSShawn Lin #include <linux/clk.h>
156e0832faSShawn Lin #include <linux/delay.h>
166e0832faSShawn Lin #include <linux/gpio/consumer.h>
179dd3c7c4SRick Wertenbroek #include <linux/iopoll.h>
18*c925cfafSRob Herring #include <linux/of.h>
196e0832faSShawn Lin #include <linux/of_pci.h>
206e0832faSShawn Lin #include <linux/phy/phy.h>
216e0832faSShawn Lin #include <linux/platform_device.h>
226e0832faSShawn Lin #include <linux/reset.h>
236e0832faSShawn Lin 
246e0832faSShawn Lin #include "../pci.h"
256e0832faSShawn Lin #include "pcie-rockchip.h"
266e0832faSShawn Lin 
rockchip_pcie_parse_dt(struct rockchip_pcie * rockchip)276e0832faSShawn Lin int rockchip_pcie_parse_dt(struct rockchip_pcie *rockchip)
286e0832faSShawn Lin {
296e0832faSShawn Lin 	struct device *dev = rockchip->dev;
306e0832faSShawn Lin 	struct platform_device *pdev = to_platform_device(dev);
316e0832faSShawn Lin 	struct device_node *node = dev->of_node;
326e0832faSShawn Lin 	struct resource *regs;
336e0832faSShawn Lin 	int err;
346e0832faSShawn Lin 
356e0832faSShawn Lin 	if (rockchip->is_rc) {
366e0832faSShawn Lin 		regs = platform_get_resource_byname(pdev,
376e0832faSShawn Lin 						    IORESOURCE_MEM,
386e0832faSShawn Lin 						    "axi-base");
396e0832faSShawn Lin 		rockchip->reg_base = devm_pci_remap_cfg_resource(dev, regs);
406e0832faSShawn Lin 		if (IS_ERR(rockchip->reg_base))
416e0832faSShawn Lin 			return PTR_ERR(rockchip->reg_base);
426e0832faSShawn Lin 	} else {
436e0832faSShawn Lin 		rockchip->mem_res =
446e0832faSShawn Lin 			platform_get_resource_byname(pdev, IORESOURCE_MEM,
456e0832faSShawn Lin 						     "mem-base");
466e0832faSShawn Lin 		if (!rockchip->mem_res)
476e0832faSShawn Lin 			return -EINVAL;
486e0832faSShawn Lin 	}
496e0832faSShawn Lin 
50e2dcd20bSDejin Zheng 	rockchip->apb_base =
51e2dcd20bSDejin Zheng 		devm_platform_ioremap_resource_byname(pdev, "apb-base");
526e0832faSShawn Lin 	if (IS_ERR(rockchip->apb_base))
536e0832faSShawn Lin 		return PTR_ERR(rockchip->apb_base);
546e0832faSShawn Lin 
556e0832faSShawn Lin 	err = rockchip_pcie_get_phys(rockchip);
566e0832faSShawn Lin 	if (err)
576e0832faSShawn Lin 		return err;
586e0832faSShawn Lin 
596e0832faSShawn Lin 	rockchip->lanes = 1;
606e0832faSShawn Lin 	err = of_property_read_u32(node, "num-lanes", &rockchip->lanes);
616e0832faSShawn Lin 	if (!err && (rockchip->lanes == 0 ||
626e0832faSShawn Lin 		     rockchip->lanes == 3 ||
636e0832faSShawn Lin 		     rockchip->lanes > 4)) {
646e0832faSShawn Lin 		dev_warn(dev, "invalid num-lanes, default to use one lane\n");
656e0832faSShawn Lin 		rockchip->lanes = 1;
666e0832faSShawn Lin 	}
676e0832faSShawn Lin 
686e0832faSShawn Lin 	rockchip->link_gen = of_pci_get_max_link_speed(node);
696e0832faSShawn Lin 	if (rockchip->link_gen < 0 || rockchip->link_gen > 2)
706e0832faSShawn Lin 		rockchip->link_gen = 2;
716e0832faSShawn Lin 
726e0832faSShawn Lin 	rockchip->core_rst = devm_reset_control_get_exclusive(dev, "core");
736e0832faSShawn Lin 	if (IS_ERR(rockchip->core_rst)) {
746e0832faSShawn Lin 		if (PTR_ERR(rockchip->core_rst) != -EPROBE_DEFER)
756e0832faSShawn Lin 			dev_err(dev, "missing core reset property in node\n");
766e0832faSShawn Lin 		return PTR_ERR(rockchip->core_rst);
776e0832faSShawn Lin 	}
786e0832faSShawn Lin 
796e0832faSShawn Lin 	rockchip->mgmt_rst = devm_reset_control_get_exclusive(dev, "mgmt");
806e0832faSShawn Lin 	if (IS_ERR(rockchip->mgmt_rst)) {
816e0832faSShawn Lin 		if (PTR_ERR(rockchip->mgmt_rst) != -EPROBE_DEFER)
826e0832faSShawn Lin 			dev_err(dev, "missing mgmt reset property in node\n");
836e0832faSShawn Lin 		return PTR_ERR(rockchip->mgmt_rst);
846e0832faSShawn Lin 	}
856e0832faSShawn Lin 
866e0832faSShawn Lin 	rockchip->mgmt_sticky_rst = devm_reset_control_get_exclusive(dev,
876e0832faSShawn Lin 								"mgmt-sticky");
886e0832faSShawn Lin 	if (IS_ERR(rockchip->mgmt_sticky_rst)) {
896e0832faSShawn Lin 		if (PTR_ERR(rockchip->mgmt_sticky_rst) != -EPROBE_DEFER)
906e0832faSShawn Lin 			dev_err(dev, "missing mgmt-sticky reset property in node\n");
916e0832faSShawn Lin 		return PTR_ERR(rockchip->mgmt_sticky_rst);
926e0832faSShawn Lin 	}
936e0832faSShawn Lin 
946e0832faSShawn Lin 	rockchip->pipe_rst = devm_reset_control_get_exclusive(dev, "pipe");
956e0832faSShawn Lin 	if (IS_ERR(rockchip->pipe_rst)) {
966e0832faSShawn Lin 		if (PTR_ERR(rockchip->pipe_rst) != -EPROBE_DEFER)
976e0832faSShawn Lin 			dev_err(dev, "missing pipe reset property in node\n");
986e0832faSShawn Lin 		return PTR_ERR(rockchip->pipe_rst);
996e0832faSShawn Lin 	}
1006e0832faSShawn Lin 
1016e0832faSShawn Lin 	rockchip->pm_rst = devm_reset_control_get_exclusive(dev, "pm");
1026e0832faSShawn Lin 	if (IS_ERR(rockchip->pm_rst)) {
1036e0832faSShawn Lin 		if (PTR_ERR(rockchip->pm_rst) != -EPROBE_DEFER)
1046e0832faSShawn Lin 			dev_err(dev, "missing pm reset property in node\n");
1056e0832faSShawn Lin 		return PTR_ERR(rockchip->pm_rst);
1066e0832faSShawn Lin 	}
1076e0832faSShawn Lin 
1086e0832faSShawn Lin 	rockchip->pclk_rst = devm_reset_control_get_exclusive(dev, "pclk");
1096e0832faSShawn Lin 	if (IS_ERR(rockchip->pclk_rst)) {
1106e0832faSShawn Lin 		if (PTR_ERR(rockchip->pclk_rst) != -EPROBE_DEFER)
1116e0832faSShawn Lin 			dev_err(dev, "missing pclk reset property in node\n");
1126e0832faSShawn Lin 		return PTR_ERR(rockchip->pclk_rst);
1136e0832faSShawn Lin 	}
1146e0832faSShawn Lin 
1156e0832faSShawn Lin 	rockchip->aclk_rst = devm_reset_control_get_exclusive(dev, "aclk");
1166e0832faSShawn Lin 	if (IS_ERR(rockchip->aclk_rst)) {
1176e0832faSShawn Lin 		if (PTR_ERR(rockchip->aclk_rst) != -EPROBE_DEFER)
1186e0832faSShawn Lin 			dev_err(dev, "missing aclk reset property in node\n");
1196e0832faSShawn Lin 		return PTR_ERR(rockchip->aclk_rst);
1206e0832faSShawn Lin 	}
1216e0832faSShawn Lin 
1226e0832faSShawn Lin 	if (rockchip->is_rc) {
12358adbfb3SChen-Yu Tsai 		rockchip->ep_gpio = devm_gpiod_get_optional(dev, "ep",
12458adbfb3SChen-Yu Tsai 							    GPIOD_OUT_HIGH);
12558adbfb3SChen-Yu Tsai 		if (IS_ERR(rockchip->ep_gpio))
12658adbfb3SChen-Yu Tsai 			return dev_err_probe(dev, PTR_ERR(rockchip->ep_gpio),
12758adbfb3SChen-Yu Tsai 					     "failed to get ep GPIO\n");
1286e0832faSShawn Lin 	}
1296e0832faSShawn Lin 
1306e0832faSShawn Lin 	rockchip->aclk_pcie = devm_clk_get(dev, "aclk");
1316e0832faSShawn Lin 	if (IS_ERR(rockchip->aclk_pcie)) {
1326e0832faSShawn Lin 		dev_err(dev, "aclk clock not found\n");
1336e0832faSShawn Lin 		return PTR_ERR(rockchip->aclk_pcie);
1346e0832faSShawn Lin 	}
1356e0832faSShawn Lin 
1366e0832faSShawn Lin 	rockchip->aclk_perf_pcie = devm_clk_get(dev, "aclk-perf");
1376e0832faSShawn Lin 	if (IS_ERR(rockchip->aclk_perf_pcie)) {
1386e0832faSShawn Lin 		dev_err(dev, "aclk_perf clock not found\n");
1396e0832faSShawn Lin 		return PTR_ERR(rockchip->aclk_perf_pcie);
1406e0832faSShawn Lin 	}
1416e0832faSShawn Lin 
1426e0832faSShawn Lin 	rockchip->hclk_pcie = devm_clk_get(dev, "hclk");
1436e0832faSShawn Lin 	if (IS_ERR(rockchip->hclk_pcie)) {
1446e0832faSShawn Lin 		dev_err(dev, "hclk clock not found\n");
1456e0832faSShawn Lin 		return PTR_ERR(rockchip->hclk_pcie);
1466e0832faSShawn Lin 	}
1476e0832faSShawn Lin 
1486e0832faSShawn Lin 	rockchip->clk_pcie_pm = devm_clk_get(dev, "pm");
1496e0832faSShawn Lin 	if (IS_ERR(rockchip->clk_pcie_pm)) {
1506e0832faSShawn Lin 		dev_err(dev, "pm clock not found\n");
1516e0832faSShawn Lin 		return PTR_ERR(rockchip->clk_pcie_pm);
1526e0832faSShawn Lin 	}
1536e0832faSShawn Lin 
1546e0832faSShawn Lin 	return 0;
1556e0832faSShawn Lin }
1566e0832faSShawn Lin EXPORT_SYMBOL_GPL(rockchip_pcie_parse_dt);
1576e0832faSShawn Lin 
1589dd3c7c4SRick Wertenbroek #define rockchip_pcie_read_addr(addr) rockchip_pcie_read(rockchip, addr)
1599dd3c7c4SRick Wertenbroek /* 100 ms max wait time for PHY PLLs to lock */
1609dd3c7c4SRick Wertenbroek #define RK_PHY_PLL_LOCK_TIMEOUT_US 100000
1619dd3c7c4SRick Wertenbroek /* Sleep should be less than 20ms */
1629dd3c7c4SRick Wertenbroek #define RK_PHY_PLL_LOCK_SLEEP_US 1000
1639dd3c7c4SRick Wertenbroek 
rockchip_pcie_init_port(struct rockchip_pcie * rockchip)1646e0832faSShawn Lin int rockchip_pcie_init_port(struct rockchip_pcie *rockchip)
1656e0832faSShawn Lin {
1666e0832faSShawn Lin 	struct device *dev = rockchip->dev;
1676e0832faSShawn Lin 	int err, i;
1686e0832faSShawn Lin 	u32 regs;
1696e0832faSShawn Lin 
1706e0832faSShawn Lin 	err = reset_control_assert(rockchip->aclk_rst);
1716e0832faSShawn Lin 	if (err) {
1726e0832faSShawn Lin 		dev_err(dev, "assert aclk_rst err %d\n", err);
1736e0832faSShawn Lin 		return err;
1746e0832faSShawn Lin 	}
1756e0832faSShawn Lin 
1766e0832faSShawn Lin 	err = reset_control_assert(rockchip->pclk_rst);
1776e0832faSShawn Lin 	if (err) {
1786e0832faSShawn Lin 		dev_err(dev, "assert pclk_rst err %d\n", err);
1796e0832faSShawn Lin 		return err;
1806e0832faSShawn Lin 	}
1816e0832faSShawn Lin 
1826e0832faSShawn Lin 	err = reset_control_assert(rockchip->pm_rst);
1836e0832faSShawn Lin 	if (err) {
1846e0832faSShawn Lin 		dev_err(dev, "assert pm_rst err %d\n", err);
1856e0832faSShawn Lin 		return err;
1866e0832faSShawn Lin 	}
1876e0832faSShawn Lin 
1886e0832faSShawn Lin 	for (i = 0; i < MAX_LANE_NUM; i++) {
1896e0832faSShawn Lin 		err = phy_init(rockchip->phys[i]);
1906e0832faSShawn Lin 		if (err) {
1916e0832faSShawn Lin 			dev_err(dev, "init phy%d err %d\n", i, err);
1926e0832faSShawn Lin 			goto err_exit_phy;
1936e0832faSShawn Lin 		}
1946e0832faSShawn Lin 	}
1956e0832faSShawn Lin 
1966e0832faSShawn Lin 	err = reset_control_assert(rockchip->core_rst);
1976e0832faSShawn Lin 	if (err) {
1986e0832faSShawn Lin 		dev_err(dev, "assert core_rst err %d\n", err);
1996e0832faSShawn Lin 		goto err_exit_phy;
2006e0832faSShawn Lin 	}
2016e0832faSShawn Lin 
2026e0832faSShawn Lin 	err = reset_control_assert(rockchip->mgmt_rst);
2036e0832faSShawn Lin 	if (err) {
2046e0832faSShawn Lin 		dev_err(dev, "assert mgmt_rst err %d\n", err);
2056e0832faSShawn Lin 		goto err_exit_phy;
2066e0832faSShawn Lin 	}
2076e0832faSShawn Lin 
2086e0832faSShawn Lin 	err = reset_control_assert(rockchip->mgmt_sticky_rst);
2096e0832faSShawn Lin 	if (err) {
2106e0832faSShawn Lin 		dev_err(dev, "assert mgmt_sticky_rst err %d\n", err);
2116e0832faSShawn Lin 		goto err_exit_phy;
2126e0832faSShawn Lin 	}
2136e0832faSShawn Lin 
2146e0832faSShawn Lin 	err = reset_control_assert(rockchip->pipe_rst);
2156e0832faSShawn Lin 	if (err) {
2166e0832faSShawn Lin 		dev_err(dev, "assert pipe_rst err %d\n", err);
2176e0832faSShawn Lin 		goto err_exit_phy;
2186e0832faSShawn Lin 	}
2196e0832faSShawn Lin 
2206e0832faSShawn Lin 	udelay(10);
2216e0832faSShawn Lin 
2226e0832faSShawn Lin 	err = reset_control_deassert(rockchip->pm_rst);
2236e0832faSShawn Lin 	if (err) {
2246e0832faSShawn Lin 		dev_err(dev, "deassert pm_rst err %d\n", err);
2256e0832faSShawn Lin 		goto err_exit_phy;
2266e0832faSShawn Lin 	}
2276e0832faSShawn Lin 
2286e0832faSShawn Lin 	err = reset_control_deassert(rockchip->aclk_rst);
2296e0832faSShawn Lin 	if (err) {
2306e0832faSShawn Lin 		dev_err(dev, "deassert aclk_rst err %d\n", err);
2316e0832faSShawn Lin 		goto err_exit_phy;
2326e0832faSShawn Lin 	}
2336e0832faSShawn Lin 
2346e0832faSShawn Lin 	err = reset_control_deassert(rockchip->pclk_rst);
2356e0832faSShawn Lin 	if (err) {
2366e0832faSShawn Lin 		dev_err(dev, "deassert pclk_rst err %d\n", err);
2376e0832faSShawn Lin 		goto err_exit_phy;
2386e0832faSShawn Lin 	}
2396e0832faSShawn Lin 
2406e0832faSShawn Lin 	if (rockchip->link_gen == 2)
2416e0832faSShawn Lin 		rockchip_pcie_write(rockchip, PCIE_CLIENT_GEN_SEL_2,
2426e0832faSShawn Lin 				    PCIE_CLIENT_CONFIG);
2436e0832faSShawn Lin 	else
2446e0832faSShawn Lin 		rockchip_pcie_write(rockchip, PCIE_CLIENT_GEN_SEL_1,
2456e0832faSShawn Lin 				    PCIE_CLIENT_CONFIG);
2466e0832faSShawn Lin 
2476e0832faSShawn Lin 	regs = PCIE_CLIENT_LINK_TRAIN_ENABLE | PCIE_CLIENT_ARI_ENABLE |
2486e0832faSShawn Lin 	       PCIE_CLIENT_CONF_LANE_NUM(rockchip->lanes);
2496e0832faSShawn Lin 
2506e0832faSShawn Lin 	if (rockchip->is_rc)
2516e0832faSShawn Lin 		regs |= PCIE_CLIENT_CONF_ENABLE | PCIE_CLIENT_MODE_RC;
2526e0832faSShawn Lin 	else
2536e0832faSShawn Lin 		regs |= PCIE_CLIENT_CONF_DISABLE | PCIE_CLIENT_MODE_EP;
2546e0832faSShawn Lin 
2556e0832faSShawn Lin 	rockchip_pcie_write(rockchip, regs, PCIE_CLIENT_CONFIG);
2566e0832faSShawn Lin 
2576e0832faSShawn Lin 	for (i = 0; i < MAX_LANE_NUM; i++) {
2586e0832faSShawn Lin 		err = phy_power_on(rockchip->phys[i]);
2596e0832faSShawn Lin 		if (err) {
2606e0832faSShawn Lin 			dev_err(dev, "power on phy%d err %d\n", i, err);
2616e0832faSShawn Lin 			goto err_power_off_phy;
2626e0832faSShawn Lin 		}
2636e0832faSShawn Lin 	}
2646e0832faSShawn Lin 
2659dd3c7c4SRick Wertenbroek 	err = readx_poll_timeout(rockchip_pcie_read_addr,
2669dd3c7c4SRick Wertenbroek 				 PCIE_CLIENT_SIDE_BAND_STATUS,
2679dd3c7c4SRick Wertenbroek 				 regs, !(regs & PCIE_CLIENT_PHY_ST),
2689dd3c7c4SRick Wertenbroek 				 RK_PHY_PLL_LOCK_SLEEP_US,
2699dd3c7c4SRick Wertenbroek 				 RK_PHY_PLL_LOCK_TIMEOUT_US);
2709dd3c7c4SRick Wertenbroek 	if (err) {
2719dd3c7c4SRick Wertenbroek 		dev_err(dev, "PHY PLLs could not lock, %d\n", err);
2729dd3c7c4SRick Wertenbroek 		goto err_power_off_phy;
2739dd3c7c4SRick Wertenbroek 	}
2749dd3c7c4SRick Wertenbroek 
2756e0832faSShawn Lin 	/*
2766e0832faSShawn Lin 	 * Please don't reorder the deassert sequence of the following
2776e0832faSShawn Lin 	 * four reset pins.
2786e0832faSShawn Lin 	 */
2796e0832faSShawn Lin 	err = reset_control_deassert(rockchip->mgmt_sticky_rst);
2806e0832faSShawn Lin 	if (err) {
2816e0832faSShawn Lin 		dev_err(dev, "deassert mgmt_sticky_rst err %d\n", err);
2826e0832faSShawn Lin 		goto err_power_off_phy;
2836e0832faSShawn Lin 	}
2846e0832faSShawn Lin 
2856e0832faSShawn Lin 	err = reset_control_deassert(rockchip->core_rst);
2866e0832faSShawn Lin 	if (err) {
2876e0832faSShawn Lin 		dev_err(dev, "deassert core_rst err %d\n", err);
2886e0832faSShawn Lin 		goto err_power_off_phy;
2896e0832faSShawn Lin 	}
2906e0832faSShawn Lin 
2916e0832faSShawn Lin 	err = reset_control_deassert(rockchip->mgmt_rst);
2926e0832faSShawn Lin 	if (err) {
2936e0832faSShawn Lin 		dev_err(dev, "deassert mgmt_rst err %d\n", err);
2946e0832faSShawn Lin 		goto err_power_off_phy;
2956e0832faSShawn Lin 	}
2966e0832faSShawn Lin 
2976e0832faSShawn Lin 	err = reset_control_deassert(rockchip->pipe_rst);
2986e0832faSShawn Lin 	if (err) {
2996e0832faSShawn Lin 		dev_err(dev, "deassert pipe_rst err %d\n", err);
3006e0832faSShawn Lin 		goto err_power_off_phy;
3016e0832faSShawn Lin 	}
3026e0832faSShawn Lin 
3036e0832faSShawn Lin 	return 0;
3046e0832faSShawn Lin err_power_off_phy:
3056e0832faSShawn Lin 	while (i--)
3066e0832faSShawn Lin 		phy_power_off(rockchip->phys[i]);
3076e0832faSShawn Lin 	i = MAX_LANE_NUM;
3086e0832faSShawn Lin err_exit_phy:
3096e0832faSShawn Lin 	while (i--)
3106e0832faSShawn Lin 		phy_exit(rockchip->phys[i]);
3116e0832faSShawn Lin 	return err;
3126e0832faSShawn Lin }
3136e0832faSShawn Lin EXPORT_SYMBOL_GPL(rockchip_pcie_init_port);
3146e0832faSShawn Lin 
rockchip_pcie_get_phys(struct rockchip_pcie * rockchip)3156e0832faSShawn Lin int rockchip_pcie_get_phys(struct rockchip_pcie *rockchip)
3166e0832faSShawn Lin {
3176e0832faSShawn Lin 	struct device *dev = rockchip->dev;
3186e0832faSShawn Lin 	struct phy *phy;
3196e0832faSShawn Lin 	char *name;
3206e0832faSShawn Lin 	u32 i;
3216e0832faSShawn Lin 
3226e0832faSShawn Lin 	phy = devm_phy_get(dev, "pcie-phy");
3236e0832faSShawn Lin 	if (!IS_ERR(phy)) {
3246e0832faSShawn Lin 		rockchip->legacy_phy = true;
3256e0832faSShawn Lin 		rockchip->phys[0] = phy;
3266e0832faSShawn Lin 		dev_warn(dev, "legacy phy model is deprecated!\n");
3276e0832faSShawn Lin 		return 0;
3286e0832faSShawn Lin 	}
3296e0832faSShawn Lin 
3306e0832faSShawn Lin 	if (PTR_ERR(phy) == -EPROBE_DEFER)
3316e0832faSShawn Lin 		return PTR_ERR(phy);
3326e0832faSShawn Lin 
3336e0832faSShawn Lin 	dev_dbg(dev, "missing legacy phy; search for per-lane PHY\n");
3346e0832faSShawn Lin 
3356e0832faSShawn Lin 	for (i = 0; i < MAX_LANE_NUM; i++) {
3366e0832faSShawn Lin 		name = kasprintf(GFP_KERNEL, "pcie-phy-%u", i);
3376e0832faSShawn Lin 		if (!name)
3386e0832faSShawn Lin 			return -ENOMEM;
3396e0832faSShawn Lin 
3406e0832faSShawn Lin 		phy = devm_of_phy_get(dev, dev->of_node, name);
3416e0832faSShawn Lin 		kfree(name);
3426e0832faSShawn Lin 
3436e0832faSShawn Lin 		if (IS_ERR(phy)) {
3446e0832faSShawn Lin 			if (PTR_ERR(phy) != -EPROBE_DEFER)
3456e0832faSShawn Lin 				dev_err(dev, "missing phy for lane %d: %ld\n",
3466e0832faSShawn Lin 					i, PTR_ERR(phy));
3476e0832faSShawn Lin 			return PTR_ERR(phy);
3486e0832faSShawn Lin 		}
3496e0832faSShawn Lin 
3506e0832faSShawn Lin 		rockchip->phys[i] = phy;
3516e0832faSShawn Lin 	}
3526e0832faSShawn Lin 
3536e0832faSShawn Lin 	return 0;
3546e0832faSShawn Lin }
3556e0832faSShawn Lin EXPORT_SYMBOL_GPL(rockchip_pcie_get_phys);
3566e0832faSShawn Lin 
rockchip_pcie_deinit_phys(struct rockchip_pcie * rockchip)3576e0832faSShawn Lin void rockchip_pcie_deinit_phys(struct rockchip_pcie *rockchip)
3586e0832faSShawn Lin {
3596e0832faSShawn Lin 	int i;
3606e0832faSShawn Lin 
3616e0832faSShawn Lin 	for (i = 0; i < MAX_LANE_NUM; i++) {
3626e0832faSShawn Lin 		/* inactive lanes are already powered off */
3636e0832faSShawn Lin 		if (rockchip->lanes_map & BIT(i))
3646e0832faSShawn Lin 			phy_power_off(rockchip->phys[i]);
3656e0832faSShawn Lin 		phy_exit(rockchip->phys[i]);
3666e0832faSShawn Lin 	}
3676e0832faSShawn Lin }
3686e0832faSShawn Lin EXPORT_SYMBOL_GPL(rockchip_pcie_deinit_phys);
3696e0832faSShawn Lin 
rockchip_pcie_enable_clocks(struct rockchip_pcie * rockchip)3706e0832faSShawn Lin int rockchip_pcie_enable_clocks(struct rockchip_pcie *rockchip)
3716e0832faSShawn Lin {
3726e0832faSShawn Lin 	struct device *dev = rockchip->dev;
3736e0832faSShawn Lin 	int err;
3746e0832faSShawn Lin 
3756e0832faSShawn Lin 	err = clk_prepare_enable(rockchip->aclk_pcie);
3766e0832faSShawn Lin 	if (err) {
3776e0832faSShawn Lin 		dev_err(dev, "unable to enable aclk_pcie clock\n");
3786e0832faSShawn Lin 		return err;
3796e0832faSShawn Lin 	}
3806e0832faSShawn Lin 
3816e0832faSShawn Lin 	err = clk_prepare_enable(rockchip->aclk_perf_pcie);
3826e0832faSShawn Lin 	if (err) {
3836e0832faSShawn Lin 		dev_err(dev, "unable to enable aclk_perf_pcie clock\n");
3846e0832faSShawn Lin 		goto err_aclk_perf_pcie;
3856e0832faSShawn Lin 	}
3866e0832faSShawn Lin 
3876e0832faSShawn Lin 	err = clk_prepare_enable(rockchip->hclk_pcie);
3886e0832faSShawn Lin 	if (err) {
3896e0832faSShawn Lin 		dev_err(dev, "unable to enable hclk_pcie clock\n");
3906e0832faSShawn Lin 		goto err_hclk_pcie;
3916e0832faSShawn Lin 	}
3926e0832faSShawn Lin 
3936e0832faSShawn Lin 	err = clk_prepare_enable(rockchip->clk_pcie_pm);
3946e0832faSShawn Lin 	if (err) {
3956e0832faSShawn Lin 		dev_err(dev, "unable to enable clk_pcie_pm clock\n");
3966e0832faSShawn Lin 		goto err_clk_pcie_pm;
3976e0832faSShawn Lin 	}
3986e0832faSShawn Lin 
3996e0832faSShawn Lin 	return 0;
4006e0832faSShawn Lin 
4016e0832faSShawn Lin err_clk_pcie_pm:
4026e0832faSShawn Lin 	clk_disable_unprepare(rockchip->hclk_pcie);
4036e0832faSShawn Lin err_hclk_pcie:
4046e0832faSShawn Lin 	clk_disable_unprepare(rockchip->aclk_perf_pcie);
4056e0832faSShawn Lin err_aclk_perf_pcie:
4066e0832faSShawn Lin 	clk_disable_unprepare(rockchip->aclk_pcie);
4076e0832faSShawn Lin 	return err;
4086e0832faSShawn Lin }
4096e0832faSShawn Lin EXPORT_SYMBOL_GPL(rockchip_pcie_enable_clocks);
4106e0832faSShawn Lin 
rockchip_pcie_disable_clocks(void * data)4116e0832faSShawn Lin void rockchip_pcie_disable_clocks(void *data)
4126e0832faSShawn Lin {
4136e0832faSShawn Lin 	struct rockchip_pcie *rockchip = data;
4146e0832faSShawn Lin 
4156e0832faSShawn Lin 	clk_disable_unprepare(rockchip->clk_pcie_pm);
4166e0832faSShawn Lin 	clk_disable_unprepare(rockchip->hclk_pcie);
4176e0832faSShawn Lin 	clk_disable_unprepare(rockchip->aclk_perf_pcie);
4186e0832faSShawn Lin 	clk_disable_unprepare(rockchip->aclk_pcie);
4196e0832faSShawn Lin }
4206e0832faSShawn Lin EXPORT_SYMBOL_GPL(rockchip_pcie_disable_clocks);
4216e0832faSShawn Lin 
rockchip_pcie_cfg_configuration_accesses(struct rockchip_pcie * rockchip,u32 type)4226e0832faSShawn Lin void rockchip_pcie_cfg_configuration_accesses(
4236e0832faSShawn Lin 		struct rockchip_pcie *rockchip, u32 type)
4246e0832faSShawn Lin {
4256e0832faSShawn Lin 	u32 ob_desc_0;
4266e0832faSShawn Lin 
4276e0832faSShawn Lin 	/* Configuration Accesses for region 0 */
4286e0832faSShawn Lin 	rockchip_pcie_write(rockchip, 0x0, PCIE_RC_BAR_CONF);
4296e0832faSShawn Lin 
4306e0832faSShawn Lin 	rockchip_pcie_write(rockchip,
4316e0832faSShawn Lin 			    (RC_REGION_0_ADDR_TRANS_L + RC_REGION_0_PASS_BITS),
4326e0832faSShawn Lin 			    PCIE_CORE_OB_REGION_ADDR0);
4336e0832faSShawn Lin 	rockchip_pcie_write(rockchip, RC_REGION_0_ADDR_TRANS_H,
4346e0832faSShawn Lin 			    PCIE_CORE_OB_REGION_ADDR1);
4356e0832faSShawn Lin 	ob_desc_0 = rockchip_pcie_read(rockchip, PCIE_CORE_OB_REGION_DESC0);
4366e0832faSShawn Lin 	ob_desc_0 &= ~(RC_REGION_0_TYPE_MASK);
4376e0832faSShawn Lin 	ob_desc_0 |= (type | (0x1 << 23));
4386e0832faSShawn Lin 	rockchip_pcie_write(rockchip, ob_desc_0, PCIE_CORE_OB_REGION_DESC0);
4396e0832faSShawn Lin 	rockchip_pcie_write(rockchip, 0x0, PCIE_CORE_OB_REGION_DESC1);
4406e0832faSShawn Lin }
4416e0832faSShawn Lin EXPORT_SYMBOL_GPL(rockchip_pcie_cfg_configuration_accesses);
442