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: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
David Brownell
2009-03-31 12:30:04 -07:00
کامیت شده توسط Greg Kroah-Hartman
والد cc835e321a
کامیت 84e250ffa7
10فایلهای تغییر یافته به همراه181 افزوده شده و 155 حذف شده

مشاهده پرونده

@@ -61,17 +61,17 @@ static void musb_do_idle(unsigned long _musb)
devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
switch (musb->xceiv.state) {
switch (musb->xceiv->state) {
case OTG_STATE_A_WAIT_BCON:
devctl &= ~MUSB_DEVCTL_SESSION;
musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
if (devctl & MUSB_DEVCTL_BDEVICE) {
musb->xceiv.state = OTG_STATE_B_IDLE;
musb->xceiv->state = OTG_STATE_B_IDLE;
MUSB_DEV_MODE(musb);
} else {
musb->xceiv.state = OTG_STATE_A_IDLE;
musb->xceiv->state = OTG_STATE_A_IDLE;
MUSB_HST_MODE(musb);
}
break;
@@ -89,7 +89,7 @@ static void musb_do_idle(unsigned long _musb)
musb->port1_status |= USB_PORT_STAT_C_SUSPEND << 16;
usb_hcd_poll_rh_status(musb_to_hcd(musb));
/* NOTE: it might really be A_WAIT_BCON ... */
musb->xceiv.state = OTG_STATE_A_HOST;
musb->xceiv->state = OTG_STATE_A_HOST;
}
break;
#endif
@@ -97,9 +97,9 @@ static void musb_do_idle(unsigned long _musb)
case OTG_STATE_A_HOST:
devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
if (devctl & MUSB_DEVCTL_BDEVICE)
musb->xceiv.state = OTG_STATE_B_IDLE;
musb->xceiv->state = OTG_STATE_B_IDLE;
else
musb->xceiv.state = OTG_STATE_A_WAIT_BCON;
musb->xceiv->state = OTG_STATE_A_WAIT_BCON;
#endif
default:
break;
@@ -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 */
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));
del_timer(&musb_idle_timer);
last_timer = jiffies;
@@ -163,8 +163,8 @@ static void omap_set_vbus(struct musb *musb, int is_on)
if (is_on) {
musb->is_active = 1;
musb->xceiv.default_a = 1;
musb->xceiv.state = OTG_STATE_A_WAIT_VRISE;
musb->xceiv->default_a = 1;
musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
devctl |= MUSB_DEVCTL_SESSION;
MUSB_HST_MODE(musb);
@@ -175,8 +175,8 @@ static void omap_set_vbus(struct musb *musb, int is_on)
* jumping right to B_IDLE...
*/
musb->xceiv.default_a = 0;
musb->xceiv.state = OTG_STATE_B_IDLE;
musb->xceiv->default_a = 0;
musb->xceiv->state = OTG_STATE_B_IDLE;
devctl &= ~MUSB_DEVCTL_SESSION;
MUSB_DEV_MODE(musb);
@@ -188,10 +188,6 @@ static void omap_set_vbus(struct musb *musb, int is_on)
otg_state_string(musb),
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);
@@ -202,24 +198,6 @@ int musb_platform_set_mode(struct musb *musb, u8 musb_mode)
devctl |= MUSB_DEVCTL_SESSION;
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;
}
@@ -231,6 +209,16 @@ int __init musb_platform_init(struct musb *musb)
omap_cfg_reg(AE5_2430_USB0HS_STP);
#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);
l = omap_readl(OTG_SYSCONFIG);
@@ -257,8 +245,6 @@ int __init musb_platform_init(struct musb *musb)
if (is_host_enabled(musb))
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;
setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb);
@@ -282,8 +268,7 @@ int musb_platform_suspend(struct musb *musb)
l |= ENABLEWAKEUP; /* enable wakeup */
omap_writel(l, OTG_SYSCONFIG);
if (musb->xceiv.set_suspend)
musb->xceiv.set_suspend(&musb->xceiv, 1);
otg_set_suspend(musb->xceiv, 1);
if (musb->set_clock)
musb->set_clock(musb->clock, 0);
@@ -300,8 +285,7 @@ static int musb_platform_resume(struct musb *musb)
if (!musb->clock)
return 0;
if (musb->xceiv.set_suspend)
musb->xceiv.set_suspend(&musb->xceiv, 0);
otg_set_suspend(musb->xceiv, 0);
if (musb->set_clock)
musb->set_clock(musb->clock, 1);