18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (c) 2014-2017, The Linux Foundation. All rights reserved. 48c2ecf20Sopenharmony_ci * Copyright (c) 2019, Linaro Ltd. 58c2ecf20Sopenharmony_ci */ 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ci#include <linux/clk-provider.h> 88c2ecf20Sopenharmony_ci#include <linux/clk.h> 98c2ecf20Sopenharmony_ci#include <linux/iopoll.h> 108c2ecf20Sopenharmony_ci#include <linux/module.h> 118c2ecf20Sopenharmony_ci#include <linux/phy/phy.h> 128c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 138c2ecf20Sopenharmony_ci#include <linux/reset.h> 148c2ecf20Sopenharmony_ci#include <linux/slab.h> 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci#include <dt-bindings/phy/phy.h> 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci#define PCIE20_PARF_PHY_STTS 0x3c 198c2ecf20Sopenharmony_ci#define PCIE2_PHY_RESET_CTRL 0x44 208c2ecf20Sopenharmony_ci#define PCIE20_PARF_PHY_REFCLK_CTRL2 0xa0 218c2ecf20Sopenharmony_ci#define PCIE20_PARF_PHY_REFCLK_CTRL3 0xa4 228c2ecf20Sopenharmony_ci#define PCIE20_PARF_PCS_SWING_CTRL1 0x88 238c2ecf20Sopenharmony_ci#define PCIE20_PARF_PCS_SWING_CTRL2 0x8c 248c2ecf20Sopenharmony_ci#define PCIE20_PARF_PCS_DEEMPH1 0x74 258c2ecf20Sopenharmony_ci#define PCIE20_PARF_PCS_DEEMPH2 0x78 268c2ecf20Sopenharmony_ci#define PCIE20_PARF_PCS_DEEMPH3 0x7c 278c2ecf20Sopenharmony_ci#define PCIE20_PARF_CONFIGBITS 0x84 288c2ecf20Sopenharmony_ci#define PCIE20_PARF_PHY_CTRL3 0x94 298c2ecf20Sopenharmony_ci#define PCIE20_PARF_PCS_CTRL 0x80 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci#define TX_AMP_VAL 120 328c2ecf20Sopenharmony_ci#define PHY_RX0_EQ_GEN1_VAL 0 338c2ecf20Sopenharmony_ci#define PHY_RX0_EQ_GEN2_VAL 4 348c2ecf20Sopenharmony_ci#define TX_DEEMPH_GEN1_VAL 24 358c2ecf20Sopenharmony_ci#define TX_DEEMPH_GEN2_3_5DB_VAL 26 368c2ecf20Sopenharmony_ci#define TX_DEEMPH_GEN2_6DB_VAL 36 378c2ecf20Sopenharmony_ci#define PHY_TX0_TERM_OFFST_VAL 0 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_cistruct qcom_phy { 408c2ecf20Sopenharmony_ci struct device *dev; 418c2ecf20Sopenharmony_ci void __iomem *base; 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci struct regulator_bulk_data vregs[2]; 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci struct reset_control *phy_reset; 468c2ecf20Sopenharmony_ci struct reset_control *pipe_reset; 478c2ecf20Sopenharmony_ci struct clk *pipe_clk; 488c2ecf20Sopenharmony_ci}; 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_cistatic int qcom_pcie2_phy_init(struct phy *phy) 518c2ecf20Sopenharmony_ci{ 528c2ecf20Sopenharmony_ci struct qcom_phy *qphy = phy_get_drvdata(phy); 538c2ecf20Sopenharmony_ci int ret; 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci ret = reset_control_deassert(qphy->phy_reset); 568c2ecf20Sopenharmony_ci if (ret) { 578c2ecf20Sopenharmony_ci dev_err(qphy->dev, "cannot deassert pipe reset\n"); 588c2ecf20Sopenharmony_ci return ret; 598c2ecf20Sopenharmony_ci } 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci ret = regulator_bulk_enable(ARRAY_SIZE(qphy->vregs), qphy->vregs); 628c2ecf20Sopenharmony_ci if (ret) 638c2ecf20Sopenharmony_ci reset_control_assert(qphy->phy_reset); 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci return ret; 668c2ecf20Sopenharmony_ci} 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_cistatic int qcom_pcie2_phy_power_on(struct phy *phy) 698c2ecf20Sopenharmony_ci{ 708c2ecf20Sopenharmony_ci struct qcom_phy *qphy = phy_get_drvdata(phy); 718c2ecf20Sopenharmony_ci int ret; 728c2ecf20Sopenharmony_ci u32 val; 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci /* Program REF_CLK source */ 758c2ecf20Sopenharmony_ci val = readl(qphy->base + PCIE20_PARF_PHY_REFCLK_CTRL2); 768c2ecf20Sopenharmony_ci val &= ~BIT(1); 778c2ecf20Sopenharmony_ci writel(val, qphy->base + PCIE20_PARF_PHY_REFCLK_CTRL2); 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci usleep_range(1000, 2000); 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci /* Don't use PAD for refclock */ 828c2ecf20Sopenharmony_ci val = readl(qphy->base + PCIE20_PARF_PHY_REFCLK_CTRL2); 838c2ecf20Sopenharmony_ci val &= ~BIT(0); 848c2ecf20Sopenharmony_ci writel(val, qphy->base + PCIE20_PARF_PHY_REFCLK_CTRL2); 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci /* Program SSP ENABLE */ 878c2ecf20Sopenharmony_ci val = readl(qphy->base + PCIE20_PARF_PHY_REFCLK_CTRL3); 888c2ecf20Sopenharmony_ci val |= BIT(0); 898c2ecf20Sopenharmony_ci writel(val, qphy->base + PCIE20_PARF_PHY_REFCLK_CTRL3); 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci usleep_range(1000, 2000); 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci /* Assert Phy SW Reset */ 948c2ecf20Sopenharmony_ci val = readl(qphy->base + PCIE2_PHY_RESET_CTRL); 958c2ecf20Sopenharmony_ci val |= BIT(0); 968c2ecf20Sopenharmony_ci writel(val, qphy->base + PCIE2_PHY_RESET_CTRL); 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci /* Program Tx Amplitude */ 998c2ecf20Sopenharmony_ci val = readl(qphy->base + PCIE20_PARF_PCS_SWING_CTRL1); 1008c2ecf20Sopenharmony_ci val &= ~0x7f; 1018c2ecf20Sopenharmony_ci val |= TX_AMP_VAL; 1028c2ecf20Sopenharmony_ci writel(val, qphy->base + PCIE20_PARF_PCS_SWING_CTRL1); 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ci val = readl(qphy->base + PCIE20_PARF_PCS_SWING_CTRL2); 1058c2ecf20Sopenharmony_ci val &= ~0x7f; 1068c2ecf20Sopenharmony_ci val |= TX_AMP_VAL; 1078c2ecf20Sopenharmony_ci writel(val, qphy->base + PCIE20_PARF_PCS_SWING_CTRL2); 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci /* Program De-Emphasis */ 1108c2ecf20Sopenharmony_ci val = readl(qphy->base + PCIE20_PARF_PCS_DEEMPH1); 1118c2ecf20Sopenharmony_ci val &= ~0x3f; 1128c2ecf20Sopenharmony_ci val |= TX_DEEMPH_GEN2_6DB_VAL; 1138c2ecf20Sopenharmony_ci writel(val, qphy->base + PCIE20_PARF_PCS_DEEMPH1); 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ci val = readl(qphy->base + PCIE20_PARF_PCS_DEEMPH2); 1168c2ecf20Sopenharmony_ci val &= ~0x3f; 1178c2ecf20Sopenharmony_ci val |= TX_DEEMPH_GEN2_3_5DB_VAL; 1188c2ecf20Sopenharmony_ci writel(val, qphy->base + PCIE20_PARF_PCS_DEEMPH2); 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ci val = readl(qphy->base + PCIE20_PARF_PCS_DEEMPH3); 1218c2ecf20Sopenharmony_ci val &= ~0x3f; 1228c2ecf20Sopenharmony_ci val |= TX_DEEMPH_GEN1_VAL; 1238c2ecf20Sopenharmony_ci writel(val, qphy->base + PCIE20_PARF_PCS_DEEMPH3); 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci /* Program Rx_Eq */ 1268c2ecf20Sopenharmony_ci val = readl(qphy->base + PCIE20_PARF_CONFIGBITS); 1278c2ecf20Sopenharmony_ci val &= ~0x7; 1288c2ecf20Sopenharmony_ci val |= PHY_RX0_EQ_GEN2_VAL; 1298c2ecf20Sopenharmony_ci writel(val, qphy->base + PCIE20_PARF_CONFIGBITS); 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_ci /* Program Tx0_term_offset */ 1328c2ecf20Sopenharmony_ci val = readl(qphy->base + PCIE20_PARF_PHY_CTRL3); 1338c2ecf20Sopenharmony_ci val &= ~0x1f; 1348c2ecf20Sopenharmony_ci val |= PHY_TX0_TERM_OFFST_VAL; 1358c2ecf20Sopenharmony_ci writel(val, qphy->base + PCIE20_PARF_PHY_CTRL3); 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci /* disable Tx2Rx Loopback */ 1388c2ecf20Sopenharmony_ci val = readl(qphy->base + PCIE20_PARF_PCS_CTRL); 1398c2ecf20Sopenharmony_ci val &= ~BIT(1); 1408c2ecf20Sopenharmony_ci writel(val, qphy->base + PCIE20_PARF_PCS_CTRL); 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci /* De-assert Phy SW Reset */ 1438c2ecf20Sopenharmony_ci val = readl(qphy->base + PCIE2_PHY_RESET_CTRL); 1448c2ecf20Sopenharmony_ci val &= ~BIT(0); 1458c2ecf20Sopenharmony_ci writel(val, qphy->base + PCIE2_PHY_RESET_CTRL); 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_ci usleep_range(1000, 2000); 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci ret = reset_control_deassert(qphy->pipe_reset); 1508c2ecf20Sopenharmony_ci if (ret) { 1518c2ecf20Sopenharmony_ci dev_err(qphy->dev, "cannot deassert pipe reset\n"); 1528c2ecf20Sopenharmony_ci goto out; 1538c2ecf20Sopenharmony_ci } 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci clk_set_rate(qphy->pipe_clk, 250000000); 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ci ret = clk_prepare_enable(qphy->pipe_clk); 1588c2ecf20Sopenharmony_ci if (ret) { 1598c2ecf20Sopenharmony_ci dev_err(qphy->dev, "failed to enable pipe clock\n"); 1608c2ecf20Sopenharmony_ci goto out; 1618c2ecf20Sopenharmony_ci } 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci ret = readl_poll_timeout(qphy->base + PCIE20_PARF_PHY_STTS, val, 1648c2ecf20Sopenharmony_ci !(val & BIT(0)), 1000, 10); 1658c2ecf20Sopenharmony_ci if (ret) 1668c2ecf20Sopenharmony_ci dev_err(qphy->dev, "phy initialization failed\n"); 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ciout: 1698c2ecf20Sopenharmony_ci return ret; 1708c2ecf20Sopenharmony_ci} 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_cistatic int qcom_pcie2_phy_power_off(struct phy *phy) 1738c2ecf20Sopenharmony_ci{ 1748c2ecf20Sopenharmony_ci struct qcom_phy *qphy = phy_get_drvdata(phy); 1758c2ecf20Sopenharmony_ci u32 val; 1768c2ecf20Sopenharmony_ci 1778c2ecf20Sopenharmony_ci val = readl(qphy->base + PCIE2_PHY_RESET_CTRL); 1788c2ecf20Sopenharmony_ci val |= BIT(0); 1798c2ecf20Sopenharmony_ci writel(val, qphy->base + PCIE2_PHY_RESET_CTRL); 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_ci clk_disable_unprepare(qphy->pipe_clk); 1828c2ecf20Sopenharmony_ci reset_control_assert(qphy->pipe_reset); 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_ci return 0; 1858c2ecf20Sopenharmony_ci} 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_cistatic int qcom_pcie2_phy_exit(struct phy *phy) 1888c2ecf20Sopenharmony_ci{ 1898c2ecf20Sopenharmony_ci struct qcom_phy *qphy = phy_get_drvdata(phy); 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_ci regulator_bulk_disable(ARRAY_SIZE(qphy->vregs), qphy->vregs); 1928c2ecf20Sopenharmony_ci reset_control_assert(qphy->phy_reset); 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_ci return 0; 1958c2ecf20Sopenharmony_ci} 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_cistatic const struct phy_ops qcom_pcie2_ops = { 1988c2ecf20Sopenharmony_ci .init = qcom_pcie2_phy_init, 1998c2ecf20Sopenharmony_ci .power_on = qcom_pcie2_phy_power_on, 2008c2ecf20Sopenharmony_ci .power_off = qcom_pcie2_phy_power_off, 2018c2ecf20Sopenharmony_ci .exit = qcom_pcie2_phy_exit, 2028c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 2038c2ecf20Sopenharmony_ci}; 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_ci/* 2068c2ecf20Sopenharmony_ci * Register a fixed rate pipe clock. 2078c2ecf20Sopenharmony_ci * 2088c2ecf20Sopenharmony_ci * The <s>_pipe_clksrc generated by PHY goes to the GCC that gate 2098c2ecf20Sopenharmony_ci * controls it. The <s>_pipe_clk coming out of the GCC is requested 2108c2ecf20Sopenharmony_ci * by the PHY driver for its operations. 2118c2ecf20Sopenharmony_ci * We register the <s>_pipe_clksrc here. The gcc driver takes care 2128c2ecf20Sopenharmony_ci * of assigning this <s>_pipe_clksrc as parent to <s>_pipe_clk. 2138c2ecf20Sopenharmony_ci * Below picture shows this relationship. 2148c2ecf20Sopenharmony_ci * 2158c2ecf20Sopenharmony_ci * +---------------+ 2168c2ecf20Sopenharmony_ci * | PHY block |<<---------------------------------------+ 2178c2ecf20Sopenharmony_ci * | | | 2188c2ecf20Sopenharmony_ci * | +-------+ | +-----+ | 2198c2ecf20Sopenharmony_ci * I/P---^-->| PLL |---^--->pipe_clksrc--->| GCC |--->pipe_clk---+ 2208c2ecf20Sopenharmony_ci * clk | +-------+ | +-----+ 2218c2ecf20Sopenharmony_ci * +---------------+ 2228c2ecf20Sopenharmony_ci */ 2238c2ecf20Sopenharmony_cistatic int phy_pipe_clksrc_register(struct qcom_phy *qphy) 2248c2ecf20Sopenharmony_ci{ 2258c2ecf20Sopenharmony_ci struct device_node *np = qphy->dev->of_node; 2268c2ecf20Sopenharmony_ci struct clk_fixed_rate *fixed; 2278c2ecf20Sopenharmony_ci struct clk_init_data init = { }; 2288c2ecf20Sopenharmony_ci int ret; 2298c2ecf20Sopenharmony_ci 2308c2ecf20Sopenharmony_ci ret = of_property_read_string(np, "clock-output-names", &init.name); 2318c2ecf20Sopenharmony_ci if (ret) { 2328c2ecf20Sopenharmony_ci dev_err(qphy->dev, "%s: No clock-output-names\n", np->name); 2338c2ecf20Sopenharmony_ci return ret; 2348c2ecf20Sopenharmony_ci } 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_ci fixed = devm_kzalloc(qphy->dev, sizeof(*fixed), GFP_KERNEL); 2378c2ecf20Sopenharmony_ci if (!fixed) 2388c2ecf20Sopenharmony_ci return -ENOMEM; 2398c2ecf20Sopenharmony_ci 2408c2ecf20Sopenharmony_ci init.ops = &clk_fixed_rate_ops; 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_ci /* controllers using QMP phys use 250MHz pipe clock interface */ 2438c2ecf20Sopenharmony_ci fixed->fixed_rate = 250000000; 2448c2ecf20Sopenharmony_ci fixed->hw.init = &init; 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_ci return devm_clk_hw_register(qphy->dev, &fixed->hw); 2478c2ecf20Sopenharmony_ci} 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_cistatic int qcom_pcie2_phy_probe(struct platform_device *pdev) 2508c2ecf20Sopenharmony_ci{ 2518c2ecf20Sopenharmony_ci struct phy_provider *phy_provider; 2528c2ecf20Sopenharmony_ci struct qcom_phy *qphy; 2538c2ecf20Sopenharmony_ci struct resource *res; 2548c2ecf20Sopenharmony_ci struct device *dev = &pdev->dev; 2558c2ecf20Sopenharmony_ci struct phy *phy; 2568c2ecf20Sopenharmony_ci int ret; 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_ci qphy = devm_kzalloc(dev, sizeof(*qphy), GFP_KERNEL); 2598c2ecf20Sopenharmony_ci if (!qphy) 2608c2ecf20Sopenharmony_ci return -ENOMEM; 2618c2ecf20Sopenharmony_ci 2628c2ecf20Sopenharmony_ci qphy->dev = dev; 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_ci res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 2658c2ecf20Sopenharmony_ci qphy->base = devm_ioremap_resource(dev, res); 2668c2ecf20Sopenharmony_ci if (IS_ERR(qphy->base)) 2678c2ecf20Sopenharmony_ci return PTR_ERR(qphy->base); 2688c2ecf20Sopenharmony_ci 2698c2ecf20Sopenharmony_ci ret = phy_pipe_clksrc_register(qphy); 2708c2ecf20Sopenharmony_ci if (ret) { 2718c2ecf20Sopenharmony_ci dev_err(dev, "failed to register pipe_clk\n"); 2728c2ecf20Sopenharmony_ci return ret; 2738c2ecf20Sopenharmony_ci } 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_ci qphy->vregs[0].supply = "vdda-vp"; 2768c2ecf20Sopenharmony_ci qphy->vregs[1].supply = "vdda-vph"; 2778c2ecf20Sopenharmony_ci ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(qphy->vregs), qphy->vregs); 2788c2ecf20Sopenharmony_ci if (ret < 0) 2798c2ecf20Sopenharmony_ci return ret; 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ci qphy->pipe_clk = devm_clk_get(dev, NULL); 2828c2ecf20Sopenharmony_ci if (IS_ERR(qphy->pipe_clk)) { 2838c2ecf20Sopenharmony_ci dev_err(dev, "failed to acquire pipe clock\n"); 2848c2ecf20Sopenharmony_ci return PTR_ERR(qphy->pipe_clk); 2858c2ecf20Sopenharmony_ci } 2868c2ecf20Sopenharmony_ci 2878c2ecf20Sopenharmony_ci qphy->phy_reset = devm_reset_control_get_exclusive(dev, "phy"); 2888c2ecf20Sopenharmony_ci if (IS_ERR(qphy->phy_reset)) { 2898c2ecf20Sopenharmony_ci dev_err(dev, "failed to acquire phy reset\n"); 2908c2ecf20Sopenharmony_ci return PTR_ERR(qphy->phy_reset); 2918c2ecf20Sopenharmony_ci } 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_ci qphy->pipe_reset = devm_reset_control_get_exclusive(dev, "pipe"); 2948c2ecf20Sopenharmony_ci if (IS_ERR(qphy->pipe_reset)) { 2958c2ecf20Sopenharmony_ci dev_err(dev, "failed to acquire pipe reset\n"); 2968c2ecf20Sopenharmony_ci return PTR_ERR(qphy->pipe_reset); 2978c2ecf20Sopenharmony_ci } 2988c2ecf20Sopenharmony_ci 2998c2ecf20Sopenharmony_ci phy = devm_phy_create(dev, dev->of_node, &qcom_pcie2_ops); 3008c2ecf20Sopenharmony_ci if (IS_ERR(phy)) { 3018c2ecf20Sopenharmony_ci dev_err(dev, "failed to create phy\n"); 3028c2ecf20Sopenharmony_ci return PTR_ERR(phy); 3038c2ecf20Sopenharmony_ci } 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ci phy_set_drvdata(phy, qphy); 3068c2ecf20Sopenharmony_ci 3078c2ecf20Sopenharmony_ci phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); 3088c2ecf20Sopenharmony_ci if (IS_ERR(phy_provider)) 3098c2ecf20Sopenharmony_ci dev_err(dev, "failed to register phy provider\n"); 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_ci return PTR_ERR_OR_ZERO(phy_provider); 3128c2ecf20Sopenharmony_ci} 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_cistatic const struct of_device_id qcom_pcie2_phy_match_table[] = { 3158c2ecf20Sopenharmony_ci { .compatible = "qcom,pcie2-phy" }, 3168c2ecf20Sopenharmony_ci {} 3178c2ecf20Sopenharmony_ci}; 3188c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, qcom_pcie2_phy_match_table); 3198c2ecf20Sopenharmony_ci 3208c2ecf20Sopenharmony_cistatic struct platform_driver qcom_pcie2_phy_driver = { 3218c2ecf20Sopenharmony_ci .probe = qcom_pcie2_phy_probe, 3228c2ecf20Sopenharmony_ci .driver = { 3238c2ecf20Sopenharmony_ci .name = "phy-qcom-pcie2", 3248c2ecf20Sopenharmony_ci .of_match_table = qcom_pcie2_phy_match_table, 3258c2ecf20Sopenharmony_ci }, 3268c2ecf20Sopenharmony_ci}; 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_cimodule_platform_driver(qcom_pcie2_phy_driver); 3298c2ecf20Sopenharmony_ci 3308c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Qualcomm PCIe PHY driver"); 3318c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2"); 332