From 84e250ffa76dddc1bad84e04248a27f442c25986 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Tue, 31 Mar 2009 12:30:04 -0700 Subject: 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 Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/omap2430.c | 62 +++++++++++++++++---------------------------- 1 file changed, 23 insertions(+), 39 deletions(-) (limited to 'drivers/usb/musb/omap2430.c') diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c index 60924ce08493..a2f443859358 100644 --- a/drivers/usb/musb/omap2430.c +++ b/drivers/usb/musb/omap2430.c @@ -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); -- cgit v1.2.2