Skip to content

Commit

Permalink
musb: proper hookup to transceiver drivers
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
David Brownell authored and Greg Kroah-Hartman committed Jun 16, 2009
1 parent cc835e3 commit 84e250f
Show file tree
Hide file tree
Showing 10 changed files with 181 additions and 155 deletions.
2 changes: 2 additions & 0 deletions drivers/usb/musb/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ comment "Enable Host or Gadget support to see Inventra options"
config USB_MUSB_HDRC
depends on (USB || USB_GADGET) && HAVE_CLK
depends on !SUPERH
select NOP_USB_XCEIV if ARCH_DAVINCI
select TWL4030_USB if MACH_OMAP_3430SDP
select USB_OTG_UTILS
tristate 'Inventra Highspeed Dual Role Controller (TI, ADI, ...)'
Expand Down Expand Up @@ -55,6 +56,7 @@ comment "Blackfin high speed USB Support"
config USB_TUSB6010
boolean "TUSB 6010 support"
depends on USB_MUSB_HDRC && !USB_MUSB_SOC
select NOP_USB_XCEIV
default y
help
The TUSB 6010 chip, from Texas Instruments, connects a discrete
Expand Down
11 changes: 8 additions & 3 deletions drivers/usb/musb/blackfin.c
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ static void musb_conn_timer_handler(unsigned long _musb)
u16 val;

spin_lock_irqsave(&musb->lock, flags);
switch (musb->xceiv.state) {
switch (musb->xceiv->state) {
case OTG_STATE_A_IDLE:
case OTG_STATE_A_WAIT_BCON:
/* Start a new session */
Expand All @@ -154,7 +154,7 @@ static void musb_conn_timer_handler(unsigned long _musb)
val = musb_readw(musb->mregs, MUSB_DEVCTL);
if (!(val & MUSB_DEVCTL_BDEVICE)) {
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 {
gpio_set_value(musb->config->gpio_vrsel, 0);

Expand Down Expand Up @@ -247,6 +247,11 @@ int __init musb_platform_init(struct musb *musb)
}
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) {
bfin_write_USB_APHY_CALIB(ANOMALY_05000346_value);
SSYNC();
Expand Down Expand Up @@ -291,7 +296,7 @@ int __init musb_platform_init(struct musb *musb)
musb_conn_timer_handler, (unsigned long) musb);
}
if (is_peripheral_enabled(musb))
musb->xceiv.set_power = bfin_set_power;
musb->xceiv->set_power = bfin_set_power;

musb->isr = blackfin_interrupt;

Expand Down
33 changes: 22 additions & 11 deletions drivers/usb/musb/davinci.c
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ static void otg_timer(unsigned long _musb)
DBG(7, "poll devctl %02x (%s)\n", devctl, otg_state_string(musb));

spin_lock_irqsave(&musb->lock, flags);
switch (musb->xceiv.state) {
switch (musb->xceiv->state) {
case OTG_STATE_A_WAIT_VFALL:
/* Wait till VBUS falls below SessionEnd (~0.2V); the 1.3 RTL
* seems to mis-handle session "start" otherwise (or in our
Expand All @@ -226,7 +226,7 @@ static void otg_timer(unsigned long _musb)
mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ);
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_INTR_VBUSERROR << DAVINCI_USB_USBINT_SHIFT);
break;
Expand All @@ -251,7 +251,7 @@ static void otg_timer(unsigned long _musb)
if (devctl & MUSB_DEVCTL_BDEVICE)
mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ);
else
musb->xceiv.state = OTG_STATE_A_IDLE;
musb->xceiv->state = OTG_STATE_A_IDLE;
break;
default:
break;
Expand Down Expand Up @@ -325,21 +325,21 @@ static irqreturn_t davinci_interrupt(int irq, void *__hci)
* to stop registering in devctl.
*/
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);
WARNING("VBUS error workaround (delay coming)\n");
} else if (is_host_enabled(musb) && drvvbus) {
musb->is_active = 1;
MUSB_HST_MODE(musb);
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;
portstate(musb->port1_status |= USB_PORT_STAT_POWER);
del_timer(&otg_workaround);
} else {
musb->is_active = 0;
MUSB_DEV_MODE(musb);
musb->xceiv.default_a = 0;
musb->xceiv.state = OTG_STATE_B_IDLE;
musb->xceiv->default_a = 0;
musb->xceiv->state = OTG_STATE_B_IDLE;
portstate(musb->port1_status &= ~USB_PORT_STAT_POWER);
}

Expand All @@ -361,7 +361,7 @@ static irqreturn_t davinci_interrupt(int irq, void *__hci)

/* poll for ID change */
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);

spin_unlock_irqrestore(&musb->lock, flags);
Expand All @@ -380,14 +380,19 @@ int __init musb_platform_init(struct musb *musb)
void __iomem *tibase = musb->ctrl_base;
u32 revision;

usb_nop_xceiv_register();
musb->xceiv = otg_get_transceiver();
if (!musb->xceiv)
return -ENODEV;

musb->mregs += DAVINCI_BASE_OFFSET;

clk_enable(musb->clock);

/* returns zero if e.g. not clocked */
revision = musb_readl(tibase, DAVINCI_USB_VERSION_REG);
if (revision == 0)
return -ENODEV;
goto fail;

if (is_host_enabled(musb))
setup_timer(&otg_workaround, otg_timer, (unsigned long) musb);
Expand Down Expand Up @@ -421,6 +426,10 @@ int __init musb_platform_init(struct musb *musb)

musb->isr = davinci_interrupt;
return 0;

fail:
usb_nop_xceiv_unregister();
return -ENODEV;
}

int musb_platform_exit(struct musb *musb)
Expand All @@ -431,7 +440,7 @@ int musb_platform_exit(struct musb *musb)
davinci_source_power(musb, 0 /*off*/, 1);

/* 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;
u8 devctl, warn = 0;

Expand Down Expand Up @@ -460,5 +469,7 @@ int musb_platform_exit(struct musb *musb)

clk_disable(musb->clock);

usb_nop_xceiv_unregister();

return 0;
}
Loading

0 comments on commit 84e250f

Please sign in to comment.