summaryrefslogtreecommitdiff
path: root/drivers/usb/musb
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/musb')
-rw-r--r--drivers/usb/musb/Kconfig2
-rw-r--r--drivers/usb/musb/blackfin.c11
-rw-r--r--drivers/usb/musb/davinci.c33
-rw-r--r--drivers/usb/musb/musb_core.c96
-rw-r--r--drivers/usb/musb/musb_core.h2
-rw-r--r--drivers/usb/musb/musb_gadget.c38
-rw-r--r--drivers/usb/musb/musb_host.c2
-rw-r--r--drivers/usb/musb/musb_virthub.c20
-rw-r--r--drivers/usb/musb/omap2430.c62
-rw-r--r--drivers/usb/musb/tusb6010.c70
10 files changed, 181 insertions, 155 deletions
diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig
index b66e8544d8b9..70073b157f0a 100644
--- a/drivers/usb/musb/Kconfig
+++ b/drivers/usb/musb/Kconfig
@@ -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, ...)'
@@ -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
diff --git a/drivers/usb/musb/blackfin.c b/drivers/usb/musb/blackfin.c
index 786134852092..f2f66ebc7362 100644
--- a/drivers/usb/musb/blackfin.c
+++ b/drivers/usb/musb/blackfin.c
@@ -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 */
@@ -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);
@@ -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();
@@ -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;
diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c
index 6e14e06ff820..180d7daa4099 100644
--- a/drivers/usb/musb/davinci.c
+++ b/drivers/usb/musb/davinci.c
@@ -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
@@ -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;
@@ -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;
@@ -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);
}
@@ -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);
@@ -380,6 +380,11 @@ 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);
@@ -387,7 +392,7 @@ int __init musb_platform_init(struct musb *musb)
/* 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);
@@ -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)
@@ -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;
@@ -460,5 +469,7 @@ int musb_platform_exit(struct musb *musb)
clk_disable(musb->clock);
+ usb_nop_xceiv_unregister();
+
return 0;
}
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index 324459b619f7..2460c3986c96 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -267,7 +267,7 @@ void musb_load_testpacket(struct musb *musb)
const char *otg_state_string(struct musb *musb)
{
- switch (musb->xceiv.state) {
+ switch (musb->xceiv->state) {
case OTG_STATE_A_IDLE: return "a_idle";
case OTG_STATE_A_WAIT_VRISE: return "a_wait_vrise";
case OTG_STATE_A_WAIT_BCON: return "a_wait_bcon";
@@ -302,11 +302,11 @@ void musb_otg_timer_func(unsigned long data)
unsigned long flags;
spin_lock_irqsave(&musb->lock, flags);
- switch (musb->xceiv.state) {
+ switch (musb->xceiv->state) {
case OTG_STATE_B_WAIT_ACON:
DBG(1, "HNP: b_wait_acon timeout; back to b_peripheral\n");
musb_g_disconnect(musb);
- musb->xceiv.state = OTG_STATE_B_PERIPHERAL;
+ musb->xceiv->state = OTG_STATE_B_PERIPHERAL;
musb->is_active = 0;
break;
case OTG_STATE_A_WAIT_BCON:
@@ -331,20 +331,20 @@ void musb_hnp_stop(struct musb *musb)
void __iomem *mbase = musb->mregs;
u8 reg;
- switch (musb->xceiv.state) {
+ switch (musb->xceiv->state) {
case OTG_STATE_A_PERIPHERAL:
case OTG_STATE_A_WAIT_VFALL:
case OTG_STATE_A_WAIT_BCON:
DBG(1, "HNP: Switching back to A-host\n");
musb_g_disconnect(musb);
- musb->xceiv.state = OTG_STATE_A_IDLE;
+ musb->xceiv->state = OTG_STATE_A_IDLE;
MUSB_HST_MODE(musb);
musb->is_active = 0;
break;
case OTG_STATE_B_HOST:
DBG(1, "HNP: Disabling HR\n");
hcd->self.is_b_host = 0;
- musb->xceiv.state = OTG_STATE_B_PERIPHERAL;
+ musb->xceiv->state = OTG_STATE_B_PERIPHERAL;
MUSB_DEV_MODE(musb);
reg = musb_readb(mbase, MUSB_POWER);
reg |= MUSB_POWER_SUSPENDM;
@@ -402,7 +402,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
if (devctl & MUSB_DEVCTL_HM) {
#ifdef CONFIG_USB_MUSB_HDRC_HCD
- switch (musb->xceiv.state) {
+ switch (musb->xceiv->state) {
case OTG_STATE_A_SUSPEND:
/* remote wakeup? later, GetPortStatus
* will stop RESUME signaling
@@ -425,12 +425,12 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
musb->rh_timer = jiffies
+ msecs_to_jiffies(20);
- musb->xceiv.state = OTG_STATE_A_HOST;
+ musb->xceiv->state = OTG_STATE_A_HOST;
musb->is_active = 1;
usb_hcd_resume_root_hub(musb_to_hcd(musb));
break;
case OTG_STATE_B_WAIT_ACON:
- musb->xceiv.state = OTG_STATE_B_PERIPHERAL;
+ musb->xceiv->state = OTG_STATE_B_PERIPHERAL;
musb->is_active = 1;
MUSB_DEV_MODE(musb);
break;
@@ -441,11 +441,11 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
}
#endif
} else {
- switch (musb->xceiv.state) {
+ switch (musb->xceiv->state) {
#ifdef CONFIG_USB_MUSB_HDRC_HCD
case OTG_STATE_A_SUSPEND:
/* possibly DISCONNECT is upcoming */
- musb->xceiv.state = OTG_STATE_A_HOST;
+ musb->xceiv->state = OTG_STATE_A_HOST;
usb_hcd_resume_root_hub(musb_to_hcd(musb));
break;
#endif
@@ -490,7 +490,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
*/
musb_writeb(mbase, MUSB_DEVCTL, MUSB_DEVCTL_SESSION);
musb->ep0_stage = MUSB_EP0_START;
- musb->xceiv.state = OTG_STATE_A_IDLE;
+ musb->xceiv->state = OTG_STATE_A_IDLE;
MUSB_HST_MODE(musb);
musb_set_vbus(musb, 1);
@@ -516,7 +516,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
* REVISIT: do delays from lots of DEBUG_KERNEL checks
* make trouble here, keeping VBUS < 4.4V ?
*/
- switch (musb->xceiv.state) {
+ switch (musb->xceiv->state) {
case OTG_STATE_A_HOST:
/* recovery is dicey once we've gotten past the
* initial stages of enumeration, but if VBUS
@@ -602,11 +602,11 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
MUSB_HST_MODE(musb);
/* indicate new connection to OTG machine */
- switch (musb->xceiv.state) {
+ switch (musb->xceiv->state) {
case OTG_STATE_B_PERIPHERAL:
if (int_usb & MUSB_INTR_SUSPEND) {
DBG(1, "HNP: SUSPEND+CONNECT, now b_host\n");
- musb->xceiv.state = OTG_STATE_B_HOST;
+ musb->xceiv->state = OTG_STATE_B_HOST;
hcd->self.is_b_host = 1;
int_usb &= ~MUSB_INTR_SUSPEND;
} else
@@ -614,13 +614,13 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
break;
case OTG_STATE_B_WAIT_ACON:
DBG(1, "HNP: Waiting to switch to b_host state\n");
- musb->xceiv.state = OTG_STATE_B_HOST;
+ musb->xceiv->state = OTG_STATE_B_HOST;
hcd->self.is_b_host = 1;
break;
default:
if ((devctl & MUSB_DEVCTL_VBUS)
== (3 << MUSB_DEVCTL_VBUS_SHIFT)) {
- musb->xceiv.state = OTG_STATE_A_HOST;
+ musb->xceiv->state = OTG_STATE_A_HOST;
hcd->self.is_b_host = 0;
}
break;
@@ -650,7 +650,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
}
} else if (is_peripheral_capable()) {
DBG(1, "BUS RESET as %s\n", otg_state_string(musb));
- switch (musb->xceiv.state) {
+ switch (musb->xceiv->state) {
#ifdef CONFIG_USB_OTG
case OTG_STATE_A_SUSPEND:
/* We need to ignore disconnect on suspend
@@ -673,12 +673,12 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
case OTG_STATE_B_WAIT_ACON:
DBG(1, "HNP: RESET (%s), to b_peripheral\n",
otg_state_string(musb));
- musb->xceiv.state = OTG_STATE_B_PERIPHERAL;
+ musb->xceiv->state = OTG_STATE_B_PERIPHERAL;
musb_g_reset(musb);
break;
#endif
case OTG_STATE_B_IDLE:
- musb->xceiv.state = OTG_STATE_B_PERIPHERAL;
+ musb->xceiv->state = OTG_STATE_B_PERIPHERAL;
/* FALLTHROUGH */
case OTG_STATE_B_PERIPHERAL:
musb_g_reset(musb);
@@ -763,7 +763,7 @@ static irqreturn_t musb_stage2_irq(struct musb *musb, u8 int_usb,
MUSB_MODE(musb), devctl);
handled = IRQ_HANDLED;
- switch (musb->xceiv.state) {
+ switch (musb->xceiv->state) {
#ifdef CONFIG_USB_MUSB_HDRC_HCD
case OTG_STATE_A_HOST:
case OTG_STATE_A_SUSPEND:
@@ -805,7 +805,7 @@ static irqreturn_t musb_stage2_irq(struct musb *musb, u8 int_usb,
otg_state_string(musb), devctl, power);
handled = IRQ_HANDLED;
- switch (musb->xceiv.state) {
+ switch (musb->xceiv->state) {
#ifdef CONFIG_USB_MUSB_OTG
case OTG_STATE_A_PERIPHERAL:
/*
@@ -817,10 +817,10 @@ static irqreturn_t musb_stage2_irq(struct musb *musb, u8 int_usb,
case OTG_STATE_B_PERIPHERAL:
musb_g_suspend(musb);
musb->is_active = is_otg_enabled(musb)
- && musb->xceiv.gadget->b_hnp_enable;
+ && musb->xceiv->gadget->b_hnp_enable;
if (musb->is_active) {
#ifdef CONFIG_USB_MUSB_OTG
- musb->xceiv.state = OTG_STATE_B_WAIT_ACON;
+ musb->xceiv->state = OTG_STATE_B_WAIT_ACON;
DBG(1, "HNP: Setting timer for b_ase0_brst\n");
musb_otg_timer.data = (unsigned long)musb;
mod_timer(&musb_otg_timer, jiffies
@@ -834,9 +834,9 @@ static irqreturn_t musb_stage2_irq(struct musb *musb, u8 int_usb,
+ msecs_to_jiffies(musb->a_wait_bcon));
break;
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->xceiv.host->b_hnp_enable;
+ && musb->xceiv->host->b_hnp_enable;
break;
case OTG_STATE_B_HOST:
/* Transition to B_PERIPHERAL, see 6.8.2.6 p 44 */
@@ -1682,7 +1682,7 @@ musb_vbus_store(struct device *dev, struct device_attribute *attr,
spin_lock_irqsave(&musb->lock, flags);
musb->a_wait_bcon = val;
- if (musb->xceiv.state == OTG_STATE_A_WAIT_BCON)
+ if (musb->xceiv->state == OTG_STATE_A_WAIT_BCON)
musb->is_active = 0;
musb_platform_try_idle(musb, jiffies + msecs_to_jiffies(val));
spin_unlock_irqrestore(&musb->lock, flags);
@@ -1743,8 +1743,8 @@ static void musb_irq_work(struct work_struct *data)
struct musb *musb = container_of(data, struct musb, irq_work);
static int old_state;
- if (musb->xceiv.state != old_state) {
- old_state = musb->xceiv.state;
+ if (musb->xceiv->state != old_state) {
+ old_state = musb->xceiv->state;
sysfs_notify(&musb->controller->kobj, NULL, "mode");
}
}
@@ -1841,7 +1841,7 @@ static void musb_free(struct musb *musb)
}
#ifdef CONFIG_USB_MUSB_OTG
- put_device(musb->xceiv.dev);
+ put_device(musb->xceiv->dev);
#endif
#ifdef CONFIG_USB_MUSB_HDRC_HCD
@@ -1922,10 +1922,18 @@ bad_config:
}
}
- /* assume vbus is off */
-
- /* platform adjusts musb->mregs and musb->isr if needed,
- * and activates clocks
+ /* The musb_platform_init() call:
+ * - adjusts musb->mregs and musb->isr if needed,
+ * - may initialize an integrated tranceiver
+ * - initializes musb->xceiv, usually by otg_get_transceiver()
+ * - activates clocks.
+ * - stops powering VBUS
+ * - assigns musb->board_set_vbus if host mode is enabled
+ *
+ * There are various transciever configurations. Blackfin,
+ * DaVinci, TUSB60x0, and others integrate them. OMAP3 uses
+ * external/discrete ones in various flavors (twl4030 family,
+ * isp1504, non-OTG, etc) mostly hooking up through ULPI.
*/
musb->isr = generic_interrupt;
status = musb_platform_init(musb);
@@ -1993,17 +2001,17 @@ bad_config:
? "DMA" : "PIO",
musb->nIrq);
-#ifdef CONFIG_USB_MUSB_HDRC_HCD
- /* host side needs more setup, except for no-host modes */
- if (musb->board_mode != MUSB_PERIPHERAL) {
+ /* host side needs more setup */
+ if (is_host_enabled(musb)) {
struct usb_hcd *hcd = musb_to_hcd(musb);
- if (musb->board_mode == MUSB_OTG)
+ otg_set_host(musb->xceiv, &hcd->self);
+
+ if (is_otg_enabled(musb))
hcd->self.otg_port = 1;
- musb->xceiv.host = &hcd->self;
+ musb->xceiv->host = &hcd->self;
hcd->power_budget = 2 * (plat->power ? : 250);
}
-#endif /* CONFIG_USB_MUSB_HDRC_HCD */
/* For the host-only role, we can activate right away.
* (We expect the ID pin to be forcibly grounded!!)
@@ -2011,8 +2019,8 @@ bad_config:
*/
if (!is_otg_enabled(musb) && is_host_enabled(musb)) {
MUSB_HST_MODE(musb);
- musb->xceiv.default_a = 1;
- musb->xceiv.state = OTG_STATE_A_IDLE;
+ musb->xceiv->default_a = 1;
+ musb->xceiv->state = OTG_STATE_A_IDLE;
status = usb_add_hcd(musb_to_hcd(musb), -1, 0);
if (status)
@@ -2027,8 +2035,8 @@ bad_config:
} else /* peripheral is enabled */ {
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;
status = musb_gadget_setup(musb);
if (status)
diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h
index c2a776ee1947..2b49c989f043 100644
--- a/drivers/usb/musb/musb_core.h
+++ b/drivers/usb/musb/musb_core.h
@@ -356,7 +356,7 @@ struct musb {
u16 int_rx;
u16 int_tx;
- struct otg_transceiver xceiv;
+ struct otg_transceiver *xceiv;
int nIrq;
unsigned irq_wake:1;
diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c
index bc197b28ac40..8dfad1189da2 100644
--- a/drivers/usb/musb/musb_gadget.c
+++ b/drivers/usb/musb/musb_gadget.c
@@ -1406,7 +1406,7 @@ static int musb_gadget_wakeup(struct usb_gadget *gadget)
spin_lock_irqsave(&musb->lock, flags);
- switch (musb->xceiv.state) {
+ switch (musb->xceiv->state) {
case OTG_STATE_B_PERIPHERAL:
/* NOTE: OTG state machine doesn't include B_SUSPENDED;
* 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)
{
struct musb *musb = gadget_to_musb(gadget);
- if (!musb->xceiv.set_power)
+ if (!musb->xceiv->set_power)
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)
@@ -1733,11 +1733,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
spin_lock_irqsave(&musb->lock, flags);
- /* REVISIT always use otg_set_peripheral(), handling
- * issues including the root hub one below ...
- */
- musb->xceiv.gadget = &musb->g;
- musb->xceiv.state = OTG_STATE_B_IDLE;
+ otg_set_peripheral(musb->xceiv, &musb->g);
musb->is_active = 1;
/* FIXME this ignores the softconnect flag. Drivers are
@@ -1749,6 +1745,8 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
if (!is_otg_enabled(musb))
musb_start(musb);
+ otg_set_peripheral(musb->xceiv, &musb->g);
+
spin_unlock_irqrestore(&musb->lock, flags);
if (is_otg_enabled(musb)) {
@@ -1762,8 +1760,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
if (retval < 0) {
DBG(1, "add_hcd failed, %d\n", retval);
spin_lock_irqsave(&musb->lock, flags);
- musb->xceiv.gadget = NULL;
- musb->xceiv.state = OTG_STATE_UNDEFINED;
+ otg_set_peripheral(musb->xceiv, NULL);
musb->gadget_driver = NULL;
musb->g.dev.driver = NULL;
spin_unlock_irqrestore(&musb->lock, flags);
@@ -1846,8 +1843,9 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
(void) musb_gadget_vbus_draw(&musb->g, 0);
- musb->xceiv.state = OTG_STATE_UNDEFINED;
+ musb->xceiv->state = OTG_STATE_UNDEFINED;
stop_activity(musb, driver);
+ otg_set_peripheral(musb->xceiv, NULL);
DBG(3, "unregistering driver %s\n", driver->function);
spin_unlock_irqrestore(&musb->lock, flags);
@@ -1883,7 +1881,7 @@ EXPORT_SYMBOL(usb_gadget_unregister_driver);
void musb_g_resume(struct musb *musb)
{
musb->is_suspended = 0;
- switch (musb->xceiv.state) {
+ switch (musb->xceiv->state) {
case OTG_STATE_B_IDLE:
break;
case OTG_STATE_B_WAIT_ACON:
@@ -1909,10 +1907,10 @@ void musb_g_suspend(struct musb *musb)
devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
DBG(3, "devctl %02x\n", devctl);
- switch (musb->xceiv.state) {
+ switch (musb->xceiv->state) {
case OTG_STATE_B_IDLE:
if ((devctl & MUSB_DEVCTL_VBUS) == MUSB_DEVCTL_VBUS)
- musb->xceiv.state = OTG_STATE_B_PERIPHERAL;
+ musb->xceiv->state = OTG_STATE_B_PERIPHERAL;
break;
case OTG_STATE_B_PERIPHERAL:
musb->is_suspended = 1;
@@ -1958,22 +1956,22 @@ void musb_g_disconnect(struct musb *musb)
spin_lock(&musb->lock);
}
- switch (musb->xceiv.state) {
+ switch (musb->xceiv->state) {
default:
#ifdef CONFIG_USB_MUSB_OTG
DBG(2, "Unhandled disconnect %s, setting a_idle\n",
otg_state_string(musb));
- musb->xceiv.state = OTG_STATE_A_IDLE;
+ musb->xceiv->state = OTG_STATE_A_IDLE;
break;
case OTG_STATE_A_PERIPHERAL:
- musb->xceiv.state = OTG_STATE_A_WAIT_VFALL;
+ musb->xceiv->state = OTG_STATE_A_WAIT_VFALL;
break;
case OTG_STATE_B_WAIT_ACON:
case OTG_STATE_B_HOST:
#endif
case OTG_STATE_B_PERIPHERAL:
case OTG_STATE_B_IDLE:
- musb->xceiv.state = OTG_STATE_B_IDLE;
+ musb->xceiv->state = OTG_STATE_B_IDLE;
break;
case OTG_STATE_B_SRP_INIT:
break;
@@ -2029,10 +2027,10 @@ __acquires(musb->lock)
* or else after HNP, as A-Device
*/
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;
} 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;
} else
WARN_ON(1);
diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
index c1bb192ecbef..0d1f15336a9c 100644
--- a/drivers/usb/musb/musb_host.c
+++ b/drivers/usb/musb/musb_host.c
@@ -2213,7 +2213,7 @@ static int musb_bus_suspend(struct usb_hcd *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;
if (is_host_active(musb) && musb->is_active) {
diff --git a/drivers/usb/musb/musb_virthub.c b/drivers/usb/musb/musb_virthub.c
index bf677acc83db..d7e1bc44f00a 100644
--- a/drivers/usb/musb/musb_virthub.c
+++ b/drivers/usb/musb/musb_virthub.c
@@ -78,18 +78,18 @@ static void musb_port_suspend(struct musb *musb, bool do_suspend)
DBG(3, "Root port suspended, power %02x\n", power);
musb->port1_status |= USB_PORT_STAT_SUSPEND;
- switch (musb->xceiv.state) {
+ switch (musb->xceiv->state) {
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->xceiv.host->b_hnp_enable;
+ && musb->xceiv->host->b_hnp_enable;
musb_platform_try_idle(musb, 0);
break;
#ifdef CONFIG_USB_MUSB_OTG
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->xceiv.host->b_hnp_enable;
+ && musb->xceiv->host->b_hnp_enable;
musb_platform_try_idle(musb, 0);
break;
#endif
@@ -116,7 +116,7 @@ static void musb_port_reset(struct musb *musb, bool do_reset)
void __iomem *mbase = musb->mregs;
#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");
musb->port1_status &= ~USB_PORT_STAT_RESET;
return;
@@ -186,14 +186,14 @@ void musb_root_disconnect(struct musb *musb)
usb_hcd_poll_rh_status(musb_to_hcd(musb));
musb->is_active = 0;
- switch (musb->xceiv.state) {
+ switch (musb->xceiv->state) {
case OTG_STATE_A_HOST:
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;
break;
case OTG_STATE_A_WAIT_VFALL:
- musb->xceiv.state = OTG_STATE_B_IDLE;
+ musb->xceiv->state = OTG_STATE_B_IDLE;
break;
default:
DBG(1, "host disconnect (%s)\n", otg_state_string(musb));
@@ -332,7 +332,7 @@ int musb_hub_control(
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;
}
put_unaligned(cpu_to_le32(musb->port1_status
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);
diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c
index 4ac1477d3569..88b587c703e9 100644
--- a/drivers/usb/musb/tusb6010.c
+++ b/drivers/usb/musb/tusb6010.c
@@ -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);
}
+static struct musb *the_musb;
+
#ifdef CONFIG_USB_GADGET_MUSB_HDRC
/* 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)
*/
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;
u32 reg;
@@ -419,7 +421,7 @@ static void musb_do_idle(unsigned long _musb)
spin_lock_irqsave(&musb->lock, flags);
- switch (musb->xceiv.state) {
+ switch (musb->xceiv->state) {
case OTG_STATE_A_WAIT_BCON:
if ((musb->a_wait_bcon != 0)
&& (musb->idle_timeout == 0
@@ -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 */
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;
@@ -532,8 +534,8 @@ static void tusb_source_power(struct musb *musb, int is_on)
if (musb->set_clock)
musb->set_clock(musb->clock, 1);
timer = OTG_TIMER_MS(OTG_TIME_A_WAIT_VRISE);
- 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;
conf |= TUSB_DEV_CONF_USB_HOST_MODE;
@@ -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 */
otg_stat = musb_readl(tbase, TUSB_DEV_OTG_STAT);
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_BCON:
- musb->xceiv.state = OTG_STATE_A_WAIT_VFALL;
+ musb->xceiv->state = OTG_STATE_A_WAIT_VFALL;
break;
case OTG_STATE_A_WAIT_VFALL:
- musb->xceiv.state = OTG_STATE_A_IDLE;
+ musb->xceiv->state = OTG_STATE_A_IDLE;
break;
default:
- musb->xceiv.state = OTG_STATE_A_IDLE;
+ musb->xceiv->state = OTG_STATE_A_IDLE;
}
musb->is_active = 0;
- musb->xceiv.default_a = 1;
+ musb->xceiv->default_a = 1;
MUSB_HST_MODE(musb);
} else {
musb->is_active = 0;
- musb->xceiv.default_a = 0;
- musb->xceiv.state = OTG_STATE_B_IDLE;
+ musb->xceiv->default_a = 0;
+ musb->xceiv->state = OTG_STATE_B_IDLE;
MUSB_DEV_MODE(musb);
}
@@ -674,7 +676,7 @@ tusb_otg_ints(struct musb *musb, u32 int_src, void __iomem *tbase)
else
default_a = is_host_enabled(musb);
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);
/* Don't allow idling immediately */
@@ -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) {
/* 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)) {
#ifdef CONFIG_USB_MUSB_HDRC_HCD
/* ? musb_root_disconnect(musb); */
@@ -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) {
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... */
- musb->xceiv.state = OTG_STATE_B_IDLE;
+ musb->xceiv->state = OTG_STATE_B_IDLE;
musb->int_usb |= MUSB_INTR_DISCONNECT;
}
musb->is_active = 0;
@@ -717,7 +719,7 @@ tusb_otg_ints(struct musb *musb, u32 int_src, void __iomem *tbase)
DBG(2, "vbus change, %s, otg %03x\n",
otg_state_string(musb), otg_stat);
- switch (musb->xceiv.state) {
+ switch (musb->xceiv->state) {
case OTG_STATE_A_IDLE:
DBG(2, "Got SRP, turning on VBUS\n");
musb_set_vbus(musb, 1);
@@ -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);
- switch (musb->xceiv.state) {
+ switch (musb->xceiv->state) {
case OTG_STATE_A_WAIT_VRISE:
/* VBUS has probably been valid for a while now,
* 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)
DBG(2, "devctl %02x\n", devctl);
break;
}
- musb->xceiv.state = OTG_STATE_A_WAIT_BCON;
+ musb->xceiv->state = OTG_STATE_A_WAIT_BCON;
musb->is_active = 0;
idle_timeout = jiffies
+ msecs_to_jiffies(musb->a_wait_bcon);
@@ -1093,9 +1095,14 @@ int __init musb_platform_init(struct musb *musb)
{
struct platform_device *pdev;
struct resource *mem;
- void __iomem *sync;
+ void __iomem *sync = NULL;
int ret;
+ usb_nop_xceiv_register();
+ musb->xceiv = otg_get_transceiver();
+ if (!musb->xceiv)
+ return -ENODEV;
+
pdev = to_platform_device(musb->controller);
/* dma address for async dma */
@@ -1106,14 +1113,16 @@ int __init musb_platform_init(struct musb *musb)
mem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
if (!mem) {
pr_debug("no sync dma resource?\n");
- return -ENODEV;
+ ret = -ENODEV;
+ goto done;
}
musb->sync = mem->start;
sync = ioremap(mem->start, mem->end - mem->start + 1);
if (!sync) {
pr_debug("ioremap for sync failed\n");
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto done;
}
musb->sync_va = sync;
@@ -1126,28 +1135,37 @@ int __init musb_platform_init(struct musb *musb)
if (ret) {
printk(KERN_ERR "Could not start tusb6010 (%d)\n",
ret);
- return -ENODEV;
+ goto done;
}
musb->isr = tusb_interrupt;
if (is_host_enabled(musb))
musb->board_set_vbus = tusb_source_power;
- if (is_peripheral_enabled(musb))
- musb->xceiv.set_power = tusb_draw_power;
+ if (is_peripheral_enabled(musb)) {
+ musb->xceiv->set_power = tusb_draw_power;
+ the_musb = 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;
}
int musb_platform_exit(struct musb *musb)
{
del_timer_sync(&musb_idle_timer);
+ the_musb = NULL;
if (musb->board_set_power)
musb->board_set_power(0);
iounmap(musb->sync_va);
-
+ usb_nop_xceiv_unregister();
return 0;
}