1*5ab43d0fSKunihiko Hayashi // SPDX-License-Identifier: GPL-2.0 2*5ab43d0fSKunihiko Hayashi /* 3*5ab43d0fSKunihiko Hayashi * phy-uniphier-usb3hs.c - HS-PHY driver for Socionext UniPhier USB3 controller 4*5ab43d0fSKunihiko Hayashi * Copyright 2015-2018 Socionext Inc. 5*5ab43d0fSKunihiko Hayashi * Author: 6*5ab43d0fSKunihiko Hayashi * Kunihiko Hayashi <hayashi.kunihiko@socionext.com> 7*5ab43d0fSKunihiko Hayashi * Contributors: 8*5ab43d0fSKunihiko Hayashi * Motoya Tanigawa <tanigawa.motoya@socionext.com> 9*5ab43d0fSKunihiko Hayashi * Masami Hiramatsu <masami.hiramatsu@linaro.org> 10*5ab43d0fSKunihiko Hayashi */ 11*5ab43d0fSKunihiko Hayashi 12*5ab43d0fSKunihiko Hayashi #include <linux/bitfield.h> 13*5ab43d0fSKunihiko Hayashi #include <linux/bitops.h> 14*5ab43d0fSKunihiko Hayashi #include <linux/clk.h> 15*5ab43d0fSKunihiko Hayashi #include <linux/io.h> 16*5ab43d0fSKunihiko Hayashi #include <linux/module.h> 17*5ab43d0fSKunihiko Hayashi #include <linux/nvmem-consumer.h> 18*5ab43d0fSKunihiko Hayashi #include <linux/of.h> 19*5ab43d0fSKunihiko Hayashi #include <linux/of_platform.h> 20*5ab43d0fSKunihiko Hayashi #include <linux/phy/phy.h> 21*5ab43d0fSKunihiko Hayashi #include <linux/platform_device.h> 22*5ab43d0fSKunihiko Hayashi #include <linux/regulator/consumer.h> 23*5ab43d0fSKunihiko Hayashi #include <linux/reset.h> 24*5ab43d0fSKunihiko Hayashi #include <linux/slab.h> 25*5ab43d0fSKunihiko Hayashi 26*5ab43d0fSKunihiko Hayashi #define HSPHY_CFG0 0x0 27*5ab43d0fSKunihiko Hayashi #define HSPHY_CFG0_HS_I_MASK GENMASK(31, 28) 28*5ab43d0fSKunihiko Hayashi #define HSPHY_CFG0_HSDISC_MASK GENMASK(27, 26) 29*5ab43d0fSKunihiko Hayashi #define HSPHY_CFG0_SWING_MASK GENMASK(17, 16) 30*5ab43d0fSKunihiko Hayashi #define HSPHY_CFG0_SEL_T_MASK GENMASK(15, 12) 31*5ab43d0fSKunihiko Hayashi #define HSPHY_CFG0_RTERM_MASK GENMASK(7, 6) 32*5ab43d0fSKunihiko Hayashi #define HSPHY_CFG0_TRIMMASK (HSPHY_CFG0_HS_I_MASK \ 33*5ab43d0fSKunihiko Hayashi | HSPHY_CFG0_SEL_T_MASK \ 34*5ab43d0fSKunihiko Hayashi | HSPHY_CFG0_RTERM_MASK) 35*5ab43d0fSKunihiko Hayashi 36*5ab43d0fSKunihiko Hayashi #define HSPHY_CFG1 0x4 37*5ab43d0fSKunihiko Hayashi #define HSPHY_CFG1_DAT_EN BIT(29) 38*5ab43d0fSKunihiko Hayashi #define HSPHY_CFG1_ADR_EN BIT(28) 39*5ab43d0fSKunihiko Hayashi #define HSPHY_CFG1_ADR_MASK GENMASK(27, 16) 40*5ab43d0fSKunihiko Hayashi #define HSPHY_CFG1_DAT_MASK GENMASK(23, 16) 41*5ab43d0fSKunihiko Hayashi 42*5ab43d0fSKunihiko Hayashi #define PHY_F(regno, msb, lsb) { (regno), (msb), (lsb) } 43*5ab43d0fSKunihiko Hayashi 44*5ab43d0fSKunihiko Hayashi #define LS_SLEW PHY_F(10, 6, 6) /* LS mode slew rate */ 45*5ab43d0fSKunihiko Hayashi #define FS_LS_DRV PHY_F(10, 5, 5) /* FS/LS slew rate */ 46*5ab43d0fSKunihiko Hayashi 47*5ab43d0fSKunihiko Hayashi #define MAX_PHY_PARAMS 2 48*5ab43d0fSKunihiko Hayashi 49*5ab43d0fSKunihiko Hayashi struct uniphier_u3hsphy_param { 50*5ab43d0fSKunihiko Hayashi struct { 51*5ab43d0fSKunihiko Hayashi int reg_no; 52*5ab43d0fSKunihiko Hayashi int msb; 53*5ab43d0fSKunihiko Hayashi int lsb; 54*5ab43d0fSKunihiko Hayashi } field; 55*5ab43d0fSKunihiko Hayashi u8 value; 56*5ab43d0fSKunihiko Hayashi }; 57*5ab43d0fSKunihiko Hayashi 58*5ab43d0fSKunihiko Hayashi struct uniphier_u3hsphy_trim_param { 59*5ab43d0fSKunihiko Hayashi unsigned int rterm; 60*5ab43d0fSKunihiko Hayashi unsigned int sel_t; 61*5ab43d0fSKunihiko Hayashi unsigned int hs_i; 62*5ab43d0fSKunihiko Hayashi }; 63*5ab43d0fSKunihiko Hayashi 64*5ab43d0fSKunihiko Hayashi #define trim_param_is_valid(p) ((p)->rterm || (p)->sel_t || (p)->hs_i) 65*5ab43d0fSKunihiko Hayashi 66*5ab43d0fSKunihiko Hayashi struct uniphier_u3hsphy_priv { 67*5ab43d0fSKunihiko Hayashi struct device *dev; 68*5ab43d0fSKunihiko Hayashi void __iomem *base; 69*5ab43d0fSKunihiko Hayashi struct clk *clk, *clk_parent, *clk_ext; 70*5ab43d0fSKunihiko Hayashi struct reset_control *rst, *rst_parent; 71*5ab43d0fSKunihiko Hayashi struct regulator *vbus; 72*5ab43d0fSKunihiko Hayashi const struct uniphier_u3hsphy_soc_data *data; 73*5ab43d0fSKunihiko Hayashi }; 74*5ab43d0fSKunihiko Hayashi 75*5ab43d0fSKunihiko Hayashi struct uniphier_u3hsphy_soc_data { 76*5ab43d0fSKunihiko Hayashi int nparams; 77*5ab43d0fSKunihiko Hayashi const struct uniphier_u3hsphy_param param[MAX_PHY_PARAMS]; 78*5ab43d0fSKunihiko Hayashi u32 config0; 79*5ab43d0fSKunihiko Hayashi u32 config1; 80*5ab43d0fSKunihiko Hayashi void (*trim_func)(struct uniphier_u3hsphy_priv *priv, u32 *pconfig, 81*5ab43d0fSKunihiko Hayashi struct uniphier_u3hsphy_trim_param *pt); 82*5ab43d0fSKunihiko Hayashi }; 83*5ab43d0fSKunihiko Hayashi 84*5ab43d0fSKunihiko Hayashi static void uniphier_u3hsphy_trim_ld20(struct uniphier_u3hsphy_priv *priv, 85*5ab43d0fSKunihiko Hayashi u32 *pconfig, 86*5ab43d0fSKunihiko Hayashi struct uniphier_u3hsphy_trim_param *pt) 87*5ab43d0fSKunihiko Hayashi { 88*5ab43d0fSKunihiko Hayashi *pconfig &= ~HSPHY_CFG0_RTERM_MASK; 89*5ab43d0fSKunihiko Hayashi *pconfig |= FIELD_PREP(HSPHY_CFG0_RTERM_MASK, pt->rterm); 90*5ab43d0fSKunihiko Hayashi 91*5ab43d0fSKunihiko Hayashi *pconfig &= ~HSPHY_CFG0_SEL_T_MASK; 92*5ab43d0fSKunihiko Hayashi *pconfig |= FIELD_PREP(HSPHY_CFG0_SEL_T_MASK, pt->sel_t); 93*5ab43d0fSKunihiko Hayashi 94*5ab43d0fSKunihiko Hayashi *pconfig &= ~HSPHY_CFG0_HS_I_MASK; 95*5ab43d0fSKunihiko Hayashi *pconfig |= FIELD_PREP(HSPHY_CFG0_HS_I_MASK, pt->hs_i); 96*5ab43d0fSKunihiko Hayashi } 97*5ab43d0fSKunihiko Hayashi 98*5ab43d0fSKunihiko Hayashi static int uniphier_u3hsphy_get_nvparam(struct uniphier_u3hsphy_priv *priv, 99*5ab43d0fSKunihiko Hayashi const char *name, unsigned int *val) 100*5ab43d0fSKunihiko Hayashi { 101*5ab43d0fSKunihiko Hayashi struct nvmem_cell *cell; 102*5ab43d0fSKunihiko Hayashi u8 *buf; 103*5ab43d0fSKunihiko Hayashi 104*5ab43d0fSKunihiko Hayashi cell = devm_nvmem_cell_get(priv->dev, name); 105*5ab43d0fSKunihiko Hayashi if (IS_ERR(cell)) 106*5ab43d0fSKunihiko Hayashi return PTR_ERR(cell); 107*5ab43d0fSKunihiko Hayashi 108*5ab43d0fSKunihiko Hayashi buf = nvmem_cell_read(cell, NULL); 109*5ab43d0fSKunihiko Hayashi if (IS_ERR(buf)) 110*5ab43d0fSKunihiko Hayashi return PTR_ERR(buf); 111*5ab43d0fSKunihiko Hayashi 112*5ab43d0fSKunihiko Hayashi *val = *buf; 113*5ab43d0fSKunihiko Hayashi 114*5ab43d0fSKunihiko Hayashi kfree(buf); 115*5ab43d0fSKunihiko Hayashi 116*5ab43d0fSKunihiko Hayashi return 0; 117*5ab43d0fSKunihiko Hayashi } 118*5ab43d0fSKunihiko Hayashi 119*5ab43d0fSKunihiko Hayashi static int uniphier_u3hsphy_get_nvparams(struct uniphier_u3hsphy_priv *priv, 120*5ab43d0fSKunihiko Hayashi struct uniphier_u3hsphy_trim_param *pt) 121*5ab43d0fSKunihiko Hayashi { 122*5ab43d0fSKunihiko Hayashi int ret; 123*5ab43d0fSKunihiko Hayashi 124*5ab43d0fSKunihiko Hayashi ret = uniphier_u3hsphy_get_nvparam(priv, "rterm", &pt->rterm); 125*5ab43d0fSKunihiko Hayashi if (ret) 126*5ab43d0fSKunihiko Hayashi return ret; 127*5ab43d0fSKunihiko Hayashi 128*5ab43d0fSKunihiko Hayashi ret = uniphier_u3hsphy_get_nvparam(priv, "sel_t", &pt->sel_t); 129*5ab43d0fSKunihiko Hayashi if (ret) 130*5ab43d0fSKunihiko Hayashi return ret; 131*5ab43d0fSKunihiko Hayashi 132*5ab43d0fSKunihiko Hayashi ret = uniphier_u3hsphy_get_nvparam(priv, "hs_i", &pt->hs_i); 133*5ab43d0fSKunihiko Hayashi if (ret) 134*5ab43d0fSKunihiko Hayashi return ret; 135*5ab43d0fSKunihiko Hayashi 136*5ab43d0fSKunihiko Hayashi return 0; 137*5ab43d0fSKunihiko Hayashi } 138*5ab43d0fSKunihiko Hayashi 139*5ab43d0fSKunihiko Hayashi static int uniphier_u3hsphy_update_config(struct uniphier_u3hsphy_priv *priv, 140*5ab43d0fSKunihiko Hayashi u32 *pconfig) 141*5ab43d0fSKunihiko Hayashi { 142*5ab43d0fSKunihiko Hayashi struct uniphier_u3hsphy_trim_param trim; 143*5ab43d0fSKunihiko Hayashi int ret, trimmed = 0; 144*5ab43d0fSKunihiko Hayashi 145*5ab43d0fSKunihiko Hayashi if (priv->data->trim_func) { 146*5ab43d0fSKunihiko Hayashi ret = uniphier_u3hsphy_get_nvparams(priv, &trim); 147*5ab43d0fSKunihiko Hayashi if (ret == -EPROBE_DEFER) 148*5ab43d0fSKunihiko Hayashi return ret; 149*5ab43d0fSKunihiko Hayashi 150*5ab43d0fSKunihiko Hayashi /* 151*5ab43d0fSKunihiko Hayashi * call trim_func only when trimming parameters that aren't 152*5ab43d0fSKunihiko Hayashi * all-zero can be acquired. All-zero parameters mean nothing 153*5ab43d0fSKunihiko Hayashi * has been written to nvmem. 154*5ab43d0fSKunihiko Hayashi */ 155*5ab43d0fSKunihiko Hayashi if (!ret && trim_param_is_valid(&trim)) { 156*5ab43d0fSKunihiko Hayashi priv->data->trim_func(priv, pconfig, &trim); 157*5ab43d0fSKunihiko Hayashi trimmed = 1; 158*5ab43d0fSKunihiko Hayashi } else { 159*5ab43d0fSKunihiko Hayashi dev_dbg(priv->dev, "can't get parameter from nvmem\n"); 160*5ab43d0fSKunihiko Hayashi } 161*5ab43d0fSKunihiko Hayashi } 162*5ab43d0fSKunihiko Hayashi 163*5ab43d0fSKunihiko Hayashi /* use default parameters without trimming values */ 164*5ab43d0fSKunihiko Hayashi if (!trimmed) { 165*5ab43d0fSKunihiko Hayashi *pconfig &= ~HSPHY_CFG0_HSDISC_MASK; 166*5ab43d0fSKunihiko Hayashi *pconfig |= FIELD_PREP(HSPHY_CFG0_HSDISC_MASK, 3); 167*5ab43d0fSKunihiko Hayashi } 168*5ab43d0fSKunihiko Hayashi 169*5ab43d0fSKunihiko Hayashi return 0; 170*5ab43d0fSKunihiko Hayashi } 171*5ab43d0fSKunihiko Hayashi 172*5ab43d0fSKunihiko Hayashi static void uniphier_u3hsphy_set_param(struct uniphier_u3hsphy_priv *priv, 173*5ab43d0fSKunihiko Hayashi const struct uniphier_u3hsphy_param *p) 174*5ab43d0fSKunihiko Hayashi { 175*5ab43d0fSKunihiko Hayashi u32 val; 176*5ab43d0fSKunihiko Hayashi u32 field_mask = GENMASK(p->field.msb, p->field.lsb); 177*5ab43d0fSKunihiko Hayashi u8 data; 178*5ab43d0fSKunihiko Hayashi 179*5ab43d0fSKunihiko Hayashi val = readl(priv->base + HSPHY_CFG1); 180*5ab43d0fSKunihiko Hayashi val &= ~HSPHY_CFG1_ADR_MASK; 181*5ab43d0fSKunihiko Hayashi val |= FIELD_PREP(HSPHY_CFG1_ADR_MASK, p->field.reg_no) 182*5ab43d0fSKunihiko Hayashi | HSPHY_CFG1_ADR_EN; 183*5ab43d0fSKunihiko Hayashi writel(val, priv->base + HSPHY_CFG1); 184*5ab43d0fSKunihiko Hayashi 185*5ab43d0fSKunihiko Hayashi val = readl(priv->base + HSPHY_CFG1); 186*5ab43d0fSKunihiko Hayashi val &= ~HSPHY_CFG1_ADR_EN; 187*5ab43d0fSKunihiko Hayashi writel(val, priv->base + HSPHY_CFG1); 188*5ab43d0fSKunihiko Hayashi 189*5ab43d0fSKunihiko Hayashi val = readl(priv->base + HSPHY_CFG1); 190*5ab43d0fSKunihiko Hayashi val &= ~FIELD_PREP(HSPHY_CFG1_DAT_MASK, field_mask); 191*5ab43d0fSKunihiko Hayashi data = field_mask & (p->value << p->field.lsb); 192*5ab43d0fSKunihiko Hayashi val |= FIELD_PREP(HSPHY_CFG1_DAT_MASK, data) | HSPHY_CFG1_DAT_EN; 193*5ab43d0fSKunihiko Hayashi writel(val, priv->base + HSPHY_CFG1); 194*5ab43d0fSKunihiko Hayashi 195*5ab43d0fSKunihiko Hayashi val = readl(priv->base + HSPHY_CFG1); 196*5ab43d0fSKunihiko Hayashi val &= ~HSPHY_CFG1_DAT_EN; 197*5ab43d0fSKunihiko Hayashi writel(val, priv->base + HSPHY_CFG1); 198*5ab43d0fSKunihiko Hayashi } 199*5ab43d0fSKunihiko Hayashi 200*5ab43d0fSKunihiko Hayashi static int uniphier_u3hsphy_power_on(struct phy *phy) 201*5ab43d0fSKunihiko Hayashi { 202*5ab43d0fSKunihiko Hayashi struct uniphier_u3hsphy_priv *priv = phy_get_drvdata(phy); 203*5ab43d0fSKunihiko Hayashi int ret; 204*5ab43d0fSKunihiko Hayashi 205*5ab43d0fSKunihiko Hayashi ret = clk_prepare_enable(priv->clk_ext); 206*5ab43d0fSKunihiko Hayashi if (ret) 207*5ab43d0fSKunihiko Hayashi return ret; 208*5ab43d0fSKunihiko Hayashi 209*5ab43d0fSKunihiko Hayashi ret = clk_prepare_enable(priv->clk); 210*5ab43d0fSKunihiko Hayashi if (ret) 211*5ab43d0fSKunihiko Hayashi goto out_clk_ext_disable; 212*5ab43d0fSKunihiko Hayashi 213*5ab43d0fSKunihiko Hayashi ret = reset_control_deassert(priv->rst); 214*5ab43d0fSKunihiko Hayashi if (ret) 215*5ab43d0fSKunihiko Hayashi goto out_clk_disable; 216*5ab43d0fSKunihiko Hayashi 217*5ab43d0fSKunihiko Hayashi if (priv->vbus) { 218*5ab43d0fSKunihiko Hayashi ret = regulator_enable(priv->vbus); 219*5ab43d0fSKunihiko Hayashi if (ret) 220*5ab43d0fSKunihiko Hayashi goto out_rst_assert; 221*5ab43d0fSKunihiko Hayashi } 222*5ab43d0fSKunihiko Hayashi 223*5ab43d0fSKunihiko Hayashi return 0; 224*5ab43d0fSKunihiko Hayashi 225*5ab43d0fSKunihiko Hayashi out_rst_assert: 226*5ab43d0fSKunihiko Hayashi reset_control_assert(priv->rst); 227*5ab43d0fSKunihiko Hayashi out_clk_disable: 228*5ab43d0fSKunihiko Hayashi clk_disable_unprepare(priv->clk); 229*5ab43d0fSKunihiko Hayashi out_clk_ext_disable: 230*5ab43d0fSKunihiko Hayashi clk_disable_unprepare(priv->clk_ext); 231*5ab43d0fSKunihiko Hayashi 232*5ab43d0fSKunihiko Hayashi return ret; 233*5ab43d0fSKunihiko Hayashi } 234*5ab43d0fSKunihiko Hayashi 235*5ab43d0fSKunihiko Hayashi static int uniphier_u3hsphy_power_off(struct phy *phy) 236*5ab43d0fSKunihiko Hayashi { 237*5ab43d0fSKunihiko Hayashi struct uniphier_u3hsphy_priv *priv = phy_get_drvdata(phy); 238*5ab43d0fSKunihiko Hayashi 239*5ab43d0fSKunihiko Hayashi if (priv->vbus) 240*5ab43d0fSKunihiko Hayashi regulator_disable(priv->vbus); 241*5ab43d0fSKunihiko Hayashi 242*5ab43d0fSKunihiko Hayashi reset_control_assert(priv->rst); 243*5ab43d0fSKunihiko Hayashi clk_disable_unprepare(priv->clk); 244*5ab43d0fSKunihiko Hayashi clk_disable_unprepare(priv->clk_ext); 245*5ab43d0fSKunihiko Hayashi 246*5ab43d0fSKunihiko Hayashi return 0; 247*5ab43d0fSKunihiko Hayashi } 248*5ab43d0fSKunihiko Hayashi 249*5ab43d0fSKunihiko Hayashi static int uniphier_u3hsphy_init(struct phy *phy) 250*5ab43d0fSKunihiko Hayashi { 251*5ab43d0fSKunihiko Hayashi struct uniphier_u3hsphy_priv *priv = phy_get_drvdata(phy); 252*5ab43d0fSKunihiko Hayashi u32 config0, config1; 253*5ab43d0fSKunihiko Hayashi int i, ret; 254*5ab43d0fSKunihiko Hayashi 255*5ab43d0fSKunihiko Hayashi ret = clk_prepare_enable(priv->clk_parent); 256*5ab43d0fSKunihiko Hayashi if (ret) 257*5ab43d0fSKunihiko Hayashi return ret; 258*5ab43d0fSKunihiko Hayashi 259*5ab43d0fSKunihiko Hayashi ret = reset_control_deassert(priv->rst_parent); 260*5ab43d0fSKunihiko Hayashi if (ret) 261*5ab43d0fSKunihiko Hayashi goto out_clk_disable; 262*5ab43d0fSKunihiko Hayashi 263*5ab43d0fSKunihiko Hayashi if (!priv->data->config0 && !priv->data->config1) 264*5ab43d0fSKunihiko Hayashi return 0; 265*5ab43d0fSKunihiko Hayashi 266*5ab43d0fSKunihiko Hayashi config0 = priv->data->config0; 267*5ab43d0fSKunihiko Hayashi config1 = priv->data->config1; 268*5ab43d0fSKunihiko Hayashi 269*5ab43d0fSKunihiko Hayashi ret = uniphier_u3hsphy_update_config(priv, &config0); 270*5ab43d0fSKunihiko Hayashi if (ret) 271*5ab43d0fSKunihiko Hayashi goto out_rst_assert; 272*5ab43d0fSKunihiko Hayashi 273*5ab43d0fSKunihiko Hayashi writel(config0, priv->base + HSPHY_CFG0); 274*5ab43d0fSKunihiko Hayashi writel(config1, priv->base + HSPHY_CFG1); 275*5ab43d0fSKunihiko Hayashi 276*5ab43d0fSKunihiko Hayashi for (i = 0; i < priv->data->nparams; i++) 277*5ab43d0fSKunihiko Hayashi uniphier_u3hsphy_set_param(priv, &priv->data->param[i]); 278*5ab43d0fSKunihiko Hayashi 279*5ab43d0fSKunihiko Hayashi return 0; 280*5ab43d0fSKunihiko Hayashi 281*5ab43d0fSKunihiko Hayashi out_rst_assert: 282*5ab43d0fSKunihiko Hayashi reset_control_assert(priv->rst_parent); 283*5ab43d0fSKunihiko Hayashi out_clk_disable: 284*5ab43d0fSKunihiko Hayashi clk_disable_unprepare(priv->clk_parent); 285*5ab43d0fSKunihiko Hayashi 286*5ab43d0fSKunihiko Hayashi return ret; 287*5ab43d0fSKunihiko Hayashi } 288*5ab43d0fSKunihiko Hayashi 289*5ab43d0fSKunihiko Hayashi static int uniphier_u3hsphy_exit(struct phy *phy) 290*5ab43d0fSKunihiko Hayashi { 291*5ab43d0fSKunihiko Hayashi struct uniphier_u3hsphy_priv *priv = phy_get_drvdata(phy); 292*5ab43d0fSKunihiko Hayashi 293*5ab43d0fSKunihiko Hayashi reset_control_assert(priv->rst_parent); 294*5ab43d0fSKunihiko Hayashi clk_disable_unprepare(priv->clk_parent); 295*5ab43d0fSKunihiko Hayashi 296*5ab43d0fSKunihiko Hayashi return 0; 297*5ab43d0fSKunihiko Hayashi } 298*5ab43d0fSKunihiko Hayashi 299*5ab43d0fSKunihiko Hayashi static const struct phy_ops uniphier_u3hsphy_ops = { 300*5ab43d0fSKunihiko Hayashi .init = uniphier_u3hsphy_init, 301*5ab43d0fSKunihiko Hayashi .exit = uniphier_u3hsphy_exit, 302*5ab43d0fSKunihiko Hayashi .power_on = uniphier_u3hsphy_power_on, 303*5ab43d0fSKunihiko Hayashi .power_off = uniphier_u3hsphy_power_off, 304*5ab43d0fSKunihiko Hayashi .owner = THIS_MODULE, 305*5ab43d0fSKunihiko Hayashi }; 306*5ab43d0fSKunihiko Hayashi 307*5ab43d0fSKunihiko Hayashi static int uniphier_u3hsphy_probe(struct platform_device *pdev) 308*5ab43d0fSKunihiko Hayashi { 309*5ab43d0fSKunihiko Hayashi struct device *dev = &pdev->dev; 310*5ab43d0fSKunihiko Hayashi struct uniphier_u3hsphy_priv *priv; 311*5ab43d0fSKunihiko Hayashi struct phy_provider *phy_provider; 312*5ab43d0fSKunihiko Hayashi struct resource *res; 313*5ab43d0fSKunihiko Hayashi struct phy *phy; 314*5ab43d0fSKunihiko Hayashi 315*5ab43d0fSKunihiko Hayashi priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 316*5ab43d0fSKunihiko Hayashi if (!priv) 317*5ab43d0fSKunihiko Hayashi return -ENOMEM; 318*5ab43d0fSKunihiko Hayashi 319*5ab43d0fSKunihiko Hayashi priv->dev = dev; 320*5ab43d0fSKunihiko Hayashi priv->data = of_device_get_match_data(dev); 321*5ab43d0fSKunihiko Hayashi if (WARN_ON(!priv->data || 322*5ab43d0fSKunihiko Hayashi priv->data->nparams > MAX_PHY_PARAMS)) 323*5ab43d0fSKunihiko Hayashi return -EINVAL; 324*5ab43d0fSKunihiko Hayashi 325*5ab43d0fSKunihiko Hayashi res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 326*5ab43d0fSKunihiko Hayashi priv->base = devm_ioremap_resource(dev, res); 327*5ab43d0fSKunihiko Hayashi if (IS_ERR(priv->base)) 328*5ab43d0fSKunihiko Hayashi return PTR_ERR(priv->base); 329*5ab43d0fSKunihiko Hayashi 330*5ab43d0fSKunihiko Hayashi priv->clk = devm_clk_get(dev, "phy"); 331*5ab43d0fSKunihiko Hayashi if (IS_ERR(priv->clk)) 332*5ab43d0fSKunihiko Hayashi return PTR_ERR(priv->clk); 333*5ab43d0fSKunihiko Hayashi 334*5ab43d0fSKunihiko Hayashi priv->clk_parent = devm_clk_get(dev, "link"); 335*5ab43d0fSKunihiko Hayashi if (IS_ERR(priv->clk_parent)) 336*5ab43d0fSKunihiko Hayashi return PTR_ERR(priv->clk_parent); 337*5ab43d0fSKunihiko Hayashi 338*5ab43d0fSKunihiko Hayashi priv->clk_ext = devm_clk_get(dev, "phy-ext"); 339*5ab43d0fSKunihiko Hayashi if (IS_ERR(priv->clk_ext)) { 340*5ab43d0fSKunihiko Hayashi if (PTR_ERR(priv->clk_ext) == -ENOENT) 341*5ab43d0fSKunihiko Hayashi priv->clk_ext = NULL; 342*5ab43d0fSKunihiko Hayashi else 343*5ab43d0fSKunihiko Hayashi return PTR_ERR(priv->clk_ext); 344*5ab43d0fSKunihiko Hayashi } 345*5ab43d0fSKunihiko Hayashi 346*5ab43d0fSKunihiko Hayashi priv->rst = devm_reset_control_get_shared(dev, "phy"); 347*5ab43d0fSKunihiko Hayashi if (IS_ERR(priv->rst)) 348*5ab43d0fSKunihiko Hayashi return PTR_ERR(priv->rst); 349*5ab43d0fSKunihiko Hayashi 350*5ab43d0fSKunihiko Hayashi priv->rst_parent = devm_reset_control_get_shared(dev, "link"); 351*5ab43d0fSKunihiko Hayashi if (IS_ERR(priv->rst_parent)) 352*5ab43d0fSKunihiko Hayashi return PTR_ERR(priv->rst_parent); 353*5ab43d0fSKunihiko Hayashi 354*5ab43d0fSKunihiko Hayashi priv->vbus = devm_regulator_get_optional(dev, "vbus"); 355*5ab43d0fSKunihiko Hayashi if (IS_ERR(priv->vbus)) { 356*5ab43d0fSKunihiko Hayashi if (PTR_ERR(priv->vbus) == -EPROBE_DEFER) 357*5ab43d0fSKunihiko Hayashi return PTR_ERR(priv->vbus); 358*5ab43d0fSKunihiko Hayashi priv->vbus = NULL; 359*5ab43d0fSKunihiko Hayashi } 360*5ab43d0fSKunihiko Hayashi 361*5ab43d0fSKunihiko Hayashi phy = devm_phy_create(dev, dev->of_node, &uniphier_u3hsphy_ops); 362*5ab43d0fSKunihiko Hayashi if (IS_ERR(phy)) 363*5ab43d0fSKunihiko Hayashi return PTR_ERR(phy); 364*5ab43d0fSKunihiko Hayashi 365*5ab43d0fSKunihiko Hayashi phy_set_drvdata(phy, priv); 366*5ab43d0fSKunihiko Hayashi phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); 367*5ab43d0fSKunihiko Hayashi 368*5ab43d0fSKunihiko Hayashi return PTR_ERR_OR_ZERO(phy_provider); 369*5ab43d0fSKunihiko Hayashi } 370*5ab43d0fSKunihiko Hayashi 371*5ab43d0fSKunihiko Hayashi static const struct uniphier_u3hsphy_soc_data uniphier_pxs2_data = { 372*5ab43d0fSKunihiko Hayashi .nparams = 0, 373*5ab43d0fSKunihiko Hayashi }; 374*5ab43d0fSKunihiko Hayashi 375*5ab43d0fSKunihiko Hayashi static const struct uniphier_u3hsphy_soc_data uniphier_ld20_data = { 376*5ab43d0fSKunihiko Hayashi .nparams = 2, 377*5ab43d0fSKunihiko Hayashi .param = { 378*5ab43d0fSKunihiko Hayashi { LS_SLEW, 1 }, 379*5ab43d0fSKunihiko Hayashi { FS_LS_DRV, 1 }, 380*5ab43d0fSKunihiko Hayashi }, 381*5ab43d0fSKunihiko Hayashi .trim_func = uniphier_u3hsphy_trim_ld20, 382*5ab43d0fSKunihiko Hayashi .config0 = 0x92316680, 383*5ab43d0fSKunihiko Hayashi .config1 = 0x00000106, 384*5ab43d0fSKunihiko Hayashi }; 385*5ab43d0fSKunihiko Hayashi 386*5ab43d0fSKunihiko Hayashi static const struct uniphier_u3hsphy_soc_data uniphier_pxs3_data = { 387*5ab43d0fSKunihiko Hayashi .nparams = 0, 388*5ab43d0fSKunihiko Hayashi .trim_func = uniphier_u3hsphy_trim_ld20, 389*5ab43d0fSKunihiko Hayashi .config0 = 0x92316680, 390*5ab43d0fSKunihiko Hayashi .config1 = 0x00000106, 391*5ab43d0fSKunihiko Hayashi }; 392*5ab43d0fSKunihiko Hayashi 393*5ab43d0fSKunihiko Hayashi static const struct of_device_id uniphier_u3hsphy_match[] = { 394*5ab43d0fSKunihiko Hayashi { 395*5ab43d0fSKunihiko Hayashi .compatible = "socionext,uniphier-pxs2-usb3-hsphy", 396*5ab43d0fSKunihiko Hayashi .data = &uniphier_pxs2_data, 397*5ab43d0fSKunihiko Hayashi }, 398*5ab43d0fSKunihiko Hayashi { 399*5ab43d0fSKunihiko Hayashi .compatible = "socionext,uniphier-ld20-usb3-hsphy", 400*5ab43d0fSKunihiko Hayashi .data = &uniphier_ld20_data, 401*5ab43d0fSKunihiko Hayashi }, 402*5ab43d0fSKunihiko Hayashi { 403*5ab43d0fSKunihiko Hayashi .compatible = "socionext,uniphier-pxs3-usb3-hsphy", 404*5ab43d0fSKunihiko Hayashi .data = &uniphier_pxs3_data, 405*5ab43d0fSKunihiko Hayashi }, 406*5ab43d0fSKunihiko Hayashi { /* sentinel */ } 407*5ab43d0fSKunihiko Hayashi }; 408*5ab43d0fSKunihiko Hayashi MODULE_DEVICE_TABLE(of, uniphier_u3hsphy_match); 409*5ab43d0fSKunihiko Hayashi 410*5ab43d0fSKunihiko Hayashi static struct platform_driver uniphier_u3hsphy_driver = { 411*5ab43d0fSKunihiko Hayashi .probe = uniphier_u3hsphy_probe, 412*5ab43d0fSKunihiko Hayashi .driver = { 413*5ab43d0fSKunihiko Hayashi .name = "uniphier-usb3-hsphy", 414*5ab43d0fSKunihiko Hayashi .of_match_table = uniphier_u3hsphy_match, 415*5ab43d0fSKunihiko Hayashi }, 416*5ab43d0fSKunihiko Hayashi }; 417*5ab43d0fSKunihiko Hayashi 418*5ab43d0fSKunihiko Hayashi module_platform_driver(uniphier_u3hsphy_driver); 419*5ab43d0fSKunihiko Hayashi 420*5ab43d0fSKunihiko Hayashi MODULE_AUTHOR("Kunihiko Hayashi <hayashi.kunihiko@socionext.com>"); 421*5ab43d0fSKunihiko Hayashi MODULE_DESCRIPTION("UniPhier HS-PHY driver for USB3 controller"); 422*5ab43d0fSKunihiko Hayashi MODULE_LICENSE("GPL v2"); 423