diff options
author | Ulrich Hecht <ulrich.hecht@gmail.com> | 2014-07-10 03:53:59 -0400 |
---|---|---|
committer | Felipe Balbi <balbi@ti.com> | 2014-07-16 11:06:32 -0400 |
commit | 8ecef00fe1f33658ee36e902dba6850b51312073 (patch) | |
tree | 208ab3f29e228e55fabac17423413d528152f7fa /drivers/usb/renesas_usbhs | |
parent | f2267089ea17fa97b796b1b4247e3f8957655df3 (diff) |
usb: renesas_usbhs: add R-Car Gen. 2 init and power control
In preparation for DT conversion to reduce reliance on platform device
callbacks.
Signed-off-by: Ulrich Hecht <ulrich.hecht+renesas@gmail.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
Diffstat (limited to 'drivers/usb/renesas_usbhs')
-rw-r--r-- | drivers/usb/renesas_usbhs/Makefile | 2 | ||||
-rw-r--r-- | drivers/usb/renesas_usbhs/common.c | 66 | ||||
-rw-r--r-- | drivers/usb/renesas_usbhs/common.h | 2 | ||||
-rw-r--r-- | drivers/usb/renesas_usbhs/rcar2.c | 77 | ||||
-rw-r--r-- | drivers/usb/renesas_usbhs/rcar2.h | 4 |
5 files changed, 145 insertions, 6 deletions
diff --git a/drivers/usb/renesas_usbhs/Makefile b/drivers/usb/renesas_usbhs/Makefile index bc8aef4311a1..9e47f477b6d2 100644 --- a/drivers/usb/renesas_usbhs/Makefile +++ b/drivers/usb/renesas_usbhs/Makefile | |||
@@ -4,7 +4,7 @@ | |||
4 | 4 | ||
5 | obj-$(CONFIG_USB_RENESAS_USBHS) += renesas_usbhs.o | 5 | obj-$(CONFIG_USB_RENESAS_USBHS) += renesas_usbhs.o |
6 | 6 | ||
7 | renesas_usbhs-y := common.o mod.o pipe.o fifo.o | 7 | renesas_usbhs-y := common.o mod.o pipe.o fifo.o rcar2.o |
8 | 8 | ||
9 | ifneq ($(CONFIG_USB_RENESAS_USBHS_HCD),) | 9 | ifneq ($(CONFIG_USB_RENESAS_USBHS_HCD),) |
10 | renesas_usbhs-y += mod_host.o | 10 | renesas_usbhs-y += mod_host.o |
diff --git a/drivers/usb/renesas_usbhs/common.c b/drivers/usb/renesas_usbhs/common.c index 17267b0a2e95..1b9bf8d83235 100644 --- a/drivers/usb/renesas_usbhs/common.c +++ b/drivers/usb/renesas_usbhs/common.c | |||
@@ -15,12 +15,14 @@ | |||
15 | * | 15 | * |
16 | */ | 16 | */ |
17 | #include <linux/err.h> | 17 | #include <linux/err.h> |
18 | #include <linux/gpio.h> | ||
18 | #include <linux/io.h> | 19 | #include <linux/io.h> |
19 | #include <linux/module.h> | 20 | #include <linux/module.h> |
20 | #include <linux/pm_runtime.h> | 21 | #include <linux/pm_runtime.h> |
21 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
22 | #include <linux/sysfs.h> | 23 | #include <linux/sysfs.h> |
23 | #include "common.h" | 24 | #include "common.h" |
25 | #include "rcar2.h" | ||
24 | 26 | ||
25 | /* | 27 | /* |
26 | * image of renesas_usbhs | 28 | * image of renesas_usbhs |
@@ -284,6 +286,8 @@ static void usbhsc_set_buswait(struct usbhs_priv *priv) | |||
284 | /* | 286 | /* |
285 | * platform default param | 287 | * platform default param |
286 | */ | 288 | */ |
289 | |||
290 | /* commonly used on old SH-Mobile SoCs */ | ||
287 | static u32 usbhsc_default_pipe_type[] = { | 291 | static u32 usbhsc_default_pipe_type[] = { |
288 | USB_ENDPOINT_XFER_CONTROL, | 292 | USB_ENDPOINT_XFER_CONTROL, |
289 | USB_ENDPOINT_XFER_ISOC, | 293 | USB_ENDPOINT_XFER_ISOC, |
@@ -297,6 +301,26 @@ static u32 usbhsc_default_pipe_type[] = { | |||
297 | USB_ENDPOINT_XFER_INT, | 301 | USB_ENDPOINT_XFER_INT, |
298 | }; | 302 | }; |
299 | 303 | ||
304 | /* commonly used on newer SH-Mobile and R-Car SoCs */ | ||
305 | static u32 usbhsc_new_pipe_type[] = { | ||
306 | USB_ENDPOINT_XFER_CONTROL, | ||
307 | USB_ENDPOINT_XFER_ISOC, | ||
308 | USB_ENDPOINT_XFER_ISOC, | ||
309 | USB_ENDPOINT_XFER_BULK, | ||
310 | USB_ENDPOINT_XFER_BULK, | ||
311 | USB_ENDPOINT_XFER_BULK, | ||
312 | USB_ENDPOINT_XFER_INT, | ||
313 | USB_ENDPOINT_XFER_INT, | ||
314 | USB_ENDPOINT_XFER_INT, | ||
315 | USB_ENDPOINT_XFER_BULK, | ||
316 | USB_ENDPOINT_XFER_BULK, | ||
317 | USB_ENDPOINT_XFER_BULK, | ||
318 | USB_ENDPOINT_XFER_BULK, | ||
319 | USB_ENDPOINT_XFER_BULK, | ||
320 | USB_ENDPOINT_XFER_BULK, | ||
321 | USB_ENDPOINT_XFER_BULK, | ||
322 | }; | ||
323 | |||
300 | /* | 324 | /* |
301 | * power control | 325 | * power control |
302 | */ | 326 | */ |
@@ -423,8 +447,7 @@ static int usbhs_probe(struct platform_device *pdev) | |||
423 | int ret; | 447 | int ret; |
424 | 448 | ||
425 | /* check platform information */ | 449 | /* check platform information */ |
426 | if (!info || | 450 | if (!info) { |
427 | !info->platform_callback.get_id) { | ||
428 | dev_err(&pdev->dev, "no platform information\n"); | 451 | dev_err(&pdev->dev, "no platform information\n"); |
429 | return -EINVAL; | 452 | return -EINVAL; |
430 | } | 453 | } |
@@ -451,13 +474,32 @@ static int usbhs_probe(struct platform_device *pdev) | |||
451 | /* | 474 | /* |
452 | * care platform info | 475 | * care platform info |
453 | */ | 476 | */ |
454 | memcpy(&priv->pfunc, | 477 | |
455 | &info->platform_callback, | ||
456 | sizeof(struct renesas_usbhs_platform_callback)); | ||
457 | memcpy(&priv->dparam, | 478 | memcpy(&priv->dparam, |
458 | &info->driver_param, | 479 | &info->driver_param, |
459 | sizeof(struct renesas_usbhs_driver_param)); | 480 | sizeof(struct renesas_usbhs_driver_param)); |
460 | 481 | ||
482 | switch (priv->dparam.type) { | ||
483 | case USBHS_TYPE_R8A7790: | ||
484 | case USBHS_TYPE_R8A7791: | ||
485 | priv->pfunc = usbhs_rcar2_ops; | ||
486 | if (!priv->dparam.pipe_type) { | ||
487 | priv->dparam.pipe_type = usbhsc_new_pipe_type; | ||
488 | priv->dparam.pipe_size = | ||
489 | ARRAY_SIZE(usbhsc_new_pipe_type); | ||
490 | } | ||
491 | break; | ||
492 | default: | ||
493 | if (!info->platform_callback.get_id) { | ||
494 | dev_err(&pdev->dev, "no platform callbacks"); | ||
495 | return -EINVAL; | ||
496 | } | ||
497 | memcpy(&priv->pfunc, | ||
498 | &info->platform_callback, | ||
499 | sizeof(struct renesas_usbhs_platform_callback)); | ||
500 | break; | ||
501 | } | ||
502 | |||
461 | /* set driver callback functions for platform */ | 503 | /* set driver callback functions for platform */ |
462 | dfunc = &info->driver_callback; | 504 | dfunc = &info->driver_callback; |
463 | dfunc->notify_hotplug = usbhsc_drvcllbck_notify_hotplug; | 505 | dfunc->notify_hotplug = usbhsc_drvcllbck_notify_hotplug; |
@@ -507,6 +549,20 @@ static int usbhs_probe(struct platform_device *pdev) | |||
507 | */ | 549 | */ |
508 | usbhs_sys_clock_ctrl(priv, 0); | 550 | usbhs_sys_clock_ctrl(priv, 0); |
509 | 551 | ||
552 | /* check GPIO determining if USB function should be enabled */ | ||
553 | if (priv->dparam.enable_gpio) { | ||
554 | gpio_request_one(priv->dparam.enable_gpio, GPIOF_IN, NULL); | ||
555 | ret = !gpio_get_value(priv->dparam.enable_gpio); | ||
556 | gpio_free(priv->dparam.enable_gpio); | ||
557 | if (ret) { | ||
558 | dev_warn(&pdev->dev, | ||
559 | "USB function not selected (GPIO %d)\n", | ||
560 | priv->dparam.enable_gpio); | ||
561 | ret = -ENOTSUPP; | ||
562 | goto probe_end_mod_exit; | ||
563 | } | ||
564 | } | ||
565 | |||
510 | /* | 566 | /* |
511 | * platform call | 567 | * platform call |
512 | * | 568 | * |
diff --git a/drivers/usb/renesas_usbhs/common.h b/drivers/usb/renesas_usbhs/common.h index c69dd2fba360..a7996da6a1bd 100644 --- a/drivers/usb/renesas_usbhs/common.h +++ b/drivers/usb/renesas_usbhs/common.h | |||
@@ -268,6 +268,8 @@ struct usbhs_priv { | |||
268 | * fifo control | 268 | * fifo control |
269 | */ | 269 | */ |
270 | struct usbhs_fifo_info fifo_info; | 270 | struct usbhs_fifo_info fifo_info; |
271 | |||
272 | struct usb_phy *phy; | ||
271 | }; | 273 | }; |
272 | 274 | ||
273 | /* | 275 | /* |
diff --git a/drivers/usb/renesas_usbhs/rcar2.c b/drivers/usb/renesas_usbhs/rcar2.c new file mode 100644 index 000000000000..e6b9dcc1c289 --- /dev/null +++ b/drivers/usb/renesas_usbhs/rcar2.c | |||
@@ -0,0 +1,77 @@ | |||
1 | /* | ||
2 | * Renesas USB driver R-Car Gen. 2 initialization and power control | ||
3 | * | ||
4 | * Copyright (C) 2014 Ulrich Hecht | ||
5 | * | ||
6 | * This program is distributed in the hope that it will be useful, | ||
7 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
8 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
9 | * GNU General Public License for more details. | ||
10 | * | ||
11 | */ | ||
12 | |||
13 | #include <linux/gpio.h> | ||
14 | #include <linux/of_gpio.h> | ||
15 | #include <linux/platform_data/gpio-rcar.h> | ||
16 | #include <linux/usb/phy.h> | ||
17 | #include "common.h" | ||
18 | #include "rcar2.h" | ||
19 | |||
20 | static int usbhs_rcar2_hardware_init(struct platform_device *pdev) | ||
21 | { | ||
22 | struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev); | ||
23 | struct usb_phy *phy; | ||
24 | |||
25 | phy = usb_get_phy_dev(&pdev->dev, 0); | ||
26 | if (IS_ERR(phy)) | ||
27 | return PTR_ERR(phy); | ||
28 | |||
29 | priv->phy = phy; | ||
30 | return 0; | ||
31 | } | ||
32 | |||
33 | static int usbhs_rcar2_hardware_exit(struct platform_device *pdev) | ||
34 | { | ||
35 | struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev); | ||
36 | |||
37 | if (!priv->phy) | ||
38 | return 0; | ||
39 | |||
40 | usb_put_phy(priv->phy); | ||
41 | priv->phy = NULL; | ||
42 | |||
43 | return 0; | ||
44 | } | ||
45 | |||
46 | static int usbhs_rcar2_power_ctrl(struct platform_device *pdev, | ||
47 | void __iomem *base, int enable) | ||
48 | { | ||
49 | struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev); | ||
50 | |||
51 | if (!priv->phy) | ||
52 | return -ENODEV; | ||
53 | |||
54 | if (enable) { | ||
55 | int retval = usb_phy_init(priv->phy); | ||
56 | |||
57 | if (!retval) | ||
58 | retval = usb_phy_set_suspend(priv->phy, 0); | ||
59 | return retval; | ||
60 | } | ||
61 | |||
62 | usb_phy_set_suspend(priv->phy, 1); | ||
63 | usb_phy_shutdown(priv->phy); | ||
64 | return 0; | ||
65 | } | ||
66 | |||
67 | static int usbhs_rcar2_get_id(struct platform_device *pdev) | ||
68 | { | ||
69 | return USBHS_GADGET; | ||
70 | } | ||
71 | |||
72 | const struct renesas_usbhs_platform_callback usbhs_rcar2_ops = { | ||
73 | .hardware_init = usbhs_rcar2_hardware_init, | ||
74 | .hardware_exit = usbhs_rcar2_hardware_exit, | ||
75 | .power_ctrl = usbhs_rcar2_power_ctrl, | ||
76 | .get_id = usbhs_rcar2_get_id, | ||
77 | }; | ||
diff --git a/drivers/usb/renesas_usbhs/rcar2.h b/drivers/usb/renesas_usbhs/rcar2.h new file mode 100644 index 000000000000..f07f10d9b3b2 --- /dev/null +++ b/drivers/usb/renesas_usbhs/rcar2.h | |||
@@ -0,0 +1,4 @@ | |||
1 | #include "common.h" | ||
2 | |||
3 | extern const struct renesas_usbhs_platform_callback | ||
4 | usbhs_rcar2_ops; | ||