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>
18c925cfafSRob 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",
124*840b7a5eSManivannan Sadhasivam GPIOD_OUT_LOW);
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