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(dev, "phy-ext");
339 	if (IS_ERR(priv->clk_ext)) {
340 		if (PTR_ERR(priv->clk_ext) == -ENOENT)
341 			priv->clk_ext = NULL;
342 		else
343 			return PTR_ERR(priv->clk_ext);
344 	}
345 
346 	priv->rst = devm_reset_control_get_shared(dev, "phy");
347 	if (IS_ERR(priv->rst))
348 		return PTR_ERR(priv->rst);
349 
350 	priv->rst_parent = devm_reset_control_get_shared(dev, "link");
351 	if (IS_ERR(priv->rst_parent))
352 		return PTR_ERR(priv->rst_parent);
353 
354 	priv->vbus = devm_regulator_get_optional(dev, "vbus");
355 	if (IS_ERR(priv->vbus)) {
356 		if (PTR_ERR(priv->vbus) == -EPROBE_DEFER)
357 			return PTR_ERR(priv->vbus);
358 		priv->vbus = NULL;
359 	}
360 
361 	phy = devm_phy_create(dev, dev->of_node, &uniphier_u3hsphy_ops);
362 	if (IS_ERR(phy))
363 		return PTR_ERR(phy);
364 
365 	phy_set_drvdata(phy, priv);
366 	phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
367 
368 	return PTR_ERR_OR_ZERO(phy_provider);
369 }
370 
371 static const struct uniphier_u3hsphy_soc_data uniphier_pxs2_data = {
372 	.nparams = 0,
373 };
374 
375 static const struct uniphier_u3hsphy_soc_data uniphier_ld20_data = {
376 	.nparams = 2,
377 	.param = {
378 		{ LS_SLEW, 1 },
379 		{ FS_LS_DRV, 1 },
380 	},
381 	.trim_func = uniphier_u3hsphy_trim_ld20,
382 	.config0 = 0x92316680,
383 	.config1 = 0x00000106,
384 };
385 
386 static const struct uniphier_u3hsphy_soc_data uniphier_pxs3_data = {
387 	.nparams = 0,
388 	.trim_func = uniphier_u3hsphy_trim_ld20,
389 	.config0 = 0x92316680,
390 	.config1 = 0x00000106,
391 };
392 
393 static const struct of_device_id uniphier_u3hsphy_match[] = {
394 	{
395 		.compatible = "socionext,uniphier-pxs2-usb3-hsphy",
396 		.data = &uniphier_pxs2_data,
397 	},
398 	{
399 		.compatible = "socionext,uniphier-ld20-usb3-hsphy",
400 		.data = &uniphier_ld20_data,
401 	},
402 	{
403 		.compatible = "socionext,uniphier-pxs3-usb3-hsphy",
404 		.data = &uniphier_pxs3_data,
405 	},
406 	{ /* sentinel */ }
407 };
408 MODULE_DEVICE_TABLE(of, uniphier_u3hsphy_match);
409 
410 static struct platform_driver uniphier_u3hsphy_driver = {
411 	.probe = uniphier_u3hsphy_probe,
412 	.driver	= {
413 		.name = "uniphier-usb3-hsphy",
414 		.of_match_table	= uniphier_u3hsphy_match,
415 	},
416 };
417 
418 module_platform_driver(uniphier_u3hsphy_driver);
419 
420 MODULE_AUTHOR("Kunihiko Hayashi <hayashi.kunihiko@socionext.com>");
421 MODULE_DESCRIPTION("UniPhier HS-PHY driver for USB3 controller");
422 MODULE_LICENSE("GPL v2");
423