13d0407baSopenharmony_ci// SPDX-License-Identifier: GPL-2.0+ 23d0407baSopenharmony_ci/* 33d0407baSopenharmony_ci * Rockchip AXI PCIe host controller driver 43d0407baSopenharmony_ci * 53d0407baSopenharmony_ci * Copyright (c) 2016 Rockchip, Inc. 63d0407baSopenharmony_ci * 73d0407baSopenharmony_ci * Author: Shawn Lin <shawn.lin@rock-chips.com> 83d0407baSopenharmony_ci * Wenrui Li <wenrui.li@rock-chips.com> 93d0407baSopenharmony_ci * 103d0407baSopenharmony_ci * Bits taken from Synopsys DesignWare Host controller driver and 113d0407baSopenharmony_ci * ARM PCI Host generic driver. 123d0407baSopenharmony_ci */ 133d0407baSopenharmony_ci 143d0407baSopenharmony_ci#include <linux/clk.h> 153d0407baSopenharmony_ci#include <linux/delay.h> 163d0407baSopenharmony_ci#include <linux/gpio/consumer.h> 173d0407baSopenharmony_ci#include <linux/module.h> 183d0407baSopenharmony_ci#include <linux/of_pci.h> 193d0407baSopenharmony_ci#include <linux/phy/phy.h> 203d0407baSopenharmony_ci#include <linux/platform_device.h> 213d0407baSopenharmony_ci#include <linux/reset.h> 223d0407baSopenharmony_ci 233d0407baSopenharmony_ci#include "../pci.h" 243d0407baSopenharmony_ci#include "pcie-rockchip.h" 253d0407baSopenharmony_ci 263d0407baSopenharmony_ci#define RK_PCIE_LANES_THREE 3 273d0407baSopenharmony_ci#define RK_PCIE_LANES_FOUR 4 283d0407baSopenharmony_ci#define RK_PCIE_LINK_GEN_MAX 2 293d0407baSopenharmony_ci#define RK_PCIE_INIT_UDELAY 10 303d0407baSopenharmony_ci#define RK_PCIE_CFG_BIT_MASK 23 313d0407baSopenharmony_ci 323d0407baSopenharmony_ciint rockchip_pcie_get_phys(struct rockchip_pcie *rockchip) 333d0407baSopenharmony_ci{ 343d0407baSopenharmony_ci struct device *dev = rockchip->dev; 353d0407baSopenharmony_ci struct phy *phy; 363d0407baSopenharmony_ci char *name; 373d0407baSopenharmony_ci u32 i; 383d0407baSopenharmony_ci 393d0407baSopenharmony_ci phy = devm_phy_get(dev, "pcie-phy"); 403d0407baSopenharmony_ci if (!IS_ERR(phy)) { 413d0407baSopenharmony_ci rockchip->legacy_phy = true; 423d0407baSopenharmony_ci rockchip->phys[0] = phy; 433d0407baSopenharmony_ci dev_warn(dev, "legacy phy model is deprecated!\n"); 443d0407baSopenharmony_ci return 0; 453d0407baSopenharmony_ci } 463d0407baSopenharmony_ci 473d0407baSopenharmony_ci if (PTR_ERR(phy) == -EPROBE_DEFER) { 483d0407baSopenharmony_ci return PTR_ERR(phy); 493d0407baSopenharmony_ci } 503d0407baSopenharmony_ci 513d0407baSopenharmony_ci dev_dbg(dev, "missing legacy phy; search for per-lane PHY\n"); 523d0407baSopenharmony_ci 533d0407baSopenharmony_ci for (i = 0; i < MAX_LANE_NUM; i++) { 543d0407baSopenharmony_ci name = kasprintf(GFP_KERNEL, "pcie-phy-%u", i); 553d0407baSopenharmony_ci if (!name) { 563d0407baSopenharmony_ci return -ENOMEM; 573d0407baSopenharmony_ci } 583d0407baSopenharmony_ci 593d0407baSopenharmony_ci phy = devm_of_phy_get(dev, dev->of_node, name); 603d0407baSopenharmony_ci kfree(name); 613d0407baSopenharmony_ci 623d0407baSopenharmony_ci if (IS_ERR(phy)) { 633d0407baSopenharmony_ci if (PTR_ERR(phy) != -EPROBE_DEFER) { 643d0407baSopenharmony_ci dev_err(dev, "missing phy for lane %d: %ld\n", i, PTR_ERR(phy)); 653d0407baSopenharmony_ci } 663d0407baSopenharmony_ci return PTR_ERR(phy); 673d0407baSopenharmony_ci } 683d0407baSopenharmony_ci 693d0407baSopenharmony_ci rockchip->phys[i] = phy; 703d0407baSopenharmony_ci } 713d0407baSopenharmony_ci 723d0407baSopenharmony_ci return 0; 733d0407baSopenharmony_ci} 743d0407baSopenharmony_ciEXPORT_SYMBOL_GPL(rockchip_pcie_get_phys); 753d0407baSopenharmony_ci 763d0407baSopenharmony_ciint rockchip_pcie_parse_dt(struct rockchip_pcie *rockchip) 773d0407baSopenharmony_ci{ 783d0407baSopenharmony_ci struct device *dev = rockchip->dev; 793d0407baSopenharmony_ci struct platform_device *pdev = to_platform_device(dev); 803d0407baSopenharmony_ci struct device_node *node = dev->of_node; 813d0407baSopenharmony_ci struct resource *regs; 823d0407baSopenharmony_ci int err; 833d0407baSopenharmony_ci 843d0407baSopenharmony_ci if (rockchip->is_rc) { 853d0407baSopenharmony_ci regs = platform_get_resource_byname(pdev, IORESOURCE_MEM, "axi-base"); 863d0407baSopenharmony_ci rockchip->reg_base = devm_pci_remap_cfg_resource(dev, regs); 873d0407baSopenharmony_ci if (IS_ERR(rockchip->reg_base)) { 883d0407baSopenharmony_ci return PTR_ERR(rockchip->reg_base); 893d0407baSopenharmony_ci } 903d0407baSopenharmony_ci } else { 913d0407baSopenharmony_ci rockchip->mem_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mem-base"); 923d0407baSopenharmony_ci if (!rockchip->mem_res) { 933d0407baSopenharmony_ci return -EINVAL; 943d0407baSopenharmony_ci } 953d0407baSopenharmony_ci } 963d0407baSopenharmony_ci 973d0407baSopenharmony_ci rockchip->apb_base = devm_platform_ioremap_resource_byname(pdev, "apb-base"); 983d0407baSopenharmony_ci if (IS_ERR(rockchip->apb_base)) { 993d0407baSopenharmony_ci return PTR_ERR(rockchip->apb_base); 1003d0407baSopenharmony_ci } 1013d0407baSopenharmony_ci 1023d0407baSopenharmony_ci err = rockchip_pcie_get_phys(rockchip); 1033d0407baSopenharmony_ci if (err) { 1043d0407baSopenharmony_ci return err; 1053d0407baSopenharmony_ci } 1063d0407baSopenharmony_ci 1073d0407baSopenharmony_ci rockchip->lanes = 1; 1083d0407baSopenharmony_ci err = of_property_read_u32(node, "num-lanes", &rockchip->lanes); 1093d0407baSopenharmony_ci if (!err && 1103d0407baSopenharmony_ci (rockchip->lanes == 0 || rockchip->lanes == RK_PCIE_LANES_THREE || rockchip->lanes > RK_PCIE_LANES_FOUR)) { 1113d0407baSopenharmony_ci dev_warn(dev, "invalid num-lanes, default to use one lane\n"); 1123d0407baSopenharmony_ci rockchip->lanes = 1; 1133d0407baSopenharmony_ci } 1143d0407baSopenharmony_ci 1153d0407baSopenharmony_ci rockchip->link_gen = of_pci_get_max_link_speed(node); 1163d0407baSopenharmony_ci if (rockchip->link_gen < 0 || rockchip->link_gen > RK_PCIE_LINK_GEN_MAX) { 1173d0407baSopenharmony_ci rockchip->link_gen = RK_PCIE_LINK_GEN_MAX; 1183d0407baSopenharmony_ci } 1193d0407baSopenharmony_ci 1203d0407baSopenharmony_ci rockchip->core_rst = devm_reset_control_get_exclusive(dev, "core"); 1213d0407baSopenharmony_ci if (IS_ERR(rockchip->core_rst)) { 1223d0407baSopenharmony_ci if (PTR_ERR(rockchip->core_rst) != -EPROBE_DEFER) { 1233d0407baSopenharmony_ci dev_err(dev, "missing core reset property in node\n"); 1243d0407baSopenharmony_ci } 1253d0407baSopenharmony_ci return PTR_ERR(rockchip->core_rst); 1263d0407baSopenharmony_ci } 1273d0407baSopenharmony_ci 1283d0407baSopenharmony_ci rockchip->mgmt_rst = devm_reset_control_get_exclusive(dev, "mgmt"); 1293d0407baSopenharmony_ci if (IS_ERR(rockchip->mgmt_rst)) { 1303d0407baSopenharmony_ci if (PTR_ERR(rockchip->mgmt_rst) != -EPROBE_DEFER) { 1313d0407baSopenharmony_ci dev_err(dev, "missing mgmt reset property in node\n"); 1323d0407baSopenharmony_ci } 1333d0407baSopenharmony_ci return PTR_ERR(rockchip->mgmt_rst); 1343d0407baSopenharmony_ci } 1353d0407baSopenharmony_ci 1363d0407baSopenharmony_ci rockchip->mgmt_sticky_rst = devm_reset_control_get_exclusive(dev, "mgmt-sticky"); 1373d0407baSopenharmony_ci if (IS_ERR(rockchip->mgmt_sticky_rst)) { 1383d0407baSopenharmony_ci if (PTR_ERR(rockchip->mgmt_sticky_rst) != -EPROBE_DEFER) { 1393d0407baSopenharmony_ci dev_err(dev, "missing mgmt-sticky reset property in node\n"); 1403d0407baSopenharmony_ci } 1413d0407baSopenharmony_ci return PTR_ERR(rockchip->mgmt_sticky_rst); 1423d0407baSopenharmony_ci } 1433d0407baSopenharmony_ci 1443d0407baSopenharmony_ci rockchip->pipe_rst = devm_reset_control_get_exclusive(dev, "pipe"); 1453d0407baSopenharmony_ci if (IS_ERR(rockchip->pipe_rst)) { 1463d0407baSopenharmony_ci if (PTR_ERR(rockchip->pipe_rst) != -EPROBE_DEFER) { 1473d0407baSopenharmony_ci dev_err(dev, "missing pipe reset property in node\n"); 1483d0407baSopenharmony_ci } 1493d0407baSopenharmony_ci return PTR_ERR(rockchip->pipe_rst); 1503d0407baSopenharmony_ci } 1513d0407baSopenharmony_ci 1523d0407baSopenharmony_ci rockchip->pm_rst = devm_reset_control_get_exclusive(dev, "pm"); 1533d0407baSopenharmony_ci if (IS_ERR(rockchip->pm_rst)) { 1543d0407baSopenharmony_ci if (PTR_ERR(rockchip->pm_rst) != -EPROBE_DEFER) { 1553d0407baSopenharmony_ci dev_err(dev, "missing pm reset property in node\n"); 1563d0407baSopenharmony_ci } 1573d0407baSopenharmony_ci return PTR_ERR(rockchip->pm_rst); 1583d0407baSopenharmony_ci } 1593d0407baSopenharmony_ci 1603d0407baSopenharmony_ci rockchip->pclk_rst = devm_reset_control_get_exclusive(dev, "pclk"); 1613d0407baSopenharmony_ci if (IS_ERR(rockchip->pclk_rst)) { 1623d0407baSopenharmony_ci if (PTR_ERR(rockchip->pclk_rst) != -EPROBE_DEFER) { 1633d0407baSopenharmony_ci dev_err(dev, "missing pclk reset property in node\n"); 1643d0407baSopenharmony_ci } 1653d0407baSopenharmony_ci return PTR_ERR(rockchip->pclk_rst); 1663d0407baSopenharmony_ci } 1673d0407baSopenharmony_ci 1683d0407baSopenharmony_ci rockchip->aclk_rst = devm_reset_control_get_exclusive(dev, "aclk"); 1693d0407baSopenharmony_ci if (IS_ERR(rockchip->aclk_rst)) { 1703d0407baSopenharmony_ci if (PTR_ERR(rockchip->aclk_rst) != -EPROBE_DEFER) { 1713d0407baSopenharmony_ci dev_err(dev, "missing aclk reset property in node\n"); 1723d0407baSopenharmony_ci } 1733d0407baSopenharmony_ci return PTR_ERR(rockchip->aclk_rst); 1743d0407baSopenharmony_ci } 1753d0407baSopenharmony_ci 1763d0407baSopenharmony_ci if (rockchip->is_rc) { 1773d0407baSopenharmony_ci rockchip->ep_gpio = devm_gpiod_get_optional(dev, "ep", GPIOD_OUT_HIGH); 1783d0407baSopenharmony_ci if (IS_ERR(rockchip->ep_gpio)) { 1793d0407baSopenharmony_ci return dev_err_probe(dev, PTR_ERR(rockchip->ep_gpio), "failed to get ep GPIO\n"); 1803d0407baSopenharmony_ci } 1813d0407baSopenharmony_ci } 1823d0407baSopenharmony_ci 1833d0407baSopenharmony_ci rockchip->aclk_pcie = devm_clk_get(dev, "aclk"); 1843d0407baSopenharmony_ci if (IS_ERR(rockchip->aclk_pcie)) { 1853d0407baSopenharmony_ci dev_err(dev, "aclk clock not found\n"); 1863d0407baSopenharmony_ci return PTR_ERR(rockchip->aclk_pcie); 1873d0407baSopenharmony_ci } 1883d0407baSopenharmony_ci 1893d0407baSopenharmony_ci rockchip->aclk_perf_pcie = devm_clk_get(dev, "aclk-perf"); 1903d0407baSopenharmony_ci if (IS_ERR(rockchip->aclk_perf_pcie)) { 1913d0407baSopenharmony_ci dev_err(dev, "aclk_perf clock not found\n"); 1923d0407baSopenharmony_ci return PTR_ERR(rockchip->aclk_perf_pcie); 1933d0407baSopenharmony_ci } 1943d0407baSopenharmony_ci 1953d0407baSopenharmony_ci rockchip->hclk_pcie = devm_clk_get(dev, "hclk"); 1963d0407baSopenharmony_ci if (IS_ERR(rockchip->hclk_pcie)) { 1973d0407baSopenharmony_ci dev_err(dev, "hclk clock not found\n"); 1983d0407baSopenharmony_ci return PTR_ERR(rockchip->hclk_pcie); 1993d0407baSopenharmony_ci } 2003d0407baSopenharmony_ci 2013d0407baSopenharmony_ci rockchip->clk_pcie_pm = devm_clk_get(dev, "pm"); 2023d0407baSopenharmony_ci if (IS_ERR(rockchip->clk_pcie_pm)) { 2033d0407baSopenharmony_ci dev_err(dev, "pm clock not found\n"); 2043d0407baSopenharmony_ci return PTR_ERR(rockchip->clk_pcie_pm); 2053d0407baSopenharmony_ci } 2063d0407baSopenharmony_ci 2073d0407baSopenharmony_ci return 0; 2083d0407baSopenharmony_ci} 2093d0407baSopenharmony_ciEXPORT_SYMBOL_GPL(rockchip_pcie_parse_dt); 2103d0407baSopenharmony_ci 2113d0407baSopenharmony_ciint rockchip_pcie_init_port(struct rockchip_pcie *rockchip) 2123d0407baSopenharmony_ci{ 2133d0407baSopenharmony_ci struct device *dev = rockchip->dev; 2143d0407baSopenharmony_ci int err, i; 2153d0407baSopenharmony_ci u32 regs; 2163d0407baSopenharmony_ci 2173d0407baSopenharmony_ci err = reset_control_assert(rockchip->aclk_rst); 2183d0407baSopenharmony_ci if (err) { 2193d0407baSopenharmony_ci dev_err(dev, "assert aclk_rst err %d\n", err); 2203d0407baSopenharmony_ci return err; 2213d0407baSopenharmony_ci } 2223d0407baSopenharmony_ci 2233d0407baSopenharmony_ci err = reset_control_assert(rockchip->pclk_rst); 2243d0407baSopenharmony_ci if (err) { 2253d0407baSopenharmony_ci dev_err(dev, "assert pclk_rst err %d\n", err); 2263d0407baSopenharmony_ci return err; 2273d0407baSopenharmony_ci } 2283d0407baSopenharmony_ci 2293d0407baSopenharmony_ci err = reset_control_assert(rockchip->pm_rst); 2303d0407baSopenharmony_ci if (err) { 2313d0407baSopenharmony_ci dev_err(dev, "assert pm_rst err %d\n", err); 2323d0407baSopenharmony_ci return err; 2333d0407baSopenharmony_ci } 2343d0407baSopenharmony_ci 2353d0407baSopenharmony_ci for (i = 0; i < MAX_LANE_NUM; i++) { 2363d0407baSopenharmony_ci err = phy_init(rockchip->phys[i]); 2373d0407baSopenharmony_ci if (err) { 2383d0407baSopenharmony_ci dev_err(dev, "init phy%d err %d\n", i, err); 2393d0407baSopenharmony_ci goto err_exit_phy; 2403d0407baSopenharmony_ci } 2413d0407baSopenharmony_ci } 2423d0407baSopenharmony_ci 2433d0407baSopenharmony_ci err = reset_control_assert(rockchip->core_rst); 2443d0407baSopenharmony_ci if (err) { 2453d0407baSopenharmony_ci dev_err(dev, "assert core_rst err %d\n", err); 2463d0407baSopenharmony_ci goto err_exit_phy; 2473d0407baSopenharmony_ci } 2483d0407baSopenharmony_ci 2493d0407baSopenharmony_ci err = reset_control_assert(rockchip->mgmt_rst); 2503d0407baSopenharmony_ci if (err) { 2513d0407baSopenharmony_ci dev_err(dev, "assert mgmt_rst err %d\n", err); 2523d0407baSopenharmony_ci goto err_exit_phy; 2533d0407baSopenharmony_ci } 2543d0407baSopenharmony_ci 2553d0407baSopenharmony_ci err = reset_control_assert(rockchip->mgmt_sticky_rst); 2563d0407baSopenharmony_ci if (err) { 2573d0407baSopenharmony_ci dev_err(dev, "assert mgmt_sticky_rst err %d\n", err); 2583d0407baSopenharmony_ci goto err_exit_phy; 2593d0407baSopenharmony_ci } 2603d0407baSopenharmony_ci 2613d0407baSopenharmony_ci err = reset_control_assert(rockchip->pipe_rst); 2623d0407baSopenharmony_ci if (err) { 2633d0407baSopenharmony_ci dev_err(dev, "assert pipe_rst err %d\n", err); 2643d0407baSopenharmony_ci goto err_exit_phy; 2653d0407baSopenharmony_ci } 2663d0407baSopenharmony_ci 2673d0407baSopenharmony_ci udelay(RK_PCIE_INIT_UDELAY); 2683d0407baSopenharmony_ci 2693d0407baSopenharmony_ci err = reset_control_deassert(rockchip->pm_rst); 2703d0407baSopenharmony_ci if (err) { 2713d0407baSopenharmony_ci dev_err(dev, "deassert pm_rst err %d\n", err); 2723d0407baSopenharmony_ci goto err_exit_phy; 2733d0407baSopenharmony_ci } 2743d0407baSopenharmony_ci 2753d0407baSopenharmony_ci err = reset_control_deassert(rockchip->aclk_rst); 2763d0407baSopenharmony_ci if (err) { 2773d0407baSopenharmony_ci dev_err(dev, "deassert aclk_rst err %d\n", err); 2783d0407baSopenharmony_ci goto err_exit_phy; 2793d0407baSopenharmony_ci } 2803d0407baSopenharmony_ci 2813d0407baSopenharmony_ci err = reset_control_deassert(rockchip->pclk_rst); 2823d0407baSopenharmony_ci if (err) { 2833d0407baSopenharmony_ci dev_err(dev, "deassert pclk_rst err %d\n", err); 2843d0407baSopenharmony_ci goto err_exit_phy; 2853d0407baSopenharmony_ci } 2863d0407baSopenharmony_ci 2873d0407baSopenharmony_ci if (rockchip->link_gen == RK_PCIE_LINK_GEN_MAX) { 2883d0407baSopenharmony_ci rockchip_pcie_write(rockchip, PCIE_CLIENT_GEN_SEL_2, PCIE_CLIENT_CONFIG); 2893d0407baSopenharmony_ci } else { 2903d0407baSopenharmony_ci rockchip_pcie_write(rockchip, PCIE_CLIENT_GEN_SEL_1, PCIE_CLIENT_CONFIG); 2913d0407baSopenharmony_ci } 2923d0407baSopenharmony_ci 2933d0407baSopenharmony_ci regs = PCIE_CLIENT_LINK_TRAIN_ENABLE | PCIE_CLIENT_ARI_ENABLE | PCIE_CLIENT_CONF_LANE_NUM(rockchip->lanes); 2943d0407baSopenharmony_ci 2953d0407baSopenharmony_ci if (rockchip->is_rc) { 2963d0407baSopenharmony_ci regs |= PCIE_CLIENT_CONF_ENABLE | PCIE_CLIENT_MODE_RC; 2973d0407baSopenharmony_ci } else { 2983d0407baSopenharmony_ci regs |= PCIE_CLIENT_CONF_DISABLE | PCIE_CLIENT_MODE_EP; 2993d0407baSopenharmony_ci } 3003d0407baSopenharmony_ci 3013d0407baSopenharmony_ci rockchip_pcie_write(rockchip, regs, PCIE_CLIENT_CONFIG); 3023d0407baSopenharmony_ci 3033d0407baSopenharmony_ci for (i = 0; i < MAX_LANE_NUM; i++) { 3043d0407baSopenharmony_ci err = phy_power_on(rockchip->phys[i]); 3053d0407baSopenharmony_ci if (err) { 3063d0407baSopenharmony_ci dev_err(dev, "power on phy%d err %d\n", i, err); 3073d0407baSopenharmony_ci goto err_power_off_phy; 3083d0407baSopenharmony_ci } 3093d0407baSopenharmony_ci } 3103d0407baSopenharmony_ci 3113d0407baSopenharmony_ci /* 3123d0407baSopenharmony_ci * Please don't reorder the deassert sequence of the following 3133d0407baSopenharmony_ci * four reset pins. 3143d0407baSopenharmony_ci */ 3153d0407baSopenharmony_ci err = reset_control_deassert(rockchip->mgmt_sticky_rst); 3163d0407baSopenharmony_ci if (err) { 3173d0407baSopenharmony_ci dev_err(dev, "deassert mgmt_sticky_rst err %d\n", err); 3183d0407baSopenharmony_ci goto err_power_off_phy; 3193d0407baSopenharmony_ci } 3203d0407baSopenharmony_ci 3213d0407baSopenharmony_ci err = reset_control_deassert(rockchip->core_rst); 3223d0407baSopenharmony_ci if (err) { 3233d0407baSopenharmony_ci dev_err(dev, "deassert core_rst err %d\n", err); 3243d0407baSopenharmony_ci goto err_power_off_phy; 3253d0407baSopenharmony_ci } 3263d0407baSopenharmony_ci 3273d0407baSopenharmony_ci err = reset_control_deassert(rockchip->mgmt_rst); 3283d0407baSopenharmony_ci if (err) { 3293d0407baSopenharmony_ci dev_err(dev, "deassert mgmt_rst err %d\n", err); 3303d0407baSopenharmony_ci goto err_power_off_phy; 3313d0407baSopenharmony_ci } 3323d0407baSopenharmony_ci 3333d0407baSopenharmony_ci err = reset_control_deassert(rockchip->pipe_rst); 3343d0407baSopenharmony_ci if (err) { 3353d0407baSopenharmony_ci dev_err(dev, "deassert pipe_rst err %d\n", err); 3363d0407baSopenharmony_ci goto err_power_off_phy; 3373d0407baSopenharmony_ci } 3383d0407baSopenharmony_ci 3393d0407baSopenharmony_ci return 0; 3403d0407baSopenharmony_cierr_power_off_phy: 3413d0407baSopenharmony_ci while (i--) { 3423d0407baSopenharmony_ci phy_power_off(rockchip->phys[i]); 3433d0407baSopenharmony_ci } 3443d0407baSopenharmony_ci i = MAX_LANE_NUM; 3453d0407baSopenharmony_cierr_exit_phy: 3463d0407baSopenharmony_ci while (i--) { 3473d0407baSopenharmony_ci phy_exit(rockchip->phys[i]); 3483d0407baSopenharmony_ci } 3493d0407baSopenharmony_ci return err; 3503d0407baSopenharmony_ci} 3513d0407baSopenharmony_ciEXPORT_SYMBOL_GPL(rockchip_pcie_init_port); 3523d0407baSopenharmony_ci 3533d0407baSopenharmony_civoid rockchip_pcie_deinit_phys(struct rockchip_pcie *rockchip) 3543d0407baSopenharmony_ci{ 3553d0407baSopenharmony_ci int i; 3563d0407baSopenharmony_ci 3573d0407baSopenharmony_ci for (i = 0; i < MAX_LANE_NUM; i++) { 3583d0407baSopenharmony_ci /* inactive lanes are already powered off */ 3593d0407baSopenharmony_ci if (rockchip->lanes_map & BIT(i)) { 3603d0407baSopenharmony_ci phy_power_off(rockchip->phys[i]); 3613d0407baSopenharmony_ci } 3623d0407baSopenharmony_ci phy_exit(rockchip->phys[i]); 3633d0407baSopenharmony_ci } 3643d0407baSopenharmony_ci} 3653d0407baSopenharmony_ciEXPORT_SYMBOL_GPL(rockchip_pcie_deinit_phys); 3663d0407baSopenharmony_ci 3673d0407baSopenharmony_ciint rockchip_pcie_enable_clocks(struct rockchip_pcie *rockchip) 3683d0407baSopenharmony_ci{ 3693d0407baSopenharmony_ci struct device *dev = rockchip->dev; 3703d0407baSopenharmony_ci int err; 3713d0407baSopenharmony_ci 3723d0407baSopenharmony_ci err = clk_prepare_enable(rockchip->aclk_pcie); 3733d0407baSopenharmony_ci if (err) { 3743d0407baSopenharmony_ci dev_err(dev, "unable to enable aclk_pcie clock\n"); 3753d0407baSopenharmony_ci return err; 3763d0407baSopenharmony_ci } 3773d0407baSopenharmony_ci 3783d0407baSopenharmony_ci err = clk_prepare_enable(rockchip->aclk_perf_pcie); 3793d0407baSopenharmony_ci if (err) { 3803d0407baSopenharmony_ci dev_err(dev, "unable to enable aclk_perf_pcie clock\n"); 3813d0407baSopenharmony_ci goto err_aclk_perf_pcie; 3823d0407baSopenharmony_ci } 3833d0407baSopenharmony_ci 3843d0407baSopenharmony_ci err = clk_prepare_enable(rockchip->hclk_pcie); 3853d0407baSopenharmony_ci if (err) { 3863d0407baSopenharmony_ci dev_err(dev, "unable to enable hclk_pcie clock\n"); 3873d0407baSopenharmony_ci goto err_hclk_pcie; 3883d0407baSopenharmony_ci } 3893d0407baSopenharmony_ci 3903d0407baSopenharmony_ci err = clk_prepare_enable(rockchip->clk_pcie_pm); 3913d0407baSopenharmony_ci if (err) { 3923d0407baSopenharmony_ci dev_err(dev, "unable to enable clk_pcie_pm clock\n"); 3933d0407baSopenharmony_ci goto err_clk_pcie_pm; 3943d0407baSopenharmony_ci } 3953d0407baSopenharmony_ci 3963d0407baSopenharmony_ci return 0; 3973d0407baSopenharmony_ci 3983d0407baSopenharmony_cierr_clk_pcie_pm: 3993d0407baSopenharmony_ci clk_disable_unprepare(rockchip->hclk_pcie); 4003d0407baSopenharmony_cierr_hclk_pcie: 4013d0407baSopenharmony_ci clk_disable_unprepare(rockchip->aclk_perf_pcie); 4023d0407baSopenharmony_cierr_aclk_perf_pcie: 4033d0407baSopenharmony_ci clk_disable_unprepare(rockchip->aclk_pcie); 4043d0407baSopenharmony_ci return err; 4053d0407baSopenharmony_ci} 4063d0407baSopenharmony_ciEXPORT_SYMBOL_GPL(rockchip_pcie_enable_clocks); 4073d0407baSopenharmony_ci 4083d0407baSopenharmony_civoid rockchip_pcie_disable_clocks(void *data) 4093d0407baSopenharmony_ci{ 4103d0407baSopenharmony_ci struct rockchip_pcie *rockchip = data; 4113d0407baSopenharmony_ci 4123d0407baSopenharmony_ci clk_disable_unprepare(rockchip->clk_pcie_pm); 4133d0407baSopenharmony_ci clk_disable_unprepare(rockchip->hclk_pcie); 4143d0407baSopenharmony_ci clk_disable_unprepare(rockchip->aclk_perf_pcie); 4153d0407baSopenharmony_ci clk_disable_unprepare(rockchip->aclk_pcie); 4163d0407baSopenharmony_ci} 4173d0407baSopenharmony_ciEXPORT_SYMBOL_GPL(rockchip_pcie_disable_clocks); 4183d0407baSopenharmony_ci 4193d0407baSopenharmony_civoid rockchip_pcie_cfg_configuration_accesses(struct rockchip_pcie *rockchip, u32 type) 4203d0407baSopenharmony_ci{ 4213d0407baSopenharmony_ci u32 ob_desc_0; 4223d0407baSopenharmony_ci 4233d0407baSopenharmony_ci /* Configuration Accesses for region 0 */ 4243d0407baSopenharmony_ci rockchip_pcie_write(rockchip, 0x0, PCIE_RC_BAR_CONF); 4253d0407baSopenharmony_ci 4263d0407baSopenharmony_ci rockchip_pcie_write(rockchip, (RC_REGION_0_ADDR_TRANS_L + RC_REGION_0_PASS_BITS), PCIE_CORE_OB_REGION_ADDR0); 4273d0407baSopenharmony_ci rockchip_pcie_write(rockchip, RC_REGION_0_ADDR_TRANS_H, PCIE_CORE_OB_REGION_ADDR1); 4283d0407baSopenharmony_ci ob_desc_0 = rockchip_pcie_read(rockchip, PCIE_CORE_OB_REGION_DESC0); 4293d0407baSopenharmony_ci ob_desc_0 &= ~(RC_REGION_0_TYPE_MASK); 4303d0407baSopenharmony_ci ob_desc_0 |= (type | (0x1 << RK_PCIE_CFG_BIT_MASK)); 4313d0407baSopenharmony_ci rockchip_pcie_write(rockchip, ob_desc_0, PCIE_CORE_OB_REGION_DESC0); 4323d0407baSopenharmony_ci rockchip_pcie_write(rockchip, 0x0, PCIE_CORE_OB_REGION_DESC1); 4333d0407baSopenharmony_ci} 4343d0407baSopenharmony_ciEXPORT_SYMBOL_GPL(rockchip_pcie_cfg_configuration_accesses); 4353d0407baSopenharmony_ci 4363d0407baSopenharmony_ciMODULE_AUTHOR("Rockchip Inc"); 4373d0407baSopenharmony_ciMODULE_DESCRIPTION("Rockchip AXI PCIe driver"); 4383d0407baSopenharmony_ciMODULE_LICENSE("GPL v2"); 439