Commit 84e250ff authored by David Brownell's avatar David Brownell Committed by Greg Kroah-Hartman

musb: proper hookup to transceiver drivers

Let the otg_transceiver in MUSB be managed by an external driver;
don't assume it's integrated.  OMAP3 chips need it to be external,
and there may be ways to interact with the transceiver which add
functionality to the system.

Platform init code is responsible for setting up the transeciver,
probably using the NOP transceiver for integrated transceivers.
External ones will use whatever the board init code provided,
such as twl4030 or something more hands-off.
Signed-off-by: default avatarDavid Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent cc835e32
...@@ -10,6 +10,7 @@ comment "Enable Host or Gadget support to see Inventra options" ...@@ -10,6 +10,7 @@ comment "Enable Host or Gadget support to see Inventra options"
config USB_MUSB_HDRC config USB_MUSB_HDRC
depends on (USB || USB_GADGET) && HAVE_CLK depends on (USB || USB_GADGET) && HAVE_CLK
depends on !SUPERH depends on !SUPERH
select NOP_USB_XCEIV if ARCH_DAVINCI
select TWL4030_USB if MACH_OMAP_3430SDP select TWL4030_USB if MACH_OMAP_3430SDP
select USB_OTG_UTILS select USB_OTG_UTILS
tristate 'Inventra Highspeed Dual Role Controller (TI, ADI, ...)' tristate 'Inventra Highspeed Dual Role Controller (TI, ADI, ...)'
...@@ -55,6 +56,7 @@ comment "Blackfin high speed USB Support" ...@@ -55,6 +56,7 @@ comment "Blackfin high speed USB Support"
config USB_TUSB6010 config USB_TUSB6010
boolean "TUSB 6010 support" boolean "TUSB 6010 support"
depends on USB_MUSB_HDRC && !USB_MUSB_SOC depends on USB_MUSB_HDRC && !USB_MUSB_SOC
select NOP_USB_XCEIV
default y default y
help help
The TUSB 6010 chip, from Texas Instruments, connects a discrete The TUSB 6010 chip, from Texas Instruments, connects a discrete
......
...@@ -143,7 +143,7 @@ static void musb_conn_timer_handler(unsigned long _musb) ...@@ -143,7 +143,7 @@ static void musb_conn_timer_handler(unsigned long _musb)
u16 val; u16 val;
spin_lock_irqsave(&musb->lock, flags); spin_lock_irqsave(&musb->lock, flags);
switch (musb->xceiv.state) { switch (musb->xceiv->state) {
case OTG_STATE_A_IDLE: case OTG_STATE_A_IDLE:
case OTG_STATE_A_WAIT_BCON: case OTG_STATE_A_WAIT_BCON:
/* Start a new session */ /* Start a new session */
...@@ -154,7 +154,7 @@ static void musb_conn_timer_handler(unsigned long _musb) ...@@ -154,7 +154,7 @@ static void musb_conn_timer_handler(unsigned long _musb)
val = musb_readw(musb->mregs, MUSB_DEVCTL); val = musb_readw(musb->mregs, MUSB_DEVCTL);
if (!(val & MUSB_DEVCTL_BDEVICE)) { if (!(val & MUSB_DEVCTL_BDEVICE)) {
gpio_set_value(musb->config->gpio_vrsel, 1); gpio_set_value(musb->config->gpio_vrsel, 1);
musb->xceiv.state = OTG_STATE_A_WAIT_BCON; musb->xceiv->state = OTG_STATE_A_WAIT_BCON;
} else { } else {
gpio_set_value(musb->config->gpio_vrsel, 0); gpio_set_value(musb->config->gpio_vrsel, 0);
...@@ -247,6 +247,11 @@ int __init musb_platform_init(struct musb *musb) ...@@ -247,6 +247,11 @@ int __init musb_platform_init(struct musb *musb)
} }
gpio_direction_output(musb->config->gpio_vrsel, 0); gpio_direction_output(musb->config->gpio_vrsel, 0);
usb_nop_xceiv_register();
musb->xceiv = otg_get_transceiver();
if (!musb->xceiv)
return -ENODEV;
if (ANOMALY_05000346) { if (ANOMALY_05000346) {
bfin_write_USB_APHY_CALIB(ANOMALY_05000346_value); bfin_write_USB_APHY_CALIB(ANOMALY_05000346_value);
SSYNC(); SSYNC();
...@@ -291,7 +296,7 @@ int __init musb_platform_init(struct musb *musb) ...@@ -291,7 +296,7 @@ int __init musb_platform_init(struct musb *musb)
musb_conn_timer_handler, (unsigned long) musb); musb_conn_timer_handler, (unsigned long) musb);
} }
if (is_peripheral_enabled(musb)) if (is_peripheral_enabled(musb))
musb->xceiv.set_power = bfin_set_power; musb->xceiv->set_power = bfin_set_power;
musb->isr = blackfin_interrupt; musb->isr = blackfin_interrupt;
......
...@@ -215,7 +215,7 @@ static void otg_timer(unsigned long _musb) ...@@ -215,7 +215,7 @@ static void otg_timer(unsigned long _musb)
DBG(7, "poll devctl %02x (%s)\n", devctl, otg_state_string(musb)); DBG(7, "poll devctl %02x (%s)\n", devctl, otg_state_string(musb));
spin_lock_irqsave(&musb->lock, flags); spin_lock_irqsave(&musb->lock, flags);
switch (musb->xceiv.state) { switch (musb->xceiv->state) {
case OTG_STATE_A_WAIT_VFALL: case OTG_STATE_A_WAIT_VFALL:
/* Wait till VBUS falls below SessionEnd (~0.2V); the 1.3 RTL /* Wait till VBUS falls below SessionEnd (~0.2V); the 1.3 RTL
* seems to mis-handle session "start" otherwise (or in our * seems to mis-handle session "start" otherwise (or in our
...@@ -226,7 +226,7 @@ static void otg_timer(unsigned long _musb) ...@@ -226,7 +226,7 @@ static void otg_timer(unsigned long _musb)
mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ); mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ);
break; break;
} }
musb->xceiv.state = OTG_STATE_A_WAIT_VRISE; musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
musb_writel(musb->ctrl_base, DAVINCI_USB_INT_SET_REG, musb_writel(musb->ctrl_base, DAVINCI_USB_INT_SET_REG,
MUSB_INTR_VBUSERROR << DAVINCI_USB_USBINT_SHIFT); MUSB_INTR_VBUSERROR << DAVINCI_USB_USBINT_SHIFT);
break; break;
...@@ -251,7 +251,7 @@ static void otg_timer(unsigned long _musb) ...@@ -251,7 +251,7 @@ static void otg_timer(unsigned long _musb)
if (devctl & MUSB_DEVCTL_BDEVICE) if (devctl & MUSB_DEVCTL_BDEVICE)
mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ); mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ);
else else
musb->xceiv.state = OTG_STATE_A_IDLE; musb->xceiv->state = OTG_STATE_A_IDLE;
break; break;
default: default:
break; break;
...@@ -325,21 +325,21 @@ static irqreturn_t davinci_interrupt(int irq, void *__hci) ...@@ -325,21 +325,21 @@ static irqreturn_t davinci_interrupt(int irq, void *__hci)
* to stop registering in devctl. * to stop registering in devctl.
*/ */
musb->int_usb &= ~MUSB_INTR_VBUSERROR; musb->int_usb &= ~MUSB_INTR_VBUSERROR;
musb->xceiv.state = OTG_STATE_A_WAIT_VFALL; musb->xceiv->state = OTG_STATE_A_WAIT_VFALL;
mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ); mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ);
WARNING("VBUS error workaround (delay coming)\n"); WARNING("VBUS error workaround (delay coming)\n");
} else if (is_host_enabled(musb) && drvvbus) { } else if (is_host_enabled(musb) && drvvbus) {
musb->is_active = 1; musb->is_active = 1;
MUSB_HST_MODE(musb); MUSB_HST_MODE(musb);
musb->xceiv.default_a = 1; musb->xceiv->default_a = 1;
musb->xceiv.state = OTG_STATE_A_WAIT_VRISE; musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
portstate(musb->port1_status |= USB_PORT_STAT_POWER); portstate(musb->port1_status |= USB_PORT_STAT_POWER);
del_timer(&otg_workaround); del_timer(&otg_workaround);
} else { } else {
musb->is_active = 0; musb->is_active = 0;
MUSB_DEV_MODE(musb); MUSB_DEV_MODE(musb);
musb->xceiv.default_a = 0; musb->xceiv->default_a = 0;
musb->xceiv.state = OTG_STATE_B_IDLE; musb->xceiv->state = OTG_STATE_B_IDLE;
portstate(musb->port1_status &= ~USB_PORT_STAT_POWER); portstate(musb->port1_status &= ~USB_PORT_STAT_POWER);
} }
...@@ -361,7 +361,7 @@ static irqreturn_t davinci_interrupt(int irq, void *__hci) ...@@ -361,7 +361,7 @@ static irqreturn_t davinci_interrupt(int irq, void *__hci)
/* poll for ID change */ /* poll for ID change */
if (is_otg_enabled(musb) if (is_otg_enabled(musb)
&& musb->xceiv.state == OTG_STATE_B_IDLE) && musb->xceiv->state == OTG_STATE_B_IDLE)
mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ); mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ);
spin_unlock_irqrestore(&musb->lock, flags); spin_unlock_irqrestore(&musb->lock, flags);
...@@ -380,6 +380,11 @@ int __init musb_platform_init(struct musb *musb) ...@@ -380,6 +380,11 @@ int __init musb_platform_init(struct musb *musb)
void __iomem *tibase = musb->ctrl_base; void __iomem *tibase = musb->ctrl_base;
u32 revision; u32 revision;
usb_nop_xceiv_register();
musb->xceiv = otg_get_transceiver();
if (!musb->xceiv)
return -ENODEV;
musb->mregs += DAVINCI_BASE_OFFSET; musb->mregs += DAVINCI_BASE_OFFSET;
clk_enable(musb->clock); clk_enable(musb->clock);
...@@ -387,7 +392,7 @@ int __init musb_platform_init(struct musb *musb) ...@@ -387,7 +392,7 @@ int __init musb_platform_init(struct musb *musb)
/* returns zero if e.g. not clocked */ /* returns zero if e.g. not clocked */
revision = musb_readl(tibase, DAVINCI_USB_VERSION_REG); revision = musb_readl(tibase, DAVINCI_USB_VERSION_REG);
if (revision == 0) if (revision == 0)
return -ENODEV; goto fail;
if (is_host_enabled(musb)) if (is_host_enabled(musb))
setup_timer(&otg_workaround, otg_timer, (unsigned long) musb); setup_timer(&otg_workaround, otg_timer, (unsigned long) musb);
...@@ -421,6 +426,10 @@ int __init musb_platform_init(struct musb *musb) ...@@ -421,6 +426,10 @@ int __init musb_platform_init(struct musb *musb)
musb->isr = davinci_interrupt; musb->isr = davinci_interrupt;
return 0; return 0;
fail:
usb_nop_xceiv_unregister();
return -ENODEV;
} }
int musb_platform_exit(struct musb *musb) int musb_platform_exit(struct musb *musb)
...@@ -431,7 +440,7 @@ int musb_platform_exit(struct musb *musb) ...@@ -431,7 +440,7 @@ int musb_platform_exit(struct musb *musb)
davinci_source_power(musb, 0 /*off*/, 1); davinci_source_power(musb, 0 /*off*/, 1);
/* delay, to avoid problems with module reload */ /* delay, to avoid problems with module reload */
if (is_host_enabled(musb) && musb->xceiv.default_a) { if (is_host_enabled(musb) && musb->xceiv->default_a) {
int maxdelay = 30; int maxdelay = 30;
u8 devctl, warn = 0; u8 devctl, warn = 0;
...@@ -460,5 +469,7 @@ int musb_platform_exit(struct musb *musb) ...@@ -460,5 +469,7 @@ int musb_platform_exit(struct musb *musb)
clk_disable(musb->clock); clk_disable(musb->clock);
usb_nop_xceiv_unregister();
return 0; return 0;
} }
This diff is collapsed.
...@@ -356,7 +356,7 @@ struct musb { ...@@ -356,7 +356,7 @@ struct musb {
u16 int_rx; u16 int_rx;
u16 int_tx; u16 int_tx;
struct otg_transceiver xceiv; struct otg_transceiver *xceiv;
int nIrq; int nIrq;
unsigned irq_wake:1; unsigned irq_wake:1;
......
...@@ -1406,7 +1406,7 @@ static int musb_gadget_wakeup(struct usb_gadget *gadget) ...@@ -1406,7 +1406,7 @@ static int musb_gadget_wakeup(struct usb_gadget *gadget)
spin_lock_irqsave(&musb->lock, flags); spin_lock_irqsave(&musb->lock, flags);
switch (musb->xceiv.state) { switch (musb->xceiv->state) {
case OTG_STATE_B_PERIPHERAL: case OTG_STATE_B_PERIPHERAL:
/* NOTE: OTG state machine doesn't include B_SUSPENDED; /* NOTE: OTG state machine doesn't include B_SUSPENDED;
* that's part of the standard usb 1.1 state machine, and * that's part of the standard usb 1.1 state machine, and
...@@ -1508,9 +1508,9 @@ static int musb_gadget_vbus_draw(struct usb_gadget *gadget, unsigned mA) ...@@ -1508,9 +1508,9 @@ static int musb_gadget_vbus_draw(struct usb_gadget *gadget, unsigned mA)
{ {
struct musb *musb = gadget_to_musb(gadget); struct musb *musb = gadget_to_musb(gadget);
if (!musb->xceiv.set_power) if (!musb->xceiv->set_power)
return -EOPNOTSUPP; return -EOPNOTSUPP;
return otg_set_power(&musb->xceiv, mA); return otg_set_power(musb->xceiv, mA);
} }
static int musb_gadget_pullup(struct usb_gadget *gadget, int is_on) static int musb_gadget_pullup(struct usb_gadget *gadget, int is_on)
...@@ -1733,11 +1733,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) ...@@ -1733,11 +1733,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
spin_lock_irqsave(&musb->lock, flags); spin_lock_irqsave(&musb->lock, flags);
/* REVISIT always use otg_set_peripheral(), handling otg_set_peripheral(musb->xceiv, &musb->g);
* issues including the root hub one below ...
*/
musb->xceiv.gadget = &musb->g;
musb->xceiv.state = OTG_STATE_B_IDLE;
musb->is_active = 1; musb->is_active = 1;
/* FIXME this ignores the softconnect flag. Drivers are /* FIXME this ignores the softconnect flag. Drivers are
...@@ -1749,6 +1745,8 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) ...@@ -1749,6 +1745,8 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
if (!is_otg_enabled(musb)) if (!is_otg_enabled(musb))
musb_start(musb); musb_start(musb);
otg_set_peripheral(musb->xceiv, &musb->g);
spin_unlock_irqrestore(&musb->lock, flags); spin_unlock_irqrestore(&musb->lock, flags);
if (is_otg_enabled(musb)) { if (is_otg_enabled(musb)) {
...@@ -1762,8 +1760,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) ...@@ -1762,8 +1760,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
if (retval < 0) { if (retval < 0) {
DBG(1, "add_hcd failed, %d\n", retval); DBG(1, "add_hcd failed, %d\n", retval);
spin_lock_irqsave(&musb->lock, flags); spin_lock_irqsave(&musb->lock, flags);
musb->xceiv.gadget = NULL; otg_set_peripheral(musb->xceiv, NULL);
musb->xceiv.state = OTG_STATE_UNDEFINED;
musb->gadget_driver = NULL; musb->gadget_driver = NULL;
musb->g.dev.driver = NULL; musb->g.dev.driver = NULL;
spin_unlock_irqrestore(&musb->lock, flags); spin_unlock_irqrestore(&musb->lock, flags);
...@@ -1846,8 +1843,9 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) ...@@ -1846,8 +1843,9 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
(void) musb_gadget_vbus_draw(&musb->g, 0); (void) musb_gadget_vbus_draw(&musb->g, 0);
musb->xceiv.state = OTG_STATE_UNDEFINED; musb->xceiv->state = OTG_STATE_UNDEFINED;
stop_activity(musb, driver); stop_activity(musb, driver);
otg_set_peripheral(musb->xceiv, NULL);
DBG(3, "unregistering driver %s\n", driver->function); DBG(3, "unregistering driver %s\n", driver->function);
spin_unlock_irqrestore(&musb->lock, flags); spin_unlock_irqrestore(&musb->lock, flags);
...@@ -1883,7 +1881,7 @@ EXPORT_SYMBOL(usb_gadget_unregister_driver); ...@@ -1883,7 +1881,7 @@ EXPORT_SYMBOL(usb_gadget_unregister_driver);
void musb_g_resume(struct musb *musb) void musb_g_resume(struct musb *musb)
{ {
musb->is_suspended = 0; musb->is_suspended = 0;
switch (musb->xceiv.state) { switch (musb->xceiv->state) {
case OTG_STATE_B_IDLE: case OTG_STATE_B_IDLE:
break; break;
case OTG_STATE_B_WAIT_ACON: case OTG_STATE_B_WAIT_ACON:
...@@ -1909,10 +1907,10 @@ void musb_g_suspend(struct musb *musb) ...@@ -1909,10 +1907,10 @@ void musb_g_suspend(struct musb *musb)
devctl = musb_readb(musb->mregs, MUSB_DEVCTL); devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
DBG(3, "devctl %02x\n", devctl); DBG(3, "devctl %02x\n", devctl);
switch (musb->xceiv.state) { switch (musb->xceiv->state) {
case OTG_STATE_B_IDLE: case OTG_STATE_B_IDLE:
if ((devctl & MUSB_DEVCTL_VBUS) == MUSB_DEVCTL_VBUS) if ((devctl & MUSB_DEVCTL_VBUS) == MUSB_DEVCTL_VBUS)
musb->xceiv.state = OTG_STATE_B_PERIPHERAL; musb->xceiv->state = OTG_STATE_B_PERIPHERAL;
break; break;
case OTG_STATE_B_PERIPHERAL: case OTG_STATE_B_PERIPHERAL:
musb->is_suspended = 1; musb->is_suspended = 1;
...@@ -1958,22 +1956,22 @@ void musb_g_disconnect(struct musb *musb) ...@@ -1958,22 +1956,22 @@ void musb_g_disconnect(struct musb *musb)
spin_lock(&musb->lock); spin_lock(&musb->lock);
} }
switch (musb->xceiv.state) { switch (musb->xceiv->state) {
default: default:
#ifdef CONFIG_USB_MUSB_OTG #ifdef CONFIG_USB_MUSB_OTG
DBG(2, "Unhandled disconnect %s, setting a_idle\n", DBG(2, "Unhandled disconnect %s, setting a_idle\n",
otg_state_string(musb)); otg_state_string(musb));
musb->xceiv.state = OTG_STATE_A_IDLE; musb->xceiv->state = OTG_STATE_A_IDLE;
break; break;
case OTG_STATE_A_PERIPHERAL: case OTG_STATE_A_PERIPHERAL:
musb->xceiv.state = OTG_STATE_A_WAIT_VFALL; musb->xceiv->state = OTG_STATE_A_WAIT_VFALL;
break; break;
case OTG_STATE_B_WAIT_ACON: case OTG_STATE_B_WAIT_ACON:
case OTG_STATE_B_HOST: case OTG_STATE_B_HOST:
#endif #endif
case OTG_STATE_B_PERIPHERAL: case OTG_STATE_B_PERIPHERAL:
case OTG_STATE_B_IDLE: case OTG_STATE_B_IDLE:
musb->xceiv.state = OTG_STATE_B_IDLE; musb->xceiv->state = OTG_STATE_B_IDLE;
break; break;
case OTG_STATE_B_SRP_INIT: case OTG_STATE_B_SRP_INIT:
break; break;
...@@ -2029,10 +2027,10 @@ __acquires(musb->lock) ...@@ -2029,10 +2027,10 @@ __acquires(musb->lock)
* or else after HNP, as A-Device * or else after HNP, as A-Device
*/ */
if (devctl & MUSB_DEVCTL_BDEVICE) { if (devctl & MUSB_DEVCTL_BDEVICE) {
musb->xceiv.state = OTG_STATE_B_PERIPHERAL; musb->xceiv->state = OTG_STATE_B_PERIPHERAL;
musb->g.is_a_peripheral = 0; musb->g.is_a_peripheral = 0;
} else if (is_otg_enabled(musb)) { } else if (is_otg_enabled(musb)) {
musb->xceiv.state = OTG_STATE_A_PERIPHERAL; musb->xceiv->state = OTG_STATE_A_PERIPHERAL;
musb->g.is_a_peripheral = 1; musb->g.is_a_peripheral = 1;
} else } else
WARN_ON(1); WARN_ON(1);
......
...@@ -2213,7 +2213,7 @@ static int musb_bus_suspend(struct usb_hcd *hcd) ...@@ -2213,7 +2213,7 @@ static int musb_bus_suspend(struct usb_hcd *hcd)
{ {
struct musb *musb = hcd_to_musb(hcd); struct musb *musb = hcd_to_musb(hcd);
if (musb->xceiv.state == OTG_STATE_A_SUSPEND) if (musb->xceiv->state == OTG_STATE_A_SUSPEND)
return 0; return 0;
if (is_host_active(musb) && musb->is_active) { if (is_host_active(musb) && musb->is_active) {
......
...@@ -78,18 +78,18 @@ static void musb_port_suspend(struct musb *musb, bool do_suspend) ...@@ -78,18 +78,18 @@ static void musb_port_suspend(struct musb *musb, bool do_suspend)
DBG(3, "Root port suspended, power %02x\n", power); DBG(3, "Root port suspended, power %02x\n", power);
musb->port1_status |= USB_PORT_STAT_SUSPEND; musb->port1_status |= USB_PORT_STAT_SUSPEND;
switch (musb->xceiv.state) { switch (musb->xceiv->state) {
case OTG_STATE_A_HOST: case OTG_STATE_A_HOST:
musb->xceiv.state = OTG_STATE_A_SUSPEND; musb->xceiv->state = OTG_STATE_A_SUSPEND;
musb->is_active = is_otg_enabled(musb) musb->is_active = is_otg_enabled(musb)
&& musb->xceiv.host->b_hnp_enable; && musb->xceiv->host->b_hnp_enable;
musb_platform_try_idle(musb, 0); musb_platform_try_idle(musb, 0);
break; break;
#ifdef CONFIG_USB_MUSB_OTG #ifdef CONFIG_USB_MUSB_OTG
case OTG_STATE_B_HOST: case OTG_STATE_B_HOST:
musb->xceiv.state = OTG_STATE_B_WAIT_ACON; musb->xceiv->state = OTG_STATE_B_WAIT_ACON;
musb->is_active = is_otg_enabled(musb) musb->is_active = is_otg_enabled(musb)
&& musb->xceiv.host->b_hnp_enable; && musb->xceiv->host->b_hnp_enable;
musb_platform_try_idle(musb, 0); musb_platform_try_idle(musb, 0);
break; break;
#endif #endif
...@@ -116,7 +116,7 @@ static void musb_port_reset(struct musb *musb, bool do_reset) ...@@ -116,7 +116,7 @@ static void musb_port_reset(struct musb *musb, bool do_reset)
void __iomem *mbase = musb->mregs; void __iomem *mbase = musb->mregs;
#ifdef CONFIG_USB_MUSB_OTG #ifdef CONFIG_USB_MUSB_OTG
if (musb->xceiv.state == OTG_STATE_B_IDLE) { if (musb->xceiv->state == OTG_STATE_B_IDLE) {
DBG(2, "HNP: Returning from HNP; no hub reset from b_idle\n"); DBG(2, "HNP: Returning from HNP; no hub reset from b_idle\n");
musb->port1_status &= ~USB_PORT_STAT_RESET; musb->port1_status &= ~USB_PORT_STAT_RESET;
return; return;
...@@ -186,14 +186,14 @@ void musb_root_disconnect(struct musb *musb) ...@@ -186,14 +186,14 @@ void musb_root_disconnect(struct musb *musb)
usb_hcd_poll_rh_status(musb_to_hcd(musb)); usb_hcd_poll_rh_status(musb_to_hcd(musb));
musb->is_active = 0; musb->is_active = 0;
switch (musb->xceiv.state) { switch (musb->xceiv->state) {
case OTG_STATE_A_HOST: case OTG_STATE_A_HOST:
case OTG_STATE_A_SUSPEND: case OTG_STATE_A_SUSPEND:
musb->xceiv.state = OTG_STATE_A_WAIT_BCON; musb->xceiv->state = OTG_STATE_A_WAIT_BCON;
musb->is_active = 0; musb->is_active = 0;
break; break;
case OTG_STATE_A_WAIT_VFALL: case OTG_STATE_A_WAIT_VFALL:
musb->xceiv.state = OTG_STATE_B_IDLE; musb->xceiv->state = OTG_STATE_B_IDLE;
break; break;
default: default:
DBG(1, "host disconnect (%s)\n", otg_state_string(musb)); DBG(1, "host disconnect (%s)\n", otg_state_string(musb));
...@@ -332,7 +332,7 @@ int musb_hub_control( ...@@ -332,7 +332,7 @@ int musb_hub_control(
musb->port1_status |= USB_PORT_STAT_C_SUSPEND << 16; musb->port1_status |= USB_PORT_STAT_C_SUSPEND << 16;
usb_hcd_poll_rh_status(musb_to_hcd(musb)); usb_hcd_poll_rh_status(musb_to_hcd(musb));
/* NOTE: it might really be A_WAIT_BCON ... */ /* NOTE: it might really be A_WAIT_BCON ... */
musb->xceiv.state = OTG_STATE_A_HOST; musb->xceiv->state = OTG_STATE_A_HOST;
} }
put_unaligned(cpu_to_le32(musb->port1_status put_unaligned(cpu_to_le32(musb->port1_status
......
...@@ -61,17 +61,17 @@ static void musb_do_idle(unsigned long _musb) ...@@ -61,17 +61,17 @@ static void musb_do_idle(unsigned long _musb)
devctl = musb_readb(musb->mregs, MUSB_DEVCTL); devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
switch (musb->xceiv.state) { switch (musb->xceiv->state) {
case OTG_STATE_A_WAIT_BCON: case OTG_STATE_A_WAIT_BCON:
devctl &= ~MUSB_DEVCTL_SESSION; devctl &= ~MUSB_DEVCTL_SESSION;
musb_writeb(musb->mregs, MUSB_DEVCTL, devctl); musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
devctl = musb_readb(musb->mregs, MUSB_DEVCTL); devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
if (devctl & MUSB_DEVCTL_BDEVICE) { if (devctl & MUSB_DEVCTL_BDEVICE) {
musb->xceiv.state = OTG_STATE_B_IDLE; musb->xceiv->state = OTG_STATE_B_IDLE;
MUSB_DEV_MODE(musb); MUSB_DEV_MODE(musb);
} else { } else {
musb->xceiv.state = OTG_STATE_A_IDLE; musb->xceiv->state = OTG_STATE_A_IDLE;
MUSB_HST_MODE(musb); MUSB_HST_MODE(musb);
} }
break; break;
...@@ -89,7 +89,7 @@ static void musb_do_idle(unsigned long _musb) ...@@ -89,7 +89,7 @@ static void musb_do_idle(unsigned long _musb)
musb->port1_status |= USB_PORT_STAT_C_SUSPEND << 16; musb->port1_status |= USB_PORT_STAT_C_SUSPEND << 16;
usb_hcd_poll_rh_status(musb_to_hcd(musb)); usb_hcd_poll_rh_status(musb_to_hcd(musb));
/* NOTE: it might really be A_WAIT_BCON ... */ /* NOTE: it might really be A_WAIT_BCON ... */
musb->xceiv.state = OTG_STATE_A_HOST; musb->xceiv->state = OTG_STATE_A_HOST;
} }
break; break;
#endif #endif
...@@ -97,9 +97,9 @@ static void musb_do_idle(unsigned long _musb) ...@@ -97,9 +97,9 @@ static void musb_do_idle(unsigned long _musb)
case OTG_STATE_A_HOST: case OTG_STATE_A_HOST:
devctl = musb_readb(musb->mregs, MUSB_DEVCTL); devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
if (devctl & MUSB_DEVCTL_BDEVICE) if (devctl & MUSB_DEVCTL_BDEVICE)
musb->xceiv.state = OTG_STATE_B_IDLE; musb->xceiv->state = OTG_STATE_B_IDLE;
else else
musb->xceiv.state = OTG_STATE_A_WAIT_BCON; musb->xceiv->state = OTG_STATE_A_WAIT_BCON;
#endif #endif
default: default:
break; break;
...@@ -118,7 +118,7 @@ void musb_platform_try_idle(struct musb *musb, unsigned long timeout) ...@@ -118,7 +118,7 @@ void musb_platform_try_idle(struct musb *musb, unsigned long timeout)
/* Never idle if active, or when VBUS timeout is not set as host */ /* Never idle if active, or when VBUS timeout is not set as host */
if (musb->is_active || ((musb->a_wait_bcon == 0) if (musb->is_active || ((musb->a_wait_bcon == 0)
&& (musb->xceiv.state == OTG_STATE_A_WAIT_BCON))) { && (musb->xceiv->state == OTG_STATE_A_WAIT_BCON))) {
DBG(4, "%s active, deleting timer\n", otg_state_string(musb)); DBG(4, "%s active, deleting timer\n", otg_state_string(musb));
del_timer(&musb_idle_timer); del_timer(&musb_idle_timer);
last_timer = jiffies; last_timer = jiffies;
...@@ -163,8 +163,8 @@ static void omap_set_vbus(struct musb *musb, int is_on) ...@@ -163,8 +163,8 @@ static void omap_set_vbus(struct musb *musb, int is_on)
if (is_on) { if (is_on) {
musb->is_active = 1; musb->is_active = 1;
musb->xceiv.default_a = 1; musb->xceiv->default_a = 1;
musb->xceiv.state = OTG_STATE_A_WAIT_VRISE; musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
devctl |= MUSB_DEVCTL_SESSION; devctl |= MUSB_DEVCTL_SESSION;
MUSB_HST_MODE(musb); MUSB_HST_MODE(musb);
...@@ -175,8 +175,8 @@ static void omap_set_vbus(struct musb *musb, int is_on) ...@@ -175,8 +175,8 @@ static void omap_set_vbus(struct musb *musb, int is_on)
* jumping right to B_IDLE... * jumping right to B_IDLE...
*/ */
musb->xceiv.default_a = 0; musb->xceiv->default_a = 0;
musb->xceiv.state = OTG_STATE_B_IDLE; musb->xceiv->state = OTG_STATE_B_IDLE;
devctl &= ~MUSB_DEVCTL_SESSION; devctl &= ~MUSB_DEVCTL_SESSION;
MUSB_DEV_MODE(musb); MUSB_DEV_MODE(musb);
...@@ -188,10 +188,6 @@ static void omap_set_vbus(struct musb *musb, int is_on) ...@@ -188,10 +188,6 @@ static void omap_set_vbus(struct musb *musb, int is_on)
otg_state_string(musb), otg_state_string(musb),
musb_readb(musb->mregs, MUSB_DEVCTL)); musb_readb(musb->mregs, MUSB_DEVCTL));
} }
static int omap_set_power(struct otg_transceiver *x, unsigned mA)
{
return 0;
}
static int musb_platform_resume(struct musb *musb); static int musb_platform_resume(struct musb *musb);
...@@ -202,24 +198,6 @@ int musb_platform_set_mode(struct musb *musb, u8 musb_mode) ...@@ -202,24 +198,6 @@ int musb_platform_set_mode(struct musb *musb, u8 musb_mode)
devctl |= MUSB_DEVCTL_SESSION; devctl |= MUSB_DEVCTL_SESSION;
musb_writeb(musb->mregs, MUSB_DEVCTL, devctl); musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
switch (musb_mode) {
#ifdef CONFIG_USB_MUSB_HDRC_HCD
case MUSB_HOST:
otg_set_host(&musb->xceiv, musb->xceiv.host);
break;
#endif
#ifdef CONFIG_USB_GADGET_MUSB_HDRC
case MUSB_PERIPHERAL:
otg_set_peripheral(&musb->xceiv, musb->xceiv.gadget);
break;
#endif
#ifdef CONFIG_USB_MUSB_OTG
case MUSB_OTG:
break;
#endif
default:
return -EINVAL;
}
return 0; return 0;
} }
...@@ -231,6 +209,16 @@ int __init musb_platform_init(struct musb *musb) ...@@ -231,6 +209,16 @@ int __init musb_platform_init(struct musb *musb)
omap_cfg_reg(AE5_2430_USB0HS_STP); omap_cfg_reg(AE5_2430_USB0HS_STP);
#endif #endif
/* We require some kind of external transceiver, hooked
* up through ULPI. TWL4030-family PMICs include one,
* which needs a driver, drivers aren't always needed.
*/
musb->xceiv = otg_get_transceiver();
if (!musb->xceiv) {
pr_err("HS USB OTG: no transceiver configured\n");
return -ENODEV;
}
musb_platform_resume(musb); musb_platform_resume(musb);
l = omap_readl(OTG_SYSCONFIG); l = omap_readl(OTG_SYSCONFIG);
...@@ -257,8 +245,6 @@ int __init musb_platform_init(struct musb *musb) ...@@ -257,8 +245,6 @@ int __init musb_platform_init(struct musb *musb)
if (is_host_enabled(musb)) if (is_host_enabled(musb))
musb->board_set_vbus = omap_set_vbus; musb->board_set_vbus = omap_set_vbus;
if (is_peripheral_enabled(musb))
musb->xceiv.set_power = omap_set_power;
musb->a_wait_bcon = MUSB_TIMEOUT_A_WAIT_BCON; musb->a_wait_bcon = MUSB_TIMEOUT_A_WAIT_BCON;
setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb); setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb);
...@@ -282,8 +268,7 @@ int musb_platform_suspend(struct musb *musb) ...@@ -282,8 +268,7 @@ int musb_platform_suspend(struct musb *musb)
l |= ENABLEWAKEUP; /* enable wakeup */ l |= ENABLEWAKEUP; /* enable wakeup */
omap_writel(l, OTG_SYSCONFIG); omap_writel(l, OTG_SYSCONFIG);
if (musb->xceiv.set_suspend) otg_set_suspend(musb->xceiv, 1);
musb->xceiv.set_suspend(&musb->xceiv, 1);
if (musb->set_clock) if (musb->set_clock)
musb->set_clock(musb->clock, 0); musb->set_clock(musb->clock, 0);
...@@ -300,8 +285,7 @@ static int musb_platform_resume(struct musb *musb) ...@@ -300,8 +285,7 @@ static int musb_platform_resume(struct musb *musb)
if (!musb->clock) if (!musb->clock)
return 0; return 0;
if (musb->xceiv.set_suspend) otg_set_suspend(musb->xceiv, 0);
musb->xceiv.set_suspend(&musb->xceiv, 0);
if (musb->set_clock) if (musb->set_clock)
musb->set_clock(musb->clock, 1); musb->set_clock(musb->clock, 1);
......
...@@ -259,6 +259,8 @@ void musb_read_fifo(struct musb_hw_ep *hw_ep, u16 len, u8 *buf) ...@@ -259,6 +259,8 @@ void musb_read_fifo(struct musb_hw_ep *hw_ep, u16 len, u8 *buf)
tusb_fifo_read_unaligned(fifo, buf, len); tusb_fifo_read_unaligned(fifo, buf, len);
} }
static struct musb *the_musb;
#ifdef CONFIG_USB_GADGET_MUSB_HDRC #ifdef CONFIG_USB_GADGET_MUSB_HDRC
/* This is used by gadget drivers, and OTG transceiver logic, allowing /* This is used by gadget drivers, and OTG transceiver logic, allowing
...@@ -269,7 +271,7 @@ void musb_read_fifo(struct musb_hw_ep *hw_ep, u16 len, u8 *buf) ...@@ -269,7 +271,7 @@ void musb_read_fifo(struct musb_hw_ep *hw_ep, u16 len, u8 *buf)
*/ */
static int tusb_draw_power(struct otg_transceiver *x, unsigned mA) static int tusb_draw_power(struct otg_transceiver *x, unsigned mA)
{ {
struct musb *musb = container_of(x, struct musb, xceiv); struct musb *musb = the_musb;
void __iomem *tbase = musb->ctrl_base; void __iomem *tbase = musb->ctrl_base;
u32 reg; u32 reg;
...@@ -419,7 +421,7 @@ static void musb_do_idle(unsigned long _musb) ...@@ -419,7 +421,7 @@ static void musb_do_idle(unsigned long _musb)
spin_lock_irqsave(&musb->lock, flags); spin_lock_irqsave(&musb->lock, flags);
switch (musb->xceiv.state) { switch (musb->xceiv->state) {
case OTG_STATE_A_WAIT_BCON: case OTG_STATE_A_WAIT_BCON:
if ((musb->a_wait_bcon != 0) if ((musb->a_wait_bcon != 0)
&& (musb->idle_timeout == 0 && (musb->idle_timeout == 0
...@@ -483,7 +485,7 @@ void musb_platform_try_idle(struct musb *musb, unsigned long timeout) ...@@ -483,7 +485,7 @@ void musb_platform_try_idle(struct musb *musb, unsigned long timeout)
/* Never idle if active, or when VBUS timeout is not set as host */ /* Never idle if active, or when VBUS timeout is not set as host */
if (musb->is_active || ((musb->a_wait_bcon == 0) if (musb->is_active || ((musb->a_wait_bcon == 0)
&& (musb->xceiv.state == OTG_STATE_A_WAIT_BCON))) { && (musb->xceiv->state == OTG_STATE_A_WAIT_BCON))) {
DBG(4, "%s active, deleting timer\n", otg_state_string(musb)); DBG(4, "%s active, deleting timer\n", otg_state_string(musb));
del_timer(&musb_idle_timer); del_timer(&musb_idle_timer);
last_timer = jiffies; last_timer = jiffies;
...@@ -532,8 +534,8 @@ static void tusb_source_power(struct musb *musb, int is_on) ...@@ -532,8 +534,8 @@ static void tusb_source_power(struct musb *musb, int is_on)
if (musb->set_clock) if (musb->set_clock)
musb->set_clock(musb->clock, 1); musb->set_clock(musb->clock, 1);
timer = OTG_TIMER_MS(OTG_TIME_A_WAIT_VRISE); timer = OTG_TIMER_MS(OTG_TIME_A_WAIT_VRISE);
musb->xceiv.default_a = 1; musb->xceiv->default_a = 1;
musb->xceiv.state = OTG_STATE_A_WAIT_VRISE; musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
devctl |= MUSB_DEVCTL_SESSION; devctl |= MUSB_DEVCTL_SESSION;
conf |= TUSB_DEV_CONF_USB_HOST_MODE; conf |= TUSB_DEV_CONF_USB_HOST_MODE;
...@@ -546,24 +548,24 @@ static void tusb_source_power(struct musb *musb, int is_on) ...@@ -546,24 +548,24 @@ static void tusb_source_power(struct musb *musb, int is_on)
/* If ID pin is grounded, we want to be a_idle */ /* If ID pin is grounded, we want to be a_idle */
otg_stat = musb_readl(tbase, TUSB_DEV_OTG_STAT); otg_stat = musb_readl(tbase, TUSB_DEV_OTG_STAT);
if (!(otg_stat & TUSB_DEV_OTG_STAT_ID_STATUS)) { if (!(otg_stat & TUSB_DEV_OTG_STAT_ID_STATUS)) {
switch (musb->xceiv.state) { switch (musb->xceiv->state) {
case OTG_STATE_A_WAIT_VRISE: case OTG_STATE_A_WAIT_VRISE:
case OTG_STATE_A_WAIT_BCON: case OTG_STATE_A_WAIT_BCON:
musb->xceiv.state = OTG_STATE_A_WAIT_VFALL; musb->xceiv->state = OTG_STATE_A_WAIT_VFALL;
break; break;
case OTG_STATE_A_WAIT_VFALL: case OTG_STATE_A_WAIT_VFALL:
musb->xceiv.state = OTG_STATE_A_IDLE; musb->xceiv->state = OTG_STATE_A_IDLE;
break; break;
default: default:
musb->xceiv.state = OTG_STATE_A_IDLE; musb->xceiv->state = OTG_STATE_A_IDLE;
} }
musb->is_active = 0; musb->is_active = 0;
musb->xceiv.default_a = 1; musb->xceiv->default_a = 1;
MUSB_HST_MODE(musb); MUSB_HST_MODE(musb);
} else { } else {
musb->is_active = 0; musb->is_active = 0;
musb->xceiv.default_a = 0; musb->xceiv->default_a = 0;
musb->xceiv.state = OTG_STATE_B_IDLE; musb->xceiv->state = OTG_STATE_B_IDLE;
MUSB_DEV_MODE(musb); MUSB_DEV_MODE(musb);
} }
...@@ -674,7 +676,7 @@ tusb_otg_ints(struct musb *musb, u32 int_src, void __iomem *tbase) ...@@ -674,7 +676,7 @@ tusb_otg_ints(struct musb *musb, u32 int_src, void __iomem *tbase)
else else
default_a = is_host_enabled(musb); default_a = is_host_enabled(musb);
DBG(2, "Default-%c\n", default_a ? 'A' : 'B'); DBG(2, "Default-%c\n", default_a ? 'A' : 'B');
musb->xceiv.default_a = default_a; musb->xceiv->default_a = default_a;
tusb_source_power(musb, default_a); tusb_source_power(musb, default_a);
/* Don't allow idling immediately */ /* Don't allow idling immediately */
...@@ -686,7 +688,7 @@ tusb_otg_ints(struct musb *musb, u32 int_src, void __iomem *tbase) ...@@ -686,7 +688,7 @@ tusb_otg_ints(struct musb *musb, u32 int_src, void __iomem *tbase)
if (int_src & TUSB_INT_SRC_VBUS_SENSE_CHNG) { if (int_src & TUSB_INT_SRC_VBUS_SENSE_CHNG) {
/* B-dev state machine: no vbus ~= disconnect */ /* B-dev state machine: no vbus ~= disconnect */
if ((is_otg_enabled(musb) && !musb->xceiv.default_a) if ((is_otg_enabled(musb) && !musb->xceiv->default_a)
|| !is_host_enabled(musb)) { || !is_host_enabled(musb)) {
#ifdef CONFIG_USB_MUSB_HDRC_HCD #ifdef CONFIG_USB_MUSB_HDRC_HCD
/* ? musb_root_disconnect(musb); */ /* ? musb_root_disconnect(musb); */
...@@ -701,9 +703,9 @@ tusb_otg_ints(struct musb *musb, u32 int_src, void __iomem *tbase) ...@@ -701,9 +703,9 @@ tusb_otg_ints(struct musb *musb, u32 int_src, void __iomem *tbase)
if (otg_stat & TUSB_DEV_OTG_STAT_SESS_END) { if (otg_stat & TUSB_DEV_OTG_STAT_SESS_END) {
DBG(1, "Forcing disconnect (no interrupt)\n"); DBG(1, "Forcing disconnect (no interrupt)\n");
if (musb->xceiv.state != OTG_STATE_B_IDLE) { if (musb->xceiv->state != OTG_STATE_B_IDLE) {
/* INTR_DISCONNECT can hide... */ /* INTR_DISCONNECT can hide... */
musb->xceiv.state = OTG_STATE_B_IDLE; musb->xceiv->state = OTG_STATE_B_IDLE;
musb->int_usb |= MUSB_INTR_DISCONNECT; musb->int_usb |= MUSB_INTR_DISCONNECT;
} }
musb->is_active = 0; musb->is_active = 0;
...@@ -717,7 +719,7 @@ tusb_otg_ints(struct musb *musb, u32 int_src, void __iomem *tbase) ...@@ -717,7 +719,7 @@ tusb_otg_ints(struct musb *musb, u32 int_src, void __iomem *tbase)
DBG(2, "vbus change, %s, otg %03x\n", DBG(2, "vbus change, %s, otg %03x\n",
otg_state_string(musb), otg_stat); otg_state_string(musb), otg_stat);
switch (musb->xceiv.state) { switch (musb->xceiv->state) {
case OTG_STATE_A_IDLE: case OTG_STATE_A_IDLE:
DBG(2, "Got SRP, turning on VBUS\n"); DBG(2, "Got SRP, turning on VBUS\n");
musb_set_vbus(musb, 1); musb_set_vbus(musb, 1);
...@@ -765,7 +767,7 @@ tusb_otg_ints(struct musb *musb, u32 int_src, void __iomem *tbase) ...@@ -765,7 +767,7 @@ tusb_otg_ints(struct musb *musb, u32 int_src, void __iomem *tbase)
DBG(4, "%s timer, %03x\n", otg_state_string(musb), otg_stat); DBG(4, "%s timer, %03x\n", otg_state_string(musb), otg_stat);
switch (musb->xceiv.state) { switch (musb->xceiv->state) {
case OTG_STATE_A_WAIT_VRISE: case OTG_STATE_A_WAIT_VRISE:
/* VBUS has probably been valid for a while now, /* VBUS has probably been valid for a while now,
* but may well have bounced out of range a bit * but may well have bounced out of range a bit
...@@ -777,7 +779,7 @@ tusb_otg_ints(struct musb *musb, u32 int_src, void __iomem *tbase) ...@@ -777,7 +779,7 @@ tusb_otg_ints(struct musb *musb, u32 int_src, void __iomem *tbase)
DBG(2, "devctl %02x\n", devctl); DBG(2, "devctl %02x\n", devctl);
break; break;
} }
musb->xceiv.state = OTG_STATE_A_WAIT_BCON; musb->xceiv->state = OTG_STATE_A_WAIT_BCON;
musb->is_active = 0; musb->is_active = 0;
idle_timeout = jiffies idle_timeout = jiffies
+ msecs_to_jiffies(musb->a_wait_bcon); + msecs_to_jiffies(musb->a_wait_bcon);
...@@ -1093,9 +1095,14 @@ int __init musb_platform_init(struct musb *musb) ...@@ -1093,9 +1095,14 @@ int __init musb_platform_init(struct musb *musb)
{ {
struct platform_device *pdev; struct platform_device *pdev;
struct resource *mem; struct resource *mem;
void __iomem *sync; void __iomem *sync = NULL;
int ret; int ret;
usb_nop_xceiv_register();
musb->xceiv = otg_get_transceiver();
if (!musb->xceiv)
return -ENODEV;
pdev = to_platform_device(musb->controller); pdev = to_platform_device(musb->controller);
/* dma address for async dma */ /* dma address for async dma */
...@@ -1106,14 +1113,16 @@ int __init musb_platform_init(struct musb *musb) ...@@ -1106,14 +1113,16 @@ int __init musb_platform_init(struct musb *musb)
mem = platform_get_resource(pdev, IORESOURCE_MEM, 1); mem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
if (!mem) { if (!mem) {
pr_debug("no sync dma resource?\n"); pr_debug("no sync dma resource?\n");
return -ENODEV; ret = -ENODEV;
goto done;
} }
musb->sync = mem->start; musb->sync = mem->start;
sync = ioremap(mem->start, mem->end - mem->start + 1); sync = ioremap(mem->start, mem->end - mem->start + 1);
if (!sync) { if (!sync) {
pr_debug("ioremap for sync failed\n"); pr_debug("ioremap for sync failed\n");
return -ENOMEM; ret = -ENOMEM;
goto done;
} }
musb->sync_va = sync; musb->sync_va = sync;
...@@ -1126,28 +1135,37 @@ int __init musb_platform_init(struct musb *musb) ...@@ -1126,28 +1135,37 @@ int __init musb_platform_init(struct musb *musb)
if (ret) { if (ret) {
printk(KERN_ERR "Could not start tusb6010 (%d)\n", printk(KERN_ERR "Could not start tusb6010 (%d)\n",
ret); ret);
return -ENODEV; goto done;
} }
musb->isr = tusb_interrupt; musb->isr = tusb_interrupt;
if (is_host_enabled(musb)) if (is_host_enabled(musb))
musb->board_set_vbus = tusb_source_power; musb->board_set_vbus = tusb_source_power;
if (is_peripheral_enabled(musb)) if (is_peripheral_enabled(musb)) {
musb->xceiv.set_power = tusb_draw_power; musb->xceiv->set_power = tusb_draw_power;
the_musb = musb;
}
setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb); setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb);
done:
if (ret < 0) {
if (sync)
iounmap(sync);
usb_nop_xceiv_unregister();
}
return ret; return ret;
} }
int musb_platform_exit(struct musb *musb) int musb_platform_exit(struct musb *musb)
{ {
del_timer_sync(&musb_idle_timer); del_timer_sync(&musb_idle_timer);
the_musb = NULL;
if (musb->board_set_power) if (musb->board_set_power)
musb->board_set_power(0); musb->board_set_power(0);
iounmap(musb->sync_va); iounmap(musb->sync_va);
usb_nop_xceiv_unregister();
return 0; return 0;
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment