diff mbox

[6/7] usb: musb: Adding musb support for OMAP4430

Message ID 1291824147-7219-1-git-send-email-hemahk@ti.com (mailing list archive)
State Awaiting Upstream, archived
Delegated to: Felipe Balbi
Headers show

Commit Message

Kalliguddi, Hema Dec. 8, 2010, 4:02 p.m. UTC
None
diff mbox

Patch

Index: linux-2.6/drivers/usb/musb/musb_core.c
===================================================================
--- linux-2.6.orig/drivers/usb/musb/musb_core.c
+++ linux-2.6/drivers/usb/musb/musb_core.c
@@ -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;
Index: linux-2.6/drivers/usb/musb/musb_core.h
===================================================================
--- linux-2.6.orig/drivers/usb/musb/musb_core.h
+++ linux-2.6/drivers/usb/musb/musb_core.h
@@ -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.
Index: linux-2.6/drivers/usb/musb/musb_gadget.c
===================================================================
--- linux-2.6.orig/drivers/usb/musb/musb_gadget.c
+++ linux-2.6/drivers/usb/musb/musb_gadget.c
@@ -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;
Index: linux-2.6/drivers/usb/musb/omap2430.c
===================================================================
--- linux-2.6.orig/drivers/usb/musb/omap2430.c
+++ linux-2.6/drivers/usb/musb/omap2430.c
@@ -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))