* [PATCH 3/3] ARM: OMAP: Add MUSB support for OMAP34xx
@ 2007-12-05 13:12 Gadiyar, Anand
2007-12-05 19:43 ` Kevin Hilman
0 siblings, 1 reply; 4+ messages in thread
From: Gadiyar, Anand @ 2007-12-05 13:12 UTC (permalink / raw)
To: linux-omap-open-source; +Cc: linux-omap
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@ti.com>
Signed-off-by: Vikram Pandita <vikram.pandita@ti.com>
Signed-off-by: Nishant Kamat <nskamat@ti.com>
---
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@nokia.com>
+ * Tony Lindgren <tony@atomide.com>
*
* 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
^ permalink raw reply [flat|nested] 4+ messages in thread* Re: [PATCH 3/3] ARM: OMAP: Add MUSB support for OMAP34xx
2007-12-05 13:12 [PATCH 3/3] ARM: OMAP: Add MUSB support for OMAP34xx Gadiyar, Anand
@ 2007-12-05 19:43 ` Kevin Hilman
2007-12-10 5:23 ` Gadiyar, Anand
0 siblings, 1 reply; 4+ messages in thread
From: Kevin Hilman @ 2007-12-05 19:43 UTC (permalink / raw)
To: Gadiyar, Anand; +Cc: linux-omap, linux-omap-open-source
"Gadiyar, Anand" <gadiyar@ti.com> writes:
> This patch adds MUSB support for OMAP34XX.
[...]
> +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);
This lock is never unlocked.
Might I recommend you turn on CONFIG_PREEMPT, and spinlock debugging
when testing. The various lock debugging features in the 'Kernel
Hacking' menu are extremely useful for this kind of thing.
Kevin
^ permalink raw reply [flat|nested] 4+ messages in thread* RE: [PATCH 3/3] ARM: OMAP: Add MUSB support for OMAP34xx
2007-12-05 19:43 ` Kevin Hilman
@ 2007-12-10 5:23 ` Gadiyar, Anand
0 siblings, 0 replies; 4+ messages in thread
From: Gadiyar, Anand @ 2007-12-10 5:23 UTC (permalink / raw)
To: Kevin Hilman; +Cc: linux-omap, linux-omap-open-source
> > +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);
>
> This lock is never unlocked.
>
> Might I recommend you turn on CONFIG_PREEMPT, and spinlock debugging
> when testing. The various lock debugging features in the 'Kernel
> Hacking' menu are extremely useful for this kind of thing.
Thanks for the pointer. I'll start using this from now on.
Anand
^ permalink raw reply [flat|nested] 4+ messages in thread
[parent not found: <af454dfc0cc2c4362e679333aa3e7644@felipebalbi.com>]
* RE: [PATCH 3/3] ARM: OMAP: Add MUSB support for OMAP34xx
[not found] <af454dfc0cc2c4362e679333aa3e7644@felipebalbi.com>
@ 2007-12-11 9:43 ` Gadiyar, Anand
0 siblings, 0 replies; 4+ messages in thread
From: Gadiyar, Anand @ 2007-12-11 9:43 UTC (permalink / raw)
To: Felipe Balbi; +Cc: linux-omap, linux-omap-open-source
[-- Attachment #1: Type: text/plain, Size: 4217 bytes --]
Felipe and others,
> > Index: linux-omap-2.6-NOV30/drivers/usb/musb/omap2430.c
> > ===================================================================
> > --- linux-omap-2.6-NOV30.orig/drivers/usb/musb/omap2430.c
<snip>
> > @@ -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;
> > +}
>
> I'd rather take the two above off and modify musb_core.h (check below)
Done. I haven't exactly done it the way you suggested. See below.
> > 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;
> > +}
>
> twl4030_phy_suspend(suspend);
> would look better. You just need to modify twl4030_phy_suspend to work
> as both suspend and resume operations.
Won't be able to do this.
twl4030_phy_suspend() takes the argument "int controller_off"
and does things differently depending on the argument.
Anyway, I think the "would look better" is a matter of taste :)
> > +
> > 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");
>
> Why did you break that line here?
The line length was 81 characters. Is that acceptable?
If it is, then I'll change it back. I didn't want to submit a patch which
failed checkpatch.pl (although that board file patch did have the extern warning).
> > 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)
>
> Instead of doing this I'd rather:
>
> @@ -476,12 +476,12 @@ extern void
> musb_platform_disable(struct musb *musb);
>
> extern void musb_hnp_stop(struct musb *musb);
>
> -#ifdef CONFIG_USB_TUSB6010
> extern void musb_platform_try_idle(struct musb *musb, unsigned long
> timeout);
> +
> +#ifdef CONFIG_USB_TUSB6010
> extern int musb_platform_get_vbus_status(struct musb *musb);
> extern void musb_platform_set_mode(struct musb *musb, u8 musb_mode);
> #else
> -#define musb_platform_try_idle(x, y) do {} while (0)
> #define musb_platform_get_vbus_status(x) 0
> #define musb_platform_set_mode(x, y) do {} while (0)
> #endif
>
I wouldn’t do it exactly this way, because musb_platform_try_idle is not defined
for Davinci and other architectures. Instead, I've done this. What say?
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);
+#else
+#define musb_platform_try_idle(x, y) do {} while (0)
+#endif
+
+#ifdef CONFIG_USB_TUSB6010
extern int musb_platform_get_vbus_status(struct musb *musb);
extern void musb_platform_set_mode(struct musb *musb, u8 musb_mode);
#else
-#define musb_platform_try_idle(x, y) do {} while (0)
#define musb_platform_get_vbus_status(x) 0
#define musb_platform_set_mode(x, y) do {} while (0)
#endif
Best Regards,
Anand
[-- Attachment #2: Type: text/plain, Size: 0 bytes --]
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2007-12-11 9:43 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-12-05 13:12 [PATCH 3/3] ARM: OMAP: Add MUSB support for OMAP34xx Gadiyar, Anand
2007-12-05 19:43 ` Kevin Hilman
2007-12-10 5:23 ` Gadiyar, Anand
[not found] <af454dfc0cc2c4362e679333aa3e7644@felipebalbi.com>
2007-12-11 9:43 ` Gadiyar, Anand
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox