18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * phy-uniphier-usb3ss.c - SS-PHY driver for Socionext UniPhier USB3 controller 48c2ecf20Sopenharmony_ci * Copyright 2015-2018 Socionext Inc. 58c2ecf20Sopenharmony_ci * Author: 68c2ecf20Sopenharmony_ci * Kunihiko Hayashi <hayashi.kunihiko@socionext.com> 78c2ecf20Sopenharmony_ci * Contributors: 88c2ecf20Sopenharmony_ci * Motoya Tanigawa <tanigawa.motoya@socionext.com> 98c2ecf20Sopenharmony_ci * Masami Hiramatsu <masami.hiramatsu@linaro.org> 108c2ecf20Sopenharmony_ci */ 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#include <linux/bitfield.h> 138c2ecf20Sopenharmony_ci#include <linux/bitops.h> 148c2ecf20Sopenharmony_ci#include <linux/clk.h> 158c2ecf20Sopenharmony_ci#include <linux/io.h> 168c2ecf20Sopenharmony_ci#include <linux/module.h> 178c2ecf20Sopenharmony_ci#include <linux/of.h> 188c2ecf20Sopenharmony_ci#include <linux/of_platform.h> 198c2ecf20Sopenharmony_ci#include <linux/phy/phy.h> 208c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 218c2ecf20Sopenharmony_ci#include <linux/regulator/consumer.h> 228c2ecf20Sopenharmony_ci#include <linux/reset.h> 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci#define SSPHY_TESTI 0x0 258c2ecf20Sopenharmony_ci#define TESTI_DAT_MASK GENMASK(13, 6) 268c2ecf20Sopenharmony_ci#define TESTI_ADR_MASK GENMASK(5, 1) 278c2ecf20Sopenharmony_ci#define TESTI_WR_EN BIT(0) 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci#define SSPHY_TESTO 0x4 308c2ecf20Sopenharmony_ci#define TESTO_DAT_MASK GENMASK(7, 0) 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci#define PHY_F(regno, msb, lsb) { (regno), (msb), (lsb) } 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci#define CDR_CPD_TRIM PHY_F(7, 3, 0) /* RxPLL charge pump current */ 358c2ecf20Sopenharmony_ci#define CDR_CPF_TRIM PHY_F(8, 3, 0) /* RxPLL charge pump current 2 */ 368c2ecf20Sopenharmony_ci#define TX_PLL_TRIM PHY_F(9, 3, 0) /* TxPLL charge pump current */ 378c2ecf20Sopenharmony_ci#define BGAP_TRIM PHY_F(11, 3, 0) /* Bandgap voltage */ 388c2ecf20Sopenharmony_ci#define CDR_TRIM PHY_F(13, 6, 5) /* Clock Data Recovery setting */ 398c2ecf20Sopenharmony_ci#define VCO_CTRL PHY_F(26, 7, 4) /* VCO control */ 408c2ecf20Sopenharmony_ci#define VCOPLL_CTRL PHY_F(27, 2, 0) /* TxPLL VCO tuning */ 418c2ecf20Sopenharmony_ci#define VCOPLL_CM PHY_F(28, 1, 0) /* TxPLL voltage */ 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci#define MAX_PHY_PARAMS 7 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_cistruct uniphier_u3ssphy_param { 468c2ecf20Sopenharmony_ci struct { 478c2ecf20Sopenharmony_ci int reg_no; 488c2ecf20Sopenharmony_ci int msb; 498c2ecf20Sopenharmony_ci int lsb; 508c2ecf20Sopenharmony_ci } field; 518c2ecf20Sopenharmony_ci u8 value; 528c2ecf20Sopenharmony_ci}; 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_cistruct uniphier_u3ssphy_priv { 558c2ecf20Sopenharmony_ci struct device *dev; 568c2ecf20Sopenharmony_ci void __iomem *base; 578c2ecf20Sopenharmony_ci struct clk *clk, *clk_ext, *clk_parent, *clk_parent_gio; 588c2ecf20Sopenharmony_ci struct reset_control *rst, *rst_parent, *rst_parent_gio; 598c2ecf20Sopenharmony_ci struct regulator *vbus; 608c2ecf20Sopenharmony_ci const struct uniphier_u3ssphy_soc_data *data; 618c2ecf20Sopenharmony_ci}; 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_cistruct uniphier_u3ssphy_soc_data { 648c2ecf20Sopenharmony_ci bool is_legacy; 658c2ecf20Sopenharmony_ci int nparams; 668c2ecf20Sopenharmony_ci const struct uniphier_u3ssphy_param param[MAX_PHY_PARAMS]; 678c2ecf20Sopenharmony_ci}; 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_cistatic void uniphier_u3ssphy_testio_write(struct uniphier_u3ssphy_priv *priv, 708c2ecf20Sopenharmony_ci u32 data) 718c2ecf20Sopenharmony_ci{ 728c2ecf20Sopenharmony_ci /* need to read TESTO twice after accessing TESTI */ 738c2ecf20Sopenharmony_ci writel(data, priv->base + SSPHY_TESTI); 748c2ecf20Sopenharmony_ci readl(priv->base + SSPHY_TESTO); 758c2ecf20Sopenharmony_ci readl(priv->base + SSPHY_TESTO); 768c2ecf20Sopenharmony_ci} 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_cistatic void uniphier_u3ssphy_set_param(struct uniphier_u3ssphy_priv *priv, 798c2ecf20Sopenharmony_ci const struct uniphier_u3ssphy_param *p) 808c2ecf20Sopenharmony_ci{ 818c2ecf20Sopenharmony_ci u32 val; 828c2ecf20Sopenharmony_ci u8 field_mask = GENMASK(p->field.msb, p->field.lsb); 838c2ecf20Sopenharmony_ci u8 data; 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci /* read previous data */ 868c2ecf20Sopenharmony_ci val = FIELD_PREP(TESTI_DAT_MASK, 1); 878c2ecf20Sopenharmony_ci val |= FIELD_PREP(TESTI_ADR_MASK, p->field.reg_no); 888c2ecf20Sopenharmony_ci uniphier_u3ssphy_testio_write(priv, val); 898c2ecf20Sopenharmony_ci val = readl(priv->base + SSPHY_TESTO) & TESTO_DAT_MASK; 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci /* update value */ 928c2ecf20Sopenharmony_ci val &= ~field_mask; 938c2ecf20Sopenharmony_ci data = field_mask & (p->value << p->field.lsb); 948c2ecf20Sopenharmony_ci val = FIELD_PREP(TESTI_DAT_MASK, data | val); 958c2ecf20Sopenharmony_ci val |= FIELD_PREP(TESTI_ADR_MASK, p->field.reg_no); 968c2ecf20Sopenharmony_ci uniphier_u3ssphy_testio_write(priv, val); 978c2ecf20Sopenharmony_ci uniphier_u3ssphy_testio_write(priv, val | TESTI_WR_EN); 988c2ecf20Sopenharmony_ci uniphier_u3ssphy_testio_write(priv, val); 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci /* read current data as dummy */ 1018c2ecf20Sopenharmony_ci val = FIELD_PREP(TESTI_DAT_MASK, 1); 1028c2ecf20Sopenharmony_ci val |= FIELD_PREP(TESTI_ADR_MASK, p->field.reg_no); 1038c2ecf20Sopenharmony_ci uniphier_u3ssphy_testio_write(priv, val); 1048c2ecf20Sopenharmony_ci readl(priv->base + SSPHY_TESTO); 1058c2ecf20Sopenharmony_ci} 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_cistatic int uniphier_u3ssphy_power_on(struct phy *phy) 1088c2ecf20Sopenharmony_ci{ 1098c2ecf20Sopenharmony_ci struct uniphier_u3ssphy_priv *priv = phy_get_drvdata(phy); 1108c2ecf20Sopenharmony_ci int ret; 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci ret = clk_prepare_enable(priv->clk_ext); 1138c2ecf20Sopenharmony_ci if (ret) 1148c2ecf20Sopenharmony_ci return ret; 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci ret = clk_prepare_enable(priv->clk); 1178c2ecf20Sopenharmony_ci if (ret) 1188c2ecf20Sopenharmony_ci goto out_clk_ext_disable; 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ci ret = reset_control_deassert(priv->rst); 1218c2ecf20Sopenharmony_ci if (ret) 1228c2ecf20Sopenharmony_ci goto out_clk_disable; 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci if (priv->vbus) { 1258c2ecf20Sopenharmony_ci ret = regulator_enable(priv->vbus); 1268c2ecf20Sopenharmony_ci if (ret) 1278c2ecf20Sopenharmony_ci goto out_rst_assert; 1288c2ecf20Sopenharmony_ci } 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci return 0; 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ciout_rst_assert: 1338c2ecf20Sopenharmony_ci reset_control_assert(priv->rst); 1348c2ecf20Sopenharmony_ciout_clk_disable: 1358c2ecf20Sopenharmony_ci clk_disable_unprepare(priv->clk); 1368c2ecf20Sopenharmony_ciout_clk_ext_disable: 1378c2ecf20Sopenharmony_ci clk_disable_unprepare(priv->clk_ext); 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ci return ret; 1408c2ecf20Sopenharmony_ci} 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_cistatic int uniphier_u3ssphy_power_off(struct phy *phy) 1438c2ecf20Sopenharmony_ci{ 1448c2ecf20Sopenharmony_ci struct uniphier_u3ssphy_priv *priv = phy_get_drvdata(phy); 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci if (priv->vbus) 1478c2ecf20Sopenharmony_ci regulator_disable(priv->vbus); 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci reset_control_assert(priv->rst); 1508c2ecf20Sopenharmony_ci clk_disable_unprepare(priv->clk); 1518c2ecf20Sopenharmony_ci clk_disable_unprepare(priv->clk_ext); 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci return 0; 1548c2ecf20Sopenharmony_ci} 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_cistatic int uniphier_u3ssphy_init(struct phy *phy) 1578c2ecf20Sopenharmony_ci{ 1588c2ecf20Sopenharmony_ci struct uniphier_u3ssphy_priv *priv = phy_get_drvdata(phy); 1598c2ecf20Sopenharmony_ci int i, ret; 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_ci ret = clk_prepare_enable(priv->clk_parent); 1628c2ecf20Sopenharmony_ci if (ret) 1638c2ecf20Sopenharmony_ci return ret; 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ci ret = clk_prepare_enable(priv->clk_parent_gio); 1668c2ecf20Sopenharmony_ci if (ret) 1678c2ecf20Sopenharmony_ci goto out_clk_disable; 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci ret = reset_control_deassert(priv->rst_parent); 1708c2ecf20Sopenharmony_ci if (ret) 1718c2ecf20Sopenharmony_ci goto out_clk_gio_disable; 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_ci ret = reset_control_deassert(priv->rst_parent_gio); 1748c2ecf20Sopenharmony_ci if (ret) 1758c2ecf20Sopenharmony_ci goto out_rst_assert; 1768c2ecf20Sopenharmony_ci 1778c2ecf20Sopenharmony_ci if (priv->data->is_legacy) 1788c2ecf20Sopenharmony_ci return 0; 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_ci for (i = 0; i < priv->data->nparams; i++) 1818c2ecf20Sopenharmony_ci uniphier_u3ssphy_set_param(priv, &priv->data->param[i]); 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_ci return 0; 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_ciout_rst_assert: 1868c2ecf20Sopenharmony_ci reset_control_assert(priv->rst_parent); 1878c2ecf20Sopenharmony_ciout_clk_gio_disable: 1888c2ecf20Sopenharmony_ci clk_disable_unprepare(priv->clk_parent_gio); 1898c2ecf20Sopenharmony_ciout_clk_disable: 1908c2ecf20Sopenharmony_ci clk_disable_unprepare(priv->clk_parent); 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_ci return ret; 1938c2ecf20Sopenharmony_ci} 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_cistatic int uniphier_u3ssphy_exit(struct phy *phy) 1968c2ecf20Sopenharmony_ci{ 1978c2ecf20Sopenharmony_ci struct uniphier_u3ssphy_priv *priv = phy_get_drvdata(phy); 1988c2ecf20Sopenharmony_ci 1998c2ecf20Sopenharmony_ci reset_control_assert(priv->rst_parent_gio); 2008c2ecf20Sopenharmony_ci reset_control_assert(priv->rst_parent); 2018c2ecf20Sopenharmony_ci clk_disable_unprepare(priv->clk_parent_gio); 2028c2ecf20Sopenharmony_ci clk_disable_unprepare(priv->clk_parent); 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci return 0; 2058c2ecf20Sopenharmony_ci} 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_cistatic const struct phy_ops uniphier_u3ssphy_ops = { 2088c2ecf20Sopenharmony_ci .init = uniphier_u3ssphy_init, 2098c2ecf20Sopenharmony_ci .exit = uniphier_u3ssphy_exit, 2108c2ecf20Sopenharmony_ci .power_on = uniphier_u3ssphy_power_on, 2118c2ecf20Sopenharmony_ci .power_off = uniphier_u3ssphy_power_off, 2128c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 2138c2ecf20Sopenharmony_ci}; 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_cistatic int uniphier_u3ssphy_probe(struct platform_device *pdev) 2168c2ecf20Sopenharmony_ci{ 2178c2ecf20Sopenharmony_ci struct device *dev = &pdev->dev; 2188c2ecf20Sopenharmony_ci struct uniphier_u3ssphy_priv *priv; 2198c2ecf20Sopenharmony_ci struct phy_provider *phy_provider; 2208c2ecf20Sopenharmony_ci struct phy *phy; 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_ci priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 2238c2ecf20Sopenharmony_ci if (!priv) 2248c2ecf20Sopenharmony_ci return -ENOMEM; 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_ci priv->dev = dev; 2278c2ecf20Sopenharmony_ci priv->data = of_device_get_match_data(dev); 2288c2ecf20Sopenharmony_ci if (WARN_ON(!priv->data || 2298c2ecf20Sopenharmony_ci priv->data->nparams > MAX_PHY_PARAMS)) 2308c2ecf20Sopenharmony_ci return -EINVAL; 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ci priv->base = devm_platform_ioremap_resource(pdev, 0); 2338c2ecf20Sopenharmony_ci if (IS_ERR(priv->base)) 2348c2ecf20Sopenharmony_ci return PTR_ERR(priv->base); 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_ci if (!priv->data->is_legacy) { 2378c2ecf20Sopenharmony_ci priv->clk = devm_clk_get(dev, "phy"); 2388c2ecf20Sopenharmony_ci if (IS_ERR(priv->clk)) 2398c2ecf20Sopenharmony_ci return PTR_ERR(priv->clk); 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_ci priv->clk_ext = devm_clk_get_optional(dev, "phy-ext"); 2428c2ecf20Sopenharmony_ci if (IS_ERR(priv->clk_ext)) 2438c2ecf20Sopenharmony_ci return PTR_ERR(priv->clk_ext); 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_ci priv->rst = devm_reset_control_get_shared(dev, "phy"); 2468c2ecf20Sopenharmony_ci if (IS_ERR(priv->rst)) 2478c2ecf20Sopenharmony_ci return PTR_ERR(priv->rst); 2488c2ecf20Sopenharmony_ci } else { 2498c2ecf20Sopenharmony_ci priv->clk_parent_gio = devm_clk_get(dev, "gio"); 2508c2ecf20Sopenharmony_ci if (IS_ERR(priv->clk_parent_gio)) 2518c2ecf20Sopenharmony_ci return PTR_ERR(priv->clk_parent_gio); 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_ci priv->rst_parent_gio = 2548c2ecf20Sopenharmony_ci devm_reset_control_get_shared(dev, "gio"); 2558c2ecf20Sopenharmony_ci if (IS_ERR(priv->rst_parent_gio)) 2568c2ecf20Sopenharmony_ci return PTR_ERR(priv->rst_parent_gio); 2578c2ecf20Sopenharmony_ci } 2588c2ecf20Sopenharmony_ci 2598c2ecf20Sopenharmony_ci priv->clk_parent = devm_clk_get(dev, "link"); 2608c2ecf20Sopenharmony_ci if (IS_ERR(priv->clk_parent)) 2618c2ecf20Sopenharmony_ci return PTR_ERR(priv->clk_parent); 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_ci priv->rst_parent = devm_reset_control_get_shared(dev, "link"); 2648c2ecf20Sopenharmony_ci if (IS_ERR(priv->rst_parent)) 2658c2ecf20Sopenharmony_ci return PTR_ERR(priv->rst_parent); 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_ci priv->vbus = devm_regulator_get_optional(dev, "vbus"); 2688c2ecf20Sopenharmony_ci if (IS_ERR(priv->vbus)) { 2698c2ecf20Sopenharmony_ci if (PTR_ERR(priv->vbus) == -EPROBE_DEFER) 2708c2ecf20Sopenharmony_ci return PTR_ERR(priv->vbus); 2718c2ecf20Sopenharmony_ci priv->vbus = NULL; 2728c2ecf20Sopenharmony_ci } 2738c2ecf20Sopenharmony_ci 2748c2ecf20Sopenharmony_ci phy = devm_phy_create(dev, dev->of_node, &uniphier_u3ssphy_ops); 2758c2ecf20Sopenharmony_ci if (IS_ERR(phy)) 2768c2ecf20Sopenharmony_ci return PTR_ERR(phy); 2778c2ecf20Sopenharmony_ci 2788c2ecf20Sopenharmony_ci phy_set_drvdata(phy, priv); 2798c2ecf20Sopenharmony_ci phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ci return PTR_ERR_OR_ZERO(phy_provider); 2828c2ecf20Sopenharmony_ci} 2838c2ecf20Sopenharmony_ci 2848c2ecf20Sopenharmony_cistatic const struct uniphier_u3ssphy_soc_data uniphier_pro4_data = { 2858c2ecf20Sopenharmony_ci .is_legacy = true, 2868c2ecf20Sopenharmony_ci}; 2878c2ecf20Sopenharmony_ci 2888c2ecf20Sopenharmony_cistatic const struct uniphier_u3ssphy_soc_data uniphier_pxs2_data = { 2898c2ecf20Sopenharmony_ci .is_legacy = false, 2908c2ecf20Sopenharmony_ci .nparams = 7, 2918c2ecf20Sopenharmony_ci .param = { 2928c2ecf20Sopenharmony_ci { CDR_CPD_TRIM, 10 }, 2938c2ecf20Sopenharmony_ci { CDR_CPF_TRIM, 3 }, 2948c2ecf20Sopenharmony_ci { TX_PLL_TRIM, 5 }, 2958c2ecf20Sopenharmony_ci { BGAP_TRIM, 9 }, 2968c2ecf20Sopenharmony_ci { CDR_TRIM, 2 }, 2978c2ecf20Sopenharmony_ci { VCOPLL_CTRL, 7 }, 2988c2ecf20Sopenharmony_ci { VCOPLL_CM, 1 }, 2998c2ecf20Sopenharmony_ci }, 3008c2ecf20Sopenharmony_ci}; 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_cistatic const struct uniphier_u3ssphy_soc_data uniphier_ld20_data = { 3038c2ecf20Sopenharmony_ci .is_legacy = false, 3048c2ecf20Sopenharmony_ci .nparams = 3, 3058c2ecf20Sopenharmony_ci .param = { 3068c2ecf20Sopenharmony_ci { CDR_CPD_TRIM, 6 }, 3078c2ecf20Sopenharmony_ci { CDR_TRIM, 2 }, 3088c2ecf20Sopenharmony_ci { VCO_CTRL, 5 }, 3098c2ecf20Sopenharmony_ci }, 3108c2ecf20Sopenharmony_ci}; 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_cistatic const struct of_device_id uniphier_u3ssphy_match[] = { 3138c2ecf20Sopenharmony_ci { 3148c2ecf20Sopenharmony_ci .compatible = "socionext,uniphier-pro4-usb3-ssphy", 3158c2ecf20Sopenharmony_ci .data = &uniphier_pro4_data, 3168c2ecf20Sopenharmony_ci }, 3178c2ecf20Sopenharmony_ci { 3188c2ecf20Sopenharmony_ci .compatible = "socionext,uniphier-pro5-usb3-ssphy", 3198c2ecf20Sopenharmony_ci .data = &uniphier_pro4_data, 3208c2ecf20Sopenharmony_ci }, 3218c2ecf20Sopenharmony_ci { 3228c2ecf20Sopenharmony_ci .compatible = "socionext,uniphier-pxs2-usb3-ssphy", 3238c2ecf20Sopenharmony_ci .data = &uniphier_pxs2_data, 3248c2ecf20Sopenharmony_ci }, 3258c2ecf20Sopenharmony_ci { 3268c2ecf20Sopenharmony_ci .compatible = "socionext,uniphier-ld20-usb3-ssphy", 3278c2ecf20Sopenharmony_ci .data = &uniphier_ld20_data, 3288c2ecf20Sopenharmony_ci }, 3298c2ecf20Sopenharmony_ci { 3308c2ecf20Sopenharmony_ci .compatible = "socionext,uniphier-pxs3-usb3-ssphy", 3318c2ecf20Sopenharmony_ci .data = &uniphier_ld20_data, 3328c2ecf20Sopenharmony_ci }, 3338c2ecf20Sopenharmony_ci { /* sentinel */ } 3348c2ecf20Sopenharmony_ci}; 3358c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, uniphier_u3ssphy_match); 3368c2ecf20Sopenharmony_ci 3378c2ecf20Sopenharmony_cistatic struct platform_driver uniphier_u3ssphy_driver = { 3388c2ecf20Sopenharmony_ci .probe = uniphier_u3ssphy_probe, 3398c2ecf20Sopenharmony_ci .driver = { 3408c2ecf20Sopenharmony_ci .name = "uniphier-usb3-ssphy", 3418c2ecf20Sopenharmony_ci .of_match_table = uniphier_u3ssphy_match, 3428c2ecf20Sopenharmony_ci }, 3438c2ecf20Sopenharmony_ci}; 3448c2ecf20Sopenharmony_ci 3458c2ecf20Sopenharmony_cimodule_platform_driver(uniphier_u3ssphy_driver); 3468c2ecf20Sopenharmony_ci 3478c2ecf20Sopenharmony_ciMODULE_AUTHOR("Kunihiko Hayashi <hayashi.kunihiko@socionext.com>"); 3488c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("UniPhier SS-PHY driver for USB3 controller"); 3498c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2"); 350