diff options
author | Keshava Munegowda <keshava_mgowda@ti.com> | 2012-07-16 09:31:08 -0400 |
---|---|---|
committer | Samuel Ortiz <sameo@linux.intel.com> | 2012-09-21 17:39:24 -0400 |
commit | 16fa3dc75c22f9769d418f19c45e11b118aab2eb (patch) | |
tree | df05b4ff423c2d4f273c71f80f7f62c74147ea54 /drivers/mfd | |
parent | 99de1cc5a77122e59640668b202280ecdb0f3c2e (diff) |
mfd: omap-usb-tll: HOST TLL platform driver
The platform driver for the TLL component of the OMAP USB host controller
is implemented. Depending on the TLL hardware revision , the TLL channels
are configured. The USB HS core driver uses this driver through exported
APIs from the TLL platform driver.
usb_tll_enable and usb_tll_disble are the exported APIs of the USB TLL
platform driver.
Signed-off-by: Keshava Munegowda <keshava_mgowda@ti.com>
Reviewed-by: Partha Basak <parthab@india.ti.com>
Acked-by: Felipe Balbi <balbi@ti.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'drivers/mfd')
-rw-r--r-- | drivers/mfd/Kconfig | 2 | ||||
-rw-r--r-- | drivers/mfd/Makefile | 2 | ||||
-rw-r--r-- | drivers/mfd/omap-usb-tll.c | 471 |
3 files changed, 473 insertions, 2 deletions
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 2143fd283a74..b9282cafa978 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig | |||
@@ -897,7 +897,7 @@ config MFD_WL1273_CORE | |||
897 | audio codec. | 897 | audio codec. |
898 | 898 | ||
899 | config MFD_OMAP_USB_HOST | 899 | config MFD_OMAP_USB_HOST |
900 | bool "Support OMAP USBHS core driver" | 900 | bool "Support OMAP USBHS core and TLL driver" |
901 | depends on USB_EHCI_HCD_OMAP || USB_OHCI_HCD_OMAP3 | 901 | depends on USB_EHCI_HCD_OMAP || USB_OHCI_HCD_OMAP3 |
902 | default y | 902 | default y |
903 | help | 903 | help |
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 95dfa14ad174..d16bc0220e1f 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile | |||
@@ -120,7 +120,7 @@ obj-$(CONFIG_MFD_TPS6586X) += tps6586x.o | |||
120 | obj-$(CONFIG_MFD_VX855) += vx855.o | 120 | obj-$(CONFIG_MFD_VX855) += vx855.o |
121 | obj-$(CONFIG_MFD_WL1273_CORE) += wl1273-core.o | 121 | obj-$(CONFIG_MFD_WL1273_CORE) += wl1273-core.o |
122 | obj-$(CONFIG_MFD_CS5535) += cs5535-mfd.o | 122 | obj-$(CONFIG_MFD_CS5535) += cs5535-mfd.o |
123 | obj-$(CONFIG_MFD_OMAP_USB_HOST) += omap-usb-host.o | 123 | obj-$(CONFIG_MFD_OMAP_USB_HOST) += omap-usb-host.o omap-usb-tll.o |
124 | obj-$(CONFIG_MFD_PM8921_CORE) += pm8921-core.o | 124 | obj-$(CONFIG_MFD_PM8921_CORE) += pm8921-core.o |
125 | obj-$(CONFIG_MFD_PM8XXX_IRQ) += pm8xxx-irq.o | 125 | obj-$(CONFIG_MFD_PM8XXX_IRQ) += pm8xxx-irq.o |
126 | obj-$(CONFIG_TPS65911_COMPARATOR) += tps65911-comparator.o | 126 | obj-$(CONFIG_TPS65911_COMPARATOR) += tps65911-comparator.o |
diff --git a/drivers/mfd/omap-usb-tll.c b/drivers/mfd/omap-usb-tll.c new file mode 100644 index 000000000000..4b7757b84301 --- /dev/null +++ b/drivers/mfd/omap-usb-tll.c | |||
@@ -0,0 +1,471 @@ | |||
1 | /** | ||
2 | * omap-usb-tll.c - The USB TLL driver for OMAP EHCI & OHCI | ||
3 | * | ||
4 | * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com | ||
5 | * Author: Keshava Munegowda <keshava_mgowda@ti.com> | ||
6 | * | ||
7 | * This program is free software: you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 of | ||
9 | * the License as published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/module.h> | ||
21 | #include <linux/types.h> | ||
22 | #include <linux/slab.h> | ||
23 | #include <linux/spinlock.h> | ||
24 | #include <linux/platform_device.h> | ||
25 | #include <linux/clk.h> | ||
26 | #include <linux/io.h> | ||
27 | #include <linux/err.h> | ||
28 | #include <plat/usb.h> | ||
29 | #include <linux/pm_runtime.h> | ||
30 | |||
31 | #define USBTLL_DRIVER_NAME "usbhs_tll" | ||
32 | |||
33 | /* TLL Register Set */ | ||
34 | #define OMAP_USBTLL_REVISION (0x00) | ||
35 | #define OMAP_USBTLL_SYSCONFIG (0x10) | ||
36 | #define OMAP_USBTLL_SYSCONFIG_CACTIVITY (1 << 8) | ||
37 | #define OMAP_USBTLL_SYSCONFIG_SIDLEMODE (1 << 3) | ||
38 | #define OMAP_USBTLL_SYSCONFIG_ENAWAKEUP (1 << 2) | ||
39 | #define OMAP_USBTLL_SYSCONFIG_SOFTRESET (1 << 1) | ||
40 | #define OMAP_USBTLL_SYSCONFIG_AUTOIDLE (1 << 0) | ||
41 | |||
42 | #define OMAP_USBTLL_SYSSTATUS (0x14) | ||
43 | #define OMAP_USBTLL_SYSSTATUS_RESETDONE (1 << 0) | ||
44 | |||
45 | #define OMAP_USBTLL_IRQSTATUS (0x18) | ||
46 | #define OMAP_USBTLL_IRQENABLE (0x1C) | ||
47 | |||
48 | #define OMAP_TLL_SHARED_CONF (0x30) | ||
49 | #define OMAP_TLL_SHARED_CONF_USB_90D_DDR_EN (1 << 6) | ||
50 | #define OMAP_TLL_SHARED_CONF_USB_180D_SDR_EN (1 << 5) | ||
51 | #define OMAP_TLL_SHARED_CONF_USB_DIVRATION (1 << 2) | ||
52 | #define OMAP_TLL_SHARED_CONF_FCLK_REQ (1 << 1) | ||
53 | #define OMAP_TLL_SHARED_CONF_FCLK_IS_ON (1 << 0) | ||
54 | |||
55 | #define OMAP_TLL_CHANNEL_CONF(num) (0x040 + 0x004 * num) | ||
56 | #define OMAP_TLL_CHANNEL_CONF_FSLSMODE_SHIFT 24 | ||
57 | #define OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF (1 << 11) | ||
58 | #define OMAP_TLL_CHANNEL_CONF_ULPI_ULPIAUTOIDLE (1 << 10) | ||
59 | #define OMAP_TLL_CHANNEL_CONF_UTMIAUTOIDLE (1 << 9) | ||
60 | #define OMAP_TLL_CHANNEL_CONF_ULPIDDRMODE (1 << 8) | ||
61 | #define OMAP_TLL_CHANNEL_CONF_CHANMODE_FSLS (1 << 1) | ||
62 | #define OMAP_TLL_CHANNEL_CONF_CHANEN (1 << 0) | ||
63 | |||
64 | #define OMAP_TLL_FSLSMODE_6PIN_PHY_DAT_SE0 0x0 | ||
65 | #define OMAP_TLL_FSLSMODE_6PIN_PHY_DP_DM 0x1 | ||
66 | #define OMAP_TLL_FSLSMODE_3PIN_PHY 0x2 | ||
67 | #define OMAP_TLL_FSLSMODE_4PIN_PHY 0x3 | ||
68 | #define OMAP_TLL_FSLSMODE_6PIN_TLL_DAT_SE0 0x4 | ||
69 | #define OMAP_TLL_FSLSMODE_6PIN_TLL_DP_DM 0x5 | ||
70 | #define OMAP_TLL_FSLSMODE_3PIN_TLL 0x6 | ||
71 | #define OMAP_TLL_FSLSMODE_4PIN_TLL 0x7 | ||
72 | #define OMAP_TLL_FSLSMODE_2PIN_TLL_DAT_SE0 0xA | ||
73 | #define OMAP_TLL_FSLSMODE_2PIN_DAT_DP_DM 0xB | ||
74 | |||
75 | #define OMAP_TLL_ULPI_FUNCTION_CTRL(num) (0x804 + 0x100 * num) | ||
76 | #define OMAP_TLL_ULPI_INTERFACE_CTRL(num) (0x807 + 0x100 * num) | ||
77 | #define OMAP_TLL_ULPI_OTG_CTRL(num) (0x80A + 0x100 * num) | ||
78 | #define OMAP_TLL_ULPI_INT_EN_RISE(num) (0x80D + 0x100 * num) | ||
79 | #define OMAP_TLL_ULPI_INT_EN_FALL(num) (0x810 + 0x100 * num) | ||
80 | #define OMAP_TLL_ULPI_INT_STATUS(num) (0x813 + 0x100 * num) | ||
81 | #define OMAP_TLL_ULPI_INT_LATCH(num) (0x814 + 0x100 * num) | ||
82 | #define OMAP_TLL_ULPI_DEBUG(num) (0x815 + 0x100 * num) | ||
83 | #define OMAP_TLL_ULPI_SCRATCH_REGISTER(num) (0x816 + 0x100 * num) | ||
84 | |||
85 | #define OMAP_REV2_TLL_CHANNEL_COUNT 2 | ||
86 | #define OMAP_TLL_CHANNEL_COUNT 3 | ||
87 | #define OMAP_TLL_CHANNEL_1_EN_MASK (1 << 0) | ||
88 | #define OMAP_TLL_CHANNEL_2_EN_MASK (1 << 1) | ||
89 | #define OMAP_TLL_CHANNEL_3_EN_MASK (1 << 2) | ||
90 | |||
91 | /* Values of USBTLL_REVISION - Note: these are not given in the TRM */ | ||
92 | #define OMAP_USBTLL_REV1 0x00000015 /* OMAP3 */ | ||
93 | #define OMAP_USBTLL_REV2 0x00000018 /* OMAP 3630 */ | ||
94 | #define OMAP_USBTLL_REV3 0x00000004 /* OMAP4 */ | ||
95 | |||
96 | #define is_ehci_tll_mode(x) (x == OMAP_EHCI_PORT_MODE_TLL) | ||
97 | |||
98 | struct usbtll_omap { | ||
99 | struct clk *usbtll_p1_fck; | ||
100 | struct clk *usbtll_p2_fck; | ||
101 | struct usbtll_omap_platform_data platdata; | ||
102 | /* secure the register updates */ | ||
103 | spinlock_t lock; | ||
104 | }; | ||
105 | |||
106 | /*-------------------------------------------------------------------------*/ | ||
107 | |||
108 | const char usbtll_driver_name[] = USBTLL_DRIVER_NAME; | ||
109 | struct platform_device *tll_pdev; | ||
110 | |||
111 | /*-------------------------------------------------------------------------*/ | ||
112 | |||
113 | static inline void usbtll_write(void __iomem *base, u32 reg, u32 val) | ||
114 | { | ||
115 | __raw_writel(val, base + reg); | ||
116 | } | ||
117 | |||
118 | static inline u32 usbtll_read(void __iomem *base, u32 reg) | ||
119 | { | ||
120 | return __raw_readl(base + reg); | ||
121 | } | ||
122 | |||
123 | static inline void usbtll_writeb(void __iomem *base, u8 reg, u8 val) | ||
124 | { | ||
125 | __raw_writeb(val, base + reg); | ||
126 | } | ||
127 | |||
128 | static inline u8 usbtll_readb(void __iomem *base, u8 reg) | ||
129 | { | ||
130 | return __raw_readb(base + reg); | ||
131 | } | ||
132 | |||
133 | /*-------------------------------------------------------------------------*/ | ||
134 | |||
135 | static bool is_ohci_port(enum usbhs_omap_port_mode pmode) | ||
136 | { | ||
137 | switch (pmode) { | ||
138 | case OMAP_OHCI_PORT_MODE_PHY_6PIN_DATSE0: | ||
139 | case OMAP_OHCI_PORT_MODE_PHY_6PIN_DPDM: | ||
140 | case OMAP_OHCI_PORT_MODE_PHY_3PIN_DATSE0: | ||
141 | case OMAP_OHCI_PORT_MODE_PHY_4PIN_DPDM: | ||
142 | case OMAP_OHCI_PORT_MODE_TLL_6PIN_DATSE0: | ||
143 | case OMAP_OHCI_PORT_MODE_TLL_6PIN_DPDM: | ||
144 | case OMAP_OHCI_PORT_MODE_TLL_3PIN_DATSE0: | ||
145 | case OMAP_OHCI_PORT_MODE_TLL_4PIN_DPDM: | ||
146 | case OMAP_OHCI_PORT_MODE_TLL_2PIN_DATSE0: | ||
147 | case OMAP_OHCI_PORT_MODE_TLL_2PIN_DPDM: | ||
148 | return true; | ||
149 | |||
150 | default: | ||
151 | return false; | ||
152 | } | ||
153 | } | ||
154 | |||
155 | /* | ||
156 | * convert the port-mode enum to a value we can use in the FSLSMODE | ||
157 | * field of USBTLL_CHANNEL_CONF | ||
158 | */ | ||
159 | static unsigned ohci_omap3_fslsmode(enum usbhs_omap_port_mode mode) | ||
160 | { | ||
161 | switch (mode) { | ||
162 | case OMAP_USBHS_PORT_MODE_UNUSED: | ||
163 | case OMAP_OHCI_PORT_MODE_PHY_6PIN_DATSE0: | ||
164 | return OMAP_TLL_FSLSMODE_6PIN_PHY_DAT_SE0; | ||
165 | |||
166 | case OMAP_OHCI_PORT_MODE_PHY_6PIN_DPDM: | ||
167 | return OMAP_TLL_FSLSMODE_6PIN_PHY_DP_DM; | ||
168 | |||
169 | case OMAP_OHCI_PORT_MODE_PHY_3PIN_DATSE0: | ||
170 | return OMAP_TLL_FSLSMODE_3PIN_PHY; | ||
171 | |||
172 | case OMAP_OHCI_PORT_MODE_PHY_4PIN_DPDM: | ||
173 | return OMAP_TLL_FSLSMODE_4PIN_PHY; | ||
174 | |||
175 | case OMAP_OHCI_PORT_MODE_TLL_6PIN_DATSE0: | ||
176 | return OMAP_TLL_FSLSMODE_6PIN_TLL_DAT_SE0; | ||
177 | |||
178 | case OMAP_OHCI_PORT_MODE_TLL_6PIN_DPDM: | ||
179 | return OMAP_TLL_FSLSMODE_6PIN_TLL_DP_DM; | ||
180 | |||
181 | case OMAP_OHCI_PORT_MODE_TLL_3PIN_DATSE0: | ||
182 | return OMAP_TLL_FSLSMODE_3PIN_TLL; | ||
183 | |||
184 | case OMAP_OHCI_PORT_MODE_TLL_4PIN_DPDM: | ||
185 | return OMAP_TLL_FSLSMODE_4PIN_TLL; | ||
186 | |||
187 | case OMAP_OHCI_PORT_MODE_TLL_2PIN_DATSE0: | ||
188 | return OMAP_TLL_FSLSMODE_2PIN_TLL_DAT_SE0; | ||
189 | |||
190 | case OMAP_OHCI_PORT_MODE_TLL_2PIN_DPDM: | ||
191 | return OMAP_TLL_FSLSMODE_2PIN_DAT_DP_DM; | ||
192 | default: | ||
193 | pr_warn("Invalid port mode, using default\n"); | ||
194 | return OMAP_TLL_FSLSMODE_6PIN_PHY_DAT_SE0; | ||
195 | } | ||
196 | } | ||
197 | |||
198 | /** | ||
199 | * usbtll_omap_probe - initialize TI-based HCDs | ||
200 | * | ||
201 | * Allocates basic resources for this USB host controller. | ||
202 | */ | ||
203 | static int __devinit usbtll_omap_probe(struct platform_device *pdev) | ||
204 | { | ||
205 | struct device *dev = &pdev->dev; | ||
206 | struct usbtll_omap_platform_data *pdata = dev->platform_data; | ||
207 | void __iomem *base; | ||
208 | struct resource *res; | ||
209 | struct usbtll_omap *tll; | ||
210 | unsigned reg; | ||
211 | unsigned long flags; | ||
212 | int ret = 0; | ||
213 | int i, ver, count; | ||
214 | |||
215 | dev_dbg(dev, "starting TI HSUSB TLL Controller\n"); | ||
216 | |||
217 | tll = kzalloc(sizeof(struct usbtll_omap), GFP_KERNEL); | ||
218 | if (!tll) { | ||
219 | dev_err(dev, "Memory allocation failed\n"); | ||
220 | ret = -ENOMEM; | ||
221 | goto end; | ||
222 | } | ||
223 | |||
224 | spin_lock_init(&tll->lock); | ||
225 | |||
226 | for (i = 0; i < OMAP3_HS_USB_PORTS; i++) | ||
227 | tll->platdata.port_mode[i] = pdata->port_mode[i]; | ||
228 | |||
229 | tll->usbtll_p1_fck = clk_get(dev, "usb_tll_hs_usb_ch0_clk"); | ||
230 | if (IS_ERR(tll->usbtll_p1_fck)) { | ||
231 | ret = PTR_ERR(tll->usbtll_p1_fck); | ||
232 | dev_err(dev, "usbtll_p1_fck failed error:%d\n", ret); | ||
233 | goto err_tll; | ||
234 | } | ||
235 | |||
236 | tll->usbtll_p2_fck = clk_get(dev, "usb_tll_hs_usb_ch1_clk"); | ||
237 | if (IS_ERR(tll->usbtll_p2_fck)) { | ||
238 | ret = PTR_ERR(tll->usbtll_p2_fck); | ||
239 | dev_err(dev, "usbtll_p2_fck failed error:%d\n", ret); | ||
240 | goto err_usbtll_p1_fck; | ||
241 | } | ||
242 | |||
243 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
244 | if (!res) { | ||
245 | dev_err(dev, "usb tll get resource failed\n"); | ||
246 | ret = -ENODEV; | ||
247 | goto err_usbtll_p2_fck; | ||
248 | } | ||
249 | |||
250 | base = ioremap(res->start, resource_size(res)); | ||
251 | if (!base) { | ||
252 | dev_err(dev, "TLL ioremap failed\n"); | ||
253 | ret = -ENOMEM; | ||
254 | goto err_usbtll_p2_fck; | ||
255 | } | ||
256 | |||
257 | platform_set_drvdata(pdev, tll); | ||
258 | pm_runtime_enable(dev); | ||
259 | pm_runtime_get_sync(dev); | ||
260 | |||
261 | spin_lock_irqsave(&tll->lock, flags); | ||
262 | |||
263 | ver = usbtll_read(base, OMAP_USBTLL_REVISION); | ||
264 | switch (ver) { | ||
265 | case OMAP_USBTLL_REV1: | ||
266 | case OMAP_USBTLL_REV2: | ||
267 | count = OMAP_TLL_CHANNEL_COUNT; | ||
268 | break; | ||
269 | case OMAP_USBTLL_REV3: | ||
270 | count = OMAP_REV2_TLL_CHANNEL_COUNT; | ||
271 | break; | ||
272 | default: | ||
273 | dev_err(dev, "TLL version failed\n"); | ||
274 | ret = -ENODEV; | ||
275 | goto err_ioremap; | ||
276 | } | ||
277 | |||
278 | if (is_ehci_tll_mode(pdata->port_mode[0]) || | ||
279 | is_ehci_tll_mode(pdata->port_mode[1]) || | ||
280 | is_ehci_tll_mode(pdata->port_mode[2]) || | ||
281 | is_ohci_port(pdata->port_mode[0]) || | ||
282 | is_ohci_port(pdata->port_mode[1]) || | ||
283 | is_ohci_port(pdata->port_mode[2])) { | ||
284 | |||
285 | /* Program Common TLL register */ | ||
286 | reg = usbtll_read(base, OMAP_TLL_SHARED_CONF); | ||
287 | reg |= (OMAP_TLL_SHARED_CONF_FCLK_IS_ON | ||
288 | | OMAP_TLL_SHARED_CONF_USB_DIVRATION); | ||
289 | reg &= ~OMAP_TLL_SHARED_CONF_USB_90D_DDR_EN; | ||
290 | reg &= ~OMAP_TLL_SHARED_CONF_USB_180D_SDR_EN; | ||
291 | |||
292 | usbtll_write(base, OMAP_TLL_SHARED_CONF, reg); | ||
293 | |||
294 | /* Enable channels now */ | ||
295 | for (i = 0; i < count; i++) { | ||
296 | reg = usbtll_read(base, OMAP_TLL_CHANNEL_CONF(i)); | ||
297 | |||
298 | if (is_ohci_port(pdata->port_mode[i])) { | ||
299 | reg |= ohci_omap3_fslsmode(pdata->port_mode[i]) | ||
300 | << OMAP_TLL_CHANNEL_CONF_FSLSMODE_SHIFT; | ||
301 | reg |= OMAP_TLL_CHANNEL_CONF_CHANMODE_FSLS; | ||
302 | } else if (pdata->port_mode[i] == | ||
303 | OMAP_EHCI_PORT_MODE_TLL) { | ||
304 | /* | ||
305 | * Disable AutoIdle, BitStuffing | ||
306 | * and use SDR Mode | ||
307 | */ | ||
308 | reg &= ~(OMAP_TLL_CHANNEL_CONF_UTMIAUTOIDLE | ||
309 | | OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF | ||
310 | | OMAP_TLL_CHANNEL_CONF_ULPIDDRMODE); | ||
311 | } else { | ||
312 | continue; | ||
313 | } | ||
314 | reg |= OMAP_TLL_CHANNEL_CONF_CHANEN; | ||
315 | usbtll_write(base, OMAP_TLL_CHANNEL_CONF(i), reg); | ||
316 | |||
317 | usbtll_writeb(base, | ||
318 | OMAP_TLL_ULPI_SCRATCH_REGISTER(i), | ||
319 | 0xbe); | ||
320 | } | ||
321 | } | ||
322 | |||
323 | err_ioremap: | ||
324 | spin_unlock_irqrestore(&tll->lock, flags); | ||
325 | iounmap(base); | ||
326 | pm_runtime_put_sync(dev); | ||
327 | tll_pdev = pdev; | ||
328 | if (!ret) | ||
329 | goto end; | ||
330 | pm_runtime_disable(dev); | ||
331 | |||
332 | err_usbtll_p2_fck: | ||
333 | clk_put(tll->usbtll_p2_fck); | ||
334 | |||
335 | err_usbtll_p1_fck: | ||
336 | clk_put(tll->usbtll_p1_fck); | ||
337 | |||
338 | err_tll: | ||
339 | kfree(tll); | ||
340 | |||
341 | end: | ||
342 | return ret; | ||
343 | } | ||
344 | |||
345 | /** | ||
346 | * usbtll_omap_remove - shutdown processing for UHH & TLL HCDs | ||
347 | * @pdev: USB Host Controller being removed | ||
348 | * | ||
349 | * Reverses the effect of usbtll_omap_probe(). | ||
350 | */ | ||
351 | static int __devexit usbtll_omap_remove(struct platform_device *pdev) | ||
352 | { | ||
353 | struct usbtll_omap *tll = platform_get_drvdata(pdev); | ||
354 | |||
355 | clk_put(tll->usbtll_p2_fck); | ||
356 | clk_put(tll->usbtll_p1_fck); | ||
357 | pm_runtime_disable(&pdev->dev); | ||
358 | kfree(tll); | ||
359 | return 0; | ||
360 | } | ||
361 | |||
362 | static int usbtll_runtime_resume(struct device *dev) | ||
363 | { | ||
364 | struct usbtll_omap *tll = dev_get_drvdata(dev); | ||
365 | struct usbtll_omap_platform_data *pdata = &tll->platdata; | ||
366 | unsigned long flags; | ||
367 | |||
368 | dev_dbg(dev, "usbtll_runtime_resume\n"); | ||
369 | |||
370 | if (!pdata) { | ||
371 | dev_dbg(dev, "missing platform_data\n"); | ||
372 | return -ENODEV; | ||
373 | } | ||
374 | |||
375 | spin_lock_irqsave(&tll->lock, flags); | ||
376 | |||
377 | if (is_ehci_tll_mode(pdata->port_mode[0])) | ||
378 | clk_enable(tll->usbtll_p1_fck); | ||
379 | |||
380 | if (is_ehci_tll_mode(pdata->port_mode[1])) | ||
381 | clk_enable(tll->usbtll_p2_fck); | ||
382 | |||
383 | spin_unlock_irqrestore(&tll->lock, flags); | ||
384 | |||
385 | return 0; | ||
386 | } | ||
387 | |||
388 | static int usbtll_runtime_suspend(struct device *dev) | ||
389 | { | ||
390 | struct usbtll_omap *tll = dev_get_drvdata(dev); | ||
391 | struct usbtll_omap_platform_data *pdata = &tll->platdata; | ||
392 | unsigned long flags; | ||
393 | |||
394 | dev_dbg(dev, "usbtll_runtime_suspend\n"); | ||
395 | |||
396 | if (!pdata) { | ||
397 | dev_dbg(dev, "missing platform_data\n"); | ||
398 | return -ENODEV; | ||
399 | } | ||
400 | |||
401 | spin_lock_irqsave(&tll->lock, flags); | ||
402 | |||
403 | if (is_ehci_tll_mode(pdata->port_mode[0])) | ||
404 | clk_disable(tll->usbtll_p1_fck); | ||
405 | |||
406 | if (is_ehci_tll_mode(pdata->port_mode[1])) | ||
407 | clk_disable(tll->usbtll_p2_fck); | ||
408 | |||
409 | spin_unlock_irqrestore(&tll->lock, flags); | ||
410 | |||
411 | return 0; | ||
412 | } | ||
413 | |||
414 | static const struct dev_pm_ops usbtllomap_dev_pm_ops = { | ||
415 | SET_RUNTIME_PM_OPS(usbtll_runtime_suspend, | ||
416 | usbtll_runtime_resume, | ||
417 | NULL) | ||
418 | }; | ||
419 | |||
420 | static struct platform_driver usbtll_omap_driver = { | ||
421 | .driver = { | ||
422 | .name = (char *)usbtll_driver_name, | ||
423 | .owner = THIS_MODULE, | ||
424 | .pm = &usbtllomap_dev_pm_ops, | ||
425 | }, | ||
426 | .probe = usbtll_omap_probe, | ||
427 | .remove = __devexit_p(usbtll_omap_remove), | ||
428 | }; | ||
429 | |||
430 | int omap_tll_enable(void) | ||
431 | { | ||
432 | if (!tll_pdev) { | ||
433 | pr_err("missing omap usbhs tll platform_data\n"); | ||
434 | return -ENODEV; | ||
435 | } | ||
436 | return pm_runtime_get_sync(&tll_pdev->dev); | ||
437 | } | ||
438 | EXPORT_SYMBOL_GPL(omap_tll_enable); | ||
439 | |||
440 | int omap_tll_disable(void) | ||
441 | { | ||
442 | if (!tll_pdev) { | ||
443 | pr_err("missing omap usbhs tll platform_data\n"); | ||
444 | return -ENODEV; | ||
445 | } | ||
446 | return pm_runtime_put_sync(&tll_pdev->dev); | ||
447 | } | ||
448 | EXPORT_SYMBOL_GPL(omap_tll_disable); | ||
449 | |||
450 | MODULE_AUTHOR("Keshava Munegowda <keshava_mgowda@ti.com>"); | ||
451 | MODULE_ALIAS("platform:" USBHS_DRIVER_NAME); | ||
452 | MODULE_LICENSE("GPL v2"); | ||
453 | MODULE_DESCRIPTION("usb tll driver for TI OMAP EHCI and OHCI controllers"); | ||
454 | |||
455 | static int __init omap_usbtll_drvinit(void) | ||
456 | { | ||
457 | return platform_driver_register(&usbtll_omap_driver); | ||
458 | } | ||
459 | |||
460 | /* | ||
461 | * init before usbhs core driver; | ||
462 | * The usbtll driver should be initialized before | ||
463 | * the usbhs core driver probe function is called. | ||
464 | */ | ||
465 | fs_initcall(omap_usbtll_drvinit); | ||
466 | |||
467 | static void __exit omap_usbtll_drvexit(void) | ||
468 | { | ||
469 | platform_driver_unregister(&usbtll_omap_driver); | ||
470 | } | ||
471 | module_exit(omap_usbtll_drvexit); | ||