diff options
author | David Brownell <dbrownell@users.sourceforge.net> | 2009-02-25 00:31:54 +0100 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2009-03-25 00:20:36 +0100 |
commit | a227fd7db74fa05d866790a4b29ba049bb5035cc (patch) | |
tree | d3f852d767e1c31394acd2c9bec811c0619df5dd | |
parent | USB: musb: only turn off vbus in OTG hosts (diff) | |
download | linux-a227fd7db74fa05d866790a4b29ba049bb5035cc.tar.xz linux-a227fd7db74fa05d866790a4b29ba049bb5035cc.zip |
USB: musb: partial DaVinci dm355 support
Partial support for DaVinci DM355, on the EVM board; peripheral
mode should work, once mainline merges DM355 support. Missing:
(a) renumbering the GPIO for DRVVBUS on the DM6446 EVM,
when DAVINCI_N_GPIO increases;
(b) disabling DM355_DEEPSLEEP.DRVVBUS_OVERRIDE so VBUS is
driven according to the ID signal, if cpu_is_..._dm355()
The new PHY control bits are ignored on DM6446.
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Cc: Kevin Hilman <khilman@deeprootsystems.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r-- | drivers/usb/musb/Kconfig | 6 | ||||
-rw-r--r-- | drivers/usb/musb/davinci.c | 63 | ||||
-rw-r--r-- | drivers/usb/musb/davinci.h | 23 |
3 files changed, 62 insertions, 30 deletions
diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig index 9985db08e7db..b66e8544d8b9 100644 --- a/drivers/usb/musb/Kconfig +++ b/drivers/usb/musb/Kconfig @@ -20,8 +20,8 @@ config USB_MUSB_HDRC it's being used with, including the USB peripheral role, or the USB host role, or both. - Texas Instruments parts using this IP include DaVinci 644x, - OMAP 243x, OMAP 343x, and TUSB 6010. + Texas Instruments familiies using this IP include DaVinci + (35x, 644x ...), OMAP 243x, OMAP 3, and TUSB 6010. Analog Devices parts using this IP include Blackfin BF54x, BF525 and BF527. @@ -40,7 +40,7 @@ config USB_MUSB_SOC default y if (BF54x && !BF544) default y if (BF52x && !BF522 && !BF523) -comment "DaVinci 644x USB support" +comment "DaVinci 35x and 644x USB support" depends on USB_MUSB_HDRC && ARCH_DAVINCI comment "OMAP 243x high speed USB support" diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c index 2dc7606f319c..10d11ab113ab 100644 --- a/drivers/usb/musb/davinci.c +++ b/drivers/usb/musb/davinci.c @@ -48,6 +48,9 @@ #include "cppi_dma.h" +#define USB_PHY_CTRL IO_ADDRESS(USBPHY_CTL_PADDR) +#define DM355_DEEPSLEEP IO_ADDRESS(DM355_DEEPSLEEP_PADDR) + /* REVISIT (PM) we should be able to keep the PHY in low power mode most * of the time (24 MHZ oscillator and PLL off, etc) by setting POWER.D0 * and, when in host mode, autosuspending idle root ports... PHYPLLON @@ -56,20 +59,26 @@ static inline void phy_on(void) { - /* start the on-chip PHY and its PLL */ - __raw_writel(USBPHY_SESNDEN | USBPHY_VBDTCTEN | USBPHY_PHYPLLON, - (void __force __iomem *) IO_ADDRESS(USBPHY_CTL_PADDR)); - while ((__raw_readl((void __force __iomem *) - IO_ADDRESS(USBPHY_CTL_PADDR)) - & USBPHY_PHYCLKGD) == 0) + u32 phy_ctrl = __raw_readl(USB_PHY_CTRL); + + /* power everything up; start the on-chip PHY and its PLL */ + phy_ctrl &= ~(USBPHY_OSCPDWN | USBPHY_OTGPDWN | USBPHY_PHYPDWN); + phy_ctrl |= USBPHY_SESNDEN | USBPHY_VBDTCTEN | USBPHY_PHYPLLON; + __raw_writel(phy_ctrl, USB_PHY_CTRL); + + /* wait for PLL to lock before proceeding */ + while ((__raw_readl(USB_PHY_CTRL) & USBPHY_PHYCLKGD) == 0) cpu_relax(); } static inline void phy_off(void) { - /* powerdown the on-chip PHY and its oscillator */ - __raw_writel(USBPHY_OSCPDWN | USBPHY_PHYPDWN, (void __force __iomem *) - IO_ADDRESS(USBPHY_CTL_PADDR)); + u32 phy_ctrl = __raw_readl(USB_PHY_CTRL); + + /* powerdown the on-chip PHY, its PLL, and the OTG block */ + phy_ctrl &= ~(USBPHY_SESNDEN | USBPHY_VBDTCTEN | USBPHY_PHYPLLON); + phy_ctrl |= USBPHY_OSCPDWN | USBPHY_OTGPDWN | USBPHY_PHYPDWN; + __raw_writel(phy_ctrl, USB_PHY_CTRL); } static int dma_off = 1; @@ -126,10 +135,6 @@ void musb_platform_disable(struct musb *musb) } -/* REVISIT it's not clear whether DaVinci can support full OTG. */ - -static int vbus_state = -1; - #ifdef CONFIG_USB_MUSB_HDRC_HCD #define portstate(stmt) stmt #else @@ -137,10 +142,19 @@ static int vbus_state = -1; #endif -/* VBUS SWITCHING IS BOARD-SPECIFIC */ +/* + * VBUS SWITCHING IS BOARD-SPECIFIC ... at least for the DM6446 EVM, + * which doesn't wire DRVVBUS to the FET that switches it. Unclear + * if that's a problem with the DM6446 chip or just with that board. + * + * In either case, the DM355 EVM automates DRVVBUS the normal way, + * when J10 is out, and TI documents it as handling OTG. + */ #ifdef CONFIG_MACH_DAVINCI_EVM +static int vbus_state = -1; + /* I2C operations are always synchronous, and require a task context. * With unloaded systems, using the shared workqueue seems to suffice * to satisfy the 100msec A_WAIT_VRISE timeout... @@ -150,12 +164,12 @@ static void evm_deferred_drvvbus(struct work_struct *ignored) gpio_set_value_cansleep(GPIO_nVBUS_DRV, vbus_state); vbus_state = !vbus_state; } -static DECLARE_WORK(evm_vbus_work, evm_deferred_drvvbus); #endif /* EVM */ static void davinci_source_power(struct musb *musb, int is_on, int immediate) { +#ifdef CONFIG_MACH_DAVINCI_EVM if (is_on) is_on = 1; @@ -163,16 +177,17 @@ static void davinci_source_power(struct musb *musb, int is_on, int immediate) return; vbus_state = !is_on; /* 0/1 vs "-1 == unknown/init" */ -#ifdef CONFIG_MACH_DAVINCI_EVM if (machine_is_davinci_evm()) { + static DECLARE_WORK(evm_vbus_work, evm_deferred_drvvbus); + if (immediate) gpio_set_value_cansleep(GPIO_nVBUS_DRV, vbus_state); else schedule_work(&evm_vbus_work); } -#endif if (immediate) vbus_state = is_on; +#endif } static void davinci_set_vbus(struct musb *musb, int is_on) @@ -391,6 +406,17 @@ int __init musb_platform_init(struct musb *musb) musb->board_set_vbus = davinci_set_vbus; davinci_source_power(musb, 0, 1); + /* dm355 EVM swaps D+/D- for signal integrity, and + * is clocked from the main 24 MHz crystal. + */ + if (machine_is_davinci_dm355_evm()) { + u32 phy_ctrl = __raw_readl(USB_PHY_CTRL); + + phy_ctrl &= ~(3 << 9); + phy_ctrl |= USBPHY_DATAPOL; + __raw_writel(phy_ctrl, USB_PHY_CTRL); + } + /* reset the controller */ musb_writel(tibase, DAVINCI_USB_CTRL_REG, 0x1); @@ -401,8 +427,7 @@ int __init musb_platform_init(struct musb *musb) /* NOTE: irqs are in mixed mode, not bypass to pure-musb */ pr_debug("DaVinci OTG revision %08x phy %03x control %02x\n", - revision, __raw_readl((void __force __iomem *) - IO_ADDRESS(USBPHY_CTL_PADDR)), + revision, __raw_readl(USB_PHY_CTRL), musb_readb(tibase, DAVINCI_USB_CTRL_REG)); musb->isr = davinci_interrupt; diff --git a/drivers/usb/musb/davinci.h b/drivers/usb/musb/davinci.h index 7fb6238e270f..046c84433cad 100644 --- a/drivers/usb/musb/davinci.h +++ b/drivers/usb/musb/davinci.h @@ -15,14 +15,21 @@ */ /* Integrated highspeed/otg PHY */ -#define USBPHY_CTL_PADDR (DAVINCI_SYSTEM_MODULE_BASE + 0x34) -#define USBPHY_PHYCLKGD (1 << 8) -#define USBPHY_SESNDEN (1 << 7) /* v(sess_end) comparator */ -#define USBPHY_VBDTCTEN (1 << 6) /* v(bus) comparator */ -#define USBPHY_PHYPLLON (1 << 4) /* override pll suspend */ -#define USBPHY_CLKO1SEL (1 << 3) -#define USBPHY_OSCPDWN (1 << 2) -#define USBPHY_PHYPDWN (1 << 0) +#define USBPHY_CTL_PADDR (DAVINCI_SYSTEM_MODULE_BASE + 0x34) +#define USBPHY_DATAPOL BIT(11) /* (dm355) switch D+/D- */ +#define USBPHY_PHYCLKGD BIT(8) +#define USBPHY_SESNDEN BIT(7) /* v(sess_end) comparator */ +#define USBPHY_VBDTCTEN BIT(6) /* v(bus) comparator */ +#define USBPHY_VBUSSENS BIT(5) /* (dm355,ro) is vbus > 0.5V */ +#define USBPHY_PHYPLLON BIT(4) /* override pll suspend */ +#define USBPHY_CLKO1SEL BIT(3) +#define USBPHY_OSCPDWN BIT(2) +#define USBPHY_OTGPDWN BIT(1) +#define USBPHY_PHYPDWN BIT(0) + +#define DM355_DEEPSLEEP_PADDR (DAVINCI_SYSTEM_MODULE_BASE + 0x48) +#define DRVVBUS_FORCE BIT(2) +#define DRVVBUS_OVERRIDE BIT(1) /* For now include usb OTG module registers here */ #define DAVINCI_USB_VERSION_REG 0x00 |