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

source code of linux/drivers/phy/renesas/phy-rcar-gen2.c