MUSB: Fix TUSB register access
[pandora-kernel.git] / drivers / usb / musb / tusb6010.c
1 /*
2  * TUSB6010 USB 2.0 OTG Dual Role controller
3  *
4  * Copyright (C) 2006 Nokia Corporation
5  * Jarkko Nikula <jarkko.nikula@nokia.com>
6  * Tony Lindgren <tony@atomide.com>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 as
10  * published by the Free Software Foundation.
11  *
12  * Notes:
13  * - Driver assumes that interface to external host (main CPU) is
14  *   configured for NOR FLASH interface instead of VLYNQ serial
15  *   interface.
16  */
17
18 #include <linux/config.h>
19 #include <linux/module.h>
20 #include <linux/kernel.h>
21 #include <linux/errno.h>
22 #include <linux/init.h>
23 #include <linux/usb.h>
24 #include <linux/irq.h>
25 #include <linux/platform_device.h>
26
27 #include "musbdefs.h"
28
29
30 /*
31  * TUSB 6010 may use a parallel bus that doesn't support byte ops;
32  * so both loading and unloading FIFOs need explicit byte counts.
33  */
34
35 void musb_write_fifo(struct musb_hw_ep *hw_ep, u16 len, const u8 *buf)
36 {
37         void __iomem    *ep_conf = hw_ep->conf;
38         void __iomem    *fifo = hw_ep->fifo;
39         u8              epnum = hw_ep->bLocalEnd;
40         u8              *bufp = (u8 *)buf;
41         int             i, remain;
42         u32             val;
43
44         prefetch(bufp);
45
46         DBG(3, "%cX ep%d count %d bufp %p\n", 'T', epnum, len, bufp);
47
48         if (epnum)
49                 musb_writel(ep_conf, TUSB_EP_TX_OFFSET,
50                             TUSB_EP_CONFIG_XFR_SIZE(len));
51         else
52                 musb_writel(ep_conf, 0, TUSB_EP0_CONFIG_DIR_TX |
53                             TUSB_EP0_CONFIG_XFR_SIZE(len));
54
55         /* Write 32-bit blocks from buffer to FIFO
56          * REVISIT: Optimize for burst ... writesl/writesw
57          */
58         if (len >= 4) {
59                 if (((unsigned long)bufp & 0x3) == 0) {
60                         for (i = 0; i < (len / 4); i++ ) {
61                                 val = *(u32 *)bufp;
62                                 bufp += 4;
63                                 musb_writel(fifo, 0, val);
64                         }
65                 } else if (((unsigned long)bufp & 0x2) == 0x2) {
66                         for (i = 0; i < (len / 4); i++ ) {
67                                 val = (u32)(*(u16 *)bufp);
68                                 bufp += 2;
69                                 val |= (*(u16 *)bufp) << 16;
70                                 bufp += 2;
71                                 musb_writel(fifo, 0, val);
72                         }
73                 } else {
74                         for (i = 0; i < (len / 4); i++ ) {
75                                 memcpy(&val, bufp, 4);
76                                 bufp += 4;
77                                 musb_writel(fifo, 0, val);
78                         }
79                 }
80                 remain = len - (i * 4);
81         } else
82                 remain = len;
83
84         if (remain) {
85                 /* Write rest of 1-3 bytes from buffer into FIFO */
86                 memcpy(&val, bufp, remain);
87                 musb_writel(fifo, 0, val);
88         }
89 }
90
91 void musb_read_fifo(struct musb_hw_ep *hw_ep, u16 len, u8 *buf)
92 {
93         void __iomem    *ep_conf = hw_ep->conf;
94         void __iomem    *fifo = hw_ep->fifo;
95         u8              epnum = hw_ep->bLocalEnd;
96         u8              *bufp = (u8 *)buf;
97         int             i, remain;
98         u32             val;
99
100         DBG(3, "%cX ep%d count %d buf %p\n", 'R', epnum, len, bufp);
101
102         if (epnum)
103                 musb_writel(ep_conf, TUSB_EP_RX_OFFSET,
104                             TUSB_EP_CONFIG_XFR_SIZE(len));
105         else
106                 musb_writel(ep_conf, 0, TUSB_EP0_CONFIG_XFR_SIZE(len));
107
108         /* Read 32-bit blocks from FIFO to buffer
109          * REVISIT: Optimize for burst ... writesl/writesw
110          */
111         if (len >= 4) {
112                 if (((unsigned long)bufp & 0x3) == 0) {
113                         for (i = 0; i < (len / 4); i++) {
114                                 val = musb_readl(fifo, 0);
115                                 *(u32 *)bufp = val;
116                                 bufp += 4;
117                         }
118                 } else if (((unsigned long)bufp & 0x2) == 0x2) {
119                         for (i = 0; i < (len / 4); i++) {
120                                 val = musb_readl(fifo, 0);
121                                 *(u16 *)bufp = (u16)(val & 0xffff);
122                                 bufp += 2;
123                                 *(u16 *)bufp = (u16)(val >> 16);
124                                 bufp += 2;
125                         }
126                 } else {
127                         for (i = 0; i < (len / 4); i++) {
128                                 val = musb_readl(fifo, 0);
129                                 memcpy(bufp, &val, 4);
130                                 bufp += 4;
131                         }
132                 }
133                 remain = len - (i * 4);
134         } else
135                 remain = len;
136
137         if (remain) {
138                 /* Read rest of 1-3 bytes from FIFO */
139                 val = musb_readl(fifo, 0);
140                 memcpy(bufp, &val, remain);
141         }
142 }
143
144 /*
145  * Enables TUSB6010 to use VBUS as power source in peripheral mode.
146  */
147 static inline void tusb_enable_vbus_charge(struct musb *musb)
148 {
149         void __iomem    *base = musb->ctrl_base;
150         u32             reg;
151
152         musb_writel(base, TUSB_PRCM_WAKEUP_MASK, 0xffff);
153         reg = musb_readl(base, TUSB_PRCM_MNGMT);
154         reg &= ~TUSB_PRCM_MNGMT_SUSPEND_MASK;
155         reg |= TUSB_PRCM_MNGMT_CPEN_MASK;
156         musb_writel(base, TUSB_PRCM_MNGMT, reg);
157 }
158
159 /*
160  * Idles TUSB6010 until next wake-up event interrupt. Use all wake-up
161  * events for now. Note that TUSB will not respond if NOR chip select
162  * wake-up event is masked. Also note that any access to TUSB will wake
163  * it up from idle.
164  */
165 static inline void tusb_allow_idle(struct musb *musb, int wakeup_mask)
166 {
167         void __iomem    *base = musb->ctrl_base;
168         u32             reg;
169
170         musb_writel(base, TUSB_PRCM_WAKEUP_MASK, wakeup_mask);
171         reg = musb_readl(base, TUSB_PRCM_MNGMT);
172         reg &= ~TUSB_PRCM_MNGMT_CPEN_MASK;
173         reg |= TUSB_PRCM_MNGMT_SUSPEND_MASK;
174         musb_writel(base, TUSB_PRCM_MNGMT, reg);
175 }
176
177 /*
178  * Updates cable VBUS status. Caller must take care of locking.
179  */
180 int musb_platform_get_vbus_status(struct musb *musb)
181 {
182         void __iomem    *base = musb->ctrl_base;
183         u32             otg_stat, prcm_mngmt;
184         int             ret = 0;
185
186         otg_stat = musb_readl(base, TUSB_DEV_OTG_STAT);
187         prcm_mngmt = musb_readl(base, TUSB_PRCM_MNGMT);
188
189         /* Temporarily enable VBUS detection if it was disabled for
190          * suspend mode. Unless it's enabled otg_stat and devctl will
191          * not show correct VBUS state.
192          */
193         if (!(prcm_mngmt & TUSB_PRCM_MNGMT_OTG_VBUS_DET_EN)) {
194                 u32 tmp = prcm_mngmt;
195                 tmp |= TUSB_PRCM_MNGMT_OTG_VBUS_DET_EN;
196                 musb_writel(base, TUSB_PRCM_MNGMT, tmp);
197                 otg_stat = musb_readl(base, TUSB_DEV_OTG_STAT);
198                 musb_writel(base, TUSB_PRCM_MNGMT, prcm_mngmt);
199         }
200
201         if (otg_stat & TUSB_DEV_OTG_STAT_VBUS_SENSE)
202                 ret = 1;
203
204         return ret;
205 }
206
207 /*
208  * Sets the TUSB6010 idles mode in peripheral mode depending on the
209  * gadget driver state and cable VBUS status. Needs to be called as
210  * the last function everywhere where there is register access to
211  * TUSB6010 because of the NOR flash wake-up capability.
212  * Caller must take care of locking.
213  */
214 void musb_platform_try_idle(struct musb *musb)
215 {
216         u32             wakeup_mask = 0;
217
218         /* Suspend with only NOR flash wake-up event enabled if no
219          * gadget driver is active.
220          */
221         if (musb->xceiv.state == OTG_STATE_UNDEFINED) {
222                 wakeup_mask = 0xffff & ~TUSB_PRCM_WNORCS;
223                 tusb_allow_idle(musb, wakeup_mask);
224                 return;
225         }
226
227         /* Use VBUS as power source if available, otherwise suspend
228          * with all wake-up events enabled.
229          *
230          * FIXME only B-device state machine ever _consumes_ VBUS.
231          */
232         if (musb_platform_get_vbus_status(musb))
233                 tusb_enable_vbus_charge(musb);
234         else {
235                 wakeup_mask = TUSB_PRCM_WLD;
236                 tusb_allow_idle(musb, wakeup_mask);
237         }
238 }
239
240 irqreturn_t tusb_interrupt(int irq, void *__hci, struct pt_regs *r)
241 {
242         struct musb     *musb = __hci;
243         void __iomem    *base = musb->ctrl_base;
244         unsigned long   flags;
245         u32             dma_src, int_src, otg_stat, musb_src = 0;
246
247         spin_lock_irqsave(&musb->Lock, flags);
248
249         dma_src = musb_readl(base, TUSB_DMA_INT_SRC);
250         int_src = musb_readl(base, TUSB_INT_SRC) & ~TUSB_INT_SRC_RESERVED_BITS;
251         otg_stat = musb_readl(base, TUSB_DEV_OTG_STAT);
252
253         DBG(3, "TUSB interrupt dma: %08x int: %08x otg: %08x\n",
254             dma_src, int_src, otg_stat);
255
256         musb->int_usb = 0;
257         musb->int_rx = 0;
258         musb->int_tx = 0;
259         musb->int_regs = r;
260
261         if (otg_stat & TUSB_DEV_OTG_STAT_ID_STATUS) {
262                 /* ID pin is up. Either A-plug was removed or TUSB6010
263                  * is in peripheral mode */
264
265                 /* Still in pheripheral mode? */
266                 if ((int_src & TUSB_INT_SRC_ID_STATUS_CHNG)) {
267                         DBG(3, "tusb: Status change\n");
268                         //goto out;
269                 }
270         }
271
272         /* Peripheral suspend. Cable may be disconnected, try to idle */
273         if (int_src & TUSB_INT_SRC_USB_IP_SUSPEND) {
274                 musb->status |= MUSB_VBUS_STATUS_CHG;
275                 schedule_work(&musb->irq_work);
276         }
277
278         /* Connect and disconnect for host mode */
279         if (int_src & TUSB_INT_SRC_USB_IP_CONN) {
280                 DBG(3, "tusb: Connected\n");
281         }
282         else if (int_src & TUSB_INT_SRC_USB_IP_DISCON) {
283                 DBG(3, "tusb: Disconnected\n");
284         }
285
286         /* VBUS state change */
287         if ((int_src & TUSB_INT_SRC_VBUS_SENSE_CHNG) ||
288             (int_src & TUSB_INT_SRC_USB_IP_VBUS_ERR))
289         {
290                 musb->status |= MUSB_VBUS_STATUS_CHG;
291                 schedule_work(&musb->irq_work);
292
293 #if 0
294                 DBG(3, "tusb: VBUS changed. VBUS state %d\n",
295                     (otg_stat & TUSB_DEV_OTG_STAT_VBUS_SENSE) ? 1 : 0);
296                 if (!(otg_stat & TUSB_DEV_OTG_STAT_VBUS_SENSE) &&
297                     !(otg_stat & TUSB_DEV_OTG_STAT_ID_STATUS)) {
298                         /* VBUS went off and ID pin is down */
299                         DBG(3, "tusb: No VBUS, starting session\n");
300                         /* Start session again, VBUS will be enabled */
301                         musb_writeb(musb_base, MGC_O_HDRC_DEVCTL,
302                                 MGC_M_DEVCTL_SESSION);
303                 }
304 #endif
305         }
306
307         /* ID pin change */
308         if (int_src & TUSB_INT_SRC_ID_STATUS_CHNG) {
309                 DBG(3, "tusb: ID pin changed. State is %d\n",
310                     (musb_readl(base, TUSB_DEV_OTG_STAT) &
311                      TUSB_DEV_OTG_STAT_ID_STATUS) ? 1 : 0);
312         }
313
314         /* OTG timer expiration */
315         if (int_src & TUSB_INT_SRC_OTG_TIMEOUT) {
316                 DBG(3, "tusb: OTG timer expired\n");
317                 musb_writel(base, TUSB_DEV_OTG_TIMER,
318                             musb_readl(base, TUSB_DEV_OTG_TIMER) |
319                             TUSB_DEV_OTG_TIMER_ENABLE);
320         }
321
322         /* TX dma callback must be handled here, RX dma callback is
323          * handled in tusb_omap_dma_cb.
324          */
325         if ((int_src & TUSB_INT_SRC_TXRX_DMA_DONE) && dma_src) {
326                 u32 real_dma_src = musb_readl(base, TUSB_DMA_INT_MASK);
327                 real_dma_src = ~real_dma_src & dma_src;
328                 if (tusb_dma_omap()) {
329                         int     tx_source = (real_dma_src & 0xffff);
330                         int     i;
331
332                         for (i = 1; i <= 15; i++) {
333                                 if (tx_source & (1 << i)) {
334                                         DBG(1, "completing ep%i %s\n", i, "tx");
335                                         musb_dma_completion(musb, i, 1);
336                                 }
337                         }
338                 }
339                 musb_writel(base, TUSB_DMA_INT_CLEAR, dma_src);
340         }
341
342         /* EP interrupts. In OCP mode tusb6010 mirrors the MUSB * interrupts */
343         if (int_src & (TUSB_INT_SRC_USB_IP_TX | TUSB_INT_SRC_USB_IP_RX)) {
344                 musb_src = musb_readl(base, TUSB_USBIP_INT_SRC);
345                 musb_writel(base, TUSB_USBIP_INT_CLEAR, musb_src);
346                 musb->int_rx = (((musb_src >> 16) & 0xffff) << 1);
347                 musb->int_tx = (musb_src & 0xffff);
348         }
349         musb->int_usb = (int_src & 0xff);
350         if (musb->int_usb || musb->int_rx || musb->int_tx)
351                 musb_interrupt(musb);
352
353         /* Acknowledge wake-up source interrupts */
354         if (int_src & TUSB_INT_SRC_DEV_WAKEUP) {
355                 u32 reg = musb_readl(base, TUSB_PRCM_WAKEUP_SOURCE);
356                 musb_writel(base, TUSB_PRCM_WAKEUP_CLEAR, reg);
357                 schedule_work(&musb->irq_work);
358         }
359
360         /* Acknowledge TUSB interrupts. Clear only non-reserved bits */
361         if (int_src)
362                 musb_writel(base, TUSB_INT_SRC_CLEAR,
363                             int_src & ~TUSB_INT_MASK_RESERVED_BITS);
364
365         spin_unlock_irqrestore(&musb->Lock, flags);
366
367         return IRQ_HANDLED;
368 }
369
370 static int dma_off;
371
372 /*
373  * Enables TUSB6010. Caller must take care of locking.
374  * REVISIT:
375  * - Check what is unnecessary in MGC_HdrcStart()
376  * - Interrupt should really be IRQT_FALLING level sensitive
377  */
378 void musb_platform_enable(struct musb * musb)
379 {
380         void __iomem    *base = musb->ctrl_base;
381
382         /* Setup TUSB6010 main interrupt mask. Enable all interrupts except SOF.
383          * REVISIT: Enable and deal with TUSB_INT_SRC_USB_IP_SOF */
384         musb_writel(base, TUSB_INT_MASK, TUSB_INT_SRC_USB_IP_SOF);
385
386         /* Setup TUSB interrupt, disable DMA and GPIO interrupts */
387         musb_writel(base, TUSB_USBIP_INT_MASK, 0);
388         musb_writel(base, TUSB_DMA_INT_MASK, 0x7fffffff);
389         musb_writel(base, TUSB_GPIO_INT_MASK, 0x1ff);
390
391         /* Clear all subsystem interrups */
392         musb_writel(base, TUSB_USBIP_INT_CLEAR, 0x7fffffff);
393         musb_writel(base, TUSB_DMA_INT_CLEAR, 0x7fffffff);
394         musb_writel(base, TUSB_GPIO_INT_CLEAR, 0x1ff);
395
396         /* Acknowledge pending interrupt(s) */
397         musb_writel(base, TUSB_INT_SRC_CLEAR,
398                     ~TUSB_INT_MASK_RESERVED_BITS);
399
400 #if 0
401         /* Set OTG timer for about one second */
402         musb_writel(base, TUSB_DEV_OTG_TIMER,
403                                 TUSB_DEV_OTG_TIMER_ENABLE |
404                 TUSB_DEV_OTG_TIMER_VAL(0x3c00000));
405 #endif
406
407         /* Only 0 clock cycles for minimum interrupt de-assertion time and
408          * interrupt polarity active low seems to work reliably here */
409         musb_writel(base, TUSB_INT_CTRL_CONF,
410                     TUSB_INT_CTRL_CONF_INT_RELCYC(0));
411
412         set_irq_type(musb->nIrq, IRQ_TYPE_LEVEL_LOW);
413
414         if (is_dma_capable() && dma_off)
415                 printk(KERN_WARNING "%s %s: dma not reactivated\n",
416                                 __FILE__, __FUNCTION__);
417         else
418                 dma_off = 1;
419 }
420
421 /*
422  * Disables TUSB6010. Caller must take care of locking.
423  */
424 void musb_platform_disable(struct musb *musb)
425 {
426         if (is_dma_capable()) {
427                 printk(KERN_WARNING "%s %s: dma still active\n",
428                                 __FILE__, __FUNCTION__);
429                 dma_off = 1;
430         }
431 }
432
433 /*
434  * Sets up TUSB6010 CPU interface specific signals and registers
435  * Note: Settings optimized for OMAP24xx
436  */
437 static void tusb_setup_cpu_interface(struct musb *musb)
438 {
439         void __iomem    *base = musb->ctrl_base;
440
441         /* Disable GPIO[7:0] pullups (used as output DMA requests) */
442         musb_writel(base, TUSB_PULLUP_1_CTRL, 0x000000FF);
443         /* Disable all pullups on NOR IF, DMAREQ0 and DMAREQ1 */
444         musb_writel(base, TUSB_PULLUP_2_CTRL, 0x01FFFFFF);
445
446         /* Turn GPIO[5:0] to DMAREQ[5:0] signals */
447         musb_writel(base, TUSB_GPIO_CONF, TUSB_GPIO_CONF_DMAREQ(0x3f));
448
449         /* Burst size 16x16 bits, all six DMA requests enabled, DMA request
450          * de-assertion time 2 system clocks p 62 */
451         musb_writel(base, TUSB_DMA_REQ_CONF,
452                 TUSB_DMA_REQ_CONF_BURST_SIZE(2) |
453                 TUSB_DMA_REQ_CONF_DMA_REQ_EN(0x3f) |
454                 TUSB_DMA_REQ_CONF_DMA_REQ_ASSER(2));
455
456         /* Set 0 wait count for synchronous burst access */
457         musb_writel(base, TUSB_WAIT_COUNT, 1);
458 }
459
460 #define TUSB_REV_MAJOR(reg_val)         ((reg_val >> 4) & 0xf)
461 #define TUSB_REV_MINOR(reg_val)         (reg_val & 0xf)
462
463 static int tusb_print_revision(struct musb *musb)
464 {
465         void __iomem    *base = musb->ctrl_base;
466
467         pr_info("tusb: Revisions: %s%i.%i %s%i.%i %s%i.%i %s%i.%i\n",
468                 "prcm",
469                 TUSB_REV_MAJOR(musb_readl(base, TUSB_PRCM_REV)),
470                 TUSB_REV_MINOR(musb_readl(base, TUSB_PRCM_REV)),
471                 "int",
472                 TUSB_REV_MAJOR(musb_readl(base, TUSB_INT_CTRL_REV)),
473                 TUSB_REV_MINOR(musb_readl(base, TUSB_INT_CTRL_REV)),
474                 "gpio",
475                 TUSB_REV_MAJOR(musb_readl(base, TUSB_GPIO_REV)),
476                 TUSB_REV_MINOR(musb_readl(base, TUSB_GPIO_REV)),
477                 "dma",
478                 TUSB_REV_MAJOR(musb_readl(base, TUSB_DMA_CTRL_REV)),
479                 TUSB_REV_MINOR(musb_readl(base, TUSB_DMA_CTRL_REV)));
480
481         return TUSB_REV_MAJOR(musb_readl(base, TUSB_INT_CTRL_REV));
482 }
483
484 static int tusb_start(struct musb *musb)
485 {
486         void __iomem    *base = musb->ctrl_base;
487         int             ret = -1;
488         unsigned long   flags;
489
490         if (musb->board_set_power)
491                 ret = musb->board_set_power(1);
492         if (ret != 0) {
493                 printk(KERN_ERR "tusb: Cannot enable TUSB6010\n");
494                 goto err;
495         }
496
497         spin_lock_irqsave(&musb->Lock, flags);
498
499         if (musb_readl(base, TUSB_PROD_TEST_RESET) !=
500                 TUSB_PROD_TEST_RESET_VAL) {
501                 printk(KERN_ERR "tusb: Unable to detect TUSB6010\n");
502                 goto err;
503         }
504
505         ret = tusb_print_revision(musb);
506         if (ret < 2) {
507                 printk(KERN_ERR "tusb: Unsupported TUSB6010 revision %i\n",
508                        ret);
509                 goto err;
510         }
511
512         /* The uint bit for "USB non-PDR interrupt enable" has to be 1 when
513          * NOR FLASH interface is used */
514         musb_writel(base, TUSB_VLYNQ_CTRL, 8);
515
516         /* Select PHY free running 60MHz as a system clock */
517         musb_writel(base, TUSB_PRCM_CONF, //FIXME: CPEN should not be needed!
518                     TUSB_PRCM_CONF_SFW_CPEN | TUSB_PRCM_CONF_SYS_CLKSEL(1));
519
520         /* VBus valid timer 1us, disable DFT/Debug and VLYNQ clocks for
521          * power saving, enable VBus detect and session end comparators,
522          * enable IDpullup, enable VBus charging */
523         musb_writel(base, TUSB_PRCM_MNGMT,
524                 TUSB_PRCM_MNGMT_VBUS_VALID_TIMER(0xa) |
525                 TUSB_PRCM_MNGMT_VBUS_VALID_FLT_EN |
526                 TUSB_PRCM_MNGMT_DFT_CLK_DIS |
527                 TUSB_PRCM_MNGMT_VLYNQ_CLK_DIS |
528                 TUSB_PRCM_MNGMT_OTG_SESS_END_EN |
529                 TUSB_PRCM_MNGMT_OTG_VBUS_DET_EN |
530                 TUSB_PRCM_MNGMT_OTG_ID_PULLUP);
531 #if 0
532         musb_writel(base, TUSB_PHY_OTG_CTRL_ENABLE,
533                 musb_readl(base, TUSB_PHY_OTG_CTRL_ENABLE) |
534                 TUSB_PHY_OTG_CTRL_WRPROTECT |
535                 TUSB_PHY_OTG_CTRL_OTG_ID_PULLUP |
536                 TUSB_PHY_OTG_CTRL_OTG_VBUS_DET_EN |
537                 TUSB_PHY_OTG_CTRL_OTG_SESS_END_EN);
538         musb_writel(base, TUSB_PHY_OTG_CTRL,
539                 musb_readl(base, TUSB_PHY_OTG_CTRL) |
540                 TUSB_PHY_OTG_CTRL_WRPROTECT |
541                 TUSB_PHY_OTG_CTRL_OTG_ID_PULLUP |
542                 TUSB_PHY_OTG_CTRL_OTG_VBUS_DET_EN |
543                 TUSB_PHY_OTG_CTRL_OTG_SESS_END_EN);
544 #endif
545         tusb_setup_cpu_interface(musb);
546
547         spin_unlock_irqrestore(&musb->Lock, flags);
548
549         return 0;
550
551 err:
552         if (musb->board_set_power)
553                 musb->board_set_power(0);
554
555         return -ENODEV;
556 }
557
558 int __devinit musb_platform_init(struct musb *musb)
559 {
560         struct platform_device  *pdev;
561         struct resource         *mem;
562         int                     ret;
563
564         pdev = to_platform_device(musb->controller);
565
566         /* dma address for async dma */
567         mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
568         musb->async = mem->start;
569
570         /* dma address for sync dma */
571         mem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
572         if (!mem) {
573                 pr_debug("no sync dma resource?\n");
574                 return -ENODEV;
575         }
576         musb->sync = mem->start;
577
578         /* Offsets from base: VLYNQ at 0x000, MUSB regs at 0x400,
579          * FIFOs at 0x600, TUSB at 0x800
580          */
581         musb->pRegs += TUSB_BASE_OFFSET;
582
583         ret = tusb_start(musb);
584         if (ret) {
585                 printk(KERN_ERR "Could not start tusb6010 (%d)\n",
586                                 ret);
587                 return -ENODEV;
588         }
589         musb->isr = tusb_interrupt;
590
591         musb_platform_try_idle(musb);
592
593         return ret;
594 }
595
596 int musb_platform_exit(struct musb *musb)
597 {
598         if (musb->board_set_power)
599                 musb->board_set_power(0);
600
601         return 0;
602 }