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