[PATCH 3/3] ARM: OMAP: Add MUSB support for OMAP34xx

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This patch adds MUSB support for OMAP34XX.

This patch depends on the previous two patches:
[PATCH 1/3] Add support for USB on OMAP34XX
[PATCH 2/3] Add support for TWL4030 USB Transceiver on OMAP34xx

Signed-off-by: Anand Gadiyar <gadiyar@xxxxxx>
Signed-off-by: Vikram Pandita <vikram.pandita@xxxxxx>
Signed-off-by: Nishant Kamat <nskamat@xxxxxx>
---
 drivers/usb/musb/Kconfig     |    1 
 drivers/usb/musb/Makefile    |    4 +
 drivers/usb/musb/musb_core.c |    3 -
 drivers/usb/musb/musb_core.h |    3 -
 drivers/usb/musb/omap2430.c  |  127 ++++++++++++++++++++++++++++++++++++++++++-
 drivers/usb/musb/omap2430.h  |   11 +++
 6 files changed, 144 insertions(+), 5 deletions(-)

Index: linux-omap-2.6-NOV30/drivers/usb/musb/Makefile
===================================================================
--- linux-omap-2.6-NOV30.orig/drivers/usb/musb/Makefile	2007-11-30 07:16:39.316083032 -0500
+++ linux-omap-2.6-NOV30/drivers/usb/musb/Makefile	2007-11-30 07:26:53.084776008 -0500
@@ -18,6 +18,10 @@
 	musb_hdrc-objs	+= omap2430.o
 endif
 
+ifeq ($(CONFIG_ARCH_OMAP3430),y)
+	musb_hdrc-objs	+= omap2430.o
+endif
+
 ifeq ($(CONFIG_USB_GADGET_MUSB_HDRC),y)
 	musb_hdrc-objs		+= musb_gadget_ep0.o musb_gadget.o
 endif
Index: linux-omap-2.6-NOV30/drivers/usb/musb/omap2430.c
===================================================================
--- linux-omap-2.6-NOV30.orig/drivers/usb/musb/omap2430.c	2007-11-30 07:16:39.316083032 -0500
+++ linux-omap-2.6-NOV30/drivers/usb/musb/omap2430.c	2007-11-30 07:32:40.334985952 -0500
@@ -1,5 +1,10 @@
 /*
- * Copyright (C) 2005-2006 by Texas Instruments
+ * Copyright (C) 2005-2007 by Texas Instruments
+ * Some code has been taken from tusb6010.c
+ * Copyrights for that are attributable to:
+ * Copyright (C) 2006 Nokia Corporation
+ * Jarkko Nikula <jarkko.nikula@xxxxxxxxx>
+ * Tony Lindgren <tony@xxxxxxxxxxx>
  *
  * This file is part of the Inventra Controller Driver for Linux.
  *
@@ -40,6 +45,108 @@
 #define	get_cpu_rev()	2
 #endif
 
+#define MUSB_TIMEOUT_A_WAIT_BCON	1100
+
+void musb_platform_set_mode(struct musb *musb, u8 musb_mode)
+{
+}
+
+int musb_platform_get_vbus_status(struct musb *musb)
+{
+	return 0;
+}
+static struct timer_list musb_idle_timer;
+
+static void musb_do_idle(unsigned long _musb)
+{
+	struct musb	*musb = (void *)_musb;
+	unsigned long	flags;
+	u8	power;
+	u8	devctl;
+
+	devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
+
+	spin_lock_irqsave(&musb->lock, flags);
+
+	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_DEV_MODE(musb);
+		} else {
+			musb->xceiv.state = OTG_STATE_A_IDLE;
+			MUSB_HST_MODE(musb);
+		}
+		break;
+#ifdef CONFIG_USB_MUSB_HDRC_HCD
+	case OTG_STATE_A_SUSPEND:
+		/* finish RESUME signaling? */
+		if (musb->port1_status & MUSB_PORT_STAT_RESUME) {
+			power = musb_readb(musb->mregs, MUSB_POWER);
+			power &= ~MUSB_POWER_RESUME;
+			DBG(1, "root port resume stopped, power %02x\n",
+									power);
+			musb_writeb(musb->mregs, MUSB_POWER, power);
+			musb->is_active = 1;
+			musb->port1_status &= ~(USB_PORT_STAT_SUSPEND
+						| MUSB_PORT_STAT_RESUME);
+			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;
+		}
+		break;
+#endif
+#ifdef CONFIG_USB_MUSB_HDRC_HCD
+	case OTG_STATE_A_HOST:
+		devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
+		if (devctl &  MUSB_DEVCTL_BDEVICE)
+			musb->xceiv.state = OTG_STATE_B_IDLE;
+		else
+			musb->xceiv.state = OTG_STATE_A_WAIT_BCON;
+#endif
+	default:
+		break;
+	}
+}
+
+
+void musb_platform_try_idle(struct musb *musb, unsigned long timeout)
+{
+	unsigned long		default_timeout = jiffies + msecs_to_jiffies(3);
+	static unsigned long	last_timer;
+
+	if (timeout == 0)
+		timeout = default_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))) {
+		DBG(4, "%s active, deleting timer\n", otg_state_string(musb));
+		del_timer(&musb_idle_timer);
+		last_timer = jiffies;
+		return;
+	}
+
+	if (time_after(last_timer, timeout)) {
+		if (!timer_pending(&musb_idle_timer))
+			last_timer = timeout;
+		else {
+			DBG(4, "Longer idle timer already pending, ignoring\n");
+			return;
+		}
+	}
+	last_timer = timeout;
+
+	DBG(4, "%s inactive, for idle timer for %lu ms\n",
+		otg_state_string(musb),
+		(unsigned long)jiffies_to_msecs(timeout - jiffies));
+	mod_timer(&musb_idle_timer, timeout);
+}
 
 void musb_platform_enable(struct musb *musb)
 {
@@ -93,6 +200,15 @@
 	return 0;
 }
 
+static int omap_set_suspend(struct otg_transceiver *x, int suspend)
+{
+	if (suspend)
+		twl4030_phy_suspend(1);
+	else
+		twl4030_phy_resume();
+	return 0;
+}
+
 int musb_platform_resume(struct musb *musb);
 
 int __init musb_platform_init(struct musb *musb)
@@ -102,11 +218,13 @@
 	/* get the clock */
 	musb->clock = clk_get((struct device *)musb->controller, "usbhs_ick");
 #else
-	musb->clock = clk_get((struct device *)musb->controller, "hsusb_ick");
+	musb->clock = clk_get((struct device *)musb->controller,
+								"hsotgusb_ick");
 #endif
 	if(IS_ERR(musb->clock))
 		return PTR_ERR(musb->clock);
 
+	musb->xceiv.set_suspend = omap_set_suspend;
 	musb_platform_resume(musb);
 
 	OTG_INTERFSEL_REG |= ULPI_12PIN;
@@ -123,6 +241,9 @@
 		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);
 
 	return 0;
 }
@@ -137,6 +258,7 @@
 	OTG_FORCESTDBY_REG |= ENABLEFORCE; /* enable MSTANDBY */
 	OTG_SYSCONFIG_REG |= AUTOIDLE;		/* enable auto idle */
 
+	musb->xceiv.set_suspend(&musb->xceiv, 1);
 	clk_disable(musb->clock);
 	return 0;
 }
@@ -144,6 +266,7 @@
 int musb_platform_resume(struct musb *musb)
 {
 	clk_enable(musb->clock);
+	musb->xceiv.set_suspend(&musb->xceiv, 0);
 
 	OTG_FORCESTDBY_REG &= ~ENABLEFORCE; /* disable MSTANDBY */
 	OTG_SYSCONFIG_REG |= SMARTSTDBY;	/* enable smart standby */
Index: linux-omap-2.6-NOV30/drivers/usb/musb/musb_core.c
===================================================================
--- linux-omap-2.6-NOV30.orig/drivers/usb/musb/musb_core.c	2007-11-30 07:16:39.316083032 -0500
+++ linux-omap-2.6-NOV30/drivers/usb/musb/musb_core.c	2007-11-30 07:26:53.085775856 -0500
@@ -991,7 +991,8 @@
 #define	can_dynfifo()	0
 #endif
 
-#ifdef CONFIG_USB_TUSB6010
+#if defined(CONFIG_USB_TUSB6010) || \
+	defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP34XX)
 static ushort __initdata fifo_mode = 4;
 #else
 static ushort __initdata fifo_mode = 2;
Index: linux-omap-2.6-NOV30/drivers/usb/musb/musb_core.h
===================================================================
--- linux-omap-2.6-NOV30.orig/drivers/usb/musb/musb_core.h	2007-11-30 07:16:39.316083032 -0500
+++ linux-omap-2.6-NOV30/drivers/usb/musb/musb_core.h	2007-11-30 07:26:53.085775856 -0500
@@ -476,7 +476,8 @@
 
 extern void musb_hnp_stop(struct musb *musb);
 
-#ifdef CONFIG_USB_TUSB6010
+#if defined(CONFIG_USB_TUSB6010) || \
+	defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP34XX)
 extern void musb_platform_try_idle(struct musb *musb, unsigned long timeout);
 extern int musb_platform_get_vbus_status(struct musb *musb);
 extern void musb_platform_set_mode(struct musb *musb, u8 musb_mode);
Index: linux-omap-2.6-NOV30/drivers/usb/musb/omap2430.h
===================================================================
--- linux-omap-2.6-NOV30.orig/drivers/usb/musb/omap2430.h	2007-11-30 07:16:39.316083032 -0500
+++ linux-omap-2.6-NOV30/drivers/usb/musb/omap2430.h	2007-11-30 07:26:53.085775856 -0500
@@ -13,6 +13,15 @@
 #if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3430)
 #include <asm/arch/hardware.h>
 #include <asm/arch/usb.h>
+
+#if defined(CONFIG_TWL4030_USB_HS_ULPI)
+extern void twl4030_phy_suspend(int controller_off);
+extern void twl4030_phy_resume(void);
+#else
+#define twl4030_phy_suspend(x)  /* not defined */
+#define twl4030_phy_resume()    /* not defined */
+#endif
+
 /*
  * OMAP2430-specific definitions
  */
@@ -21,7 +30,7 @@
 #if	defined(CONFIG_ARCH_OMAP2430)
 #define	OMAP_HSOTG_BASE		(OMAP243X_HS_BASE)
 #elif	defined(CONFIG_ARCH_OMAP3430)
-#define	OMAP_HSOTG_BASE		(HS_BASE)
+#define	OMAP_HSOTG_BASE		(OMAP34XX_HSUSB_OTG_BASE)
 #endif
 #define OMAP_HSOTG(offset)	__REG32(OMAP_HSOTG_BASE + 0x400 + (offset))
 #define OTG_REVISION_REG	OMAP_HSOTG(0x0)
Index: linux-omap-2.6-NOV30/drivers/usb/musb/Kconfig
===================================================================
--- linux-omap-2.6-NOV30.orig/drivers/usb/musb/Kconfig	2007-11-30 04:53:40.000000000 -0500
+++ linux-omap-2.6-NOV30/drivers/usb/musb/Kconfig	2007-11-30 08:39:46.261952024 -0500
@@ -9,6 +9,7 @@
 # (M)HDRC = (Multipoint) Highspeed Dual-Role Controller
 config USB_MUSB_HDRC
 	depends on USB || USB_GADGET
+	select TWL4030_USB if MACH_OMAP_3430SDP
 	tristate 'Inventra Highspeed Dual Role Controller (TI, ...)'
 	help
 	  Say Y here if your system has a dual role high speed USB
-
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Arm (vger)]     [ARM Kernel]     [ARM MSM]     [Linux Tegra]     [Linux WPAN Networking]     [Linux Wireless Networking]     [Maemo Users]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Trails]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux