xref: /linux/drivers/phy/renesas/phy-rcar-gen2.c (revision 44f57d78)
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 #include <linux/of_device.h>
20 
21 #define USBHS_LPSTS			0x02
22 #define USBHS_UGCTRL			0x80
23 #define USBHS_UGCTRL2			0x84
24 #define USBHS_UGSTS			0x88	/* From technical update */
25 
26 /* Low Power Status register (LPSTS) */
27 #define USBHS_LPSTS_SUSPM		0x4000
28 
29 /* USB General control register (UGCTRL) */
30 #define USBHS_UGCTRL_CONNECT		0x00000004
31 #define USBHS_UGCTRL_PLLRESET		0x00000001
32 
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
42 
43 /* USB General status register (UGSTS) */
44 #define USBHS_UGSTS_LOCK		0x00000100 /* From technical update */
45 
46 #define PHYS_PER_CHANNEL	2
47 
48 struct rcar_gen2_phy {
49 	struct phy *phy;
50 	struct rcar_gen2_channel *channel;
51 	int number;
52 	u32 select_value;
53 };
54 
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];
59 	int selected_phy;
60 	u32 select_mask;
61 };
62 
63 struct rcar_gen2_phy_driver {
64 	void __iomem *base;
65 	struct clk *clk;
66 	spinlock_t lock;
67 	int num_channels;
68 	struct rcar_gen2_channel *channels;
69 };
70 
71 struct rcar_gen2_phy_data {
72 	const struct phy_ops *gen2_phy_ops;
73 	const u32 (*select_value)[PHYS_PER_CHANNEL];
74 };
75 
76 static int rcar_gen2_phy_init(struct phy *p)
77 {
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;
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(drv->clk);
94 
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);
101 	return 0;
102 }
103 
104 static int rcar_gen2_phy_exit(struct phy *p)
105 {
106 	struct rcar_gen2_phy *phy = phy_get_drvdata(p);
107 	struct rcar_gen2_channel *channel = phy->channel;
108 
109 	clk_disable_unprepare(channel->drv->clk);
110 
111 	channel->selected_phy = -1;
112 
113 	return 0;
114 }
115 
116 static int rcar_gen2_phy_power_on(struct phy *p)
117 {
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;
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(base + USBHS_UGCTRL);
133 	value &= ~USBHS_UGCTRL_PLLRESET;
134 	writel(value, base + USBHS_UGCTRL);
135 
136 	value = readw(base + USBHS_LPSTS);
137 	value |= USBHS_LPSTS_SUSPM;
138 	writew(value, base + USBHS_LPSTS);
139 
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);
146 			goto out;
147 		}
148 		udelay(1);
149 	}
150 
151 	/* Timed out waiting for the PLL lock */
152 	err = -ETIMEDOUT;
153 
154 out:
155 	spin_unlock_irqrestore(&drv->lock, flags);
156 
157 	return err;
158 }
159 
160 static int rcar_gen2_phy_power_off(struct phy *p)
161 {
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;
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(base + USBHS_UGCTRL);
176 	value &= ~USBHS_UGCTRL_CONNECT;
177 	writel(value, base + USBHS_UGCTRL);
178 
179 	value = readw(base + USBHS_LPSTS);
180 	value &= ~USBHS_LPSTS_SUSPM;
181 	writew(value, base + USBHS_LPSTS);
182 
183 	value = readl(base + USBHS_UGCTRL);
184 	value |= USBHS_UGCTRL_PLLRESET;
185 	writel(value, base + USBHS_UGCTRL);
186 
187 	spin_unlock_irqrestore(&drv->lock, flags);
188 
189 	return 0;
190 }
191 
192 static int rz_g1c_phy_power_on(struct phy *p)
193 {
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;
197 	unsigned long flags;
198 	u32 value;
199 
200 	spin_lock_irqsave(&drv->lock, flags);
201 
202 	/* Power on USBHS PHY */
203 	value = readl(base + USBHS_UGCTRL);
204 	value &= ~USBHS_UGCTRL_PLLRESET;
205 	writel(value, 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(base + USBHS_LPSTS);
212 		value |= USBHS_LPSTS_SUSPM;
213 		writew(value, base + USBHS_LPSTS);
214 	}
215 
216 	spin_unlock_irqrestore(&drv->lock, flags);
217 
218 	return 0;
219 }
220 
221 static int rz_g1c_phy_power_off(struct phy *p)
222 {
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;
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(base + USBHS_LPSTS);
233 		value &= ~USBHS_LPSTS_SUSPM;
234 		writew(value, base + USBHS_LPSTS);
235 	}
236 
237 	value = readl(base + USBHS_UGCTRL);
238 	value |= USBHS_UGCTRL_PLLRESET;
239 	writel(value, base + USBHS_UGCTRL);
240 
241 	spin_unlock_irqrestore(&drv->lock, flags);
242 
243 	return 0;
244 }
245 
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,
252 };
253 
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,
260 };
261 
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 },
265 };
266 
267 static const u32 usb20_select_value[][PHYS_PER_CHANNEL] = {
268 	{ USBHS_UGCTRL2_USB0SEL_USB20, USBHS_UGCTRL2_USB0SEL_HS_USB20 },
269 };
270 
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,
274 };
275 
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,
279 };
280 
281 static const struct of_device_id rcar_gen2_phy_match_table[] = {
282 	{
283 		.compatible = "renesas,usb-phy-r8a77470",
284 		.data = &rz_g1c_usb_phy_data,
285 	},
286 	{
287 		.compatible = "renesas,usb-phy-r8a7790",
288 		.data = &rcar_gen2_usb_phy_data,
289 	},
290 	{
291 		.compatible = "renesas,usb-phy-r8a7791",
292 		.data = &rcar_gen2_usb_phy_data,
293 	},
294 	{
295 		.compatible = "renesas,usb-phy-r8a7794",
296 		.data = &rcar_gen2_usb_phy_data,
297 	},
298 	{
299 		.compatible = "renesas,rcar-gen2-usb-phy",
300 		.data = &rcar_gen2_usb_phy_data,
301 	},
302 	{ /* sentinel */ },
303 };
304 MODULE_DEVICE_TABLE(of, rcar_gen2_phy_match_table);
305 
306 static struct phy *rcar_gen2_phy_xlate(struct device *dev,
307 				       struct of_phandle_args *args)
308 {
309 	struct rcar_gen2_phy_driver *drv;
310 	struct device_node *np = args->np;
311 	int i;
312 
313 	drv = dev_get_drvdata(dev);
314 	if (!drv)
315 		return ERR_PTR(-EINVAL);
316 
317 	for (i = 0; i < drv->num_channels; i++) {
318 		if (np == drv->channels[i].of_node)
319 			break;
320 	}
321 
322 	if (i >= drv->num_channels || args->args[0] >= 2)
323 		return ERR_PTR(-ENODEV);
324 
325 	return drv->channels[i].phys[args->args[0]].phy;
326 }
327 
328 static const u32 select_mask[] = {
329 	[0]	= USBHS_UGCTRL2_USB0SEL,
330 	[2]	= USBHS_UGCTRL2_USB2SEL,
331 };
332 
333 static int rcar_gen2_phy_probe(struct platform_device *pdev)
334 {
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;
340 	void __iomem *base;
341 	struct clk *clk;
342 	const struct rcar_gen2_phy_data *data;
343 	int i = 0;
344 
345 	if (!dev->of_node) {
346 		dev_err(dev,
347 			"This driver is required to be instantiated from device tree\n");
348 		return -EINVAL;
349 	}
350 
351 	clk = devm_clk_get(dev, "usbhs");
352 	if (IS_ERR(clk)) {
353 		dev_err(dev, "Can't get USBHS clock\n");
354 		return PTR_ERR(clk);
355 	}
356 
357 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
358 	base = devm_ioremap_resource(dev, res);
359 	if (IS_ERR(base))
360 		return PTR_ERR(base);
361 
362 	drv = devm_kzalloc(dev, 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(dev->of_node);
376 	drv->channels = devm_kcalloc(dev, drv->num_channels,
377 				     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, "reg", &channel_num);
392 		if (error || channel_num > 2) {
393 			dev_err(dev, "Invalid \"reg\" property\n");
394 			return error;
395 		}
396 		channel->select_mask = select_mask[channel_num];
397 
398 		for (n = 0; n < PHYS_PER_CHANNEL; n++) {
399 			struct rcar_gen2_phy *phy = &channel->phys[n];
400 
401 			phy->channel = channel;
402 			phy->number = n;
403 			phy->select_value = data->select_value[channel_num][n];
404 
405 			phy->phy = devm_phy_create(dev, NULL,
406 						   data->gen2_phy_ops);
407 			if (IS_ERR(phy->phy)) {
408 				dev_err(dev, "Failed to create PHY\n");
409 				return PTR_ERR(phy->phy);
410 			}
411 			phy_set_drvdata(phy->phy, phy);
412 		}
413 
414 		i++;
415 	}
416 
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);
421 	}
422 
423 	dev_set_drvdata(dev, drv);
424 
425 	return 0;
426 }
427 
428 static struct platform_driver rcar_gen2_phy_driver = {
429 	.driver = {
430 		.name		= "phy_rcar_gen2",
431 		.of_match_table	= rcar_gen2_phy_match_table,
432 	},
433 	.probe	= rcar_gen2_phy_probe,
434 };
435 
436 module_platform_driver(rcar_gen2_phy_driver);
437 
438 MODULE_LICENSE("GPL v2");
439 MODULE_DESCRIPTION("Renesas R-Car Gen2 PHY");
440 MODULE_AUTHOR("Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>");
441