diff options
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/musb/omap2430.c | 2 | ||||
-rw-r--r-- | drivers/usb/phy/Kconfig | 21 | ||||
-rw-r--r-- | drivers/usb/phy/Makefile | 2 | ||||
-rw-r--r-- | drivers/usb/phy/phy-omap-control.c | 319 | ||||
-rw-r--r-- | drivers/usb/phy/phy-omap-usb3.c | 361 | ||||
-rw-r--r-- | drivers/usb/phy/phy-twl6030-usb.c | 2 |
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 | ||
78 | config 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 | |||
88 | config 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 | |||
99 | config AM335X_CONTROL_USB | 78 | config 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 | |||
13 | obj-$(CONFIG_MV_U3D_PHY) += phy-mv-u3d-usb.o | 13 | obj-$(CONFIG_MV_U3D_PHY) += phy-mv-u3d-usb.o |
14 | obj-$(CONFIG_NOP_USB_XCEIV) += phy-generic.o | 14 | obj-$(CONFIG_NOP_USB_XCEIV) += phy-generic.o |
15 | obj-$(CONFIG_TAHVO_USB) += phy-tahvo.o | 15 | obj-$(CONFIG_TAHVO_USB) += phy-tahvo.o |
16 | obj-$(CONFIG_OMAP_CONTROL_USB) += phy-omap-control.o | ||
17 | obj-$(CONFIG_AM335X_CONTROL_USB) += phy-am335x-control.o | 16 | obj-$(CONFIG_AM335X_CONTROL_USB) += phy-am335x-control.o |
18 | obj-$(CONFIG_AM335X_PHY_USB) += phy-am335x.o | 17 | obj-$(CONFIG_AM335X_PHY_USB) += phy-am335x.o |
19 | obj-$(CONFIG_OMAP_OTG) += phy-omap-otg.o | 18 | obj-$(CONFIG_OMAP_OTG) += phy-omap-otg.o |
20 | obj-$(CONFIG_OMAP_USB3) += phy-omap-usb3.o | ||
21 | obj-$(CONFIG_SAMSUNG_USBPHY) += phy-samsung-usb.o | 19 | obj-$(CONFIG_SAMSUNG_USBPHY) += phy-samsung-usb.o |
22 | obj-$(CONFIG_SAMSUNG_USB2PHY) += phy-samsung-usb2.o | 20 | obj-$(CONFIG_SAMSUNG_USB2PHY) += phy-samsung-usb2.o |
23 | obj-$(CONFIG_SAMSUNG_USB3PHY) += phy-samsung-usb3.o | 21 | obj-$(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 | */ | ||
34 | void 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 | } | ||
109 | EXPORT_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 | */ | ||
118 | static 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 | */ | ||
136 | static 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 | */ | ||
155 | static 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 | */ | ||
174 | void 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 | } | ||
206 | EXPORT_SYMBOL_GPL(omap_control_usb_set_mode); | ||
207 | |||
208 | #ifdef CONFIG_OF | ||
209 | |||
210 | static const enum omap_control_usb_type otghs_data = OMAP_CTRL_TYPE_OTGHS; | ||
211 | static const enum omap_control_usb_type usb2_data = OMAP_CTRL_TYPE_USB2; | ||
212 | static const enum omap_control_usb_type pipe3_data = OMAP_CTRL_TYPE_PIPE3; | ||
213 | static const enum omap_control_usb_type dra7usb2_data = OMAP_CTRL_TYPE_DRA7USB2; | ||
214 | static const enum omap_control_usb_type am437usb2_data = OMAP_CTRL_TYPE_AM437USB2; | ||
215 | |||
216 | static 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 | }; | ||
239 | MODULE_DEVICE_TABLE(of, omap_control_usb_id_table); | ||
240 | #endif | ||
241 | |||
242 | |||
243 | static 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 | |||
295 | static 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 | |||
304 | static int __init omap_control_usb_init(void) | ||
305 | { | ||
306 | return platform_driver_register(&omap_control_usb_driver); | ||
307 | } | ||
308 | subsys_initcall(omap_control_usb_init); | ||
309 | |||
310 | static void __exit omap_control_usb_exit(void) | ||
311 | { | ||
312 | platform_driver_unregister(&omap_control_usb_driver); | ||
313 | } | ||
314 | module_exit(omap_control_usb_exit); | ||
315 | |||
316 | MODULE_ALIAS("platform: omap_control_usb"); | ||
317 | MODULE_AUTHOR("Texas Instruments Inc."); | ||
318 | MODULE_DESCRIPTION("OMAP Control Module USB Driver"); | ||
319 | MODULE_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 | |||
60 | struct usb_dpll_map { | ||
61 | unsigned long rate; | ||
62 | struct usb_dpll_params params; | ||
63 | }; | ||
64 | |||
65 | static 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 | |||
74 | static 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 | |||
86 | static 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 | |||
125 | static 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 | |||
140 | static 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 | |||
184 | static 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 | |||
198 | static 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 | |||
273 | static 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 | |||
289 | static 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 | |||
300 | static 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 | |||
320 | err2: | ||
321 | clk_disable(phy->optclk); | ||
322 | |||
323 | err1: | ||
324 | return ret; | ||
325 | } | ||
326 | |||
327 | static 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 | ||
338 | static const struct of_device_id omap_usb3_id_table[] = { | ||
339 | { .compatible = "ti,omap-usb3" }, | ||
340 | {} | ||
341 | }; | ||
342 | MODULE_DEVICE_TABLE(of, omap_usb3_id_table); | ||
343 | #endif | ||
344 | |||
345 | static 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 | |||
356 | module_platform_driver(omap_usb3_driver); | ||
357 | |||
358 | MODULE_ALIAS("platform: omap_usb3"); | ||
359 | MODULE_AUTHOR("Texas Instruments Inc."); | ||
360 | MODULE_DESCRIPTION("OMAP USB3 phy driver"); | ||
361 | MODULE_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> |