0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #include <linux/bitfield.h>
0013 #include <linux/bitops.h>
0014 #include <linux/clk.h>
0015 #include <linux/io.h>
0016 #include <linux/module.h>
0017 #include <linux/nvmem-consumer.h>
0018 #include <linux/of.h>
0019 #include <linux/of_platform.h>
0020 #include <linux/phy/phy.h>
0021 #include <linux/platform_device.h>
0022 #include <linux/regulator/consumer.h>
0023 #include <linux/reset.h>
0024 #include <linux/slab.h>
0025
0026 #define HSPHY_CFG0 0x0
0027 #define HSPHY_CFG0_HS_I_MASK GENMASK(31, 28)
0028 #define HSPHY_CFG0_HSDISC_MASK GENMASK(27, 26)
0029 #define HSPHY_CFG0_SWING_MASK GENMASK(17, 16)
0030 #define HSPHY_CFG0_SEL_T_MASK GENMASK(15, 12)
0031 #define HSPHY_CFG0_RTERM_MASK GENMASK(7, 6)
0032 #define HSPHY_CFG0_TRIMMASK (HSPHY_CFG0_HS_I_MASK \
0033 | HSPHY_CFG0_SEL_T_MASK \
0034 | HSPHY_CFG0_RTERM_MASK)
0035
0036 #define HSPHY_CFG1 0x4
0037 #define HSPHY_CFG1_DAT_EN BIT(29)
0038 #define HSPHY_CFG1_ADR_EN BIT(28)
0039 #define HSPHY_CFG1_ADR_MASK GENMASK(27, 16)
0040 #define HSPHY_CFG1_DAT_MASK GENMASK(23, 16)
0041
0042 #define PHY_F(regno, msb, lsb) { (regno), (msb), (lsb) }
0043
0044 #define RX_CHK_SYNC PHY_F(0, 5, 5)
0045 #define RX_SYNC_SEL PHY_F(1, 1, 0)
0046 #define LS_SLEW PHY_F(10, 6, 6)
0047 #define FS_LS_DRV PHY_F(10, 5, 5)
0048
0049 #define MAX_PHY_PARAMS 4
0050
0051 struct uniphier_u3hsphy_param {
0052 struct {
0053 int reg_no;
0054 int msb;
0055 int lsb;
0056 } field;
0057 u8 value;
0058 };
0059
0060 struct uniphier_u3hsphy_trim_param {
0061 unsigned int rterm;
0062 unsigned int sel_t;
0063 unsigned int hs_i;
0064 };
0065
0066 #define trim_param_is_valid(p) ((p)->rterm || (p)->sel_t || (p)->hs_i)
0067
0068 struct uniphier_u3hsphy_priv {
0069 struct device *dev;
0070 void __iomem *base;
0071 struct clk *clk, *clk_parent, *clk_ext, *clk_parent_gio;
0072 struct reset_control *rst, *rst_parent, *rst_parent_gio;
0073 struct regulator *vbus;
0074 const struct uniphier_u3hsphy_soc_data *data;
0075 };
0076
0077 struct uniphier_u3hsphy_soc_data {
0078 bool is_legacy;
0079 int nparams;
0080 const struct uniphier_u3hsphy_param param[MAX_PHY_PARAMS];
0081 u32 config0;
0082 u32 config1;
0083 void (*trim_func)(struct uniphier_u3hsphy_priv *priv, u32 *pconfig,
0084 struct uniphier_u3hsphy_trim_param *pt);
0085 };
0086
0087 static void uniphier_u3hsphy_trim_ld20(struct uniphier_u3hsphy_priv *priv,
0088 u32 *pconfig,
0089 struct uniphier_u3hsphy_trim_param *pt)
0090 {
0091 *pconfig &= ~HSPHY_CFG0_RTERM_MASK;
0092 *pconfig |= FIELD_PREP(HSPHY_CFG0_RTERM_MASK, pt->rterm);
0093
0094 *pconfig &= ~HSPHY_CFG0_SEL_T_MASK;
0095 *pconfig |= FIELD_PREP(HSPHY_CFG0_SEL_T_MASK, pt->sel_t);
0096
0097 *pconfig &= ~HSPHY_CFG0_HS_I_MASK;
0098 *pconfig |= FIELD_PREP(HSPHY_CFG0_HS_I_MASK, pt->hs_i);
0099 }
0100
0101 static int uniphier_u3hsphy_get_nvparam(struct uniphier_u3hsphy_priv *priv,
0102 const char *name, unsigned int *val)
0103 {
0104 struct nvmem_cell *cell;
0105 u8 *buf;
0106
0107 cell = devm_nvmem_cell_get(priv->dev, name);
0108 if (IS_ERR(cell))
0109 return PTR_ERR(cell);
0110
0111 buf = nvmem_cell_read(cell, NULL);
0112 if (IS_ERR(buf))
0113 return PTR_ERR(buf);
0114
0115 *val = *buf;
0116
0117 kfree(buf);
0118
0119 return 0;
0120 }
0121
0122 static int uniphier_u3hsphy_get_nvparams(struct uniphier_u3hsphy_priv *priv,
0123 struct uniphier_u3hsphy_trim_param *pt)
0124 {
0125 int ret;
0126
0127 ret = uniphier_u3hsphy_get_nvparam(priv, "rterm", &pt->rterm);
0128 if (ret)
0129 return ret;
0130
0131 ret = uniphier_u3hsphy_get_nvparam(priv, "sel_t", &pt->sel_t);
0132 if (ret)
0133 return ret;
0134
0135 ret = uniphier_u3hsphy_get_nvparam(priv, "hs_i", &pt->hs_i);
0136 if (ret)
0137 return ret;
0138
0139 return 0;
0140 }
0141
0142 static int uniphier_u3hsphy_update_config(struct uniphier_u3hsphy_priv *priv,
0143 u32 *pconfig)
0144 {
0145 struct uniphier_u3hsphy_trim_param trim;
0146 int ret, trimmed = 0;
0147
0148 if (priv->data->trim_func) {
0149 ret = uniphier_u3hsphy_get_nvparams(priv, &trim);
0150 if (ret == -EPROBE_DEFER)
0151 return ret;
0152
0153
0154
0155
0156
0157
0158 if (!ret && trim_param_is_valid(&trim)) {
0159 priv->data->trim_func(priv, pconfig, &trim);
0160 trimmed = 1;
0161 } else {
0162 dev_dbg(priv->dev, "can't get parameter from nvmem\n");
0163 }
0164 }
0165
0166
0167 if (!trimmed) {
0168 *pconfig &= ~HSPHY_CFG0_HSDISC_MASK;
0169 *pconfig |= FIELD_PREP(HSPHY_CFG0_HSDISC_MASK, 3);
0170 }
0171
0172 return 0;
0173 }
0174
0175 static void uniphier_u3hsphy_set_param(struct uniphier_u3hsphy_priv *priv,
0176 const struct uniphier_u3hsphy_param *p)
0177 {
0178 u32 val;
0179 u32 field_mask = GENMASK(p->field.msb, p->field.lsb);
0180 u8 data;
0181
0182 val = readl(priv->base + HSPHY_CFG1);
0183 val &= ~HSPHY_CFG1_ADR_MASK;
0184 val |= FIELD_PREP(HSPHY_CFG1_ADR_MASK, p->field.reg_no)
0185 | HSPHY_CFG1_ADR_EN;
0186 writel(val, priv->base + HSPHY_CFG1);
0187
0188 val = readl(priv->base + HSPHY_CFG1);
0189 val &= ~HSPHY_CFG1_ADR_EN;
0190 writel(val, priv->base + HSPHY_CFG1);
0191
0192 val = readl(priv->base + HSPHY_CFG1);
0193 val &= ~FIELD_PREP(HSPHY_CFG1_DAT_MASK, field_mask);
0194 data = field_mask & (p->value << p->field.lsb);
0195 val |= FIELD_PREP(HSPHY_CFG1_DAT_MASK, data) | HSPHY_CFG1_DAT_EN;
0196 writel(val, priv->base + HSPHY_CFG1);
0197
0198 val = readl(priv->base + HSPHY_CFG1);
0199 val &= ~HSPHY_CFG1_DAT_EN;
0200 writel(val, priv->base + HSPHY_CFG1);
0201 }
0202
0203 static int uniphier_u3hsphy_power_on(struct phy *phy)
0204 {
0205 struct uniphier_u3hsphy_priv *priv = phy_get_drvdata(phy);
0206 int ret;
0207
0208 ret = clk_prepare_enable(priv->clk_ext);
0209 if (ret)
0210 return ret;
0211
0212 ret = clk_prepare_enable(priv->clk);
0213 if (ret)
0214 goto out_clk_ext_disable;
0215
0216 ret = reset_control_deassert(priv->rst);
0217 if (ret)
0218 goto out_clk_disable;
0219
0220 if (priv->vbus) {
0221 ret = regulator_enable(priv->vbus);
0222 if (ret)
0223 goto out_rst_assert;
0224 }
0225
0226 return 0;
0227
0228 out_rst_assert:
0229 reset_control_assert(priv->rst);
0230 out_clk_disable:
0231 clk_disable_unprepare(priv->clk);
0232 out_clk_ext_disable:
0233 clk_disable_unprepare(priv->clk_ext);
0234
0235 return ret;
0236 }
0237
0238 static int uniphier_u3hsphy_power_off(struct phy *phy)
0239 {
0240 struct uniphier_u3hsphy_priv *priv = phy_get_drvdata(phy);
0241
0242 if (priv->vbus)
0243 regulator_disable(priv->vbus);
0244
0245 reset_control_assert(priv->rst);
0246 clk_disable_unprepare(priv->clk);
0247 clk_disable_unprepare(priv->clk_ext);
0248
0249 return 0;
0250 }
0251
0252 static int uniphier_u3hsphy_init(struct phy *phy)
0253 {
0254 struct uniphier_u3hsphy_priv *priv = phy_get_drvdata(phy);
0255 u32 config0, config1;
0256 int i, ret;
0257
0258 ret = clk_prepare_enable(priv->clk_parent);
0259 if (ret)
0260 return ret;
0261
0262 ret = clk_prepare_enable(priv->clk_parent_gio);
0263 if (ret)
0264 goto out_clk_disable;
0265
0266 ret = reset_control_deassert(priv->rst_parent);
0267 if (ret)
0268 goto out_clk_gio_disable;
0269
0270 ret = reset_control_deassert(priv->rst_parent_gio);
0271 if (ret)
0272 goto out_rst_assert;
0273
0274 if ((priv->data->is_legacy)
0275 || (!priv->data->config0 && !priv->data->config1))
0276 return 0;
0277
0278 config0 = priv->data->config0;
0279 config1 = priv->data->config1;
0280
0281 ret = uniphier_u3hsphy_update_config(priv, &config0);
0282 if (ret)
0283 goto out_rst_assert;
0284
0285 writel(config0, priv->base + HSPHY_CFG0);
0286 writel(config1, priv->base + HSPHY_CFG1);
0287
0288 for (i = 0; i < priv->data->nparams; i++)
0289 uniphier_u3hsphy_set_param(priv, &priv->data->param[i]);
0290
0291 return 0;
0292
0293 out_rst_assert:
0294 reset_control_assert(priv->rst_parent);
0295 out_clk_gio_disable:
0296 clk_disable_unprepare(priv->clk_parent_gio);
0297 out_clk_disable:
0298 clk_disable_unprepare(priv->clk_parent);
0299
0300 return ret;
0301 }
0302
0303 static int uniphier_u3hsphy_exit(struct phy *phy)
0304 {
0305 struct uniphier_u3hsphy_priv *priv = phy_get_drvdata(phy);
0306
0307 reset_control_assert(priv->rst_parent_gio);
0308 reset_control_assert(priv->rst_parent);
0309 clk_disable_unprepare(priv->clk_parent_gio);
0310 clk_disable_unprepare(priv->clk_parent);
0311
0312 return 0;
0313 }
0314
0315 static const struct phy_ops uniphier_u3hsphy_ops = {
0316 .init = uniphier_u3hsphy_init,
0317 .exit = uniphier_u3hsphy_exit,
0318 .power_on = uniphier_u3hsphy_power_on,
0319 .power_off = uniphier_u3hsphy_power_off,
0320 .owner = THIS_MODULE,
0321 };
0322
0323 static int uniphier_u3hsphy_probe(struct platform_device *pdev)
0324 {
0325 struct device *dev = &pdev->dev;
0326 struct uniphier_u3hsphy_priv *priv;
0327 struct phy_provider *phy_provider;
0328 struct phy *phy;
0329
0330 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
0331 if (!priv)
0332 return -ENOMEM;
0333
0334 priv->dev = dev;
0335 priv->data = of_device_get_match_data(dev);
0336 if (WARN_ON(!priv->data ||
0337 priv->data->nparams > MAX_PHY_PARAMS))
0338 return -EINVAL;
0339
0340 priv->base = devm_platform_ioremap_resource(pdev, 0);
0341 if (IS_ERR(priv->base))
0342 return PTR_ERR(priv->base);
0343
0344 if (!priv->data->is_legacy) {
0345 priv->clk = devm_clk_get(dev, "phy");
0346 if (IS_ERR(priv->clk))
0347 return PTR_ERR(priv->clk);
0348
0349 priv->clk_ext = devm_clk_get_optional(dev, "phy-ext");
0350 if (IS_ERR(priv->clk_ext))
0351 return PTR_ERR(priv->clk_ext);
0352
0353 priv->rst = devm_reset_control_get_shared(dev, "phy");
0354 if (IS_ERR(priv->rst))
0355 return PTR_ERR(priv->rst);
0356
0357 } else {
0358 priv->clk_parent_gio = devm_clk_get(dev, "gio");
0359 if (IS_ERR(priv->clk_parent_gio))
0360 return PTR_ERR(priv->clk_parent_gio);
0361
0362 priv->rst_parent_gio =
0363 devm_reset_control_get_shared(dev, "gio");
0364 if (IS_ERR(priv->rst_parent_gio))
0365 return PTR_ERR(priv->rst_parent_gio);
0366 }
0367
0368 priv->clk_parent = devm_clk_get(dev, "link");
0369 if (IS_ERR(priv->clk_parent))
0370 return PTR_ERR(priv->clk_parent);
0371
0372 priv->rst_parent = devm_reset_control_get_shared(dev, "link");
0373 if (IS_ERR(priv->rst_parent))
0374 return PTR_ERR(priv->rst_parent);
0375
0376 priv->vbus = devm_regulator_get_optional(dev, "vbus");
0377 if (IS_ERR(priv->vbus)) {
0378 if (PTR_ERR(priv->vbus) == -EPROBE_DEFER)
0379 return PTR_ERR(priv->vbus);
0380 priv->vbus = NULL;
0381 }
0382
0383 phy = devm_phy_create(dev, dev->of_node, &uniphier_u3hsphy_ops);
0384 if (IS_ERR(phy))
0385 return PTR_ERR(phy);
0386
0387 phy_set_drvdata(phy, priv);
0388 phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
0389
0390 return PTR_ERR_OR_ZERO(phy_provider);
0391 }
0392
0393 static const struct uniphier_u3hsphy_soc_data uniphier_pro5_data = {
0394 .is_legacy = true,
0395 .nparams = 0,
0396 };
0397
0398 static const struct uniphier_u3hsphy_soc_data uniphier_pxs2_data = {
0399 .is_legacy = false,
0400 .nparams = 2,
0401 .param = {
0402 { RX_CHK_SYNC, 1 },
0403 { RX_SYNC_SEL, 1 },
0404 },
0405 };
0406
0407 static const struct uniphier_u3hsphy_soc_data uniphier_ld20_data = {
0408 .is_legacy = false,
0409 .nparams = 4,
0410 .param = {
0411 { RX_CHK_SYNC, 1 },
0412 { RX_SYNC_SEL, 1 },
0413 { LS_SLEW, 1 },
0414 { FS_LS_DRV, 1 },
0415 },
0416 .trim_func = uniphier_u3hsphy_trim_ld20,
0417 .config0 = 0x92316680,
0418 .config1 = 0x00000106,
0419 };
0420
0421 static const struct uniphier_u3hsphy_soc_data uniphier_pxs3_data = {
0422 .is_legacy = false,
0423 .nparams = 2,
0424 .param = {
0425 { RX_CHK_SYNC, 1 },
0426 { RX_SYNC_SEL, 1 },
0427 },
0428 .trim_func = uniphier_u3hsphy_trim_ld20,
0429 .config0 = 0x92316680,
0430 .config1 = 0x00000106,
0431 };
0432
0433 static const struct of_device_id uniphier_u3hsphy_match[] = {
0434 {
0435 .compatible = "socionext,uniphier-pro5-usb3-hsphy",
0436 .data = &uniphier_pro5_data,
0437 },
0438 {
0439 .compatible = "socionext,uniphier-pxs2-usb3-hsphy",
0440 .data = &uniphier_pxs2_data,
0441 },
0442 {
0443 .compatible = "socionext,uniphier-ld20-usb3-hsphy",
0444 .data = &uniphier_ld20_data,
0445 },
0446 {
0447 .compatible = "socionext,uniphier-pxs3-usb3-hsphy",
0448 .data = &uniphier_pxs3_data,
0449 },
0450 {
0451 .compatible = "socionext,uniphier-nx1-usb3-hsphy",
0452 .data = &uniphier_pxs3_data,
0453 },
0454 { }
0455 };
0456 MODULE_DEVICE_TABLE(of, uniphier_u3hsphy_match);
0457
0458 static struct platform_driver uniphier_u3hsphy_driver = {
0459 .probe = uniphier_u3hsphy_probe,
0460 .driver = {
0461 .name = "uniphier-usb3-hsphy",
0462 .of_match_table = uniphier_u3hsphy_match,
0463 },
0464 };
0465
0466 module_platform_driver(uniphier_u3hsphy_driver);
0467
0468 MODULE_AUTHOR("Kunihiko Hayashi <hayashi.kunihiko@socionext.com>");
0469 MODULE_DESCRIPTION("UniPhier HS-PHY driver for USB3 controller");
0470 MODULE_LICENSE("GPL v2");