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
];
74 const u32 num_channels
;
77 static int rcar_gen2_phy_init(struct phy
*p
)
79 struct rcar_gen2_phy
*phy
= phy_get_drvdata(p
);
80 struct rcar_gen2_channel
*channel
= phy
->channel
;
81 struct rcar_gen2_phy_driver
*drv
= channel
->drv
;
86 * Try to acquire exclusive access to PHY. The first driver calling
87 * phy_init() on a given channel wins, and all attempts to use another
88 * PHY on this channel will fail until phy_exit() is called by the first
89 * driver. Achieving this with cmpxcgh() should be SMP-safe.
91 if (cmpxchg(&channel
->selected_phy
, -1, phy
->number
) != -1)
94 clk_prepare_enable(drv
->clk
);
96 spin_lock_irqsave(&drv
->lock
, flags
);
97 ugctrl2
= readl(drv
->base
+ USBHS_UGCTRL2
);
98 ugctrl2
&= ~channel
->select_mask
;
99 ugctrl2
|= phy
->select_value
;
100 writel(ugctrl2
, drv
->base
+ USBHS_UGCTRL2
);
101 spin_unlock_irqrestore(&drv
->lock
, flags
);
105 static int rcar_gen2_phy_exit(struct phy
*p
)
107 struct rcar_gen2_phy
*phy
= phy_get_drvdata(p
);
108 struct rcar_gen2_channel
*channel
= phy
->channel
;
110 clk_disable_unprepare(channel
->drv
->clk
);
112 channel
->selected_phy
= -1;
117 static int rcar_gen2_phy_power_on(struct phy
*p
)
119 struct rcar_gen2_phy
*phy
= phy_get_drvdata(p
);
120 struct rcar_gen2_phy_driver
*drv
= phy
->channel
->drv
;
121 void __iomem
*base
= drv
->base
;
126 /* Skip if it's not USBHS */
127 if (phy
->select_value
!= USBHS_UGCTRL2_USB0SEL_HS_USB
)
130 spin_lock_irqsave(&drv
->lock
, flags
);
132 /* Power on USBHS PHY */
133 value
= readl(base
+ USBHS_UGCTRL
);
134 value
&= ~USBHS_UGCTRL_PLLRESET
;
135 writel(value
, base
+ USBHS_UGCTRL
);
137 value
= readw(base
+ USBHS_LPSTS
);
138 value
|= USBHS_LPSTS_SUSPM
;
139 writew(value
, base
+ USBHS_LPSTS
);
141 for (i
= 0; i
< 20; i
++) {
142 value
= readl(base
+ USBHS_UGSTS
);
143 if ((value
& USBHS_UGSTS_LOCK
) == USBHS_UGSTS_LOCK
) {
144 value
= readl(base
+ USBHS_UGCTRL
);
145 value
|= USBHS_UGCTRL_CONNECT
;
146 writel(value
, base
+ USBHS_UGCTRL
);
152 /* Timed out waiting for the PLL lock */
156 spin_unlock_irqrestore(&drv
->lock
, flags
);
161 static int rcar_gen2_phy_power_off(struct phy
*p
)
163 struct rcar_gen2_phy
*phy
= phy_get_drvdata(p
);
164 struct rcar_gen2_phy_driver
*drv
= phy
->channel
->drv
;
165 void __iomem
*base
= drv
->base
;
169 /* Skip if it's not USBHS */
170 if (phy
->select_value
!= USBHS_UGCTRL2_USB0SEL_HS_USB
)
173 spin_lock_irqsave(&drv
->lock
, flags
);
175 /* Power off USBHS PHY */
176 value
= readl(base
+ USBHS_UGCTRL
);
177 value
&= ~USBHS_UGCTRL_CONNECT
;
178 writel(value
, base
+ USBHS_UGCTRL
);
180 value
= readw(base
+ USBHS_LPSTS
);
181 value
&= ~USBHS_LPSTS_SUSPM
;
182 writew(value
, base
+ USBHS_LPSTS
);
184 value
= readl(base
+ USBHS_UGCTRL
);
185 value
|= USBHS_UGCTRL_PLLRESET
;
186 writel(value
, base
+ USBHS_UGCTRL
);
188 spin_unlock_irqrestore(&drv
->lock
, flags
);
193 static int rz_g1c_phy_power_on(struct phy
*p
)
195 struct rcar_gen2_phy
*phy
= phy_get_drvdata(p
);
196 struct rcar_gen2_phy_driver
*drv
= phy
->channel
->drv
;
197 void __iomem
*base
= drv
->base
;
201 spin_lock_irqsave(&drv
->lock
, flags
);
203 /* Power on USBHS PHY */
204 value
= readl(base
+ USBHS_UGCTRL
);
205 value
&= ~USBHS_UGCTRL_PLLRESET
;
206 writel(value
, base
+ USBHS_UGCTRL
);
208 /* As per the data sheet wait 340 micro sec for power stable */
211 if (phy
->select_value
== USBHS_UGCTRL2_USB0SEL_HS_USB20
) {
212 value
= readw(base
+ USBHS_LPSTS
);
213 value
|= USBHS_LPSTS_SUSPM
;
214 writew(value
, base
+ USBHS_LPSTS
);
217 spin_unlock_irqrestore(&drv
->lock
, flags
);
222 static int rz_g1c_phy_power_off(struct phy
*p
)
224 struct rcar_gen2_phy
*phy
= phy_get_drvdata(p
);
225 struct rcar_gen2_phy_driver
*drv
= phy
->channel
->drv
;
226 void __iomem
*base
= drv
->base
;
230 spin_lock_irqsave(&drv
->lock
, flags
);
231 /* Power off USBHS PHY */
232 if (phy
->select_value
== USBHS_UGCTRL2_USB0SEL_HS_USB20
) {
233 value
= readw(base
+ USBHS_LPSTS
);
234 value
&= ~USBHS_LPSTS_SUSPM
;
235 writew(value
, base
+ USBHS_LPSTS
);
238 value
= readl(base
+ USBHS_UGCTRL
);
239 value
|= USBHS_UGCTRL_PLLRESET
;
240 writel(value
, base
+ USBHS_UGCTRL
);
242 spin_unlock_irqrestore(&drv
->lock
, flags
);
247 static const struct phy_ops rcar_gen2_phy_ops
= {
248 .init
= rcar_gen2_phy_init
,
249 .exit
= rcar_gen2_phy_exit
,
250 .power_on
= rcar_gen2_phy_power_on
,
251 .power_off
= rcar_gen2_phy_power_off
,
252 .owner
= THIS_MODULE
,
255 static const struct phy_ops rz_g1c_phy_ops
= {
256 .init
= rcar_gen2_phy_init
,
257 .exit
= rcar_gen2_phy_exit
,
258 .power_on
= rz_g1c_phy_power_on
,
259 .power_off
= rz_g1c_phy_power_off
,
260 .owner
= THIS_MODULE
,
263 static const u32 pci_select_value
[][PHYS_PER_CHANNEL
] = {
264 [0] = { USBHS_UGCTRL2_USB0SEL_PCI
, USBHS_UGCTRL2_USB0SEL_HS_USB
},
265 [2] = { USBHS_UGCTRL2_USB2SEL_PCI
, USBHS_UGCTRL2_USB2SEL_USB30
},
268 static const u32 usb20_select_value
[][PHYS_PER_CHANNEL
] = {
269 { USBHS_UGCTRL2_USB0SEL_USB20
, USBHS_UGCTRL2_USB0SEL_HS_USB20
},
272 static const struct rcar_gen2_phy_data rcar_gen2_usb_phy_data
= {
273 .gen2_phy_ops
= &rcar_gen2_phy_ops
,
274 .select_value
= pci_select_value
,
275 .num_channels
= ARRAY_SIZE(pci_select_value
),
278 static const struct rcar_gen2_phy_data rz_g1c_usb_phy_data
= {
279 .gen2_phy_ops
= &rz_g1c_phy_ops
,
280 .select_value
= usb20_select_value
,
281 .num_channels
= ARRAY_SIZE(usb20_select_value
),
284 static const struct of_device_id rcar_gen2_phy_match_table
[] = {
286 .compatible
= "renesas,usb-phy-r8a77470",
287 .data
= &rz_g1c_usb_phy_data
,
290 .compatible
= "renesas,usb-phy-r8a7790",
291 .data
= &rcar_gen2_usb_phy_data
,
294 .compatible
= "renesas,usb-phy-r8a7791",
295 .data
= &rcar_gen2_usb_phy_data
,
298 .compatible
= "renesas,usb-phy-r8a7794",
299 .data
= &rcar_gen2_usb_phy_data
,
302 .compatible
= "renesas,rcar-gen2-usb-phy",
303 .data
= &rcar_gen2_usb_phy_data
,
307 MODULE_DEVICE_TABLE(of
, rcar_gen2_phy_match_table
);
309 static struct phy
*rcar_gen2_phy_xlate(struct device
*dev
,
310 struct of_phandle_args
*args
)
312 struct rcar_gen2_phy_driver
*drv
;
313 struct device_node
*np
= args
->np
;
316 drv
= dev_get_drvdata(dev
);
318 return ERR_PTR(-EINVAL
);
320 for (i
= 0; i
< drv
->num_channels
; i
++) {
321 if (np
== drv
->channels
[i
].of_node
)
325 if (i
>= drv
->num_channels
|| args
->args
[0] >= 2)
326 return ERR_PTR(-ENODEV
);
328 return drv
->channels
[i
].phys
[args
->args
[0]].phy
;
331 static const u32 select_mask
[] = {
332 [0] = USBHS_UGCTRL2_USB0SEL
,
333 [2] = USBHS_UGCTRL2_USB2SEL
,
336 static int rcar_gen2_phy_probe(struct platform_device
*pdev
)
338 struct device
*dev
= &pdev
->dev
;
339 struct rcar_gen2_phy_driver
*drv
;
340 struct phy_provider
*provider
;
341 struct device_node
*np
;
342 struct resource
*res
;
345 const struct rcar_gen2_phy_data
*data
;
350 "This driver is required to be instantiated from device tree\n");
354 clk
= devm_clk_get(dev
, "usbhs");
356 dev_err(dev
, "Can't get USBHS clock\n");
360 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
361 base
= devm_ioremap_resource(dev
, res
);
363 return PTR_ERR(base
);
365 drv
= devm_kzalloc(dev
, sizeof(*drv
), GFP_KERNEL
);
369 spin_lock_init(&drv
->lock
);
374 data
= of_device_get_match_data(dev
);
378 drv
->num_channels
= of_get_child_count(dev
->of_node
);
379 drv
->channels
= devm_kcalloc(dev
, drv
->num_channels
,
380 sizeof(struct rcar_gen2_channel
),
385 for_each_child_of_node(dev
->of_node
, np
) {
386 struct rcar_gen2_channel
*channel
= drv
->channels
+ i
;
390 channel
->of_node
= np
;
392 channel
->selected_phy
= -1;
394 error
= of_property_read_u32(np
, "reg", &channel_num
);
395 if (error
|| channel_num
>= data
->num_channels
) {
396 dev_err(dev
, "Invalid \"reg\" property\n");
400 channel
->select_mask
= select_mask
[channel_num
];
402 for (n
= 0; n
< PHYS_PER_CHANNEL
; n
++) {
403 struct rcar_gen2_phy
*phy
= &channel
->phys
[n
];
405 phy
->channel
= channel
;
407 phy
->select_value
= data
->select_value
[channel_num
][n
];
409 phy
->phy
= devm_phy_create(dev
, NULL
,
411 if (IS_ERR(phy
->phy
)) {
412 dev_err(dev
, "Failed to create PHY\n");
414 return PTR_ERR(phy
->phy
);
416 phy_set_drvdata(phy
->phy
, phy
);
422 provider
= devm_of_phy_provider_register(dev
, rcar_gen2_phy_xlate
);
423 if (IS_ERR(provider
)) {
424 dev_err(dev
, "Failed to register PHY provider\n");
425 return PTR_ERR(provider
);
428 dev_set_drvdata(dev
, drv
);
433 static struct platform_driver rcar_gen2_phy_driver
= {
435 .name
= "phy_rcar_gen2",
436 .of_match_table
= rcar_gen2_phy_match_table
,
438 .probe
= rcar_gen2_phy_probe
,
441 module_platform_driver(rcar_gen2_phy_driver
);
443 MODULE_LICENSE("GPL v2");
444 MODULE_DESCRIPTION("Renesas R-Car Gen2 PHY");
445 MODULE_AUTHOR("Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>");