1 // SPDX-License-Identifier: GPL-2.0
3 * Renesas R-Car Gen2 PHY driver
5 * Copyright (C) 2014 Renesas Solutions Corp.
6 * Copyright (C) 2014 Cogent Embedded, Inc.
7 * Copyright (C) 2019 Renesas Electronics Corp.
10 #include <linux/clk.h>
11 #include <linux/delay.h>
13 #include <linux/module.h>
15 #include <linux/phy/phy.h>
16 #include <linux/platform_device.h>
17 #include <linux/spinlock.h>
18 #include <linux/atomic.h>
19 #include <linux/of_device.h>
21 #define USBHS_LPSTS 0x02
22 #define USBHS_UGCTRL 0x80
23 #define USBHS_UGCTRL2 0x84
24 #define USBHS_UGSTS 0x88 /* From technical update */
26 /* Low Power Status register (LPSTS) */
27 #define USBHS_LPSTS_SUSPM 0x4000
29 /* USB General control register (UGCTRL) */
30 #define USBHS_UGCTRL_CONNECT 0x00000004
31 #define USBHS_UGCTRL_PLLRESET 0x00000001
33 /* USB General control register 2 (UGCTRL2) */
34 #define USBHS_UGCTRL2_USB2SEL 0x80000000
35 #define USBHS_UGCTRL2_USB2SEL_PCI 0x00000000
36 #define USBHS_UGCTRL2_USB2SEL_USB30 0x80000000
37 #define USBHS_UGCTRL2_USB0SEL 0x00000030
38 #define USBHS_UGCTRL2_USB0SEL_PCI 0x00000010
39 #define USBHS_UGCTRL2_USB0SEL_HS_USB 0x00000030
40 #define USBHS_UGCTRL2_USB0SEL_USB20 0x00000010
41 #define USBHS_UGCTRL2_USB0SEL_HS_USB20 0x00000020
43 /* USB General status register (UGSTS) */
44 #define USBHS_UGSTS_LOCK 0x00000100 /* From technical update */
46 #define PHYS_PER_CHANNEL 2
48 struct rcar_gen2_phy
{
50 struct rcar_gen2_channel
*channel
;
55 struct rcar_gen2_channel
{
56 struct device_node
*of_node
;
57 struct rcar_gen2_phy_driver
*drv
;
58 struct rcar_gen2_phy phys
[PHYS_PER_CHANNEL
];
63 struct rcar_gen2_phy_driver
{
68 struct rcar_gen2_channel
*channels
;
71 struct rcar_gen2_phy_data
{
72 const struct phy_ops
*gen2_phy_ops
;
73 const u32 (*select_value
)[PHYS_PER_CHANNEL
];
76 static int rcar_gen2_phy_init(struct phy
*p
)
78 struct rcar_gen2_phy
*phy
= phy_get_drvdata(p
);
79 struct rcar_gen2_channel
*channel
= phy
->channel
;
80 struct rcar_gen2_phy_driver
*drv
= channel
->drv
;
85 * Try to acquire exclusive access to PHY. The first driver calling
86 * phy_init() on a given channel wins, and all attempts to use another
87 * PHY on this channel will fail until phy_exit() is called by the first
88 * driver. Achieving this with cmpxcgh() should be SMP-safe.
90 if (cmpxchg(&channel
->selected_phy
, -1, phy
->number
) != -1)
93 clk_prepare_enable(drv
->clk
);
95 spin_lock_irqsave(&drv
->lock
, flags
);
96 ugctrl2
= readl(drv
->base
+ USBHS_UGCTRL2
);
97 ugctrl2
&= ~channel
->select_mask
;
98 ugctrl2
|= phy
->select_value
;
99 writel(ugctrl2
, drv
->base
+ USBHS_UGCTRL2
);
100 spin_unlock_irqrestore(&drv
->lock
, flags
);
104 static int rcar_gen2_phy_exit(struct phy
*p
)
106 struct rcar_gen2_phy
*phy
= phy_get_drvdata(p
);
107 struct rcar_gen2_channel
*channel
= phy
->channel
;
109 clk_disable_unprepare(channel
->drv
->clk
);
111 channel
->selected_phy
= -1;
116 static int rcar_gen2_phy_power_on(struct phy
*p
)
118 struct rcar_gen2_phy
*phy
= phy_get_drvdata(p
);
119 struct rcar_gen2_phy_driver
*drv
= phy
->channel
->drv
;
120 void __iomem
*base
= drv
->base
;
125 /* Skip if it's not USBHS */
126 if (phy
->select_value
!= USBHS_UGCTRL2_USB0SEL_HS_USB
)
129 spin_lock_irqsave(&drv
->lock
, flags
);
131 /* Power on USBHS PHY */
132 value
= readl(base
+ USBHS_UGCTRL
);
133 value
&= ~USBHS_UGCTRL_PLLRESET
;
134 writel(value
, base
+ USBHS_UGCTRL
);
136 value
= readw(base
+ USBHS_LPSTS
);
137 value
|= USBHS_LPSTS_SUSPM
;
138 writew(value
, base
+ USBHS_LPSTS
);
140 for (i
= 0; i
< 20; i
++) {
141 value
= readl(base
+ USBHS_UGSTS
);
142 if ((value
& USBHS_UGSTS_LOCK
) == USBHS_UGSTS_LOCK
) {
143 value
= readl(base
+ USBHS_UGCTRL
);
144 value
|= USBHS_UGCTRL_CONNECT
;
145 writel(value
, base
+ USBHS_UGCTRL
);
151 /* Timed out waiting for the PLL lock */
155 spin_unlock_irqrestore(&drv
->lock
, flags
);
160 static int rcar_gen2_phy_power_off(struct phy
*p
)
162 struct rcar_gen2_phy
*phy
= phy_get_drvdata(p
);
163 struct rcar_gen2_phy_driver
*drv
= phy
->channel
->drv
;
164 void __iomem
*base
= drv
->base
;
168 /* Skip if it's not USBHS */
169 if (phy
->select_value
!= USBHS_UGCTRL2_USB0SEL_HS_USB
)
172 spin_lock_irqsave(&drv
->lock
, flags
);
174 /* Power off USBHS PHY */
175 value
= readl(base
+ USBHS_UGCTRL
);
176 value
&= ~USBHS_UGCTRL_CONNECT
;
177 writel(value
, base
+ USBHS_UGCTRL
);
179 value
= readw(base
+ USBHS_LPSTS
);
180 value
&= ~USBHS_LPSTS_SUSPM
;
181 writew(value
, base
+ USBHS_LPSTS
);
183 value
= readl(base
+ USBHS_UGCTRL
);
184 value
|= USBHS_UGCTRL_PLLRESET
;
185 writel(value
, base
+ USBHS_UGCTRL
);
187 spin_unlock_irqrestore(&drv
->lock
, flags
);
192 static int rz_g1c_phy_power_on(struct phy
*p
)
194 struct rcar_gen2_phy
*phy
= phy_get_drvdata(p
);
195 struct rcar_gen2_phy_driver
*drv
= phy
->channel
->drv
;
196 void __iomem
*base
= drv
->base
;
200 spin_lock_irqsave(&drv
->lock
, flags
);
202 /* Power on USBHS PHY */
203 value
= readl(base
+ USBHS_UGCTRL
);
204 value
&= ~USBHS_UGCTRL_PLLRESET
;
205 writel(value
, base
+ USBHS_UGCTRL
);
207 /* As per the data sheet wait 340 micro sec for power stable */
210 if (phy
->select_value
== USBHS_UGCTRL2_USB0SEL_HS_USB20
) {
211 value
= readw(base
+ USBHS_LPSTS
);
212 value
|= USBHS_LPSTS_SUSPM
;
213 writew(value
, base
+ USBHS_LPSTS
);
216 spin_unlock_irqrestore(&drv
->lock
, flags
);
221 static int rz_g1c_phy_power_off(struct phy
*p
)
223 struct rcar_gen2_phy
*phy
= phy_get_drvdata(p
);
224 struct rcar_gen2_phy_driver
*drv
= phy
->channel
->drv
;
225 void __iomem
*base
= drv
->base
;
229 spin_lock_irqsave(&drv
->lock
, flags
);
230 /* Power off USBHS PHY */
231 if (phy
->select_value
== USBHS_UGCTRL2_USB0SEL_HS_USB20
) {
232 value
= readw(base
+ USBHS_LPSTS
);
233 value
&= ~USBHS_LPSTS_SUSPM
;
234 writew(value
, base
+ USBHS_LPSTS
);
237 value
= readl(base
+ USBHS_UGCTRL
);
238 value
|= USBHS_UGCTRL_PLLRESET
;
239 writel(value
, base
+ USBHS_UGCTRL
);
241 spin_unlock_irqrestore(&drv
->lock
, flags
);
246 static const struct phy_ops rcar_gen2_phy_ops
= {
247 .init
= rcar_gen2_phy_init
,
248 .exit
= rcar_gen2_phy_exit
,
249 .power_on
= rcar_gen2_phy_power_on
,
250 .power_off
= rcar_gen2_phy_power_off
,
251 .owner
= THIS_MODULE
,
254 static const struct phy_ops rz_g1c_phy_ops
= {
255 .init
= rcar_gen2_phy_init
,
256 .exit
= rcar_gen2_phy_exit
,
257 .power_on
= rz_g1c_phy_power_on
,
258 .power_off
= rz_g1c_phy_power_off
,
259 .owner
= THIS_MODULE
,
262 static const u32 pci_select_value
[][PHYS_PER_CHANNEL
] = {
263 [0] = { USBHS_UGCTRL2_USB0SEL_PCI
, USBHS_UGCTRL2_USB0SEL_HS_USB
},
264 [2] = { USBHS_UGCTRL2_USB2SEL_PCI
, USBHS_UGCTRL2_USB2SEL_USB30
},
267 static const u32 usb20_select_value
[][PHYS_PER_CHANNEL
] = {
268 { USBHS_UGCTRL2_USB0SEL_USB20
, USBHS_UGCTRL2_USB0SEL_HS_USB20
},
271 static const struct rcar_gen2_phy_data rcar_gen2_usb_phy_data
= {
272 .gen2_phy_ops
= &rcar_gen2_phy_ops
,
273 .select_value
= pci_select_value
,
276 static const struct rcar_gen2_phy_data rz_g1c_usb_phy_data
= {
277 .gen2_phy_ops
= &rz_g1c_phy_ops
,
278 .select_value
= usb20_select_value
,
281 static const struct of_device_id rcar_gen2_phy_match_table
[] = {
283 .compatible
= "renesas,usb-phy-r8a77470",
284 .data
= &rz_g1c_usb_phy_data
,
287 .compatible
= "renesas,usb-phy-r8a7790",
288 .data
= &rcar_gen2_usb_phy_data
,
291 .compatible
= "renesas,usb-phy-r8a7791",
292 .data
= &rcar_gen2_usb_phy_data
,
295 .compatible
= "renesas,usb-phy-r8a7794",
296 .data
= &rcar_gen2_usb_phy_data
,
299 .compatible
= "renesas,rcar-gen2-usb-phy",
300 .data
= &rcar_gen2_usb_phy_data
,
304 MODULE_DEVICE_TABLE(of
, rcar_gen2_phy_match_table
);
306 static struct phy
*rcar_gen2_phy_xlate(struct device
*dev
,
307 struct of_phandle_args
*args
)
309 struct rcar_gen2_phy_driver
*drv
;
310 struct device_node
*np
= args
->np
;
313 drv
= dev_get_drvdata(dev
);
315 return ERR_PTR(-EINVAL
);
317 for (i
= 0; i
< drv
->num_channels
; i
++) {
318 if (np
== drv
->channels
[i
].of_node
)
322 if (i
>= drv
->num_channels
|| args
->args
[0] >= 2)
323 return ERR_PTR(-ENODEV
);
325 return drv
->channels
[i
].phys
[args
->args
[0]].phy
;
328 static const u32 select_mask
[] = {
329 [0] = USBHS_UGCTRL2_USB0SEL
,
330 [2] = USBHS_UGCTRL2_USB2SEL
,
333 static int rcar_gen2_phy_probe(struct platform_device
*pdev
)
335 struct device
*dev
= &pdev
->dev
;
336 struct rcar_gen2_phy_driver
*drv
;
337 struct phy_provider
*provider
;
338 struct device_node
*np
;
339 struct resource
*res
;
342 const struct rcar_gen2_phy_data
*data
;
347 "This driver is required to be instantiated from device tree\n");
351 clk
= devm_clk_get(dev
, "usbhs");
353 dev_err(dev
, "Can't get USBHS clock\n");
357 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
358 base
= devm_ioremap_resource(dev
, res
);
360 return PTR_ERR(base
);
362 drv
= devm_kzalloc(dev
, sizeof(*drv
), GFP_KERNEL
);
366 spin_lock_init(&drv
->lock
);
371 data
= of_device_get_match_data(dev
);
375 drv
->num_channels
= of_get_child_count(dev
->of_node
);
376 drv
->channels
= devm_kcalloc(dev
, drv
->num_channels
,
377 sizeof(struct rcar_gen2_channel
),
382 for_each_child_of_node(dev
->of_node
, np
) {
383 struct rcar_gen2_channel
*channel
= drv
->channels
+ i
;
387 channel
->of_node
= np
;
389 channel
->selected_phy
= -1;
391 error
= of_property_read_u32(np
, "reg", &channel_num
);
392 if (error
|| channel_num
> 2) {
393 dev_err(dev
, "Invalid \"reg\" property\n");
396 channel
->select_mask
= select_mask
[channel_num
];
398 for (n
= 0; n
< PHYS_PER_CHANNEL
; n
++) {
399 struct rcar_gen2_phy
*phy
= &channel
->phys
[n
];
401 phy
->channel
= channel
;
403 phy
->select_value
= data
->select_value
[channel_num
][n
];
405 phy
->phy
= devm_phy_create(dev
, NULL
,
407 if (IS_ERR(phy
->phy
)) {
408 dev_err(dev
, "Failed to create PHY\n");
409 return PTR_ERR(phy
->phy
);
411 phy_set_drvdata(phy
->phy
, phy
);
417 provider
= devm_of_phy_provider_register(dev
, rcar_gen2_phy_xlate
);
418 if (IS_ERR(provider
)) {
419 dev_err(dev
, "Failed to register PHY provider\n");
420 return PTR_ERR(provider
);
423 dev_set_drvdata(dev
, drv
);
428 static struct platform_driver rcar_gen2_phy_driver
= {
430 .name
= "phy_rcar_gen2",
431 .of_match_table
= rcar_gen2_phy_match_table
,
433 .probe
= rcar_gen2_phy_probe
,
436 module_platform_driver(rcar_gen2_phy_driver
);
438 MODULE_LICENSE("GPL v2");
439 MODULE_DESCRIPTION("Renesas R-Car Gen2 PHY");
440 MODULE_AUTHOR("Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>");