15ab43d0fSKunihiko Hayashi // SPDX-License-Identifier: GPL-2.0 25ab43d0fSKunihiko Hayashi /* 35ab43d0fSKunihiko Hayashi * phy-uniphier-usb3hs.c - HS-PHY driver for Socionext UniPhier USB3 controller 45ab43d0fSKunihiko Hayashi * Copyright 2015-2018 Socionext Inc. 55ab43d0fSKunihiko Hayashi * Author: 65ab43d0fSKunihiko Hayashi * Kunihiko Hayashi <hayashi.kunihiko@socionext.com> 75ab43d0fSKunihiko Hayashi * Contributors: 85ab43d0fSKunihiko Hayashi * Motoya Tanigawa <tanigawa.motoya@socionext.com> 95ab43d0fSKunihiko Hayashi * Masami Hiramatsu <masami.hiramatsu@linaro.org> 105ab43d0fSKunihiko Hayashi */ 115ab43d0fSKunihiko Hayashi 125ab43d0fSKunihiko Hayashi #include <linux/bitfield.h> 135ab43d0fSKunihiko Hayashi #include <linux/bitops.h> 145ab43d0fSKunihiko Hayashi #include <linux/clk.h> 155ab43d0fSKunihiko Hayashi #include <linux/io.h> 165ab43d0fSKunihiko Hayashi #include <linux/module.h> 175ab43d0fSKunihiko Hayashi #include <linux/nvmem-consumer.h> 185ab43d0fSKunihiko Hayashi #include <linux/of.h> 195ab43d0fSKunihiko Hayashi #include <linux/of_platform.h> 205ab43d0fSKunihiko Hayashi #include <linux/phy/phy.h> 215ab43d0fSKunihiko Hayashi #include <linux/platform_device.h> 225ab43d0fSKunihiko Hayashi #include <linux/regulator/consumer.h> 235ab43d0fSKunihiko Hayashi #include <linux/reset.h> 245ab43d0fSKunihiko Hayashi #include <linux/slab.h> 255ab43d0fSKunihiko Hayashi 265ab43d0fSKunihiko Hayashi #define HSPHY_CFG0 0x0 275ab43d0fSKunihiko Hayashi #define HSPHY_CFG0_HS_I_MASK GENMASK(31, 28) 285ab43d0fSKunihiko Hayashi #define HSPHY_CFG0_HSDISC_MASK GENMASK(27, 26) 295ab43d0fSKunihiko Hayashi #define HSPHY_CFG0_SWING_MASK GENMASK(17, 16) 305ab43d0fSKunihiko Hayashi #define HSPHY_CFG0_SEL_T_MASK GENMASK(15, 12) 315ab43d0fSKunihiko Hayashi #define HSPHY_CFG0_RTERM_MASK GENMASK(7, 6) 325ab43d0fSKunihiko Hayashi #define HSPHY_CFG0_TRIMMASK (HSPHY_CFG0_HS_I_MASK \ 335ab43d0fSKunihiko Hayashi | HSPHY_CFG0_SEL_T_MASK \ 345ab43d0fSKunihiko Hayashi | HSPHY_CFG0_RTERM_MASK) 355ab43d0fSKunihiko Hayashi 365ab43d0fSKunihiko Hayashi #define HSPHY_CFG1 0x4 375ab43d0fSKunihiko Hayashi #define HSPHY_CFG1_DAT_EN BIT(29) 385ab43d0fSKunihiko Hayashi #define HSPHY_CFG1_ADR_EN BIT(28) 395ab43d0fSKunihiko Hayashi #define HSPHY_CFG1_ADR_MASK GENMASK(27, 16) 405ab43d0fSKunihiko Hayashi #define HSPHY_CFG1_DAT_MASK GENMASK(23, 16) 415ab43d0fSKunihiko Hayashi 425ab43d0fSKunihiko Hayashi #define PHY_F(regno, msb, lsb) { (regno), (msb), (lsb) } 435ab43d0fSKunihiko Hayashi 44*25858c52SKunihiko Hayashi #define RX_CHK_SYNC PHY_F(0, 5, 5) /* RX sync mode */ 45*25858c52SKunihiko Hayashi #define RX_SYNC_SEL PHY_F(1, 1, 0) /* RX sync length */ 465ab43d0fSKunihiko Hayashi #define LS_SLEW PHY_F(10, 6, 6) /* LS mode slew rate */ 475ab43d0fSKunihiko Hayashi #define FS_LS_DRV PHY_F(10, 5, 5) /* FS/LS slew rate */ 485ab43d0fSKunihiko Hayashi 49*25858c52SKunihiko Hayashi #define MAX_PHY_PARAMS 4 505ab43d0fSKunihiko Hayashi 515ab43d0fSKunihiko Hayashi struct uniphier_u3hsphy_param { 525ab43d0fSKunihiko Hayashi struct { 535ab43d0fSKunihiko Hayashi int reg_no; 545ab43d0fSKunihiko Hayashi int msb; 555ab43d0fSKunihiko Hayashi int lsb; 565ab43d0fSKunihiko Hayashi } field; 575ab43d0fSKunihiko Hayashi u8 value; 585ab43d0fSKunihiko Hayashi }; 595ab43d0fSKunihiko Hayashi 605ab43d0fSKunihiko Hayashi struct uniphier_u3hsphy_trim_param { 615ab43d0fSKunihiko Hayashi unsigned int rterm; 625ab43d0fSKunihiko Hayashi unsigned int sel_t; 635ab43d0fSKunihiko Hayashi unsigned int hs_i; 645ab43d0fSKunihiko Hayashi }; 655ab43d0fSKunihiko Hayashi 665ab43d0fSKunihiko Hayashi #define trim_param_is_valid(p) ((p)->rterm || (p)->sel_t || (p)->hs_i) 675ab43d0fSKunihiko Hayashi 685ab43d0fSKunihiko Hayashi struct uniphier_u3hsphy_priv { 695ab43d0fSKunihiko Hayashi struct device *dev; 705ab43d0fSKunihiko Hayashi void __iomem *base; 71e68c2a8aSKunihiko Hayashi struct clk *clk, *clk_parent, *clk_ext, *clk_parent_gio; 72e68c2a8aSKunihiko Hayashi struct reset_control *rst, *rst_parent, *rst_parent_gio; 735ab43d0fSKunihiko Hayashi struct regulator *vbus; 745ab43d0fSKunihiko Hayashi const struct uniphier_u3hsphy_soc_data *data; 755ab43d0fSKunihiko Hayashi }; 765ab43d0fSKunihiko Hayashi 775ab43d0fSKunihiko Hayashi struct uniphier_u3hsphy_soc_data { 78e68c2a8aSKunihiko Hayashi bool is_legacy; 795ab43d0fSKunihiko Hayashi int nparams; 805ab43d0fSKunihiko Hayashi const struct uniphier_u3hsphy_param param[MAX_PHY_PARAMS]; 815ab43d0fSKunihiko Hayashi u32 config0; 825ab43d0fSKunihiko Hayashi u32 config1; 835ab43d0fSKunihiko Hayashi void (*trim_func)(struct uniphier_u3hsphy_priv *priv, u32 *pconfig, 845ab43d0fSKunihiko Hayashi struct uniphier_u3hsphy_trim_param *pt); 855ab43d0fSKunihiko Hayashi }; 865ab43d0fSKunihiko Hayashi 875ab43d0fSKunihiko Hayashi static void uniphier_u3hsphy_trim_ld20(struct uniphier_u3hsphy_priv *priv, 885ab43d0fSKunihiko Hayashi u32 *pconfig, 895ab43d0fSKunihiko Hayashi struct uniphier_u3hsphy_trim_param *pt) 905ab43d0fSKunihiko Hayashi { 915ab43d0fSKunihiko Hayashi *pconfig &= ~HSPHY_CFG0_RTERM_MASK; 925ab43d0fSKunihiko Hayashi *pconfig |= FIELD_PREP(HSPHY_CFG0_RTERM_MASK, pt->rterm); 935ab43d0fSKunihiko Hayashi 945ab43d0fSKunihiko Hayashi *pconfig &= ~HSPHY_CFG0_SEL_T_MASK; 955ab43d0fSKunihiko Hayashi *pconfig |= FIELD_PREP(HSPHY_CFG0_SEL_T_MASK, pt->sel_t); 965ab43d0fSKunihiko Hayashi 975ab43d0fSKunihiko Hayashi *pconfig &= ~HSPHY_CFG0_HS_I_MASK; 985ab43d0fSKunihiko Hayashi *pconfig |= FIELD_PREP(HSPHY_CFG0_HS_I_MASK, pt->hs_i); 995ab43d0fSKunihiko Hayashi } 1005ab43d0fSKunihiko Hayashi 1015ab43d0fSKunihiko Hayashi static int uniphier_u3hsphy_get_nvparam(struct uniphier_u3hsphy_priv *priv, 1025ab43d0fSKunihiko Hayashi const char *name, unsigned int *val) 1035ab43d0fSKunihiko Hayashi { 1045ab43d0fSKunihiko Hayashi struct nvmem_cell *cell; 1055ab43d0fSKunihiko Hayashi u8 *buf; 1065ab43d0fSKunihiko Hayashi 1075ab43d0fSKunihiko Hayashi cell = devm_nvmem_cell_get(priv->dev, name); 1085ab43d0fSKunihiko Hayashi if (IS_ERR(cell)) 1095ab43d0fSKunihiko Hayashi return PTR_ERR(cell); 1105ab43d0fSKunihiko Hayashi 1115ab43d0fSKunihiko Hayashi buf = nvmem_cell_read(cell, NULL); 1125ab43d0fSKunihiko Hayashi if (IS_ERR(buf)) 1135ab43d0fSKunihiko Hayashi return PTR_ERR(buf); 1145ab43d0fSKunihiko Hayashi 1155ab43d0fSKunihiko Hayashi *val = *buf; 1165ab43d0fSKunihiko Hayashi 1175ab43d0fSKunihiko Hayashi kfree(buf); 1185ab43d0fSKunihiko Hayashi 1195ab43d0fSKunihiko Hayashi return 0; 1205ab43d0fSKunihiko Hayashi } 1215ab43d0fSKunihiko Hayashi 1225ab43d0fSKunihiko Hayashi static int uniphier_u3hsphy_get_nvparams(struct uniphier_u3hsphy_priv *priv, 1235ab43d0fSKunihiko Hayashi struct uniphier_u3hsphy_trim_param *pt) 1245ab43d0fSKunihiko Hayashi { 1255ab43d0fSKunihiko Hayashi int ret; 1265ab43d0fSKunihiko Hayashi 1275ab43d0fSKunihiko Hayashi ret = uniphier_u3hsphy_get_nvparam(priv, "rterm", &pt->rterm); 1285ab43d0fSKunihiko Hayashi if (ret) 1295ab43d0fSKunihiko Hayashi return ret; 1305ab43d0fSKunihiko Hayashi 1315ab43d0fSKunihiko Hayashi ret = uniphier_u3hsphy_get_nvparam(priv, "sel_t", &pt->sel_t); 1325ab43d0fSKunihiko Hayashi if (ret) 1335ab43d0fSKunihiko Hayashi return ret; 1345ab43d0fSKunihiko Hayashi 1355ab43d0fSKunihiko Hayashi ret = uniphier_u3hsphy_get_nvparam(priv, "hs_i", &pt->hs_i); 1365ab43d0fSKunihiko Hayashi if (ret) 1375ab43d0fSKunihiko Hayashi return ret; 1385ab43d0fSKunihiko Hayashi 1395ab43d0fSKunihiko Hayashi return 0; 1405ab43d0fSKunihiko Hayashi } 1415ab43d0fSKunihiko Hayashi 1425ab43d0fSKunihiko Hayashi static int uniphier_u3hsphy_update_config(struct uniphier_u3hsphy_priv *priv, 1435ab43d0fSKunihiko Hayashi u32 *pconfig) 1445ab43d0fSKunihiko Hayashi { 1455ab43d0fSKunihiko Hayashi struct uniphier_u3hsphy_trim_param trim; 1465ab43d0fSKunihiko Hayashi int ret, trimmed = 0; 1475ab43d0fSKunihiko Hayashi 1485ab43d0fSKunihiko Hayashi if (priv->data->trim_func) { 1495ab43d0fSKunihiko Hayashi ret = uniphier_u3hsphy_get_nvparams(priv, &trim); 1505ab43d0fSKunihiko Hayashi if (ret == -EPROBE_DEFER) 1515ab43d0fSKunihiko Hayashi return ret; 1525ab43d0fSKunihiko Hayashi 1535ab43d0fSKunihiko Hayashi /* 1545ab43d0fSKunihiko Hayashi * call trim_func only when trimming parameters that aren't 1555ab43d0fSKunihiko Hayashi * all-zero can be acquired. All-zero parameters mean nothing 1565ab43d0fSKunihiko Hayashi * has been written to nvmem. 1575ab43d0fSKunihiko Hayashi */ 1585ab43d0fSKunihiko Hayashi if (!ret && trim_param_is_valid(&trim)) { 1595ab43d0fSKunihiko Hayashi priv->data->trim_func(priv, pconfig, &trim); 1605ab43d0fSKunihiko Hayashi trimmed = 1; 1615ab43d0fSKunihiko Hayashi } else { 1625ab43d0fSKunihiko Hayashi dev_dbg(priv->dev, "can't get parameter from nvmem\n"); 1635ab43d0fSKunihiko Hayashi } 1645ab43d0fSKunihiko Hayashi } 1655ab43d0fSKunihiko Hayashi 1665ab43d0fSKunihiko Hayashi /* use default parameters without trimming values */ 1675ab43d0fSKunihiko Hayashi if (!trimmed) { 1685ab43d0fSKunihiko Hayashi *pconfig &= ~HSPHY_CFG0_HSDISC_MASK; 1695ab43d0fSKunihiko Hayashi *pconfig |= FIELD_PREP(HSPHY_CFG0_HSDISC_MASK, 3); 1705ab43d0fSKunihiko Hayashi } 1715ab43d0fSKunihiko Hayashi 1725ab43d0fSKunihiko Hayashi return 0; 1735ab43d0fSKunihiko Hayashi } 1745ab43d0fSKunihiko Hayashi 1755ab43d0fSKunihiko Hayashi static void uniphier_u3hsphy_set_param(struct uniphier_u3hsphy_priv *priv, 1765ab43d0fSKunihiko Hayashi const struct uniphier_u3hsphy_param *p) 1775ab43d0fSKunihiko Hayashi { 1785ab43d0fSKunihiko Hayashi u32 val; 1795ab43d0fSKunihiko Hayashi u32 field_mask = GENMASK(p->field.msb, p->field.lsb); 1805ab43d0fSKunihiko Hayashi u8 data; 1815ab43d0fSKunihiko Hayashi 1825ab43d0fSKunihiko Hayashi val = readl(priv->base + HSPHY_CFG1); 1835ab43d0fSKunihiko Hayashi val &= ~HSPHY_CFG1_ADR_MASK; 1845ab43d0fSKunihiko Hayashi val |= FIELD_PREP(HSPHY_CFG1_ADR_MASK, p->field.reg_no) 1855ab43d0fSKunihiko Hayashi | HSPHY_CFG1_ADR_EN; 1865ab43d0fSKunihiko Hayashi writel(val, priv->base + HSPHY_CFG1); 1875ab43d0fSKunihiko Hayashi 1885ab43d0fSKunihiko Hayashi val = readl(priv->base + HSPHY_CFG1); 1895ab43d0fSKunihiko Hayashi val &= ~HSPHY_CFG1_ADR_EN; 1905ab43d0fSKunihiko Hayashi writel(val, priv->base + HSPHY_CFG1); 1915ab43d0fSKunihiko Hayashi 1925ab43d0fSKunihiko Hayashi val = readl(priv->base + HSPHY_CFG1); 1935ab43d0fSKunihiko Hayashi val &= ~FIELD_PREP(HSPHY_CFG1_DAT_MASK, field_mask); 1945ab43d0fSKunihiko Hayashi data = field_mask & (p->value << p->field.lsb); 1955ab43d0fSKunihiko Hayashi val |= FIELD_PREP(HSPHY_CFG1_DAT_MASK, data) | HSPHY_CFG1_DAT_EN; 1965ab43d0fSKunihiko Hayashi writel(val, priv->base + HSPHY_CFG1); 1975ab43d0fSKunihiko Hayashi 1985ab43d0fSKunihiko Hayashi val = readl(priv->base + HSPHY_CFG1); 1995ab43d0fSKunihiko Hayashi val &= ~HSPHY_CFG1_DAT_EN; 2005ab43d0fSKunihiko Hayashi writel(val, priv->base + HSPHY_CFG1); 2015ab43d0fSKunihiko Hayashi } 2025ab43d0fSKunihiko Hayashi 2035ab43d0fSKunihiko Hayashi static int uniphier_u3hsphy_power_on(struct phy *phy) 2045ab43d0fSKunihiko Hayashi { 2055ab43d0fSKunihiko Hayashi struct uniphier_u3hsphy_priv *priv = phy_get_drvdata(phy); 2065ab43d0fSKunihiko Hayashi int ret; 2075ab43d0fSKunihiko Hayashi 2085ab43d0fSKunihiko Hayashi ret = clk_prepare_enable(priv->clk_ext); 2095ab43d0fSKunihiko Hayashi if (ret) 2105ab43d0fSKunihiko Hayashi return ret; 2115ab43d0fSKunihiko Hayashi 2125ab43d0fSKunihiko Hayashi ret = clk_prepare_enable(priv->clk); 2135ab43d0fSKunihiko Hayashi if (ret) 2145ab43d0fSKunihiko Hayashi goto out_clk_ext_disable; 2155ab43d0fSKunihiko Hayashi 2165ab43d0fSKunihiko Hayashi ret = reset_control_deassert(priv->rst); 2175ab43d0fSKunihiko Hayashi if (ret) 2185ab43d0fSKunihiko Hayashi goto out_clk_disable; 2195ab43d0fSKunihiko Hayashi 2205ab43d0fSKunihiko Hayashi if (priv->vbus) { 2215ab43d0fSKunihiko Hayashi ret = regulator_enable(priv->vbus); 2225ab43d0fSKunihiko Hayashi if (ret) 2235ab43d0fSKunihiko Hayashi goto out_rst_assert; 2245ab43d0fSKunihiko Hayashi } 2255ab43d0fSKunihiko Hayashi 2265ab43d0fSKunihiko Hayashi return 0; 2275ab43d0fSKunihiko Hayashi 2285ab43d0fSKunihiko Hayashi out_rst_assert: 2295ab43d0fSKunihiko Hayashi reset_control_assert(priv->rst); 2305ab43d0fSKunihiko Hayashi out_clk_disable: 2315ab43d0fSKunihiko Hayashi clk_disable_unprepare(priv->clk); 2325ab43d0fSKunihiko Hayashi out_clk_ext_disable: 2335ab43d0fSKunihiko Hayashi clk_disable_unprepare(priv->clk_ext); 2345ab43d0fSKunihiko Hayashi 2355ab43d0fSKunihiko Hayashi return ret; 2365ab43d0fSKunihiko Hayashi } 2375ab43d0fSKunihiko Hayashi 2385ab43d0fSKunihiko Hayashi static int uniphier_u3hsphy_power_off(struct phy *phy) 2395ab43d0fSKunihiko Hayashi { 2405ab43d0fSKunihiko Hayashi struct uniphier_u3hsphy_priv *priv = phy_get_drvdata(phy); 2415ab43d0fSKunihiko Hayashi 2425ab43d0fSKunihiko Hayashi if (priv->vbus) 2435ab43d0fSKunihiko Hayashi regulator_disable(priv->vbus); 2445ab43d0fSKunihiko Hayashi 2455ab43d0fSKunihiko Hayashi reset_control_assert(priv->rst); 2465ab43d0fSKunihiko Hayashi clk_disable_unprepare(priv->clk); 2475ab43d0fSKunihiko Hayashi clk_disable_unprepare(priv->clk_ext); 2485ab43d0fSKunihiko Hayashi 2495ab43d0fSKunihiko Hayashi return 0; 2505ab43d0fSKunihiko Hayashi } 2515ab43d0fSKunihiko Hayashi 2525ab43d0fSKunihiko Hayashi static int uniphier_u3hsphy_init(struct phy *phy) 2535ab43d0fSKunihiko Hayashi { 2545ab43d0fSKunihiko Hayashi struct uniphier_u3hsphy_priv *priv = phy_get_drvdata(phy); 2555ab43d0fSKunihiko Hayashi u32 config0, config1; 2565ab43d0fSKunihiko Hayashi int i, ret; 2575ab43d0fSKunihiko Hayashi 2585ab43d0fSKunihiko Hayashi ret = clk_prepare_enable(priv->clk_parent); 2595ab43d0fSKunihiko Hayashi if (ret) 2605ab43d0fSKunihiko Hayashi return ret; 2615ab43d0fSKunihiko Hayashi 262e68c2a8aSKunihiko Hayashi ret = clk_prepare_enable(priv->clk_parent_gio); 2635ab43d0fSKunihiko Hayashi if (ret) 2645ab43d0fSKunihiko Hayashi goto out_clk_disable; 2655ab43d0fSKunihiko Hayashi 266e68c2a8aSKunihiko Hayashi ret = reset_control_deassert(priv->rst_parent); 267e68c2a8aSKunihiko Hayashi if (ret) 268e68c2a8aSKunihiko Hayashi goto out_clk_gio_disable; 269e68c2a8aSKunihiko Hayashi 270e68c2a8aSKunihiko Hayashi ret = reset_control_deassert(priv->rst_parent_gio); 271e68c2a8aSKunihiko Hayashi if (ret) 272e68c2a8aSKunihiko Hayashi goto out_rst_assert; 273e68c2a8aSKunihiko Hayashi 274e68c2a8aSKunihiko Hayashi if ((priv->data->is_legacy) 275e68c2a8aSKunihiko Hayashi || (!priv->data->config0 && !priv->data->config1)) 2765ab43d0fSKunihiko Hayashi return 0; 2775ab43d0fSKunihiko Hayashi 2785ab43d0fSKunihiko Hayashi config0 = priv->data->config0; 2795ab43d0fSKunihiko Hayashi config1 = priv->data->config1; 2805ab43d0fSKunihiko Hayashi 2815ab43d0fSKunihiko Hayashi ret = uniphier_u3hsphy_update_config(priv, &config0); 2825ab43d0fSKunihiko Hayashi if (ret) 2835ab43d0fSKunihiko Hayashi goto out_rst_assert; 2845ab43d0fSKunihiko Hayashi 2855ab43d0fSKunihiko Hayashi writel(config0, priv->base + HSPHY_CFG0); 2865ab43d0fSKunihiko Hayashi writel(config1, priv->base + HSPHY_CFG1); 2875ab43d0fSKunihiko Hayashi 2885ab43d0fSKunihiko Hayashi for (i = 0; i < priv->data->nparams; i++) 2895ab43d0fSKunihiko Hayashi uniphier_u3hsphy_set_param(priv, &priv->data->param[i]); 2905ab43d0fSKunihiko Hayashi 2915ab43d0fSKunihiko Hayashi return 0; 2925ab43d0fSKunihiko Hayashi 2935ab43d0fSKunihiko Hayashi out_rst_assert: 2945ab43d0fSKunihiko Hayashi reset_control_assert(priv->rst_parent); 295e68c2a8aSKunihiko Hayashi out_clk_gio_disable: 296e68c2a8aSKunihiko Hayashi clk_disable_unprepare(priv->clk_parent_gio); 2975ab43d0fSKunihiko Hayashi out_clk_disable: 2985ab43d0fSKunihiko Hayashi clk_disable_unprepare(priv->clk_parent); 2995ab43d0fSKunihiko Hayashi 3005ab43d0fSKunihiko Hayashi return ret; 3015ab43d0fSKunihiko Hayashi } 3025ab43d0fSKunihiko Hayashi 3035ab43d0fSKunihiko Hayashi static int uniphier_u3hsphy_exit(struct phy *phy) 3045ab43d0fSKunihiko Hayashi { 3055ab43d0fSKunihiko Hayashi struct uniphier_u3hsphy_priv *priv = phy_get_drvdata(phy); 3065ab43d0fSKunihiko Hayashi 307e68c2a8aSKunihiko Hayashi reset_control_assert(priv->rst_parent_gio); 3085ab43d0fSKunihiko Hayashi reset_control_assert(priv->rst_parent); 309e68c2a8aSKunihiko Hayashi clk_disable_unprepare(priv->clk_parent_gio); 3105ab43d0fSKunihiko Hayashi clk_disable_unprepare(priv->clk_parent); 3115ab43d0fSKunihiko Hayashi 3125ab43d0fSKunihiko Hayashi return 0; 3135ab43d0fSKunihiko Hayashi } 3145ab43d0fSKunihiko Hayashi 3155ab43d0fSKunihiko Hayashi static const struct phy_ops uniphier_u3hsphy_ops = { 3165ab43d0fSKunihiko Hayashi .init = uniphier_u3hsphy_init, 3175ab43d0fSKunihiko Hayashi .exit = uniphier_u3hsphy_exit, 3185ab43d0fSKunihiko Hayashi .power_on = uniphier_u3hsphy_power_on, 3195ab43d0fSKunihiko Hayashi .power_off = uniphier_u3hsphy_power_off, 3205ab43d0fSKunihiko Hayashi .owner = THIS_MODULE, 3215ab43d0fSKunihiko Hayashi }; 3225ab43d0fSKunihiko Hayashi 3235ab43d0fSKunihiko Hayashi static int uniphier_u3hsphy_probe(struct platform_device *pdev) 3245ab43d0fSKunihiko Hayashi { 3255ab43d0fSKunihiko Hayashi struct device *dev = &pdev->dev; 3265ab43d0fSKunihiko Hayashi struct uniphier_u3hsphy_priv *priv; 3275ab43d0fSKunihiko Hayashi struct phy_provider *phy_provider; 3285ab43d0fSKunihiko Hayashi struct phy *phy; 3295ab43d0fSKunihiko Hayashi 3305ab43d0fSKunihiko Hayashi priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 3315ab43d0fSKunihiko Hayashi if (!priv) 3325ab43d0fSKunihiko Hayashi return -ENOMEM; 3335ab43d0fSKunihiko Hayashi 3345ab43d0fSKunihiko Hayashi priv->dev = dev; 3355ab43d0fSKunihiko Hayashi priv->data = of_device_get_match_data(dev); 3365ab43d0fSKunihiko Hayashi if (WARN_ON(!priv->data || 3375ab43d0fSKunihiko Hayashi priv->data->nparams > MAX_PHY_PARAMS)) 3385ab43d0fSKunihiko Hayashi return -EINVAL; 3395ab43d0fSKunihiko Hayashi 34040d76346SKunihiko Hayashi priv->base = devm_platform_ioremap_resource(pdev, 0); 3415ab43d0fSKunihiko Hayashi if (IS_ERR(priv->base)) 3425ab43d0fSKunihiko Hayashi return PTR_ERR(priv->base); 3435ab43d0fSKunihiko Hayashi 344e68c2a8aSKunihiko Hayashi if (!priv->data->is_legacy) { 3455ab43d0fSKunihiko Hayashi priv->clk = devm_clk_get(dev, "phy"); 3465ab43d0fSKunihiko Hayashi if (IS_ERR(priv->clk)) 3475ab43d0fSKunihiko Hayashi return PTR_ERR(priv->clk); 3485ab43d0fSKunihiko Hayashi 349752d31a3SChunfeng Yun priv->clk_ext = devm_clk_get_optional(dev, "phy-ext"); 350752d31a3SChunfeng Yun if (IS_ERR(priv->clk_ext)) 3515ab43d0fSKunihiko Hayashi return PTR_ERR(priv->clk_ext); 3525ab43d0fSKunihiko Hayashi 3535ab43d0fSKunihiko Hayashi priv->rst = devm_reset_control_get_shared(dev, "phy"); 3545ab43d0fSKunihiko Hayashi if (IS_ERR(priv->rst)) 3555ab43d0fSKunihiko Hayashi return PTR_ERR(priv->rst); 3565ab43d0fSKunihiko Hayashi 357e68c2a8aSKunihiko Hayashi } else { 358e68c2a8aSKunihiko Hayashi priv->clk_parent_gio = devm_clk_get(dev, "gio"); 359e68c2a8aSKunihiko Hayashi if (IS_ERR(priv->clk_parent_gio)) 360e68c2a8aSKunihiko Hayashi return PTR_ERR(priv->clk_parent_gio); 361e68c2a8aSKunihiko Hayashi 362e68c2a8aSKunihiko Hayashi priv->rst_parent_gio = 363e68c2a8aSKunihiko Hayashi devm_reset_control_get_shared(dev, "gio"); 364e68c2a8aSKunihiko Hayashi if (IS_ERR(priv->rst_parent_gio)) 365e68c2a8aSKunihiko Hayashi return PTR_ERR(priv->rst_parent_gio); 366e68c2a8aSKunihiko Hayashi } 367e68c2a8aSKunihiko Hayashi 368e68c2a8aSKunihiko Hayashi priv->clk_parent = devm_clk_get(dev, "link"); 369e68c2a8aSKunihiko Hayashi if (IS_ERR(priv->clk_parent)) 370e68c2a8aSKunihiko Hayashi return PTR_ERR(priv->clk_parent); 371e68c2a8aSKunihiko Hayashi 3725ab43d0fSKunihiko Hayashi priv->rst_parent = devm_reset_control_get_shared(dev, "link"); 3735ab43d0fSKunihiko Hayashi if (IS_ERR(priv->rst_parent)) 3745ab43d0fSKunihiko Hayashi return PTR_ERR(priv->rst_parent); 3755ab43d0fSKunihiko Hayashi 3765ab43d0fSKunihiko Hayashi priv->vbus = devm_regulator_get_optional(dev, "vbus"); 3775ab43d0fSKunihiko Hayashi if (IS_ERR(priv->vbus)) { 3785ab43d0fSKunihiko Hayashi if (PTR_ERR(priv->vbus) == -EPROBE_DEFER) 3795ab43d0fSKunihiko Hayashi return PTR_ERR(priv->vbus); 3805ab43d0fSKunihiko Hayashi priv->vbus = NULL; 3815ab43d0fSKunihiko Hayashi } 3825ab43d0fSKunihiko Hayashi 3835ab43d0fSKunihiko Hayashi phy = devm_phy_create(dev, dev->of_node, &uniphier_u3hsphy_ops); 3845ab43d0fSKunihiko Hayashi if (IS_ERR(phy)) 3855ab43d0fSKunihiko Hayashi return PTR_ERR(phy); 3865ab43d0fSKunihiko Hayashi 3875ab43d0fSKunihiko Hayashi phy_set_drvdata(phy, priv); 3885ab43d0fSKunihiko Hayashi phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); 3895ab43d0fSKunihiko Hayashi 3905ab43d0fSKunihiko Hayashi return PTR_ERR_OR_ZERO(phy_provider); 3915ab43d0fSKunihiko Hayashi } 3925ab43d0fSKunihiko Hayashi 393e68c2a8aSKunihiko Hayashi static const struct uniphier_u3hsphy_soc_data uniphier_pro5_data = { 394e68c2a8aSKunihiko Hayashi .is_legacy = true, 395e68c2a8aSKunihiko Hayashi .nparams = 0, 396e68c2a8aSKunihiko Hayashi }; 397e68c2a8aSKunihiko Hayashi 3985ab43d0fSKunihiko Hayashi static const struct uniphier_u3hsphy_soc_data uniphier_pxs2_data = { 399e68c2a8aSKunihiko Hayashi .is_legacy = false, 400*25858c52SKunihiko Hayashi .nparams = 2, 401*25858c52SKunihiko Hayashi .param = { 402*25858c52SKunihiko Hayashi { RX_CHK_SYNC, 1 }, 403*25858c52SKunihiko Hayashi { RX_SYNC_SEL, 1 }, 404*25858c52SKunihiko Hayashi }, 4055ab43d0fSKunihiko Hayashi }; 4065ab43d0fSKunihiko Hayashi 4075ab43d0fSKunihiko Hayashi static const struct uniphier_u3hsphy_soc_data uniphier_ld20_data = { 408e68c2a8aSKunihiko Hayashi .is_legacy = false, 409*25858c52SKunihiko Hayashi .nparams = 4, 4105ab43d0fSKunihiko Hayashi .param = { 411*25858c52SKunihiko Hayashi { RX_CHK_SYNC, 1 }, 412*25858c52SKunihiko Hayashi { RX_SYNC_SEL, 1 }, 4135ab43d0fSKunihiko Hayashi { LS_SLEW, 1 }, 4145ab43d0fSKunihiko Hayashi { FS_LS_DRV, 1 }, 4155ab43d0fSKunihiko Hayashi }, 4165ab43d0fSKunihiko Hayashi .trim_func = uniphier_u3hsphy_trim_ld20, 4175ab43d0fSKunihiko Hayashi .config0 = 0x92316680, 4185ab43d0fSKunihiko Hayashi .config1 = 0x00000106, 4195ab43d0fSKunihiko Hayashi }; 4205ab43d0fSKunihiko Hayashi 4215ab43d0fSKunihiko Hayashi static const struct uniphier_u3hsphy_soc_data uniphier_pxs3_data = { 422e68c2a8aSKunihiko Hayashi .is_legacy = false, 423*25858c52SKunihiko Hayashi .nparams = 2, 424*25858c52SKunihiko Hayashi .param = { 425*25858c52SKunihiko Hayashi { RX_CHK_SYNC, 1 }, 426*25858c52SKunihiko Hayashi { RX_SYNC_SEL, 1 }, 427*25858c52SKunihiko Hayashi }, 4285ab43d0fSKunihiko Hayashi .trim_func = uniphier_u3hsphy_trim_ld20, 4295ab43d0fSKunihiko Hayashi .config0 = 0x92316680, 4305ab43d0fSKunihiko Hayashi .config1 = 0x00000106, 4315ab43d0fSKunihiko Hayashi }; 4325ab43d0fSKunihiko Hayashi 4335ab43d0fSKunihiko Hayashi static const struct of_device_id uniphier_u3hsphy_match[] = { 4345ab43d0fSKunihiko Hayashi { 435e68c2a8aSKunihiko Hayashi .compatible = "socionext,uniphier-pro5-usb3-hsphy", 436e68c2a8aSKunihiko Hayashi .data = &uniphier_pro5_data, 437e68c2a8aSKunihiko Hayashi }, 438e68c2a8aSKunihiko Hayashi { 4395ab43d0fSKunihiko Hayashi .compatible = "socionext,uniphier-pxs2-usb3-hsphy", 4405ab43d0fSKunihiko Hayashi .data = &uniphier_pxs2_data, 4415ab43d0fSKunihiko Hayashi }, 4425ab43d0fSKunihiko Hayashi { 4435ab43d0fSKunihiko Hayashi .compatible = "socionext,uniphier-ld20-usb3-hsphy", 4445ab43d0fSKunihiko Hayashi .data = &uniphier_ld20_data, 4455ab43d0fSKunihiko Hayashi }, 4465ab43d0fSKunihiko Hayashi { 4475ab43d0fSKunihiko Hayashi .compatible = "socionext,uniphier-pxs3-usb3-hsphy", 4485ab43d0fSKunihiko Hayashi .data = &uniphier_pxs3_data, 4495ab43d0fSKunihiko Hayashi }, 4505ab43d0fSKunihiko Hayashi { /* sentinel */ } 4515ab43d0fSKunihiko Hayashi }; 4525ab43d0fSKunihiko Hayashi MODULE_DEVICE_TABLE(of, uniphier_u3hsphy_match); 4535ab43d0fSKunihiko Hayashi 4545ab43d0fSKunihiko Hayashi static struct platform_driver uniphier_u3hsphy_driver = { 4555ab43d0fSKunihiko Hayashi .probe = uniphier_u3hsphy_probe, 4565ab43d0fSKunihiko Hayashi .driver = { 4575ab43d0fSKunihiko Hayashi .name = "uniphier-usb3-hsphy", 4585ab43d0fSKunihiko Hayashi .of_match_table = uniphier_u3hsphy_match, 4595ab43d0fSKunihiko Hayashi }, 4605ab43d0fSKunihiko Hayashi }; 4615ab43d0fSKunihiko Hayashi 4625ab43d0fSKunihiko Hayashi module_platform_driver(uniphier_u3hsphy_driver); 4635ab43d0fSKunihiko Hayashi 4645ab43d0fSKunihiko Hayashi MODULE_AUTHOR("Kunihiko Hayashi <hayashi.kunihiko@socionext.com>"); 4655ab43d0fSKunihiko Hayashi MODULE_DESCRIPTION("UniPhier HS-PHY driver for USB3 controller"); 4665ab43d0fSKunihiko Hayashi MODULE_LICENSE("GPL v2"); 467