xref: /OK3568_Linux_fs/kernel/drivers/phy/renesas/phy-rcar-gen2.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Renesas R-Car Gen2 PHY driver
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Copyright (C) 2014 Renesas Solutions Corp.
6*4882a593Smuzhiyun  * Copyright (C) 2014 Cogent Embedded, Inc.
7*4882a593Smuzhiyun  * Copyright (C) 2019 Renesas Electronics Corp.
8*4882a593Smuzhiyun  */
9*4882a593Smuzhiyun 
10*4882a593Smuzhiyun #include <linux/clk.h>
11*4882a593Smuzhiyun #include <linux/delay.h>
12*4882a593Smuzhiyun #include <linux/io.h>
13*4882a593Smuzhiyun #include <linux/module.h>
14*4882a593Smuzhiyun #include <linux/of.h>
15*4882a593Smuzhiyun #include <linux/phy/phy.h>
16*4882a593Smuzhiyun #include <linux/platform_device.h>
17*4882a593Smuzhiyun #include <linux/spinlock.h>
18*4882a593Smuzhiyun #include <linux/atomic.h>
19*4882a593Smuzhiyun #include <linux/of_device.h>
20*4882a593Smuzhiyun 
21*4882a593Smuzhiyun #define USBHS_LPSTS			0x02
22*4882a593Smuzhiyun #define USBHS_UGCTRL			0x80
23*4882a593Smuzhiyun #define USBHS_UGCTRL2			0x84
24*4882a593Smuzhiyun #define USBHS_UGSTS			0x88	/* From technical update */
25*4882a593Smuzhiyun 
26*4882a593Smuzhiyun /* Low Power Status register (LPSTS) */
27*4882a593Smuzhiyun #define USBHS_LPSTS_SUSPM		0x4000
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun /* USB General control register (UGCTRL) */
30*4882a593Smuzhiyun #define USBHS_UGCTRL_CONNECT		0x00000004
31*4882a593Smuzhiyun #define USBHS_UGCTRL_PLLRESET		0x00000001
32*4882a593Smuzhiyun 
33*4882a593Smuzhiyun /* USB General control register 2 (UGCTRL2) */
34*4882a593Smuzhiyun #define USBHS_UGCTRL2_USB2SEL		0x80000000
35*4882a593Smuzhiyun #define USBHS_UGCTRL2_USB2SEL_PCI	0x00000000
36*4882a593Smuzhiyun #define USBHS_UGCTRL2_USB2SEL_USB30	0x80000000
37*4882a593Smuzhiyun #define USBHS_UGCTRL2_USB0SEL		0x00000030
38*4882a593Smuzhiyun #define USBHS_UGCTRL2_USB0SEL_PCI	0x00000010
39*4882a593Smuzhiyun #define USBHS_UGCTRL2_USB0SEL_HS_USB	0x00000030
40*4882a593Smuzhiyun #define USBHS_UGCTRL2_USB0SEL_USB20	0x00000010
41*4882a593Smuzhiyun #define USBHS_UGCTRL2_USB0SEL_HS_USB20	0x00000020
42*4882a593Smuzhiyun 
43*4882a593Smuzhiyun /* USB General status register (UGSTS) */
44*4882a593Smuzhiyun #define USBHS_UGSTS_LOCK		0x00000100 /* From technical update */
45*4882a593Smuzhiyun 
46*4882a593Smuzhiyun #define PHYS_PER_CHANNEL	2
47*4882a593Smuzhiyun 
48*4882a593Smuzhiyun struct rcar_gen2_phy {
49*4882a593Smuzhiyun 	struct phy *phy;
50*4882a593Smuzhiyun 	struct rcar_gen2_channel *channel;
51*4882a593Smuzhiyun 	int number;
52*4882a593Smuzhiyun 	u32 select_value;
53*4882a593Smuzhiyun };
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun struct rcar_gen2_channel {
56*4882a593Smuzhiyun 	struct device_node *of_node;
57*4882a593Smuzhiyun 	struct rcar_gen2_phy_driver *drv;
58*4882a593Smuzhiyun 	struct rcar_gen2_phy phys[PHYS_PER_CHANNEL];
59*4882a593Smuzhiyun 	int selected_phy;
60*4882a593Smuzhiyun 	u32 select_mask;
61*4882a593Smuzhiyun };
62*4882a593Smuzhiyun 
63*4882a593Smuzhiyun struct rcar_gen2_phy_driver {
64*4882a593Smuzhiyun 	void __iomem *base;
65*4882a593Smuzhiyun 	struct clk *clk;
66*4882a593Smuzhiyun 	spinlock_t lock;
67*4882a593Smuzhiyun 	int num_channels;
68*4882a593Smuzhiyun 	struct rcar_gen2_channel *channels;
69*4882a593Smuzhiyun };
70*4882a593Smuzhiyun 
71*4882a593Smuzhiyun struct rcar_gen2_phy_data {
72*4882a593Smuzhiyun 	const struct phy_ops *gen2_phy_ops;
73*4882a593Smuzhiyun 	const u32 (*select_value)[PHYS_PER_CHANNEL];
74*4882a593Smuzhiyun 	const u32 num_channels;
75*4882a593Smuzhiyun };
76*4882a593Smuzhiyun 
rcar_gen2_phy_init(struct phy * p)77*4882a593Smuzhiyun static int rcar_gen2_phy_init(struct phy *p)
78*4882a593Smuzhiyun {
79*4882a593Smuzhiyun 	struct rcar_gen2_phy *phy = phy_get_drvdata(p);
80*4882a593Smuzhiyun 	struct rcar_gen2_channel *channel = phy->channel;
81*4882a593Smuzhiyun 	struct rcar_gen2_phy_driver *drv = channel->drv;
82*4882a593Smuzhiyun 	unsigned long flags;
83*4882a593Smuzhiyun 	u32 ugctrl2;
84*4882a593Smuzhiyun 
85*4882a593Smuzhiyun 	/*
86*4882a593Smuzhiyun 	 * Try to acquire exclusive access to PHY.  The first driver calling
87*4882a593Smuzhiyun 	 * phy_init()  on a given channel wins, and all attempts  to use another
88*4882a593Smuzhiyun 	 * PHY on this channel will fail until phy_exit() is called by the first
89*4882a593Smuzhiyun 	 * driver.   Achieving this with cmpxcgh() should be SMP-safe.
90*4882a593Smuzhiyun 	 */
91*4882a593Smuzhiyun 	if (cmpxchg(&channel->selected_phy, -1, phy->number) != -1)
92*4882a593Smuzhiyun 		return -EBUSY;
93*4882a593Smuzhiyun 
94*4882a593Smuzhiyun 	clk_prepare_enable(drv->clk);
95*4882a593Smuzhiyun 
96*4882a593Smuzhiyun 	spin_lock_irqsave(&drv->lock, flags);
97*4882a593Smuzhiyun 	ugctrl2 = readl(drv->base + USBHS_UGCTRL2);
98*4882a593Smuzhiyun 	ugctrl2 &= ~channel->select_mask;
99*4882a593Smuzhiyun 	ugctrl2 |= phy->select_value;
100*4882a593Smuzhiyun 	writel(ugctrl2, drv->base + USBHS_UGCTRL2);
101*4882a593Smuzhiyun 	spin_unlock_irqrestore(&drv->lock, flags);
102*4882a593Smuzhiyun 	return 0;
103*4882a593Smuzhiyun }
104*4882a593Smuzhiyun 
rcar_gen2_phy_exit(struct phy * p)105*4882a593Smuzhiyun static int rcar_gen2_phy_exit(struct phy *p)
106*4882a593Smuzhiyun {
107*4882a593Smuzhiyun 	struct rcar_gen2_phy *phy = phy_get_drvdata(p);
108*4882a593Smuzhiyun 	struct rcar_gen2_channel *channel = phy->channel;
109*4882a593Smuzhiyun 
110*4882a593Smuzhiyun 	clk_disable_unprepare(channel->drv->clk);
111*4882a593Smuzhiyun 
112*4882a593Smuzhiyun 	channel->selected_phy = -1;
113*4882a593Smuzhiyun 
114*4882a593Smuzhiyun 	return 0;
115*4882a593Smuzhiyun }
116*4882a593Smuzhiyun 
rcar_gen2_phy_power_on(struct phy * p)117*4882a593Smuzhiyun static int rcar_gen2_phy_power_on(struct phy *p)
118*4882a593Smuzhiyun {
119*4882a593Smuzhiyun 	struct rcar_gen2_phy *phy = phy_get_drvdata(p);
120*4882a593Smuzhiyun 	struct rcar_gen2_phy_driver *drv = phy->channel->drv;
121*4882a593Smuzhiyun 	void __iomem *base = drv->base;
122*4882a593Smuzhiyun 	unsigned long flags;
123*4882a593Smuzhiyun 	u32 value;
124*4882a593Smuzhiyun 	int err = 0, i;
125*4882a593Smuzhiyun 
126*4882a593Smuzhiyun 	/* Skip if it's not USBHS */
127*4882a593Smuzhiyun 	if (phy->select_value != USBHS_UGCTRL2_USB0SEL_HS_USB)
128*4882a593Smuzhiyun 		return 0;
129*4882a593Smuzhiyun 
130*4882a593Smuzhiyun 	spin_lock_irqsave(&drv->lock, flags);
131*4882a593Smuzhiyun 
132*4882a593Smuzhiyun 	/* Power on USBHS PHY */
133*4882a593Smuzhiyun 	value = readl(base + USBHS_UGCTRL);
134*4882a593Smuzhiyun 	value &= ~USBHS_UGCTRL_PLLRESET;
135*4882a593Smuzhiyun 	writel(value, base + USBHS_UGCTRL);
136*4882a593Smuzhiyun 
137*4882a593Smuzhiyun 	value = readw(base + USBHS_LPSTS);
138*4882a593Smuzhiyun 	value |= USBHS_LPSTS_SUSPM;
139*4882a593Smuzhiyun 	writew(value, base + USBHS_LPSTS);
140*4882a593Smuzhiyun 
141*4882a593Smuzhiyun 	for (i = 0; i < 20; i++) {
142*4882a593Smuzhiyun 		value = readl(base + USBHS_UGSTS);
143*4882a593Smuzhiyun 		if ((value & USBHS_UGSTS_LOCK) == USBHS_UGSTS_LOCK) {
144*4882a593Smuzhiyun 			value = readl(base + USBHS_UGCTRL);
145*4882a593Smuzhiyun 			value |= USBHS_UGCTRL_CONNECT;
146*4882a593Smuzhiyun 			writel(value, base + USBHS_UGCTRL);
147*4882a593Smuzhiyun 			goto out;
148*4882a593Smuzhiyun 		}
149*4882a593Smuzhiyun 		udelay(1);
150*4882a593Smuzhiyun 	}
151*4882a593Smuzhiyun 
152*4882a593Smuzhiyun 	/* Timed out waiting for the PLL lock */
153*4882a593Smuzhiyun 	err = -ETIMEDOUT;
154*4882a593Smuzhiyun 
155*4882a593Smuzhiyun out:
156*4882a593Smuzhiyun 	spin_unlock_irqrestore(&drv->lock, flags);
157*4882a593Smuzhiyun 
158*4882a593Smuzhiyun 	return err;
159*4882a593Smuzhiyun }
160*4882a593Smuzhiyun 
rcar_gen2_phy_power_off(struct phy * p)161*4882a593Smuzhiyun static int rcar_gen2_phy_power_off(struct phy *p)
162*4882a593Smuzhiyun {
163*4882a593Smuzhiyun 	struct rcar_gen2_phy *phy = phy_get_drvdata(p);
164*4882a593Smuzhiyun 	struct rcar_gen2_phy_driver *drv = phy->channel->drv;
165*4882a593Smuzhiyun 	void __iomem *base = drv->base;
166*4882a593Smuzhiyun 	unsigned long flags;
167*4882a593Smuzhiyun 	u32 value;
168*4882a593Smuzhiyun 
169*4882a593Smuzhiyun 	/* Skip if it's not USBHS */
170*4882a593Smuzhiyun 	if (phy->select_value != USBHS_UGCTRL2_USB0SEL_HS_USB)
171*4882a593Smuzhiyun 		return 0;
172*4882a593Smuzhiyun 
173*4882a593Smuzhiyun 	spin_lock_irqsave(&drv->lock, flags);
174*4882a593Smuzhiyun 
175*4882a593Smuzhiyun 	/* Power off USBHS PHY */
176*4882a593Smuzhiyun 	value = readl(base + USBHS_UGCTRL);
177*4882a593Smuzhiyun 	value &= ~USBHS_UGCTRL_CONNECT;
178*4882a593Smuzhiyun 	writel(value, base + USBHS_UGCTRL);
179*4882a593Smuzhiyun 
180*4882a593Smuzhiyun 	value = readw(base + USBHS_LPSTS);
181*4882a593Smuzhiyun 	value &= ~USBHS_LPSTS_SUSPM;
182*4882a593Smuzhiyun 	writew(value, base + USBHS_LPSTS);
183*4882a593Smuzhiyun 
184*4882a593Smuzhiyun 	value = readl(base + USBHS_UGCTRL);
185*4882a593Smuzhiyun 	value |= USBHS_UGCTRL_PLLRESET;
186*4882a593Smuzhiyun 	writel(value, base + USBHS_UGCTRL);
187*4882a593Smuzhiyun 
188*4882a593Smuzhiyun 	spin_unlock_irqrestore(&drv->lock, flags);
189*4882a593Smuzhiyun 
190*4882a593Smuzhiyun 	return 0;
191*4882a593Smuzhiyun }
192*4882a593Smuzhiyun 
rz_g1c_phy_power_on(struct phy * p)193*4882a593Smuzhiyun static int rz_g1c_phy_power_on(struct phy *p)
194*4882a593Smuzhiyun {
195*4882a593Smuzhiyun 	struct rcar_gen2_phy *phy = phy_get_drvdata(p);
196*4882a593Smuzhiyun 	struct rcar_gen2_phy_driver *drv = phy->channel->drv;
197*4882a593Smuzhiyun 	void __iomem *base = drv->base;
198*4882a593Smuzhiyun 	unsigned long flags;
199*4882a593Smuzhiyun 	u32 value;
200*4882a593Smuzhiyun 
201*4882a593Smuzhiyun 	spin_lock_irqsave(&drv->lock, flags);
202*4882a593Smuzhiyun 
203*4882a593Smuzhiyun 	/* Power on USBHS PHY */
204*4882a593Smuzhiyun 	value = readl(base + USBHS_UGCTRL);
205*4882a593Smuzhiyun 	value &= ~USBHS_UGCTRL_PLLRESET;
206*4882a593Smuzhiyun 	writel(value, base + USBHS_UGCTRL);
207*4882a593Smuzhiyun 
208*4882a593Smuzhiyun 	/* As per the data sheet wait 340 micro sec for power stable */
209*4882a593Smuzhiyun 	udelay(340);
210*4882a593Smuzhiyun 
211*4882a593Smuzhiyun 	if (phy->select_value == USBHS_UGCTRL2_USB0SEL_HS_USB20) {
212*4882a593Smuzhiyun 		value = readw(base + USBHS_LPSTS);
213*4882a593Smuzhiyun 		value |= USBHS_LPSTS_SUSPM;
214*4882a593Smuzhiyun 		writew(value, base + USBHS_LPSTS);
215*4882a593Smuzhiyun 	}
216*4882a593Smuzhiyun 
217*4882a593Smuzhiyun 	spin_unlock_irqrestore(&drv->lock, flags);
218*4882a593Smuzhiyun 
219*4882a593Smuzhiyun 	return 0;
220*4882a593Smuzhiyun }
221*4882a593Smuzhiyun 
rz_g1c_phy_power_off(struct phy * p)222*4882a593Smuzhiyun static int rz_g1c_phy_power_off(struct phy *p)
223*4882a593Smuzhiyun {
224*4882a593Smuzhiyun 	struct rcar_gen2_phy *phy = phy_get_drvdata(p);
225*4882a593Smuzhiyun 	struct rcar_gen2_phy_driver *drv = phy->channel->drv;
226*4882a593Smuzhiyun 	void __iomem *base = drv->base;
227*4882a593Smuzhiyun 	unsigned long flags;
228*4882a593Smuzhiyun 	u32 value;
229*4882a593Smuzhiyun 
230*4882a593Smuzhiyun 	spin_lock_irqsave(&drv->lock, flags);
231*4882a593Smuzhiyun 	/* Power off USBHS PHY */
232*4882a593Smuzhiyun 	if (phy->select_value == USBHS_UGCTRL2_USB0SEL_HS_USB20) {
233*4882a593Smuzhiyun 		value = readw(base + USBHS_LPSTS);
234*4882a593Smuzhiyun 		value &= ~USBHS_LPSTS_SUSPM;
235*4882a593Smuzhiyun 		writew(value, base + USBHS_LPSTS);
236*4882a593Smuzhiyun 	}
237*4882a593Smuzhiyun 
238*4882a593Smuzhiyun 	value = readl(base + USBHS_UGCTRL);
239*4882a593Smuzhiyun 	value |= USBHS_UGCTRL_PLLRESET;
240*4882a593Smuzhiyun 	writel(value, base + USBHS_UGCTRL);
241*4882a593Smuzhiyun 
242*4882a593Smuzhiyun 	spin_unlock_irqrestore(&drv->lock, flags);
243*4882a593Smuzhiyun 
244*4882a593Smuzhiyun 	return 0;
245*4882a593Smuzhiyun }
246*4882a593Smuzhiyun 
247*4882a593Smuzhiyun static const struct phy_ops rcar_gen2_phy_ops = {
248*4882a593Smuzhiyun 	.init		= rcar_gen2_phy_init,
249*4882a593Smuzhiyun 	.exit		= rcar_gen2_phy_exit,
250*4882a593Smuzhiyun 	.power_on	= rcar_gen2_phy_power_on,
251*4882a593Smuzhiyun 	.power_off	= rcar_gen2_phy_power_off,
252*4882a593Smuzhiyun 	.owner		= THIS_MODULE,
253*4882a593Smuzhiyun };
254*4882a593Smuzhiyun 
255*4882a593Smuzhiyun static const struct phy_ops rz_g1c_phy_ops = {
256*4882a593Smuzhiyun 	.init		= rcar_gen2_phy_init,
257*4882a593Smuzhiyun 	.exit		= rcar_gen2_phy_exit,
258*4882a593Smuzhiyun 	.power_on	= rz_g1c_phy_power_on,
259*4882a593Smuzhiyun 	.power_off	= rz_g1c_phy_power_off,
260*4882a593Smuzhiyun 	.owner		= THIS_MODULE,
261*4882a593Smuzhiyun };
262*4882a593Smuzhiyun 
263*4882a593Smuzhiyun static const u32 pci_select_value[][PHYS_PER_CHANNEL] = {
264*4882a593Smuzhiyun 	[0]	= { USBHS_UGCTRL2_USB0SEL_PCI, USBHS_UGCTRL2_USB0SEL_HS_USB },
265*4882a593Smuzhiyun 	[2]	= { USBHS_UGCTRL2_USB2SEL_PCI, USBHS_UGCTRL2_USB2SEL_USB30 },
266*4882a593Smuzhiyun };
267*4882a593Smuzhiyun 
268*4882a593Smuzhiyun static const u32 usb20_select_value[][PHYS_PER_CHANNEL] = {
269*4882a593Smuzhiyun 	{ USBHS_UGCTRL2_USB0SEL_USB20, USBHS_UGCTRL2_USB0SEL_HS_USB20 },
270*4882a593Smuzhiyun };
271*4882a593Smuzhiyun 
272*4882a593Smuzhiyun static const struct rcar_gen2_phy_data rcar_gen2_usb_phy_data = {
273*4882a593Smuzhiyun 	.gen2_phy_ops = &rcar_gen2_phy_ops,
274*4882a593Smuzhiyun 	.select_value = pci_select_value,
275*4882a593Smuzhiyun 	.num_channels = ARRAY_SIZE(pci_select_value),
276*4882a593Smuzhiyun };
277*4882a593Smuzhiyun 
278*4882a593Smuzhiyun static const struct rcar_gen2_phy_data rz_g1c_usb_phy_data = {
279*4882a593Smuzhiyun 	.gen2_phy_ops = &rz_g1c_phy_ops,
280*4882a593Smuzhiyun 	.select_value = usb20_select_value,
281*4882a593Smuzhiyun 	.num_channels = ARRAY_SIZE(usb20_select_value),
282*4882a593Smuzhiyun };
283*4882a593Smuzhiyun 
284*4882a593Smuzhiyun static const struct of_device_id rcar_gen2_phy_match_table[] = {
285*4882a593Smuzhiyun 	{
286*4882a593Smuzhiyun 		.compatible = "renesas,usb-phy-r8a77470",
287*4882a593Smuzhiyun 		.data = &rz_g1c_usb_phy_data,
288*4882a593Smuzhiyun 	},
289*4882a593Smuzhiyun 	{
290*4882a593Smuzhiyun 		.compatible = "renesas,usb-phy-r8a7790",
291*4882a593Smuzhiyun 		.data = &rcar_gen2_usb_phy_data,
292*4882a593Smuzhiyun 	},
293*4882a593Smuzhiyun 	{
294*4882a593Smuzhiyun 		.compatible = "renesas,usb-phy-r8a7791",
295*4882a593Smuzhiyun 		.data = &rcar_gen2_usb_phy_data,
296*4882a593Smuzhiyun 	},
297*4882a593Smuzhiyun 	{
298*4882a593Smuzhiyun 		.compatible = "renesas,usb-phy-r8a7794",
299*4882a593Smuzhiyun 		.data = &rcar_gen2_usb_phy_data,
300*4882a593Smuzhiyun 	},
301*4882a593Smuzhiyun 	{
302*4882a593Smuzhiyun 		.compatible = "renesas,rcar-gen2-usb-phy",
303*4882a593Smuzhiyun 		.data = &rcar_gen2_usb_phy_data,
304*4882a593Smuzhiyun 	},
305*4882a593Smuzhiyun 	{ /* sentinel */ },
306*4882a593Smuzhiyun };
307*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, rcar_gen2_phy_match_table);
308*4882a593Smuzhiyun 
rcar_gen2_phy_xlate(struct device * dev,struct of_phandle_args * args)309*4882a593Smuzhiyun static struct phy *rcar_gen2_phy_xlate(struct device *dev,
310*4882a593Smuzhiyun 				       struct of_phandle_args *args)
311*4882a593Smuzhiyun {
312*4882a593Smuzhiyun 	struct rcar_gen2_phy_driver *drv;
313*4882a593Smuzhiyun 	struct device_node *np = args->np;
314*4882a593Smuzhiyun 	int i;
315*4882a593Smuzhiyun 
316*4882a593Smuzhiyun 	drv = dev_get_drvdata(dev);
317*4882a593Smuzhiyun 	if (!drv)
318*4882a593Smuzhiyun 		return ERR_PTR(-EINVAL);
319*4882a593Smuzhiyun 
320*4882a593Smuzhiyun 	for (i = 0; i < drv->num_channels; i++) {
321*4882a593Smuzhiyun 		if (np == drv->channels[i].of_node)
322*4882a593Smuzhiyun 			break;
323*4882a593Smuzhiyun 	}
324*4882a593Smuzhiyun 
325*4882a593Smuzhiyun 	if (i >= drv->num_channels || args->args[0] >= 2)
326*4882a593Smuzhiyun 		return ERR_PTR(-ENODEV);
327*4882a593Smuzhiyun 
328*4882a593Smuzhiyun 	return drv->channels[i].phys[args->args[0]].phy;
329*4882a593Smuzhiyun }
330*4882a593Smuzhiyun 
331*4882a593Smuzhiyun static const u32 select_mask[] = {
332*4882a593Smuzhiyun 	[0]	= USBHS_UGCTRL2_USB0SEL,
333*4882a593Smuzhiyun 	[2]	= USBHS_UGCTRL2_USB2SEL,
334*4882a593Smuzhiyun };
335*4882a593Smuzhiyun 
rcar_gen2_phy_probe(struct platform_device * pdev)336*4882a593Smuzhiyun static int rcar_gen2_phy_probe(struct platform_device *pdev)
337*4882a593Smuzhiyun {
338*4882a593Smuzhiyun 	struct device *dev = &pdev->dev;
339*4882a593Smuzhiyun 	struct rcar_gen2_phy_driver *drv;
340*4882a593Smuzhiyun 	struct phy_provider *provider;
341*4882a593Smuzhiyun 	struct device_node *np;
342*4882a593Smuzhiyun 	struct resource *res;
343*4882a593Smuzhiyun 	void __iomem *base;
344*4882a593Smuzhiyun 	struct clk *clk;
345*4882a593Smuzhiyun 	const struct rcar_gen2_phy_data *data;
346*4882a593Smuzhiyun 	int i = 0;
347*4882a593Smuzhiyun 
348*4882a593Smuzhiyun 	if (!dev->of_node) {
349*4882a593Smuzhiyun 		dev_err(dev,
350*4882a593Smuzhiyun 			"This driver is required to be instantiated from device tree\n");
351*4882a593Smuzhiyun 		return -EINVAL;
352*4882a593Smuzhiyun 	}
353*4882a593Smuzhiyun 
354*4882a593Smuzhiyun 	clk = devm_clk_get(dev, "usbhs");
355*4882a593Smuzhiyun 	if (IS_ERR(clk)) {
356*4882a593Smuzhiyun 		dev_err(dev, "Can't get USBHS clock\n");
357*4882a593Smuzhiyun 		return PTR_ERR(clk);
358*4882a593Smuzhiyun 	}
359*4882a593Smuzhiyun 
360*4882a593Smuzhiyun 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
361*4882a593Smuzhiyun 	base = devm_ioremap_resource(dev, res);
362*4882a593Smuzhiyun 	if (IS_ERR(base))
363*4882a593Smuzhiyun 		return PTR_ERR(base);
364*4882a593Smuzhiyun 
365*4882a593Smuzhiyun 	drv = devm_kzalloc(dev, sizeof(*drv), GFP_KERNEL);
366*4882a593Smuzhiyun 	if (!drv)
367*4882a593Smuzhiyun 		return -ENOMEM;
368*4882a593Smuzhiyun 
369*4882a593Smuzhiyun 	spin_lock_init(&drv->lock);
370*4882a593Smuzhiyun 
371*4882a593Smuzhiyun 	drv->clk = clk;
372*4882a593Smuzhiyun 	drv->base = base;
373*4882a593Smuzhiyun 
374*4882a593Smuzhiyun 	data = of_device_get_match_data(dev);
375*4882a593Smuzhiyun 	if (!data)
376*4882a593Smuzhiyun 		return -EINVAL;
377*4882a593Smuzhiyun 
378*4882a593Smuzhiyun 	drv->num_channels = of_get_child_count(dev->of_node);
379*4882a593Smuzhiyun 	drv->channels = devm_kcalloc(dev, drv->num_channels,
380*4882a593Smuzhiyun 				     sizeof(struct rcar_gen2_channel),
381*4882a593Smuzhiyun 				     GFP_KERNEL);
382*4882a593Smuzhiyun 	if (!drv->channels)
383*4882a593Smuzhiyun 		return -ENOMEM;
384*4882a593Smuzhiyun 
385*4882a593Smuzhiyun 	for_each_child_of_node(dev->of_node, np) {
386*4882a593Smuzhiyun 		struct rcar_gen2_channel *channel = drv->channels + i;
387*4882a593Smuzhiyun 		u32 channel_num;
388*4882a593Smuzhiyun 		int error, n;
389*4882a593Smuzhiyun 
390*4882a593Smuzhiyun 		channel->of_node = np;
391*4882a593Smuzhiyun 		channel->drv = drv;
392*4882a593Smuzhiyun 		channel->selected_phy = -1;
393*4882a593Smuzhiyun 
394*4882a593Smuzhiyun 		error = of_property_read_u32(np, "reg", &channel_num);
395*4882a593Smuzhiyun 		if (error || channel_num >= data->num_channels) {
396*4882a593Smuzhiyun 			dev_err(dev, "Invalid \"reg\" property\n");
397*4882a593Smuzhiyun 			of_node_put(np);
398*4882a593Smuzhiyun 			return error;
399*4882a593Smuzhiyun 		}
400*4882a593Smuzhiyun 		channel->select_mask = select_mask[channel_num];
401*4882a593Smuzhiyun 
402*4882a593Smuzhiyun 		for (n = 0; n < PHYS_PER_CHANNEL; n++) {
403*4882a593Smuzhiyun 			struct rcar_gen2_phy *phy = &channel->phys[n];
404*4882a593Smuzhiyun 
405*4882a593Smuzhiyun 			phy->channel = channel;
406*4882a593Smuzhiyun 			phy->number = n;
407*4882a593Smuzhiyun 			phy->select_value = data->select_value[channel_num][n];
408*4882a593Smuzhiyun 
409*4882a593Smuzhiyun 			phy->phy = devm_phy_create(dev, NULL,
410*4882a593Smuzhiyun 						   data->gen2_phy_ops);
411*4882a593Smuzhiyun 			if (IS_ERR(phy->phy)) {
412*4882a593Smuzhiyun 				dev_err(dev, "Failed to create PHY\n");
413*4882a593Smuzhiyun 				of_node_put(np);
414*4882a593Smuzhiyun 				return PTR_ERR(phy->phy);
415*4882a593Smuzhiyun 			}
416*4882a593Smuzhiyun 			phy_set_drvdata(phy->phy, phy);
417*4882a593Smuzhiyun 		}
418*4882a593Smuzhiyun 
419*4882a593Smuzhiyun 		i++;
420*4882a593Smuzhiyun 	}
421*4882a593Smuzhiyun 
422*4882a593Smuzhiyun 	provider = devm_of_phy_provider_register(dev, rcar_gen2_phy_xlate);
423*4882a593Smuzhiyun 	if (IS_ERR(provider)) {
424*4882a593Smuzhiyun 		dev_err(dev, "Failed to register PHY provider\n");
425*4882a593Smuzhiyun 		return PTR_ERR(provider);
426*4882a593Smuzhiyun 	}
427*4882a593Smuzhiyun 
428*4882a593Smuzhiyun 	dev_set_drvdata(dev, drv);
429*4882a593Smuzhiyun 
430*4882a593Smuzhiyun 	return 0;
431*4882a593Smuzhiyun }
432*4882a593Smuzhiyun 
433*4882a593Smuzhiyun static struct platform_driver rcar_gen2_phy_driver = {
434*4882a593Smuzhiyun 	.driver = {
435*4882a593Smuzhiyun 		.name		= "phy_rcar_gen2",
436*4882a593Smuzhiyun 		.of_match_table	= rcar_gen2_phy_match_table,
437*4882a593Smuzhiyun 	},
438*4882a593Smuzhiyun 	.probe	= rcar_gen2_phy_probe,
439*4882a593Smuzhiyun };
440*4882a593Smuzhiyun 
441*4882a593Smuzhiyun module_platform_driver(rcar_gen2_phy_driver);
442*4882a593Smuzhiyun 
443*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
444*4882a593Smuzhiyun MODULE_DESCRIPTION("Renesas R-Car Gen2 PHY");
445*4882a593Smuzhiyun MODULE_AUTHOR("Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>");
446