aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/musb/omap2430.c2
-rw-r--r--drivers/usb/phy/Kconfig21
-rw-r--r--drivers/usb/phy/Makefile2
-rw-r--r--drivers/usb/phy/phy-omap-control.c319
-rw-r--r--drivers/usb/phy/phy-omap-usb3.c361
-rw-r--r--drivers/usb/phy/phy-twl6030-usb.c2
6 files changed, 2 insertions, 705 deletions
diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c
index 8aa59a2c5eb2..d341c149a2f9 100644
--- a/drivers/usb/musb/omap2430.c
+++ b/drivers/usb/musb/omap2430.c
@@ -37,7 +37,7 @@
37#include <linux/err.h> 37#include <linux/err.h>
38#include <linux/delay.h> 38#include <linux/delay.h>
39#include <linux/usb/musb-omap.h> 39#include <linux/usb/musb-omap.h>
40#include <linux/usb/omap_control_usb.h> 40#include <linux/phy/omap_control_phy.h>
41#include <linux/of_platform.h> 41#include <linux/of_platform.h>
42 42
43#include "musb_core.h" 43#include "musb_core.h"
diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig
index 7d1451d5bbea..416e0c8cf6ff 100644
--- a/drivers/usb/phy/Kconfig
+++ b/drivers/usb/phy/Kconfig
@@ -75,27 +75,6 @@ config NOP_USB_XCEIV
75 built-in with usb ip or which are autonomous and doesn't require any 75 built-in with usb ip or which are autonomous and doesn't require any
76 phy programming such as ISP1x04 etc. 76 phy programming such as ISP1x04 etc.
77 77
78config OMAP_CONTROL_USB
79 tristate "OMAP CONTROL USB Driver"
80 depends on ARCH_OMAP2PLUS || COMPILE_TEST
81 help
82 Enable this to add support for the USB part present in the control
83 module. This driver has API to power on the USB2 PHY and to write to
84 the mailbox. The mailbox is present only in omap4 and the register to
85 power on the USB2 PHY is present in OMAP4 and OMAP5. OMAP5 has an
86 additional register to power on USB3 PHY.
87
88config OMAP_USB3
89 tristate "OMAP USB3 PHY Driver"
90 depends on ARCH_OMAP2PLUS || COMPILE_TEST
91 select OMAP_CONTROL_USB
92 select USB_PHY
93 help
94 Enable this to support the USB3 PHY that is part of SOC. This
95 driver takes care of all the PHY functionality apart from comparator.
96 This driver interacts with the "OMAP Control USB Driver" to power
97 on/off the PHY.
98
99config AM335X_CONTROL_USB 78config AM335X_CONTROL_USB
100 tristate 79 tristate
101 80
diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile
index be58adae3496..f8fa719a31b9 100644
--- a/drivers/usb/phy/Makefile
+++ b/drivers/usb/phy/Makefile
@@ -13,11 +13,9 @@ obj-$(CONFIG_ISP1301_OMAP) += phy-isp1301-omap.o
13obj-$(CONFIG_MV_U3D_PHY) += phy-mv-u3d-usb.o 13obj-$(CONFIG_MV_U3D_PHY) += phy-mv-u3d-usb.o
14obj-$(CONFIG_NOP_USB_XCEIV) += phy-generic.o 14obj-$(CONFIG_NOP_USB_XCEIV) += phy-generic.o
15obj-$(CONFIG_TAHVO_USB) += phy-tahvo.o 15obj-$(CONFIG_TAHVO_USB) += phy-tahvo.o
16obj-$(CONFIG_OMAP_CONTROL_USB) += phy-omap-control.o
17obj-$(CONFIG_AM335X_CONTROL_USB) += phy-am335x-control.o 16obj-$(CONFIG_AM335X_CONTROL_USB) += phy-am335x-control.o
18obj-$(CONFIG_AM335X_PHY_USB) += phy-am335x.o 17obj-$(CONFIG_AM335X_PHY_USB) += phy-am335x.o
19obj-$(CONFIG_OMAP_OTG) += phy-omap-otg.o 18obj-$(CONFIG_OMAP_OTG) += phy-omap-otg.o
20obj-$(CONFIG_OMAP_USB3) += phy-omap-usb3.o
21obj-$(CONFIG_SAMSUNG_USBPHY) += phy-samsung-usb.o 19obj-$(CONFIG_SAMSUNG_USBPHY) += phy-samsung-usb.o
22obj-$(CONFIG_SAMSUNG_USB2PHY) += phy-samsung-usb2.o 20obj-$(CONFIG_SAMSUNG_USB2PHY) += phy-samsung-usb2.o
23obj-$(CONFIG_SAMSUNG_USB3PHY) += phy-samsung-usb3.o 21obj-$(CONFIG_SAMSUNG_USB3PHY) += phy-samsung-usb3.o
diff --git a/drivers/usb/phy/phy-omap-control.c b/drivers/usb/phy/phy-omap-control.c
deleted file mode 100644
index e7253182e47d..000000000000
--- a/drivers/usb/phy/phy-omap-control.c
+++ /dev/null
@@ -1,319 +0,0 @@
1/*
2 * omap-control-usb.c - The USB part of control module.
3 *
4 * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * Author: Kishon Vijay Abraham I <kishon@ti.com>
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 */
18
19#include <linux/module.h>
20#include <linux/platform_device.h>
21#include <linux/slab.h>
22#include <linux/of.h>
23#include <linux/of_device.h>
24#include <linux/err.h>
25#include <linux/io.h>
26#include <linux/clk.h>
27#include <linux/usb/omap_control_usb.h>
28
29/**
30 * omap_control_usb_phy_power - power on/off the phy using control module reg
31 * @dev: the control module device
32 * @on: 0 or 1, based on powering on or off the PHY
33 */
34void omap_control_usb_phy_power(struct device *dev, int on)
35{
36 u32 val;
37 unsigned long rate;
38 struct omap_control_usb *control_usb;
39
40 if (IS_ERR(dev) || !dev) {
41 pr_err("%s: invalid device\n", __func__);
42 return;
43 }
44
45 control_usb = dev_get_drvdata(dev);
46 if (!control_usb) {
47 dev_err(dev, "%s: invalid control usb device\n", __func__);
48 return;
49 }
50
51 if (control_usb->type == OMAP_CTRL_TYPE_OTGHS)
52 return;
53
54 val = readl(control_usb->power);
55
56 switch (control_usb->type) {
57 case OMAP_CTRL_TYPE_USB2:
58 if (on)
59 val &= ~OMAP_CTRL_DEV_PHY_PD;
60 else
61 val |= OMAP_CTRL_DEV_PHY_PD;
62 break;
63
64 case OMAP_CTRL_TYPE_PIPE3:
65 rate = clk_get_rate(control_usb->sys_clk);
66 rate = rate/1000000;
67
68 if (on) {
69 val &= ~(OMAP_CTRL_USB_PWRCTL_CLK_CMD_MASK |
70 OMAP_CTRL_USB_PWRCTL_CLK_FREQ_MASK);
71 val |= OMAP_CTRL_USB3_PHY_TX_RX_POWERON <<
72 OMAP_CTRL_USB_PWRCTL_CLK_CMD_SHIFT;
73 val |= rate << OMAP_CTRL_USB_PWRCTL_CLK_FREQ_SHIFT;
74 } else {
75 val &= ~OMAP_CTRL_USB_PWRCTL_CLK_CMD_MASK;
76 val |= OMAP_CTRL_USB3_PHY_TX_RX_POWEROFF <<
77 OMAP_CTRL_USB_PWRCTL_CLK_CMD_SHIFT;
78 }
79 break;
80
81 case OMAP_CTRL_TYPE_DRA7USB2:
82 if (on)
83 val &= ~OMAP_CTRL_USB2_PHY_PD;
84 else
85 val |= OMAP_CTRL_USB2_PHY_PD;
86 break;
87
88 case OMAP_CTRL_TYPE_AM437USB2:
89 if (on) {
90 val &= ~(AM437X_CTRL_USB2_PHY_PD |
91 AM437X_CTRL_USB2_OTG_PD);
92 val |= (AM437X_CTRL_USB2_OTGVDET_EN |
93 AM437X_CTRL_USB2_OTGSESSEND_EN);
94 } else {
95 val &= ~(AM437X_CTRL_USB2_OTGVDET_EN |
96 AM437X_CTRL_USB2_OTGSESSEND_EN);
97 val |= (AM437X_CTRL_USB2_PHY_PD |
98 AM437X_CTRL_USB2_OTG_PD);
99 }
100 break;
101 default:
102 dev_err(dev, "%s: type %d not recognized\n",
103 __func__, control_usb->type);
104 break;
105 }
106
107 writel(val, control_usb->power);
108}
109EXPORT_SYMBOL_GPL(omap_control_usb_phy_power);
110
111/**
112 * omap_control_usb_host_mode - set AVALID, VBUSVALID and ID pin in grounded
113 * @ctrl_usb: struct omap_control_usb *
114 *
115 * Writes to the mailbox register to notify the usb core that a usb
116 * device has been connected.
117 */
118static void omap_control_usb_host_mode(struct omap_control_usb *ctrl_usb)
119{
120 u32 val;
121
122 val = readl(ctrl_usb->otghs_control);
123 val &= ~(OMAP_CTRL_DEV_IDDIG | OMAP_CTRL_DEV_SESSEND);
124 val |= OMAP_CTRL_DEV_AVALID | OMAP_CTRL_DEV_VBUSVALID;
125 writel(val, ctrl_usb->otghs_control);
126}
127
128/**
129 * omap_control_usb_device_mode - set AVALID, VBUSVALID and ID pin in high
130 * impedance
131 * @ctrl_usb: struct omap_control_usb *
132 *
133 * Writes to the mailbox register to notify the usb core that it has been
134 * connected to a usb host.
135 */
136static void omap_control_usb_device_mode(struct omap_control_usb *ctrl_usb)
137{
138 u32 val;
139
140 val = readl(ctrl_usb->otghs_control);
141 val &= ~OMAP_CTRL_DEV_SESSEND;
142 val |= OMAP_CTRL_DEV_IDDIG | OMAP_CTRL_DEV_AVALID |
143 OMAP_CTRL_DEV_VBUSVALID;
144 writel(val, ctrl_usb->otghs_control);
145}
146
147/**
148 * omap_control_usb_set_sessionend - Enable SESSIONEND and IDIG to high
149 * impedance
150 * @ctrl_usb: struct omap_control_usb *
151 *
152 * Writes to the mailbox register to notify the usb core it's now in
153 * disconnected state.
154 */
155static void omap_control_usb_set_sessionend(struct omap_control_usb *ctrl_usb)
156{
157 u32 val;
158
159 val = readl(ctrl_usb->otghs_control);
160 val &= ~(OMAP_CTRL_DEV_AVALID | OMAP_CTRL_DEV_VBUSVALID);
161 val |= OMAP_CTRL_DEV_IDDIG | OMAP_CTRL_DEV_SESSEND;
162 writel(val, ctrl_usb->otghs_control);
163}
164
165/**
166 * omap_control_usb_set_mode - Calls to functions to set USB in one of host mode
167 * or device mode or to denote disconnected state
168 * @dev: the control module device
169 * @mode: The mode to which usb should be configured
170 *
171 * This is an API to write to the mailbox register to notify the usb core that
172 * a usb device has been connected.
173 */
174void omap_control_usb_set_mode(struct device *dev,
175 enum omap_control_usb_mode mode)
176{
177 struct omap_control_usb *ctrl_usb;
178
179 if (IS_ERR(dev) || !dev)
180 return;
181
182 ctrl_usb = dev_get_drvdata(dev);
183
184 if (!ctrl_usb) {
185 dev_err(dev, "Invalid control usb device\n");
186 return;
187 }
188
189 if (ctrl_usb->type != OMAP_CTRL_TYPE_OTGHS)
190 return;
191
192 switch (mode) {
193 case USB_MODE_HOST:
194 omap_control_usb_host_mode(ctrl_usb);
195 break;
196 case USB_MODE_DEVICE:
197 omap_control_usb_device_mode(ctrl_usb);
198 break;
199 case USB_MODE_DISCONNECT:
200 omap_control_usb_set_sessionend(ctrl_usb);
201 break;
202 default:
203 dev_vdbg(dev, "invalid omap control usb mode\n");
204 }
205}
206EXPORT_SYMBOL_GPL(omap_control_usb_set_mode);
207
208#ifdef CONFIG_OF
209
210static const enum omap_control_usb_type otghs_data = OMAP_CTRL_TYPE_OTGHS;
211static const enum omap_control_usb_type usb2_data = OMAP_CTRL_TYPE_USB2;
212static const enum omap_control_usb_type pipe3_data = OMAP_CTRL_TYPE_PIPE3;
213static const enum omap_control_usb_type dra7usb2_data = OMAP_CTRL_TYPE_DRA7USB2;
214static const enum omap_control_usb_type am437usb2_data = OMAP_CTRL_TYPE_AM437USB2;
215
216static const struct of_device_id omap_control_usb_id_table[] = {
217 {
218 .compatible = "ti,control-phy-otghs",
219 .data = &otghs_data,
220 },
221 {
222 .compatible = "ti,control-phy-usb2",
223 .data = &usb2_data,
224 },
225 {
226 .compatible = "ti,control-phy-pipe3",
227 .data = &pipe3_data,
228 },
229 {
230 .compatible = "ti,control-phy-dra7usb2",
231 .data = &dra7usb2_data,
232 },
233 {
234 .compatible = "ti,control-phy-am437usb2",
235 .data = &am437usb2_data,
236 },
237 {},
238};
239MODULE_DEVICE_TABLE(of, omap_control_usb_id_table);
240#endif
241
242
243static int omap_control_usb_probe(struct platform_device *pdev)
244{
245 struct resource *res;
246 const struct of_device_id *of_id;
247 struct omap_control_usb *control_usb;
248
249 of_id = of_match_device(of_match_ptr(omap_control_usb_id_table),
250 &pdev->dev);
251 if (!of_id)
252 return -EINVAL;
253
254 control_usb = devm_kzalloc(&pdev->dev, sizeof(*control_usb),
255 GFP_KERNEL);
256 if (!control_usb) {
257 dev_err(&pdev->dev, "unable to alloc memory for control usb\n");
258 return -ENOMEM;
259 }
260
261 control_usb->dev = &pdev->dev;
262 control_usb->type = *(enum omap_control_usb_type *)of_id->data;
263
264 if (control_usb->type == OMAP_CTRL_TYPE_OTGHS) {
265 res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
266 "otghs_control");
267 control_usb->otghs_control = devm_ioremap_resource(
268 &pdev->dev, res);
269 if (IS_ERR(control_usb->otghs_control))
270 return PTR_ERR(control_usb->otghs_control);
271 } else {
272 res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
273 "power");
274 control_usb->power = devm_ioremap_resource(&pdev->dev, res);
275 if (IS_ERR(control_usb->power)) {
276 dev_err(&pdev->dev, "Couldn't get power register\n");
277 return PTR_ERR(control_usb->power);
278 }
279 }
280
281 if (control_usb->type == OMAP_CTRL_TYPE_PIPE3) {
282 control_usb->sys_clk = devm_clk_get(control_usb->dev,
283 "sys_clkin");
284 if (IS_ERR(control_usb->sys_clk)) {
285 pr_err("%s: unable to get sys_clkin\n", __func__);
286 return -EINVAL;
287 }
288 }
289
290 dev_set_drvdata(control_usb->dev, control_usb);
291
292 return 0;
293}
294
295static struct platform_driver omap_control_usb_driver = {
296 .probe = omap_control_usb_probe,
297 .driver = {
298 .name = "omap-control-usb",
299 .owner = THIS_MODULE,
300 .of_match_table = of_match_ptr(omap_control_usb_id_table),
301 },
302};
303
304static int __init omap_control_usb_init(void)
305{
306 return platform_driver_register(&omap_control_usb_driver);
307}
308subsys_initcall(omap_control_usb_init);
309
310static void __exit omap_control_usb_exit(void)
311{
312 platform_driver_unregister(&omap_control_usb_driver);
313}
314module_exit(omap_control_usb_exit);
315
316MODULE_ALIAS("platform: omap_control_usb");
317MODULE_AUTHOR("Texas Instruments Inc.");
318MODULE_DESCRIPTION("OMAP Control Module USB Driver");
319MODULE_LICENSE("GPL v2");
diff --git a/drivers/usb/phy/phy-omap-usb3.c b/drivers/usb/phy/phy-omap-usb3.c
deleted file mode 100644
index 0c6ba29bdddd..000000000000
--- a/drivers/usb/phy/phy-omap-usb3.c
+++ /dev/null
@@ -1,361 +0,0 @@
1/*
2 * omap-usb3 - USB PHY, talking to dwc3 controller in OMAP.
3 *
4 * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * Author: Kishon Vijay Abraham I <kishon@ti.com>
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 */
18
19#include <linux/module.h>
20#include <linux/platform_device.h>
21#include <linux/slab.h>
22#include <linux/usb/omap_usb.h>
23#include <linux/of.h>
24#include <linux/clk.h>
25#include <linux/err.h>
26#include <linux/pm_runtime.h>
27#include <linux/delay.h>
28#include <linux/usb/omap_control_usb.h>
29#include <linux/of_platform.h>
30
31#define PLL_STATUS 0x00000004
32#define PLL_GO 0x00000008
33#define PLL_CONFIGURATION1 0x0000000C
34#define PLL_CONFIGURATION2 0x00000010
35#define PLL_CONFIGURATION3 0x00000014
36#define PLL_CONFIGURATION4 0x00000020
37
38#define PLL_REGM_MASK 0x001FFE00
39#define PLL_REGM_SHIFT 0x9
40#define PLL_REGM_F_MASK 0x0003FFFF
41#define PLL_REGM_F_SHIFT 0x0
42#define PLL_REGN_MASK 0x000001FE
43#define PLL_REGN_SHIFT 0x1
44#define PLL_SELFREQDCO_MASK 0x0000000E
45#define PLL_SELFREQDCO_SHIFT 0x1
46#define PLL_SD_MASK 0x0003FC00
47#define PLL_SD_SHIFT 0x9
48#define SET_PLL_GO 0x1
49#define PLL_TICOPWDN 0x10000
50#define PLL_LOCK 0x2
51#define PLL_IDLE 0x1
52
53/*
54 * This is an Empirical value that works, need to confirm the actual
55 * value required for the USB3PHY_PLL_CONFIGURATION2.PLL_IDLE status
56 * to be correctly reflected in the USB3PHY_PLL_STATUS register.
57 */
58# define PLL_IDLE_TIME 100;
59
60struct usb_dpll_map {
61 unsigned long rate;
62 struct usb_dpll_params params;
63};
64
65static struct usb_dpll_map dpll_map[] = {
66 {12000000, {1250, 5, 4, 20, 0} }, /* 12 MHz */
67 {16800000, {3125, 20, 4, 20, 0} }, /* 16.8 MHz */
68 {19200000, {1172, 8, 4, 20, 65537} }, /* 19.2 MHz */
69 {20000000, {1000, 7, 4, 10, 0} }, /* 20 MHz */
70 {26000000, {1250, 12, 4, 20, 0} }, /* 26 MHz */
71 {38400000, {3125, 47, 4, 20, 92843} }, /* 38.4 MHz */
72};
73
74static struct usb_dpll_params *omap_usb3_get_dpll_params(unsigned long rate)
75{
76 int i;
77
78 for (i = 0; i < ARRAY_SIZE(dpll_map); i++) {
79 if (rate == dpll_map[i].rate)
80 return &dpll_map[i].params;
81 }
82
83 return NULL;
84}
85
86static int omap_usb3_suspend(struct usb_phy *x, int suspend)
87{
88 struct omap_usb *phy = phy_to_omapusb(x);
89 int val;
90 int timeout = PLL_IDLE_TIME;
91
92 if (suspend && !phy->is_suspended) {
93 val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
94 val |= PLL_IDLE;
95 omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val);
96
97 do {
98 val = omap_usb_readl(phy->pll_ctrl_base, PLL_STATUS);
99 if (val & PLL_TICOPWDN)
100 break;
101 udelay(1);
102 } while (--timeout);
103
104 omap_control_usb_phy_power(phy->control_dev, 0);
105
106 phy->is_suspended = 1;
107 } else if (!suspend && phy->is_suspended) {
108 phy->is_suspended = 0;
109
110 val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
111 val &= ~PLL_IDLE;
112 omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val);
113
114 do {
115 val = omap_usb_readl(phy->pll_ctrl_base, PLL_STATUS);
116 if (!(val & PLL_TICOPWDN))
117 break;
118 udelay(1);
119 } while (--timeout);
120 }
121
122 return 0;
123}
124
125static void omap_usb_dpll_relock(struct omap_usb *phy)
126{
127 u32 val;
128 unsigned long timeout;
129
130 omap_usb_writel(phy->pll_ctrl_base, PLL_GO, SET_PLL_GO);
131
132 timeout = jiffies + msecs_to_jiffies(20);
133 do {
134 val = omap_usb_readl(phy->pll_ctrl_base, PLL_STATUS);
135 if (val & PLL_LOCK)
136 break;
137 } while (!WARN_ON(time_after(jiffies, timeout)));
138}
139
140static int omap_usb_dpll_lock(struct omap_usb *phy)
141{
142 u32 val;
143 unsigned long rate;
144 struct usb_dpll_params *dpll_params;
145
146 rate = clk_get_rate(phy->sys_clk);
147 dpll_params = omap_usb3_get_dpll_params(rate);
148 if (!dpll_params) {
149 dev_err(phy->dev,
150 "No DPLL configuration for %lu Hz SYS CLK\n", rate);
151 return -EINVAL;
152 }
153
154 val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION1);
155 val &= ~PLL_REGN_MASK;
156 val |= dpll_params->n << PLL_REGN_SHIFT;
157 omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION1, val);
158
159 val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
160 val &= ~PLL_SELFREQDCO_MASK;
161 val |= dpll_params->freq << PLL_SELFREQDCO_SHIFT;
162 omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val);
163
164 val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION1);
165 val &= ~PLL_REGM_MASK;
166 val |= dpll_params->m << PLL_REGM_SHIFT;
167 omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION1, val);
168
169 val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION4);
170 val &= ~PLL_REGM_F_MASK;
171 val |= dpll_params->mf << PLL_REGM_F_SHIFT;
172 omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION4, val);
173
174 val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION3);
175 val &= ~PLL_SD_MASK;
176 val |= dpll_params->sd << PLL_SD_SHIFT;
177 omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION3, val);
178
179 omap_usb_dpll_relock(phy);
180
181 return 0;
182}
183
184static int omap_usb3_init(struct usb_phy *x)
185{
186 struct omap_usb *phy = phy_to_omapusb(x);
187 int ret;
188
189 ret = omap_usb_dpll_lock(phy);
190 if (ret)
191 return ret;
192
193 omap_control_usb_phy_power(phy->control_dev, 1);
194
195 return 0;
196}
197
198static int omap_usb3_probe(struct platform_device *pdev)
199{
200 struct omap_usb *phy;
201 struct resource *res;
202 struct device_node *node = pdev->dev.of_node;
203 struct device_node *control_node;
204 struct platform_device *control_pdev;
205
206 if (!node)
207 return -EINVAL;
208
209 phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL);
210 if (!phy) {
211 dev_err(&pdev->dev, "unable to alloc mem for OMAP USB3 PHY\n");
212 return -ENOMEM;
213 }
214
215 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pll_ctrl");
216 phy->pll_ctrl_base = devm_ioremap_resource(&pdev->dev, res);
217 if (IS_ERR(phy->pll_ctrl_base))
218 return PTR_ERR(phy->pll_ctrl_base);
219
220 phy->dev = &pdev->dev;
221
222 phy->phy.dev = phy->dev;
223 phy->phy.label = "omap-usb3";
224 phy->phy.init = omap_usb3_init;
225 phy->phy.set_suspend = omap_usb3_suspend;
226 phy->phy.type = USB_PHY_TYPE_USB3;
227
228 phy->is_suspended = 1;
229 phy->wkupclk = devm_clk_get(phy->dev, "usb_phy_cm_clk32k");
230 if (IS_ERR(phy->wkupclk)) {
231 dev_err(&pdev->dev, "unable to get usb_phy_cm_clk32k\n");
232 return PTR_ERR(phy->wkupclk);
233 }
234 clk_prepare(phy->wkupclk);
235
236 phy->optclk = devm_clk_get(phy->dev, "usb_otg_ss_refclk960m");
237 if (IS_ERR(phy->optclk)) {
238 dev_err(&pdev->dev, "unable to get usb_otg_ss_refclk960m\n");
239 return PTR_ERR(phy->optclk);
240 }
241 clk_prepare(phy->optclk);
242
243 phy->sys_clk = devm_clk_get(phy->dev, "sys_clkin");
244 if (IS_ERR(phy->sys_clk)) {
245 pr_err("%s: unable to get sys_clkin\n", __func__);
246 return -EINVAL;
247 }
248
249 control_node = of_parse_phandle(node, "ctrl-module", 0);
250 if (!control_node) {
251 dev_err(&pdev->dev, "Failed to get control device phandle\n");
252 return -EINVAL;
253 }
254 control_pdev = of_find_device_by_node(control_node);
255 if (!control_pdev) {
256 dev_err(&pdev->dev, "Failed to get control device\n");
257 return -EINVAL;
258 }
259
260 phy->control_dev = &control_pdev->dev;
261
262 omap_control_usb_phy_power(phy->control_dev, 0);
263 usb_add_phy_dev(&phy->phy);
264
265 platform_set_drvdata(pdev, phy);
266
267 pm_runtime_enable(phy->dev);
268 pm_runtime_get(&pdev->dev);
269
270 return 0;
271}
272
273static int omap_usb3_remove(struct platform_device *pdev)
274{
275 struct omap_usb *phy = platform_get_drvdata(pdev);
276
277 clk_unprepare(phy->wkupclk);
278 clk_unprepare(phy->optclk);
279 usb_remove_phy(&phy->phy);
280 if (!pm_runtime_suspended(&pdev->dev))
281 pm_runtime_put(&pdev->dev);
282 pm_runtime_disable(&pdev->dev);
283
284 return 0;
285}
286
287#ifdef CONFIG_PM_RUNTIME
288
289static int omap_usb3_runtime_suspend(struct device *dev)
290{
291 struct platform_device *pdev = to_platform_device(dev);
292 struct omap_usb *phy = platform_get_drvdata(pdev);
293
294 clk_disable(phy->wkupclk);
295 clk_disable(phy->optclk);
296
297 return 0;
298}
299
300static int omap_usb3_runtime_resume(struct device *dev)
301{
302 u32 ret = 0;
303 struct platform_device *pdev = to_platform_device(dev);
304 struct omap_usb *phy = platform_get_drvdata(pdev);
305
306 ret = clk_enable(phy->optclk);
307 if (ret) {
308 dev_err(phy->dev, "Failed to enable optclk %d\n", ret);
309 goto err1;
310 }
311
312 ret = clk_enable(phy->wkupclk);
313 if (ret) {
314 dev_err(phy->dev, "Failed to enable wkupclk %d\n", ret);
315 goto err2;
316 }
317
318 return 0;
319
320err2:
321 clk_disable(phy->optclk);
322
323err1:
324 return ret;
325}
326
327static const struct dev_pm_ops omap_usb3_pm_ops = {
328 SET_RUNTIME_PM_OPS(omap_usb3_runtime_suspend, omap_usb3_runtime_resume,
329 NULL)
330};
331
332#define DEV_PM_OPS (&omap_usb3_pm_ops)
333#else
334#define DEV_PM_OPS NULL
335#endif
336
337#ifdef CONFIG_OF
338static const struct of_device_id omap_usb3_id_table[] = {
339 { .compatible = "ti,omap-usb3" },
340 {}
341};
342MODULE_DEVICE_TABLE(of, omap_usb3_id_table);
343#endif
344
345static struct platform_driver omap_usb3_driver = {
346 .probe = omap_usb3_probe,
347 .remove = omap_usb3_remove,
348 .driver = {
349 .name = "omap-usb3",
350 .owner = THIS_MODULE,
351 .pm = DEV_PM_OPS,
352 .of_match_table = of_match_ptr(omap_usb3_id_table),
353 },
354};
355
356module_platform_driver(omap_usb3_driver);
357
358MODULE_ALIAS("platform: omap_usb3");
359MODULE_AUTHOR("Texas Instruments Inc.");
360MODULE_DESCRIPTION("OMAP USB3 phy driver");
361MODULE_LICENSE("GPL v2");
diff --git a/drivers/usb/phy/phy-twl6030-usb.c b/drivers/usb/phy/phy-twl6030-usb.c
index 214172b68d5d..04778cf80d60 100644
--- a/drivers/usb/phy/phy-twl6030-usb.c
+++ b/drivers/usb/phy/phy-twl6030-usb.c
@@ -27,7 +27,7 @@
27#include <linux/io.h> 27#include <linux/io.h>
28#include <linux/usb/musb-omap.h> 28#include <linux/usb/musb-omap.h>
29#include <linux/usb/phy_companion.h> 29#include <linux/usb/phy_companion.h>
30#include <linux/usb/omap_usb.h> 30#include <linux/phy/omap_usb.h>
31#include <linux/i2c/twl.h> 31#include <linux/i2c/twl.h>
32#include <linux/regulator/consumer.h> 32#include <linux/regulator/consumer.h>
33#include <linux/err.h> 33#include <linux/err.h>