1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * Renesas R-Car Gen3 for USB2.0 PHY driver |
4 | * |
5 | * Copyright (C) 2015-2017 Renesas Electronics Corporation |
6 | * |
7 | * This is based on the phy-rcar-gen2 driver: |
8 | * Copyright (C) 2014 Renesas Solutions Corp. |
9 | * Copyright (C) 2014 Cogent Embedded, Inc. |
10 | */ |
11 | |
12 | #include <linux/extcon-provider.h> |
13 | #include <linux/interrupt.h> |
14 | #include <linux/io.h> |
15 | #include <linux/module.h> |
16 | #include <linux/mutex.h> |
17 | #include <linux/of.h> |
18 | #include <linux/phy/phy.h> |
19 | #include <linux/platform_device.h> |
20 | #include <linux/pm_runtime.h> |
21 | #include <linux/regulator/consumer.h> |
22 | #include <linux/string.h> |
23 | #include <linux/usb/of.h> |
24 | #include <linux/workqueue.h> |
25 | |
26 | /******* USB2.0 Host registers (original offset is +0x200) *******/ |
27 | #define USB2_INT_ENABLE 0x000 |
28 | #define USB2_USBCTR 0x00c |
29 | #define USB2_SPD_RSM_TIMSET 0x10c |
30 | #define USB2_OC_TIMSET 0x110 |
31 | #define USB2_COMMCTRL 0x600 |
32 | #define USB2_OBINTSTA 0x604 |
33 | #define USB2_OBINTEN 0x608 |
34 | #define USB2_VBCTRL 0x60c |
35 | #define USB2_LINECTRL1 0x610 |
36 | #define USB2_ADPCTRL 0x630 |
37 | |
38 | /* INT_ENABLE */ |
39 | #define USB2_INT_ENABLE_UCOM_INTEN BIT(3) |
40 | #define USB2_INT_ENABLE_USBH_INTB_EN BIT(2) /* For EHCI */ |
41 | #define USB2_INT_ENABLE_USBH_INTA_EN BIT(1) /* For OHCI */ |
42 | |
43 | /* USBCTR */ |
44 | #define USB2_USBCTR_DIRPD BIT(2) |
45 | #define USB2_USBCTR_PLL_RST BIT(1) |
46 | |
47 | /* SPD_RSM_TIMSET */ |
48 | #define USB2_SPD_RSM_TIMSET_INIT 0x014e029b |
49 | |
50 | /* OC_TIMSET */ |
51 | #define USB2_OC_TIMSET_INIT 0x000209ab |
52 | |
53 | /* COMMCTRL */ |
54 | #define USB2_COMMCTRL_OTG_PERI BIT(31) /* 1 = Peripheral mode */ |
55 | |
56 | /* OBINTSTA and OBINTEN */ |
57 | #define USB2_OBINT_SESSVLDCHG BIT(12) |
58 | #define USB2_OBINT_IDDIGCHG BIT(11) |
59 | #define USB2_OBINT_BITS (USB2_OBINT_SESSVLDCHG | \ |
60 | USB2_OBINT_IDDIGCHG) |
61 | |
62 | /* VBCTRL */ |
63 | #define USB2_VBCTRL_OCCLREN BIT(16) |
64 | #define USB2_VBCTRL_DRVVBUSSEL BIT(8) |
65 | #define USB2_VBCTRL_VBOUT BIT(0) |
66 | |
67 | /* LINECTRL1 */ |
68 | #define USB2_LINECTRL1_DPRPD_EN BIT(19) |
69 | #define USB2_LINECTRL1_DP_RPD BIT(18) |
70 | #define USB2_LINECTRL1_DMRPD_EN BIT(17) |
71 | #define USB2_LINECTRL1_DM_RPD BIT(16) |
72 | #define USB2_LINECTRL1_OPMODE_NODRV BIT(6) |
73 | |
74 | /* ADPCTRL */ |
75 | #define USB2_ADPCTRL_OTGSESSVLD BIT(20) |
76 | #define USB2_ADPCTRL_IDDIG BIT(19) |
77 | #define USB2_ADPCTRL_IDPULLUP BIT(5) /* 1 = ID sampling is enabled */ |
78 | #define USB2_ADPCTRL_DRVVBUS BIT(4) |
79 | |
80 | /* RZ/G2L specific */ |
81 | #define USB2_OBINT_IDCHG_EN BIT(0) |
82 | #define USB2_LINECTRL1_USB2_IDMON BIT(0) |
83 | |
84 | #define NUM_OF_PHYS 4 |
85 | enum rcar_gen3_phy_index { |
86 | PHY_INDEX_BOTH_HC, |
87 | PHY_INDEX_OHCI, |
88 | PHY_INDEX_EHCI, |
89 | PHY_INDEX_HSUSB |
90 | }; |
91 | |
92 | static const u32 rcar_gen3_int_enable[NUM_OF_PHYS] = { |
93 | USB2_INT_ENABLE_USBH_INTB_EN | USB2_INT_ENABLE_USBH_INTA_EN, |
94 | USB2_INT_ENABLE_USBH_INTA_EN, |
95 | USB2_INT_ENABLE_USBH_INTB_EN, |
96 | 0 |
97 | }; |
98 | |
99 | struct rcar_gen3_phy { |
100 | struct phy *phy; |
101 | struct rcar_gen3_chan *ch; |
102 | u32 int_enable_bits; |
103 | bool initialized; |
104 | bool otg_initialized; |
105 | bool powered; |
106 | }; |
107 | |
108 | struct rcar_gen3_chan { |
109 | void __iomem *base; |
110 | struct device *dev; /* platform_device's device */ |
111 | struct extcon_dev *extcon; |
112 | struct rcar_gen3_phy rphys[NUM_OF_PHYS]; |
113 | struct regulator *vbus; |
114 | struct work_struct work; |
115 | struct mutex lock; /* protects rphys[...].powered */ |
116 | enum usb_dr_mode dr_mode; |
117 | int irq; |
118 | u32 obint_enable_bits; |
119 | bool extcon_host; |
120 | bool is_otg_channel; |
121 | bool uses_otg_pins; |
122 | bool soc_no_adp_ctrl; |
123 | }; |
124 | |
125 | struct rcar_gen3_phy_drv_data { |
126 | const struct phy_ops *phy_usb2_ops; |
127 | bool no_adp_ctrl; |
128 | }; |
129 | |
130 | /* |
131 | * Combination about is_otg_channel and uses_otg_pins: |
132 | * |
133 | * Parameters || Behaviors |
134 | * is_otg_channel | uses_otg_pins || irqs | role sysfs |
135 | * ---------------------+---------------++--------------+------------ |
136 | * true | true || enabled | enabled |
137 | * true | false || disabled | enabled |
138 | * false | any || disabled | disabled |
139 | */ |
140 | |
141 | static void rcar_gen3_phy_usb2_work(struct work_struct *work) |
142 | { |
143 | struct rcar_gen3_chan *ch = container_of(work, struct rcar_gen3_chan, |
144 | work); |
145 | |
146 | if (ch->extcon_host) { |
147 | extcon_set_state_sync(edev: ch->extcon, EXTCON_USB_HOST, state: true); |
148 | extcon_set_state_sync(edev: ch->extcon, EXTCON_USB, state: false); |
149 | } else { |
150 | extcon_set_state_sync(edev: ch->extcon, EXTCON_USB_HOST, state: false); |
151 | extcon_set_state_sync(edev: ch->extcon, EXTCON_USB, state: true); |
152 | } |
153 | } |
154 | |
155 | static void rcar_gen3_set_host_mode(struct rcar_gen3_chan *ch, int host) |
156 | { |
157 | void __iomem *usb2_base = ch->base; |
158 | u32 val = readl(addr: usb2_base + USB2_COMMCTRL); |
159 | |
160 | dev_vdbg(ch->dev, "%s: %08x, %d\n" , __func__, val, host); |
161 | if (host) |
162 | val &= ~USB2_COMMCTRL_OTG_PERI; |
163 | else |
164 | val |= USB2_COMMCTRL_OTG_PERI; |
165 | writel(val, addr: usb2_base + USB2_COMMCTRL); |
166 | } |
167 | |
168 | static void rcar_gen3_set_linectrl(struct rcar_gen3_chan *ch, int dp, int dm) |
169 | { |
170 | void __iomem *usb2_base = ch->base; |
171 | u32 val = readl(addr: usb2_base + USB2_LINECTRL1); |
172 | |
173 | dev_vdbg(ch->dev, "%s: %08x, %d, %d\n" , __func__, val, dp, dm); |
174 | val &= ~(USB2_LINECTRL1_DP_RPD | USB2_LINECTRL1_DM_RPD); |
175 | if (dp) |
176 | val |= USB2_LINECTRL1_DP_RPD; |
177 | if (dm) |
178 | val |= USB2_LINECTRL1_DM_RPD; |
179 | writel(val, addr: usb2_base + USB2_LINECTRL1); |
180 | } |
181 | |
182 | static void rcar_gen3_enable_vbus_ctrl(struct rcar_gen3_chan *ch, int vbus) |
183 | { |
184 | void __iomem *usb2_base = ch->base; |
185 | u32 vbus_ctrl_reg = USB2_ADPCTRL; |
186 | u32 vbus_ctrl_val = USB2_ADPCTRL_DRVVBUS; |
187 | u32 val; |
188 | |
189 | dev_vdbg(ch->dev, "%s: %08x, %d\n" , __func__, val, vbus); |
190 | if (ch->soc_no_adp_ctrl) { |
191 | vbus_ctrl_reg = USB2_VBCTRL; |
192 | vbus_ctrl_val = USB2_VBCTRL_VBOUT; |
193 | } |
194 | |
195 | val = readl(addr: usb2_base + vbus_ctrl_reg); |
196 | if (vbus) |
197 | val |= vbus_ctrl_val; |
198 | else |
199 | val &= ~vbus_ctrl_val; |
200 | writel(val, addr: usb2_base + vbus_ctrl_reg); |
201 | } |
202 | |
203 | static void rcar_gen3_control_otg_irq(struct rcar_gen3_chan *ch, int enable) |
204 | { |
205 | void __iomem *usb2_base = ch->base; |
206 | u32 val = readl(addr: usb2_base + USB2_OBINTEN); |
207 | |
208 | if (ch->uses_otg_pins && enable) |
209 | val |= ch->obint_enable_bits; |
210 | else |
211 | val &= ~ch->obint_enable_bits; |
212 | writel(val, addr: usb2_base + USB2_OBINTEN); |
213 | } |
214 | |
215 | static void rcar_gen3_init_for_host(struct rcar_gen3_chan *ch) |
216 | { |
217 | rcar_gen3_set_linectrl(ch, dp: 1, dm: 1); |
218 | rcar_gen3_set_host_mode(ch, host: 1); |
219 | rcar_gen3_enable_vbus_ctrl(ch, vbus: 1); |
220 | |
221 | ch->extcon_host = true; |
222 | schedule_work(work: &ch->work); |
223 | } |
224 | |
225 | static void rcar_gen3_init_for_peri(struct rcar_gen3_chan *ch) |
226 | { |
227 | rcar_gen3_set_linectrl(ch, dp: 0, dm: 1); |
228 | rcar_gen3_set_host_mode(ch, host: 0); |
229 | rcar_gen3_enable_vbus_ctrl(ch, vbus: 0); |
230 | |
231 | ch->extcon_host = false; |
232 | schedule_work(work: &ch->work); |
233 | } |
234 | |
235 | static void rcar_gen3_init_for_b_host(struct rcar_gen3_chan *ch) |
236 | { |
237 | void __iomem *usb2_base = ch->base; |
238 | u32 val; |
239 | |
240 | val = readl(addr: usb2_base + USB2_LINECTRL1); |
241 | writel(val: val | USB2_LINECTRL1_OPMODE_NODRV, addr: usb2_base + USB2_LINECTRL1); |
242 | |
243 | rcar_gen3_set_linectrl(ch, dp: 1, dm: 1); |
244 | rcar_gen3_set_host_mode(ch, host: 1); |
245 | rcar_gen3_enable_vbus_ctrl(ch, vbus: 0); |
246 | |
247 | val = readl(addr: usb2_base + USB2_LINECTRL1); |
248 | writel(val: val & ~USB2_LINECTRL1_OPMODE_NODRV, addr: usb2_base + USB2_LINECTRL1); |
249 | } |
250 | |
251 | static void rcar_gen3_init_for_a_peri(struct rcar_gen3_chan *ch) |
252 | { |
253 | rcar_gen3_set_linectrl(ch, dp: 0, dm: 1); |
254 | rcar_gen3_set_host_mode(ch, host: 0); |
255 | rcar_gen3_enable_vbus_ctrl(ch, vbus: 1); |
256 | } |
257 | |
258 | static void rcar_gen3_init_from_a_peri_to_a_host(struct rcar_gen3_chan *ch) |
259 | { |
260 | rcar_gen3_control_otg_irq(ch, enable: 0); |
261 | |
262 | rcar_gen3_enable_vbus_ctrl(ch, vbus: 1); |
263 | rcar_gen3_init_for_host(ch); |
264 | |
265 | rcar_gen3_control_otg_irq(ch, enable: 1); |
266 | } |
267 | |
268 | static bool rcar_gen3_check_id(struct rcar_gen3_chan *ch) |
269 | { |
270 | if (!ch->uses_otg_pins) |
271 | return (ch->dr_mode == USB_DR_MODE_HOST) ? false : true; |
272 | |
273 | if (ch->soc_no_adp_ctrl) |
274 | return !!(readl(addr: ch->base + USB2_LINECTRL1) & USB2_LINECTRL1_USB2_IDMON); |
275 | |
276 | return !!(readl(addr: ch->base + USB2_ADPCTRL) & USB2_ADPCTRL_IDDIG); |
277 | } |
278 | |
279 | static void rcar_gen3_device_recognition(struct rcar_gen3_chan *ch) |
280 | { |
281 | if (!rcar_gen3_check_id(ch)) |
282 | rcar_gen3_init_for_host(ch); |
283 | else |
284 | rcar_gen3_init_for_peri(ch); |
285 | } |
286 | |
287 | static bool rcar_gen3_is_host(struct rcar_gen3_chan *ch) |
288 | { |
289 | return !(readl(addr: ch->base + USB2_COMMCTRL) & USB2_COMMCTRL_OTG_PERI); |
290 | } |
291 | |
292 | static enum phy_mode rcar_gen3_get_phy_mode(struct rcar_gen3_chan *ch) |
293 | { |
294 | if (rcar_gen3_is_host(ch)) |
295 | return PHY_MODE_USB_HOST; |
296 | |
297 | return PHY_MODE_USB_DEVICE; |
298 | } |
299 | |
300 | static bool rcar_gen3_is_any_rphy_initialized(struct rcar_gen3_chan *ch) |
301 | { |
302 | int i; |
303 | |
304 | for (i = 0; i < NUM_OF_PHYS; i++) { |
305 | if (ch->rphys[i].initialized) |
306 | return true; |
307 | } |
308 | |
309 | return false; |
310 | } |
311 | |
312 | static bool rcar_gen3_needs_init_otg(struct rcar_gen3_chan *ch) |
313 | { |
314 | int i; |
315 | |
316 | for (i = 0; i < NUM_OF_PHYS; i++) { |
317 | if (ch->rphys[i].otg_initialized) |
318 | return false; |
319 | } |
320 | |
321 | return true; |
322 | } |
323 | |
324 | static bool rcar_gen3_are_all_rphys_power_off(struct rcar_gen3_chan *ch) |
325 | { |
326 | int i; |
327 | |
328 | for (i = 0; i < NUM_OF_PHYS; i++) { |
329 | if (ch->rphys[i].powered) |
330 | return false; |
331 | } |
332 | |
333 | return true; |
334 | } |
335 | |
336 | static ssize_t role_store(struct device *dev, struct device_attribute *attr, |
337 | const char *buf, size_t count) |
338 | { |
339 | struct rcar_gen3_chan *ch = dev_get_drvdata(dev); |
340 | bool is_b_device; |
341 | enum phy_mode cur_mode, new_mode; |
342 | |
343 | if (!ch->is_otg_channel || !rcar_gen3_is_any_rphy_initialized(ch)) |
344 | return -EIO; |
345 | |
346 | if (sysfs_streq(s1: buf, s2: "host" )) |
347 | new_mode = PHY_MODE_USB_HOST; |
348 | else if (sysfs_streq(s1: buf, s2: "peripheral" )) |
349 | new_mode = PHY_MODE_USB_DEVICE; |
350 | else |
351 | return -EINVAL; |
352 | |
353 | /* is_b_device: true is B-Device. false is A-Device. */ |
354 | is_b_device = rcar_gen3_check_id(ch); |
355 | cur_mode = rcar_gen3_get_phy_mode(ch); |
356 | |
357 | /* If current and new mode is the same, this returns the error */ |
358 | if (cur_mode == new_mode) |
359 | return -EINVAL; |
360 | |
361 | if (new_mode == PHY_MODE_USB_HOST) { /* And is_host must be false */ |
362 | if (!is_b_device) /* A-Peripheral */ |
363 | rcar_gen3_init_from_a_peri_to_a_host(ch); |
364 | else /* B-Peripheral */ |
365 | rcar_gen3_init_for_b_host(ch); |
366 | } else { /* And is_host must be true */ |
367 | if (!is_b_device) /* A-Host */ |
368 | rcar_gen3_init_for_a_peri(ch); |
369 | else /* B-Host */ |
370 | rcar_gen3_init_for_peri(ch); |
371 | } |
372 | |
373 | return count; |
374 | } |
375 | |
376 | static ssize_t role_show(struct device *dev, struct device_attribute *attr, |
377 | char *buf) |
378 | { |
379 | struct rcar_gen3_chan *ch = dev_get_drvdata(dev); |
380 | |
381 | if (!ch->is_otg_channel || !rcar_gen3_is_any_rphy_initialized(ch)) |
382 | return -EIO; |
383 | |
384 | return sprintf(buf, fmt: "%s\n" , rcar_gen3_is_host(ch) ? "host" : |
385 | "peripheral" ); |
386 | } |
387 | static DEVICE_ATTR_RW(role); |
388 | |
389 | static void rcar_gen3_init_otg(struct rcar_gen3_chan *ch) |
390 | { |
391 | void __iomem *usb2_base = ch->base; |
392 | u32 val; |
393 | |
394 | /* Should not use functions of read-modify-write a register */ |
395 | val = readl(addr: usb2_base + USB2_LINECTRL1); |
396 | val = (val & ~USB2_LINECTRL1_DP_RPD) | USB2_LINECTRL1_DPRPD_EN | |
397 | USB2_LINECTRL1_DMRPD_EN | USB2_LINECTRL1_DM_RPD; |
398 | writel(val, addr: usb2_base + USB2_LINECTRL1); |
399 | |
400 | if (!ch->soc_no_adp_ctrl) { |
401 | val = readl(addr: usb2_base + USB2_VBCTRL); |
402 | val &= ~USB2_VBCTRL_OCCLREN; |
403 | writel(val: val | USB2_VBCTRL_DRVVBUSSEL, addr: usb2_base + USB2_VBCTRL); |
404 | val = readl(addr: usb2_base + USB2_ADPCTRL); |
405 | writel(val: val | USB2_ADPCTRL_IDPULLUP, addr: usb2_base + USB2_ADPCTRL); |
406 | } |
407 | msleep(msecs: 20); |
408 | |
409 | writel(val: 0xffffffff, addr: usb2_base + USB2_OBINTSTA); |
410 | writel(val: ch->obint_enable_bits, addr: usb2_base + USB2_OBINTEN); |
411 | |
412 | rcar_gen3_device_recognition(ch); |
413 | } |
414 | |
415 | static irqreturn_t rcar_gen3_phy_usb2_irq(int irq, void *_ch) |
416 | { |
417 | struct rcar_gen3_chan *ch = _ch; |
418 | void __iomem *usb2_base = ch->base; |
419 | u32 status = readl(addr: usb2_base + USB2_OBINTSTA); |
420 | irqreturn_t ret = IRQ_NONE; |
421 | |
422 | if (status & ch->obint_enable_bits) { |
423 | dev_vdbg(ch->dev, "%s: %08x\n" , __func__, status); |
424 | writel(val: ch->obint_enable_bits, addr: usb2_base + USB2_OBINTSTA); |
425 | rcar_gen3_device_recognition(ch); |
426 | ret = IRQ_HANDLED; |
427 | } |
428 | |
429 | return ret; |
430 | } |
431 | |
432 | static int rcar_gen3_phy_usb2_init(struct phy *p) |
433 | { |
434 | struct rcar_gen3_phy *rphy = phy_get_drvdata(phy: p); |
435 | struct rcar_gen3_chan *channel = rphy->ch; |
436 | void __iomem *usb2_base = channel->base; |
437 | u32 val; |
438 | int ret; |
439 | |
440 | if (!rcar_gen3_is_any_rphy_initialized(ch: channel) && channel->irq >= 0) { |
441 | INIT_WORK(&channel->work, rcar_gen3_phy_usb2_work); |
442 | ret = request_irq(irq: channel->irq, handler: rcar_gen3_phy_usb2_irq, |
443 | IRQF_SHARED, name: dev_name(dev: channel->dev), dev: channel); |
444 | if (ret < 0) { |
445 | dev_err(channel->dev, "No irq handler (%d)\n" , channel->irq); |
446 | return ret; |
447 | } |
448 | } |
449 | |
450 | /* Initialize USB2 part */ |
451 | val = readl(addr: usb2_base + USB2_INT_ENABLE); |
452 | val |= USB2_INT_ENABLE_UCOM_INTEN | rphy->int_enable_bits; |
453 | writel(val, addr: usb2_base + USB2_INT_ENABLE); |
454 | writel(USB2_SPD_RSM_TIMSET_INIT, addr: usb2_base + USB2_SPD_RSM_TIMSET); |
455 | writel(USB2_OC_TIMSET_INIT, addr: usb2_base + USB2_OC_TIMSET); |
456 | |
457 | /* Initialize otg part */ |
458 | if (channel->is_otg_channel) { |
459 | if (rcar_gen3_needs_init_otg(ch: channel)) |
460 | rcar_gen3_init_otg(ch: channel); |
461 | rphy->otg_initialized = true; |
462 | } |
463 | |
464 | rphy->initialized = true; |
465 | |
466 | return 0; |
467 | } |
468 | |
469 | static int rcar_gen3_phy_usb2_exit(struct phy *p) |
470 | { |
471 | struct rcar_gen3_phy *rphy = phy_get_drvdata(phy: p); |
472 | struct rcar_gen3_chan *channel = rphy->ch; |
473 | void __iomem *usb2_base = channel->base; |
474 | u32 val; |
475 | |
476 | rphy->initialized = false; |
477 | |
478 | if (channel->is_otg_channel) |
479 | rphy->otg_initialized = false; |
480 | |
481 | val = readl(addr: usb2_base + USB2_INT_ENABLE); |
482 | val &= ~rphy->int_enable_bits; |
483 | if (!rcar_gen3_is_any_rphy_initialized(ch: channel)) |
484 | val &= ~USB2_INT_ENABLE_UCOM_INTEN; |
485 | writel(val, addr: usb2_base + USB2_INT_ENABLE); |
486 | |
487 | if (channel->irq >= 0 && !rcar_gen3_is_any_rphy_initialized(ch: channel)) |
488 | free_irq(channel->irq, channel); |
489 | |
490 | return 0; |
491 | } |
492 | |
493 | static int rcar_gen3_phy_usb2_power_on(struct phy *p) |
494 | { |
495 | struct rcar_gen3_phy *rphy = phy_get_drvdata(phy: p); |
496 | struct rcar_gen3_chan *channel = rphy->ch; |
497 | void __iomem *usb2_base = channel->base; |
498 | u32 val; |
499 | int ret = 0; |
500 | |
501 | mutex_lock(&channel->lock); |
502 | if (!rcar_gen3_are_all_rphys_power_off(ch: channel)) |
503 | goto out; |
504 | |
505 | if (channel->vbus) { |
506 | ret = regulator_enable(regulator: channel->vbus); |
507 | if (ret) |
508 | goto out; |
509 | } |
510 | |
511 | val = readl(addr: usb2_base + USB2_USBCTR); |
512 | val |= USB2_USBCTR_PLL_RST; |
513 | writel(val, addr: usb2_base + USB2_USBCTR); |
514 | val &= ~USB2_USBCTR_PLL_RST; |
515 | writel(val, addr: usb2_base + USB2_USBCTR); |
516 | |
517 | out: |
518 | /* The powered flag should be set for any other phys anyway */ |
519 | rphy->powered = true; |
520 | mutex_unlock(lock: &channel->lock); |
521 | |
522 | return 0; |
523 | } |
524 | |
525 | static int rcar_gen3_phy_usb2_power_off(struct phy *p) |
526 | { |
527 | struct rcar_gen3_phy *rphy = phy_get_drvdata(phy: p); |
528 | struct rcar_gen3_chan *channel = rphy->ch; |
529 | int ret = 0; |
530 | |
531 | mutex_lock(&channel->lock); |
532 | rphy->powered = false; |
533 | |
534 | if (!rcar_gen3_are_all_rphys_power_off(ch: channel)) |
535 | goto out; |
536 | |
537 | if (channel->vbus) |
538 | ret = regulator_disable(regulator: channel->vbus); |
539 | |
540 | out: |
541 | mutex_unlock(lock: &channel->lock); |
542 | |
543 | return ret; |
544 | } |
545 | |
546 | static const struct phy_ops rcar_gen3_phy_usb2_ops = { |
547 | .init = rcar_gen3_phy_usb2_init, |
548 | .exit = rcar_gen3_phy_usb2_exit, |
549 | .power_on = rcar_gen3_phy_usb2_power_on, |
550 | .power_off = rcar_gen3_phy_usb2_power_off, |
551 | .owner = THIS_MODULE, |
552 | }; |
553 | |
554 | static const struct phy_ops rz_g1c_phy_usb2_ops = { |
555 | .init = rcar_gen3_phy_usb2_init, |
556 | .exit = rcar_gen3_phy_usb2_exit, |
557 | .owner = THIS_MODULE, |
558 | }; |
559 | |
560 | static const struct rcar_gen3_phy_drv_data rcar_gen3_phy_usb2_data = { |
561 | .phy_usb2_ops = &rcar_gen3_phy_usb2_ops, |
562 | .no_adp_ctrl = false, |
563 | }; |
564 | |
565 | static const struct rcar_gen3_phy_drv_data rz_g1c_phy_usb2_data = { |
566 | .phy_usb2_ops = &rz_g1c_phy_usb2_ops, |
567 | .no_adp_ctrl = false, |
568 | }; |
569 | |
570 | static const struct rcar_gen3_phy_drv_data rz_g2l_phy_usb2_data = { |
571 | .phy_usb2_ops = &rcar_gen3_phy_usb2_ops, |
572 | .no_adp_ctrl = true, |
573 | }; |
574 | |
575 | static const struct of_device_id rcar_gen3_phy_usb2_match_table[] = { |
576 | { |
577 | .compatible = "renesas,usb2-phy-r8a77470" , |
578 | .data = &rz_g1c_phy_usb2_data, |
579 | }, |
580 | { |
581 | .compatible = "renesas,usb2-phy-r8a7795" , |
582 | .data = &rcar_gen3_phy_usb2_data, |
583 | }, |
584 | { |
585 | .compatible = "renesas,usb2-phy-r8a7796" , |
586 | .data = &rcar_gen3_phy_usb2_data, |
587 | }, |
588 | { |
589 | .compatible = "renesas,usb2-phy-r8a77965" , |
590 | .data = &rcar_gen3_phy_usb2_data, |
591 | }, |
592 | { |
593 | .compatible = "renesas,rzg2l-usb2-phy" , |
594 | .data = &rz_g2l_phy_usb2_data, |
595 | }, |
596 | { |
597 | .compatible = "renesas,rcar-gen3-usb2-phy" , |
598 | .data = &rcar_gen3_phy_usb2_data, |
599 | }, |
600 | { /* sentinel */ }, |
601 | }; |
602 | MODULE_DEVICE_TABLE(of, rcar_gen3_phy_usb2_match_table); |
603 | |
604 | static const unsigned int rcar_gen3_phy_cable[] = { |
605 | EXTCON_USB, |
606 | EXTCON_USB_HOST, |
607 | EXTCON_NONE, |
608 | }; |
609 | |
610 | static struct phy *rcar_gen3_phy_usb2_xlate(struct device *dev, |
611 | const struct of_phandle_args *args) |
612 | { |
613 | struct rcar_gen3_chan *ch = dev_get_drvdata(dev); |
614 | |
615 | if (args->args_count == 0) /* For old version dts */ |
616 | return ch->rphys[PHY_INDEX_BOTH_HC].phy; |
617 | else if (args->args_count > 1) /* Prevent invalid args count */ |
618 | return ERR_PTR(error: -ENODEV); |
619 | |
620 | if (args->args[0] >= NUM_OF_PHYS) |
621 | return ERR_PTR(error: -ENODEV); |
622 | |
623 | return ch->rphys[args->args[0]].phy; |
624 | } |
625 | |
626 | static enum usb_dr_mode rcar_gen3_get_dr_mode(struct device_node *np) |
627 | { |
628 | enum usb_dr_mode candidate = USB_DR_MODE_UNKNOWN; |
629 | int i; |
630 | |
631 | /* |
632 | * If one of device nodes has other dr_mode except UNKNOWN, |
633 | * this function returns UNKNOWN. To achieve backward compatibility, |
634 | * this loop starts the index as 0. |
635 | */ |
636 | for (i = 0; i < NUM_OF_PHYS; i++) { |
637 | enum usb_dr_mode mode = of_usb_get_dr_mode_by_phy(np, arg0: i); |
638 | |
639 | if (mode != USB_DR_MODE_UNKNOWN) { |
640 | if (candidate == USB_DR_MODE_UNKNOWN) |
641 | candidate = mode; |
642 | else if (candidate != mode) |
643 | return USB_DR_MODE_UNKNOWN; |
644 | } |
645 | } |
646 | |
647 | return candidate; |
648 | } |
649 | |
650 | static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev) |
651 | { |
652 | const struct rcar_gen3_phy_drv_data *phy_data; |
653 | struct device *dev = &pdev->dev; |
654 | struct rcar_gen3_chan *channel; |
655 | struct phy_provider *provider; |
656 | int ret = 0, i; |
657 | |
658 | if (!dev->of_node) { |
659 | dev_err(dev, "This driver needs device tree\n" ); |
660 | return -EINVAL; |
661 | } |
662 | |
663 | channel = devm_kzalloc(dev, size: sizeof(*channel), GFP_KERNEL); |
664 | if (!channel) |
665 | return -ENOMEM; |
666 | |
667 | channel->base = devm_platform_ioremap_resource(pdev, index: 0); |
668 | if (IS_ERR(ptr: channel->base)) |
669 | return PTR_ERR(ptr: channel->base); |
670 | |
671 | channel->obint_enable_bits = USB2_OBINT_BITS; |
672 | /* get irq number here and request_irq for OTG in phy_init */ |
673 | channel->irq = platform_get_irq_optional(pdev, 0); |
674 | channel->dr_mode = rcar_gen3_get_dr_mode(np: dev->of_node); |
675 | if (channel->dr_mode != USB_DR_MODE_UNKNOWN) { |
676 | channel->is_otg_channel = true; |
677 | channel->uses_otg_pins = !of_property_read_bool(np: dev->of_node, |
678 | propname: "renesas,no-otg-pins" ); |
679 | channel->extcon = devm_extcon_dev_allocate(dev, |
680 | cable: rcar_gen3_phy_cable); |
681 | if (IS_ERR(ptr: channel->extcon)) |
682 | return PTR_ERR(ptr: channel->extcon); |
683 | |
684 | ret = devm_extcon_dev_register(dev, edev: channel->extcon); |
685 | if (ret < 0) { |
686 | dev_err(dev, "Failed to register extcon\n" ); |
687 | return ret; |
688 | } |
689 | } |
690 | |
691 | /* |
692 | * devm_phy_create() will call pm_runtime_enable(&phy->dev); |
693 | * And then, phy-core will manage runtime pm for this device. |
694 | */ |
695 | pm_runtime_enable(dev); |
696 | |
697 | phy_data = of_device_get_match_data(dev); |
698 | if (!phy_data) { |
699 | ret = -EINVAL; |
700 | goto error; |
701 | } |
702 | |
703 | channel->soc_no_adp_ctrl = phy_data->no_adp_ctrl; |
704 | if (phy_data->no_adp_ctrl) |
705 | channel->obint_enable_bits = USB2_OBINT_IDCHG_EN; |
706 | |
707 | mutex_init(&channel->lock); |
708 | for (i = 0; i < NUM_OF_PHYS; i++) { |
709 | channel->rphys[i].phy = devm_phy_create(dev, NULL, |
710 | ops: phy_data->phy_usb2_ops); |
711 | if (IS_ERR(ptr: channel->rphys[i].phy)) { |
712 | dev_err(dev, "Failed to create USB2 PHY\n" ); |
713 | ret = PTR_ERR(ptr: channel->rphys[i].phy); |
714 | goto error; |
715 | } |
716 | channel->rphys[i].ch = channel; |
717 | channel->rphys[i].int_enable_bits = rcar_gen3_int_enable[i]; |
718 | phy_set_drvdata(phy: channel->rphys[i].phy, data: &channel->rphys[i]); |
719 | } |
720 | |
721 | channel->vbus = devm_regulator_get_optional(dev, id: "vbus" ); |
722 | if (IS_ERR(ptr: channel->vbus)) { |
723 | if (PTR_ERR(ptr: channel->vbus) == -EPROBE_DEFER) { |
724 | ret = PTR_ERR(ptr: channel->vbus); |
725 | goto error; |
726 | } |
727 | channel->vbus = NULL; |
728 | } |
729 | |
730 | platform_set_drvdata(pdev, data: channel); |
731 | channel->dev = dev; |
732 | |
733 | provider = devm_of_phy_provider_register(dev, rcar_gen3_phy_usb2_xlate); |
734 | if (IS_ERR(ptr: provider)) { |
735 | dev_err(dev, "Failed to register PHY provider\n" ); |
736 | ret = PTR_ERR(ptr: provider); |
737 | goto error; |
738 | } else if (channel->is_otg_channel) { |
739 | ret = device_create_file(device: dev, entry: &dev_attr_role); |
740 | if (ret < 0) |
741 | goto error; |
742 | } |
743 | |
744 | return 0; |
745 | |
746 | error: |
747 | pm_runtime_disable(dev); |
748 | |
749 | return ret; |
750 | } |
751 | |
752 | static void rcar_gen3_phy_usb2_remove(struct platform_device *pdev) |
753 | { |
754 | struct rcar_gen3_chan *channel = platform_get_drvdata(pdev); |
755 | |
756 | if (channel->is_otg_channel) |
757 | device_remove_file(dev: &pdev->dev, attr: &dev_attr_role); |
758 | |
759 | pm_runtime_disable(dev: &pdev->dev); |
760 | }; |
761 | |
762 | static struct platform_driver rcar_gen3_phy_usb2_driver = { |
763 | .driver = { |
764 | .name = "phy_rcar_gen3_usb2" , |
765 | .of_match_table = rcar_gen3_phy_usb2_match_table, |
766 | }, |
767 | .probe = rcar_gen3_phy_usb2_probe, |
768 | .remove_new = rcar_gen3_phy_usb2_remove, |
769 | }; |
770 | module_platform_driver(rcar_gen3_phy_usb2_driver); |
771 | |
772 | MODULE_LICENSE("GPL v2" ); |
773 | MODULE_DESCRIPTION("Renesas R-Car Gen3 USB 2.0 PHY" ); |
774 | MODULE_AUTHOR("Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>" ); |
775 | |