Commit | Line | Data |
---|---|---|
8ecef00f UH |
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> | |
420974a0 | 15 | #include <linux/phy/phy.h> |
8ecef00f UH |
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); | |
8ecef00f | 23 | |
420974a0 YS |
24 | if (IS_ENABLED(CONFIG_GENERIC_PHY)) { |
25 | struct phy *phy = phy_get(&pdev->dev, "usb"); | |
26 | ||
27 | if (IS_ERR(phy)) | |
28 | return PTR_ERR(phy); | |
29 | ||
30 | priv->phy = phy; | |
31 | return 0; | |
32 | } | |
33 | ||
5f6aea34 YS |
34 | if (IS_ENABLED(CONFIG_USB_PHY)) { |
35 | struct usb_phy *usb_phy = usb_get_phy_dev(&pdev->dev, 0); | |
8ecef00f | 36 | |
5f6aea34 YS |
37 | if (IS_ERR(usb_phy)) |
38 | return PTR_ERR(usb_phy); | |
39 | ||
40 | priv->usb_phy = usb_phy; | |
41 | return 0; | |
42 | } | |
43 | ||
44 | return -ENXIO; | |
8ecef00f UH |
45 | } |
46 | ||
47 | static int usbhs_rcar2_hardware_exit(struct platform_device *pdev) | |
48 | { | |
49 | struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev); | |
50 | ||
420974a0 YS |
51 | if (priv->phy) { |
52 | phy_put(priv->phy); | |
53 | priv->phy = NULL; | |
54 | } | |
55 | ||
5f6aea34 YS |
56 | if (priv->usb_phy) { |
57 | usb_put_phy(priv->usb_phy); | |
58 | priv->usb_phy = NULL; | |
59 | } | |
8ecef00f UH |
60 | |
61 | return 0; | |
62 | } | |
63 | ||
64 | static int usbhs_rcar2_power_ctrl(struct platform_device *pdev, | |
65 | void __iomem *base, int enable) | |
66 | { | |
67 | struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev); | |
5f6aea34 | 68 | int retval = -ENODEV; |
8ecef00f | 69 | |
420974a0 YS |
70 | if (priv->phy) { |
71 | if (enable) { | |
72 | retval = phy_init(priv->phy); | |
73 | ||
74 | if (!retval) | |
75 | retval = phy_power_on(priv->phy); | |
76 | } else { | |
77 | phy_power_off(priv->phy); | |
78 | phy_exit(priv->phy); | |
79 | retval = 0; | |
80 | } | |
81 | } | |
82 | ||
5f6aea34 YS |
83 | if (priv->usb_phy) { |
84 | if (enable) { | |
85 | retval = usb_phy_init(priv->usb_phy); | |
8ecef00f | 86 | |
5f6aea34 YS |
87 | if (!retval) |
88 | retval = usb_phy_set_suspend(priv->usb_phy, 0); | |
89 | } else { | |
90 | usb_phy_set_suspend(priv->usb_phy, 1); | |
91 | usb_phy_shutdown(priv->usb_phy); | |
92 | retval = 0; | |
93 | } | |
8ecef00f UH |
94 | } |
95 | ||
5f6aea34 | 96 | return retval; |
8ecef00f UH |
97 | } |
98 | ||
99 | static int usbhs_rcar2_get_id(struct platform_device *pdev) | |
100 | { | |
101 | return USBHS_GADGET; | |
102 | } | |
103 | ||
104 | const struct renesas_usbhs_platform_callback usbhs_rcar2_ops = { | |
105 | .hardware_init = usbhs_rcar2_hardware_init, | |
106 | .hardware_exit = usbhs_rcar2_hardware_exit, | |
107 | .power_ctrl = usbhs_rcar2_power_ctrl, | |
108 | .get_id = usbhs_rcar2_get_id, | |
109 | }; |