===================================================================
@@ -2116,6 +2116,11 @@ bad_config:
& MUSB_DEVCTL_BDEVICE
? 'B' : 'A'));
+ /*
+ * Host only mode, check whether the device is already
+ * connected
+ */
+ otg_get_last_event(musb->xceiv);
} else /* peripheral is enabled */ {
MUSB_DEV_MODE(musb);
musb->xceiv->default_a = 0;
===================================================================
@@ -411,6 +411,7 @@ struct musb {
struct timer_list otg_timer;
#endif
+ struct notifier_block nb;
/* called with IRQs blocked; ON/nonzero implies starting a session,
* and waiting at least a_wait_vrise_tmout.
===================================================================
@@ -1809,6 +1809,7 @@ int usb_gadget_probe_driver(struct usb_g
hcd->self.uses_pio_for_control = 1;
}
}
+ otg_get_last_event(musb->xceiv);
}
return retval;
===================================================================
@@ -57,13 +57,8 @@ static void musb_do_idle(unsigned long _
spin_lock_irqsave(&musb->lock, flags);
- devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
-
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;
@@ -142,20 +137,34 @@ static void omap2430_try_idle(struct mus
static void omap2430_set_vbus(struct musb *musb, int is_on)
{
u8 devctl;
+ long int timeout = 0xFFFFFFFF;
/* HDRC controls CPEN, but beware current surges during device
* connect. They can trigger transient overcurrent conditions
* that must be ignored.
*/
-
devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
if (is_on) {
- musb->is_active = 1;
- musb->xceiv->default_a = 1;
- musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
- devctl |= MUSB_DEVCTL_SESSION;
-
- MUSB_HST_MODE(musb);
+ if (musb->xceiv->state == OTG_STATE_A_IDLE) {
+ /* start the session */
+ devctl |= MUSB_DEVCTL_SESSION;
+ musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
+
+ while (musb_readb(musb->mregs, MUSB_DEVCTL) & 0x80
+ && timeout == 0) {
+ timeout--;
+ }
+ if (!timeout)
+ pr_warning("musb not configured as A device\n");
+ else if (musb->xceiv->set_vbus)
+ otg_set_vbus(musb->xceiv, 1);
+ } else {
+ musb->is_active = 1;
+ musb->xceiv->default_a = 1;
+ musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
+ devctl |= MUSB_DEVCTL_SESSION;
+ MUSB_HST_MODE(musb);
+ }
} else {
musb->is_active = 0;
@@ -214,9 +223,64 @@ static inline void omap2430_low_level_ex
musb_writel(musb->mregs, OTG_FORCESTDBY, l);
}
+/* blocking notifier support */
+static int musb_otg_notifications(struct notifier_block *nb,
+ unsigned long event, void *unused)
+{
+ struct musb *musb = container_of(nb, struct musb, nb);
+ struct device *dev = musb->controller;
+ struct musb_hdrc_platform_data *pdata = dev->platform_data;
+ struct omap_musb_board_data *data = pdata->board_data;
+
+ switch (event) {
+ case USB_EVENT_ID:
+ DBG(4, "ID GND\n");
+
+ if (is_otg_enabled(musb)) {
+ if (musb->gadget_driver) {
+ otg_init(musb->xceiv);
+
+ if (data->interface_type ==
+ MUSB_INTERFACE_UTMI)
+ omap2430_set_vbus(musb, 1);
+
+ }
+ } else {
+ otg_init(musb->xceiv);
+ if (data->interface_type ==
+ MUSB_INTERFACE_UTMI)
+ omap2430_set_vbus(musb, 1);
+ }
+ break;
+
+ case USB_EVENT_VBUS:
+ DBG(4, "VBUS Connect\n");
+
+ otg_init(musb->xceiv);
+ break;
+
+ case USB_EVENT_NONE:
+ DBG(4, "VBUS Disconnect\n");
+
+ if (data->interface_type == MUSB_INTERFACE_UTMI) {
+ if (musb->xceiv->set_vbus)
+ otg_set_vbus(musb->xceiv, 0);
+ }
+ otg_shutdown(musb->xceiv);
+ break;
+ default:
+ DBG(4, "ID float\n");
+ return NOTIFY_DONE;
+ }
+
+ return NOTIFY_OK;
+}
+
static int omap2430_platform_init(struct musb *musb, void *board_data)
{
- u32 l;
+ u32 l, status = 0;
struct omap_musb_board_data *data = board_data;
/* We require some kind of external transceiver, hooked
@@ -269,6 +333,12 @@ static int omap2430_platform_init(struct
if (is_host_enabled(musb))