diff options
Diffstat (limited to 'drivers/usb/musb/da8xx.c')
-rw-r--r-- | drivers/usb/musb/da8xx.c | 608 |
1 files changed, 608 insertions, 0 deletions
diff --git a/drivers/usb/musb/da8xx.c b/drivers/usb/musb/da8xx.c new file mode 100644 index 000000000000..662ed34980bd --- /dev/null +++ b/drivers/usb/musb/da8xx.c | |||
@@ -0,0 +1,608 @@ | |||
1 | /* | ||
2 | * Texas Instruments DA8xx/OMAP-L1x "glue layer" | ||
3 | * | ||
4 | * Copyright (c) 2008-2009 MontaVista Software, Inc. <source@mvista.com> | ||
5 | * | ||
6 | * Based on the DaVinci "glue layer" code. | ||
7 | * Copyright (C) 2005-2006 by Texas Instruments | ||
8 | * | ||
9 | * This file is part of the Inventra Controller Driver for Linux. | ||
10 | * | ||
11 | * The Inventra Controller Driver for Linux is free software; you | ||
12 | * can redistribute it and/or modify it under the terms of the GNU | ||
13 | * General Public License version 2 as published by the Free Software | ||
14 | * Foundation. | ||
15 | * | ||
16 | * The Inventra Controller Driver for Linux is distributed in | ||
17 | * the hope that it will be useful, but WITHOUT ANY WARRANTY; | ||
18 | * without even the implied warranty of MERCHANTABILITY or | ||
19 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public | ||
20 | * License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with The Inventra Controller Driver for Linux ; if not, | ||
24 | * write to the Free Software Foundation, Inc., 59 Temple Place, | ||
25 | * Suite 330, Boston, MA 02111-1307 USA | ||
26 | * | ||
27 | */ | ||
28 | |||
29 | #include <linux/init.h> | ||
30 | #include <linux/clk.h> | ||
31 | #include <linux/io.h> | ||
32 | #include <linux/platform_device.h> | ||
33 | #include <linux/dma-mapping.h> | ||
34 | |||
35 | #include <mach/da8xx.h> | ||
36 | #include <mach/usb.h> | ||
37 | |||
38 | #include "musb_core.h" | ||
39 | |||
40 | /* | ||
41 | * DA8XX specific definitions | ||
42 | */ | ||
43 | |||
44 | /* USB 2.0 OTG module registers */ | ||
45 | #define DA8XX_USB_REVISION_REG 0x00 | ||
46 | #define DA8XX_USB_CTRL_REG 0x04 | ||
47 | #define DA8XX_USB_STAT_REG 0x08 | ||
48 | #define DA8XX_USB_EMULATION_REG 0x0c | ||
49 | #define DA8XX_USB_MODE_REG 0x10 /* Transparent, CDC, [Generic] RNDIS */ | ||
50 | #define DA8XX_USB_AUTOREQ_REG 0x14 | ||
51 | #define DA8XX_USB_SRP_FIX_TIME_REG 0x18 | ||
52 | #define DA8XX_USB_TEARDOWN_REG 0x1c | ||
53 | #define DA8XX_USB_INTR_SRC_REG 0x20 | ||
54 | #define DA8XX_USB_INTR_SRC_SET_REG 0x24 | ||
55 | #define DA8XX_USB_INTR_SRC_CLEAR_REG 0x28 | ||
56 | #define DA8XX_USB_INTR_MASK_REG 0x2c | ||
57 | #define DA8XX_USB_INTR_MASK_SET_REG 0x30 | ||
58 | #define DA8XX_USB_INTR_MASK_CLEAR_REG 0x34 | ||
59 | #define DA8XX_USB_INTR_SRC_MASKED_REG 0x38 | ||
60 | #define DA8XX_USB_END_OF_INTR_REG 0x3c | ||
61 | #define DA8XX_USB_GENERIC_RNDIS_EP_SIZE_REG(n) (0x50 + (((n) - 1) << 2)) | ||
62 | |||
63 | /* Control register bits */ | ||
64 | #define DA8XX_SOFT_RESET_MASK 1 | ||
65 | |||
66 | #define DA8XX_USB_TX_EP_MASK 0x1f /* EP0 + 4 Tx EPs */ | ||
67 | #define DA8XX_USB_RX_EP_MASK 0x1e /* 4 Rx EPs */ | ||
68 | |||
69 | /* USB interrupt register bits */ | ||
70 | #define DA8XX_INTR_USB_SHIFT 16 | ||
71 | #define DA8XX_INTR_USB_MASK (0x1ff << DA8XX_INTR_USB_SHIFT) /* 8 Mentor */ | ||
72 | /* interrupts and DRVVBUS interrupt */ | ||
73 | #define DA8XX_INTR_DRVVBUS 0x100 | ||
74 | #define DA8XX_INTR_RX_SHIFT 8 | ||
75 | #define DA8XX_INTR_RX_MASK (DA8XX_USB_RX_EP_MASK << DA8XX_INTR_RX_SHIFT) | ||
76 | #define DA8XX_INTR_TX_SHIFT 0 | ||
77 | #define DA8XX_INTR_TX_MASK (DA8XX_USB_TX_EP_MASK << DA8XX_INTR_TX_SHIFT) | ||
78 | |||
79 | #define DA8XX_MENTOR_CORE_OFFSET 0x400 | ||
80 | |||
81 | #define CFGCHIP2 IO_ADDRESS(DA8XX_SYSCFG0_BASE + DA8XX_CFGCHIP2_REG) | ||
82 | |||
83 | struct da8xx_glue { | ||
84 | struct device *dev; | ||
85 | struct platform_device *musb; | ||
86 | struct clk *clk; | ||
87 | }; | ||
88 | |||
89 | /* | ||
90 | * REVISIT (PM): we should be able to keep the PHY in low power mode most | ||
91 | * of the time (24 MHz oscillator and PLL off, etc.) by setting POWER.D0 | ||
92 | * and, when in host mode, autosuspending idle root ports... PHY_PLLON | ||
93 | * (overriding SUSPENDM?) then likely needs to stay off. | ||
94 | */ | ||
95 | |||
96 | static inline void phy_on(void) | ||
97 | { | ||
98 | u32 cfgchip2 = __raw_readl(CFGCHIP2); | ||
99 | |||
100 | /* | ||
101 | * Start the on-chip PHY and its PLL. | ||
102 | */ | ||
103 | cfgchip2 &= ~(CFGCHIP2_RESET | CFGCHIP2_PHYPWRDN | CFGCHIP2_OTGPWRDN); | ||
104 | cfgchip2 |= CFGCHIP2_PHY_PLLON; | ||
105 | __raw_writel(cfgchip2, CFGCHIP2); | ||
106 | |||
107 | pr_info("Waiting for USB PHY clock good...\n"); | ||
108 | while (!(__raw_readl(CFGCHIP2) & CFGCHIP2_PHYCLKGD)) | ||
109 | cpu_relax(); | ||
110 | } | ||
111 | |||
112 | static inline void phy_off(void) | ||
113 | { | ||
114 | u32 cfgchip2 = __raw_readl(CFGCHIP2); | ||
115 | |||
116 | /* | ||
117 | * Ensure that USB 1.1 reference clock is not being sourced from | ||
118 | * USB 2.0 PHY. Otherwise do not power down the PHY. | ||
119 | */ | ||
120 | if (!(cfgchip2 & CFGCHIP2_USB1PHYCLKMUX) && | ||
121 | (cfgchip2 & CFGCHIP2_USB1SUSPENDM)) { | ||
122 | pr_warning("USB 1.1 clocked from USB 2.0 PHY -- " | ||
123 | "can't power it down\n"); | ||
124 | return; | ||
125 | } | ||
126 | |||
127 | /* | ||
128 | * Power down the on-chip PHY. | ||
129 | */ | ||
130 | cfgchip2 |= CFGCHIP2_PHYPWRDN | CFGCHIP2_OTGPWRDN; | ||
131 | __raw_writel(cfgchip2, CFGCHIP2); | ||
132 | } | ||
133 | |||
134 | /* | ||
135 | * Because we don't set CTRL.UINT, it's "important" to: | ||
136 | * - not read/write INTRUSB/INTRUSBE (except during | ||
137 | * initial setup, as a workaround); | ||
138 | * - use INTSET/INTCLR instead. | ||
139 | */ | ||
140 | |||
141 | /** | ||
142 | * da8xx_musb_enable - enable interrupts | ||
143 | */ | ||
144 | static void da8xx_musb_enable(struct musb *musb) | ||
145 | { | ||
146 | void __iomem *reg_base = musb->ctrl_base; | ||
147 | u32 mask; | ||
148 | |||
149 | /* Workaround: setup IRQs through both register sets. */ | ||
150 | mask = ((musb->epmask & DA8XX_USB_TX_EP_MASK) << DA8XX_INTR_TX_SHIFT) | | ||
151 | ((musb->epmask & DA8XX_USB_RX_EP_MASK) << DA8XX_INTR_RX_SHIFT) | | ||
152 | DA8XX_INTR_USB_MASK; | ||
153 | musb_writel(reg_base, DA8XX_USB_INTR_MASK_SET_REG, mask); | ||
154 | |||
155 | /* Force the DRVVBUS IRQ so we can start polling for ID change. */ | ||
156 | if (is_otg_enabled(musb)) | ||
157 | musb_writel(reg_base, DA8XX_USB_INTR_SRC_SET_REG, | ||
158 | DA8XX_INTR_DRVVBUS << DA8XX_INTR_USB_SHIFT); | ||
159 | } | ||
160 | |||
161 | /** | ||
162 | * da8xx_musb_disable - disable HDRC and flush interrupts | ||
163 | */ | ||
164 | static void da8xx_musb_disable(struct musb *musb) | ||
165 | { | ||
166 | void __iomem *reg_base = musb->ctrl_base; | ||
167 | |||
168 | musb_writel(reg_base, DA8XX_USB_INTR_MASK_CLEAR_REG, | ||
169 | DA8XX_INTR_USB_MASK | | ||
170 | DA8XX_INTR_TX_MASK | DA8XX_INTR_RX_MASK); | ||
171 | musb_writeb(musb->mregs, MUSB_DEVCTL, 0); | ||
172 | musb_writel(reg_base, DA8XX_USB_END_OF_INTR_REG, 0); | ||
173 | } | ||
174 | |||
175 | #ifdef CONFIG_USB_MUSB_HDRC_HCD | ||
176 | #define portstate(stmt) stmt | ||
177 | #else | ||
178 | #define portstate(stmt) | ||
179 | #endif | ||
180 | |||
181 | static void da8xx_musb_set_vbus(struct musb *musb, int is_on) | ||
182 | { | ||
183 | WARN_ON(is_on && is_peripheral_active(musb)); | ||
184 | } | ||
185 | |||
186 | #define POLL_SECONDS 2 | ||
187 | |||
188 | static struct timer_list otg_workaround; | ||
189 | |||
190 | static void otg_timer(unsigned long _musb) | ||
191 | { | ||
192 | struct musb *musb = (void *)_musb; | ||
193 | void __iomem *mregs = musb->mregs; | ||
194 | u8 devctl; | ||
195 | unsigned long flags; | ||
196 | |||
197 | /* | ||
198 | * We poll because DaVinci's won't expose several OTG-critical | ||
199 | * status change events (from the transceiver) otherwise. | ||
200 | */ | ||
201 | devctl = musb_readb(mregs, MUSB_DEVCTL); | ||
202 | dev_dbg(musb->controller, "Poll devctl %02x (%s)\n", devctl, | ||
203 | otg_state_string(musb->xceiv->state)); | ||
204 | |||
205 | spin_lock_irqsave(&musb->lock, flags); | ||
206 | switch (musb->xceiv->state) { | ||
207 | case OTG_STATE_A_WAIT_BCON: | ||
208 | devctl &= ~MUSB_DEVCTL_SESSION; | ||
209 | musb_writeb(musb->mregs, MUSB_DEVCTL, devctl); | ||
210 | |||
211 | devctl = musb_readb(musb->mregs, MUSB_DEVCTL); | ||
212 | if (devctl & MUSB_DEVCTL_BDEVICE) { | ||
213 | musb->xceiv->state = OTG_STATE_B_IDLE; | ||
214 | MUSB_DEV_MODE(musb); | ||
215 | } else { | ||
216 | musb->xceiv->state = OTG_STATE_A_IDLE; | ||
217 | MUSB_HST_MODE(musb); | ||
218 | } | ||
219 | break; | ||
220 | case OTG_STATE_A_WAIT_VFALL: | ||
221 | /* | ||
222 | * Wait till VBUS falls below SessionEnd (~0.2 V); the 1.3 | ||
223 | * RTL seems to mis-handle session "start" otherwise (or in | ||
224 | * our case "recover"), in routine "VBUS was valid by the time | ||
225 | * VBUSERR got reported during enumeration" cases. | ||
226 | */ | ||
227 | if (devctl & MUSB_DEVCTL_VBUS) { | ||
228 | mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ); | ||
229 | break; | ||
230 | } | ||
231 | musb->xceiv->state = OTG_STATE_A_WAIT_VRISE; | ||
232 | musb_writel(musb->ctrl_base, DA8XX_USB_INTR_SRC_SET_REG, | ||
233 | MUSB_INTR_VBUSERROR << DA8XX_INTR_USB_SHIFT); | ||
234 | break; | ||
235 | case OTG_STATE_B_IDLE: | ||
236 | if (!is_peripheral_enabled(musb)) | ||
237 | break; | ||
238 | |||
239 | /* | ||
240 | * There's no ID-changed IRQ, so we have no good way to tell | ||
241 | * when to switch to the A-Default state machine (by setting | ||
242 | * the DEVCTL.Session bit). | ||
243 | * | ||
244 | * Workaround: whenever we're in B_IDLE, try setting the | ||
245 | * session flag every few seconds. If it works, ID was | ||
246 | * grounded and we're now in the A-Default state machine. | ||
247 | * | ||
248 | * NOTE: setting the session flag is _supposed_ to trigger | ||
249 | * SRP but clearly it doesn't. | ||
250 | */ | ||
251 | musb_writeb(mregs, MUSB_DEVCTL, devctl | MUSB_DEVCTL_SESSION); | ||
252 | devctl = musb_readb(mregs, MUSB_DEVCTL); | ||
253 | if (devctl & MUSB_DEVCTL_BDEVICE) | ||
254 | mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ); | ||
255 | else | ||
256 | musb->xceiv->state = OTG_STATE_A_IDLE; | ||
257 | break; | ||
258 | default: | ||
259 | break; | ||
260 | } | ||
261 | spin_unlock_irqrestore(&musb->lock, flags); | ||
262 | } | ||
263 | |||
264 | static void da8xx_musb_try_idle(struct musb *musb, unsigned long timeout) | ||
265 | { | ||
266 | static unsigned long last_timer; | ||
267 | |||
268 | if (!is_otg_enabled(musb)) | ||
269 | return; | ||
270 | |||
271 | if (timeout == 0) | ||
272 | timeout = jiffies + msecs_to_jiffies(3); | ||
273 | |||
274 | /* Never idle if active, or when VBUS timeout is not set as host */ | ||
275 | if (musb->is_active || (musb->a_wait_bcon == 0 && | ||
276 | musb->xceiv->state == OTG_STATE_A_WAIT_BCON)) { | ||
277 | dev_dbg(musb->controller, "%s active, deleting timer\n", | ||
278 | otg_state_string(musb->xceiv->state)); | ||
279 | del_timer(&otg_workaround); | ||
280 | last_timer = jiffies; | ||
281 | return; | ||
282 | } | ||
283 | |||
284 | if (time_after(last_timer, timeout) && timer_pending(&otg_workaround)) { | ||
285 | dev_dbg(musb->controller, "Longer idle timer already pending, ignoring...\n"); | ||
286 | return; | ||
287 | } | ||
288 | last_timer = timeout; | ||
289 | |||
290 | dev_dbg(musb->controller, "%s inactive, starting idle timer for %u ms\n", | ||
291 | otg_state_string(musb->xceiv->state), | ||
292 | jiffies_to_msecs(timeout - jiffies)); | ||
293 | mod_timer(&otg_workaround, timeout); | ||
294 | } | ||
295 | |||
296 | static irqreturn_t da8xx_musb_interrupt(int irq, void *hci) | ||
297 | { | ||
298 | struct musb *musb = hci; | ||
299 | void __iomem *reg_base = musb->ctrl_base; | ||
300 | unsigned long flags; | ||
301 | irqreturn_t ret = IRQ_NONE; | ||
302 | u32 status; | ||
303 | |||
304 | spin_lock_irqsave(&musb->lock, flags); | ||
305 | |||
306 | /* | ||
307 | * NOTE: DA8XX shadows the Mentor IRQs. Don't manage them through | ||
308 | * the Mentor registers (except for setup), use the TI ones and EOI. | ||
309 | */ | ||
310 | |||
311 | /* Acknowledge and handle non-CPPI interrupts */ | ||
312 | status = musb_readl(reg_base, DA8XX_USB_INTR_SRC_MASKED_REG); | ||
313 | if (!status) | ||
314 | goto eoi; | ||
315 | |||
316 | musb_writel(reg_base, DA8XX_USB_INTR_SRC_CLEAR_REG, status); | ||
317 | dev_dbg(musb->controller, "USB IRQ %08x\n", status); | ||
318 | |||
319 | musb->int_rx = (status & DA8XX_INTR_RX_MASK) >> DA8XX_INTR_RX_SHIFT; | ||
320 | musb->int_tx = (status & DA8XX_INTR_TX_MASK) >> DA8XX_INTR_TX_SHIFT; | ||
321 | musb->int_usb = (status & DA8XX_INTR_USB_MASK) >> DA8XX_INTR_USB_SHIFT; | ||
322 | |||
323 | /* | ||
324 | * DRVVBUS IRQs are the only proxy we have (a very poor one!) for | ||
325 | * DA8xx's missing ID change IRQ. We need an ID change IRQ to | ||
326 | * switch appropriately between halves of the OTG state machine. | ||
327 | * Managing DEVCTL.Session per Mentor docs requires that we know its | ||
328 | * value but DEVCTL.BDevice is invalid without DEVCTL.Session set. | ||
329 | * Also, DRVVBUS pulses for SRP (but not at 5 V)... | ||
330 | */ | ||
331 | if (status & (DA8XX_INTR_DRVVBUS << DA8XX_INTR_USB_SHIFT)) { | ||
332 | int drvvbus = musb_readl(reg_base, DA8XX_USB_STAT_REG); | ||
333 | void __iomem *mregs = musb->mregs; | ||
334 | u8 devctl = musb_readb(mregs, MUSB_DEVCTL); | ||
335 | int err; | ||
336 | |||
337 | err = is_host_enabled(musb) && (musb->int_usb & | ||
338 | MUSB_INTR_VBUSERROR); | ||
339 | if (err) { | ||
340 | /* | ||
341 | * The Mentor core doesn't debounce VBUS as needed | ||
342 | * to cope with device connect current spikes. This | ||
343 | * means it's not uncommon for bus-powered devices | ||
344 | * to get VBUS errors during enumeration. | ||
345 | * | ||
346 | * This is a workaround, but newer RTL from Mentor | ||
347 | * seems to allow a better one: "re"-starting sessions | ||
348 | * without waiting for VBUS to stop registering in | ||
349 | * devctl. | ||
350 | */ | ||
351 | musb->int_usb &= ~MUSB_INTR_VBUSERROR; | ||
352 | musb->xceiv->state = OTG_STATE_A_WAIT_VFALL; | ||
353 | mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ); | ||
354 | WARNING("VBUS error workaround (delay coming)\n"); | ||
355 | } else if (is_host_enabled(musb) && drvvbus) { | ||
356 | MUSB_HST_MODE(musb); | ||
357 | musb->xceiv->default_a = 1; | ||
358 | musb->xceiv->state = OTG_STATE_A_WAIT_VRISE; | ||
359 | portstate(musb->port1_status |= USB_PORT_STAT_POWER); | ||
360 | del_timer(&otg_workaround); | ||
361 | } else { | ||
362 | musb->is_active = 0; | ||
363 | MUSB_DEV_MODE(musb); | ||
364 | musb->xceiv->default_a = 0; | ||
365 | musb->xceiv->state = OTG_STATE_B_IDLE; | ||
366 | portstate(musb->port1_status &= ~USB_PORT_STAT_POWER); | ||
367 | } | ||
368 | |||
369 | dev_dbg(musb->controller, "VBUS %s (%s)%s, devctl %02x\n", | ||
370 | drvvbus ? "on" : "off", | ||
371 | otg_state_string(musb->xceiv->state), | ||
372 | err ? " ERROR" : "", | ||
373 | devctl); | ||
374 | ret = IRQ_HANDLED; | ||
375 | } | ||
376 | |||
377 | if (musb->int_tx || musb->int_rx || musb->int_usb) | ||
378 | ret |= musb_interrupt(musb); | ||
379 | |||
380 | eoi: | ||
381 | /* EOI needs to be written for the IRQ to be re-asserted. */ | ||
382 | if (ret == IRQ_HANDLED || status) | ||
383 | musb_writel(reg_base, DA8XX_USB_END_OF_INTR_REG, 0); | ||
384 | |||
385 | /* Poll for ID change */ | ||
386 | if (is_otg_enabled(musb) && musb->xceiv->state == OTG_STATE_B_IDLE) | ||
387 | mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ); | ||
388 | |||
389 | spin_unlock_irqrestore(&musb->lock, flags); | ||
390 | |||
391 | return ret; | ||
392 | } | ||
393 | |||
394 | static int da8xx_musb_set_mode(struct musb *musb, u8 musb_mode) | ||
395 | { | ||
396 | u32 cfgchip2 = __raw_readl(CFGCHIP2); | ||
397 | |||
398 | cfgchip2 &= ~CFGCHIP2_OTGMODE; | ||
399 | switch (musb_mode) { | ||
400 | #ifdef CONFIG_USB_MUSB_HDRC_HCD | ||
401 | case MUSB_HOST: /* Force VBUS valid, ID = 0 */ | ||
402 | cfgchip2 |= CFGCHIP2_FORCE_HOST; | ||
403 | break; | ||
404 | #endif | ||
405 | #ifdef CONFIG_USB_GADGET_MUSB_HDRC | ||
406 | case MUSB_PERIPHERAL: /* Force VBUS valid, ID = 1 */ | ||
407 | cfgchip2 |= CFGCHIP2_FORCE_DEVICE; | ||
408 | break; | ||
409 | #endif | ||
410 | #ifdef CONFIG_USB_MUSB_OTG | ||
411 | case MUSB_OTG: /* Don't override the VBUS/ID comparators */ | ||
412 | cfgchip2 |= CFGCHIP2_NO_OVERRIDE; | ||
413 | break; | ||
414 | #endif | ||
415 | default: | ||
416 | dev_dbg(musb->controller, "Trying to set unsupported mode %u\n", musb_mode); | ||
417 | } | ||
418 | |||
419 | __raw_writel(cfgchip2, CFGCHIP2); | ||
420 | return 0; | ||
421 | } | ||
422 | |||
423 | static int da8xx_musb_init(struct musb *musb) | ||
424 | { | ||
425 | void __iomem *reg_base = musb->ctrl_base; | ||
426 | u32 rev; | ||
427 | |||
428 | musb->mregs += DA8XX_MENTOR_CORE_OFFSET; | ||
429 | |||
430 | /* Returns zero if e.g. not clocked */ | ||
431 | rev = musb_readl(reg_base, DA8XX_USB_REVISION_REG); | ||
432 | if (!rev) | ||
433 | goto fail; | ||
434 | |||
435 | usb_nop_xceiv_register(); | ||
436 | musb->xceiv = otg_get_transceiver(); | ||
437 | if (!musb->xceiv) | ||
438 | goto fail; | ||
439 | |||
440 | if (is_host_enabled(musb)) | ||
441 | setup_timer(&otg_workaround, otg_timer, (unsigned long)musb); | ||
442 | |||
443 | /* Reset the controller */ | ||
444 | musb_writel(reg_base, DA8XX_USB_CTRL_REG, DA8XX_SOFT_RESET_MASK); | ||
445 | |||
446 | /* Start the on-chip PHY and its PLL. */ | ||
447 | phy_on(); | ||
448 | |||
449 | msleep(5); | ||
450 | |||
451 | /* NOTE: IRQs are in mixed mode, not bypass to pure MUSB */ | ||
452 | pr_debug("DA8xx OTG revision %08x, PHY %03x, control %02x\n", | ||
453 | rev, __raw_readl(CFGCHIP2), | ||
454 | musb_readb(reg_base, DA8XX_USB_CTRL_REG)); | ||
455 | |||
456 | musb->isr = da8xx_musb_interrupt; | ||
457 | return 0; | ||
458 | fail: | ||
459 | return -ENODEV; | ||
460 | } | ||
461 | |||
462 | static int da8xx_musb_exit(struct musb *musb) | ||
463 | { | ||
464 | if (is_host_enabled(musb)) | ||
465 | del_timer_sync(&otg_workaround); | ||
466 | |||
467 | phy_off(); | ||
468 | |||
469 | otg_put_transceiver(musb->xceiv); | ||
470 | usb_nop_xceiv_unregister(); | ||
471 | |||
472 | return 0; | ||
473 | } | ||
474 | |||
475 | static const struct musb_platform_ops da8xx_ops = { | ||
476 | .init = da8xx_musb_init, | ||
477 | .exit = da8xx_musb_exit, | ||
478 | |||
479 | .enable = da8xx_musb_enable, | ||
480 | .disable = da8xx_musb_disable, | ||
481 | |||
482 | .set_mode = da8xx_musb_set_mode, | ||
483 | .try_idle = da8xx_musb_try_idle, | ||
484 | |||
485 | .set_vbus = da8xx_musb_set_vbus, | ||
486 | }; | ||
487 | |||
488 | static u64 da8xx_dmamask = DMA_BIT_MASK(32); | ||
489 | |||
490 | static int __init da8xx_probe(struct platform_device *pdev) | ||
491 | { | ||
492 | struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data; | ||
493 | struct platform_device *musb; | ||
494 | struct da8xx_glue *glue; | ||
495 | |||
496 | struct clk *clk; | ||
497 | |||
498 | int ret = -ENOMEM; | ||
499 | |||
500 | glue = kzalloc(sizeof(*glue), GFP_KERNEL); | ||
501 | if (!glue) { | ||
502 | dev_err(&pdev->dev, "failed to allocate glue context\n"); | ||
503 | goto err0; | ||
504 | } | ||
505 | |||
506 | musb = platform_device_alloc("musb-hdrc", -1); | ||
507 | if (!musb) { | ||
508 | dev_err(&pdev->dev, "failed to allocate musb device\n"); | ||
509 | goto err1; | ||
510 | } | ||
511 | |||
512 | clk = clk_get(&pdev->dev, "usb20"); | ||
513 | if (IS_ERR(clk)) { | ||
514 | dev_err(&pdev->dev, "failed to get clock\n"); | ||
515 | ret = PTR_ERR(clk); | ||
516 | goto err2; | ||
517 | } | ||
518 | |||
519 | ret = clk_enable(clk); | ||
520 | if (ret) { | ||
521 | dev_err(&pdev->dev, "failed to enable clock\n"); | ||
522 | goto err3; | ||
523 | } | ||
524 | |||
525 | musb->dev.parent = &pdev->dev; | ||
526 | musb->dev.dma_mask = &da8xx_dmamask; | ||
527 | musb->dev.coherent_dma_mask = da8xx_dmamask; | ||
528 | |||
529 | glue->dev = &pdev->dev; | ||
530 | glue->musb = musb; | ||
531 | glue->clk = clk; | ||
532 | |||
533 | pdata->platform_ops = &da8xx_ops; | ||
534 | |||
535 | platform_set_drvdata(pdev, glue); | ||
536 | |||
537 | ret = platform_device_add_resources(musb, pdev->resource, | ||
538 | pdev->num_resources); | ||
539 | if (ret) { | ||
540 | dev_err(&pdev->dev, "failed to add resources\n"); | ||
541 | goto err4; | ||
542 | } | ||
543 | |||
544 | ret = platform_device_add_data(musb, pdata, sizeof(*pdata)); | ||
545 | if (ret) { | ||
546 | dev_err(&pdev->dev, "failed to add platform_data\n"); | ||
547 | goto err4; | ||
548 | } | ||
549 | |||
550 | ret = platform_device_add(musb); | ||
551 | if (ret) { | ||
552 | dev_err(&pdev->dev, "failed to register musb device\n"); | ||
553 | goto err4; | ||
554 | } | ||
555 | |||
556 | return 0; | ||
557 | |||
558 | err4: | ||
559 | clk_disable(clk); | ||
560 | |||
561 | err3: | ||
562 | clk_put(clk); | ||
563 | |||
564 | err2: | ||
565 | platform_device_put(musb); | ||
566 | |||
567 | err1: | ||
568 | kfree(glue); | ||
569 | |||
570 | err0: | ||
571 | return ret; | ||
572 | } | ||
573 | |||
574 | static int __exit da8xx_remove(struct platform_device *pdev) | ||
575 | { | ||
576 | struct da8xx_glue *glue = platform_get_drvdata(pdev); | ||
577 | |||
578 | platform_device_del(glue->musb); | ||
579 | platform_device_put(glue->musb); | ||
580 | clk_disable(glue->clk); | ||
581 | clk_put(glue->clk); | ||
582 | kfree(glue); | ||
583 | |||
584 | return 0; | ||
585 | } | ||
586 | |||
587 | static struct platform_driver da8xx_driver = { | ||
588 | .remove = __exit_p(da8xx_remove), | ||
589 | .driver = { | ||
590 | .name = "musb-da8xx", | ||
591 | }, | ||
592 | }; | ||
593 | |||
594 | MODULE_DESCRIPTION("DA8xx/OMAP-L1x MUSB Glue Layer"); | ||
595 | MODULE_AUTHOR("Sergei Shtylyov <sshtylyov@ru.mvista.com>"); | ||
596 | MODULE_LICENSE("GPL v2"); | ||
597 | |||
598 | static int __init da8xx_init(void) | ||
599 | { | ||
600 | return platform_driver_probe(&da8xx_driver, da8xx_probe); | ||
601 | } | ||
602 | subsys_initcall(da8xx_init); | ||
603 | |||
604 | static void __exit da8xx_exit(void) | ||
605 | { | ||
606 | platform_driver_unregister(&da8xx_driver); | ||
607 | } | ||
608 | module_exit(da8xx_exit); | ||