xref: /linux/drivers/phy/socionext/phy-uniphier-usb3hs.c (revision 5ab43d0f86979d6741c1dda685af3e053982e03e)
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