Commit 32b98a74 authored by David Brownell's avatar David Brownell Committed by Kevin Hilman

musb_hdrc updates for dm355

Update musb/davinci.c and Kconfig for the newish DM355 chips:

 - Support new controls:
    * PHY control bits for swapping D+/D- signals, OTG powerdown
    * DRVVBUS control bits
 - The DM355 EVM board swaps D+/D- for better signal integrity
 - Use clk_enable()/clk_disable() now that they work right

Plus some minor cleanup:  "void __iomem *" pointers work right now
(after some arch/arm changes), the DM6446 EVM stuff vanishes more
completely on other boards.

Eventually the board-specific stuff should move out of this part of
the driver, but that will affect more generic MUSB code.
Signed-off-by: default avatarDavid Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: default avatarKevin Hilman <khilman@deeprootsystems.com>
parent d6e7aae8
...@@ -19,8 +19,8 @@ config USB_MUSB_HDRC ...@@ -19,8 +19,8 @@ config USB_MUSB_HDRC
it's being used with, including the USB peripheral role, it's being used with, including the USB peripheral role,
or the USB host role, or both. or the USB host role, or both.
Texas Instruments parts using this IP include DaVinci 644x, Texas Instruments familiies using this IP include DaVinci
OMAP 243x, OMAP 343x, and TUSB 6010. (35x, 644x ...), OMAP 243x, OMAP 3, and TUSB 6010.
If you do not know what this is, please say N. If you do not know what this is, please say N.
...@@ -34,7 +34,7 @@ config USB_MUSB_SOC ...@@ -34,7 +34,7 @@ config USB_MUSB_SOC
default y if ARCH_OMAP2430 default y if ARCH_OMAP2430
default y if ARCH_OMAP34XX default y if ARCH_OMAP34XX
comment "DaVinci 644x USB support" comment "DaVinci 35x and 644x USB support"
depends on USB_MUSB_HDRC && ARCH_DAVINCI depends on USB_MUSB_HDRC && ARCH_DAVINCI
comment "OMAP 243x high speed USB support" comment "OMAP 243x high speed USB support"
......
...@@ -35,6 +35,8 @@ ...@@ -35,6 +35,8 @@
#include <mach/hardware.h> #include <mach/hardware.h>
#include <mach/memory.h> #include <mach/memory.h>
#include <mach/gpio.h> #include <mach/gpio.h>
#include <mach/cpu.h>
#include <asm/mach-types.h> #include <asm/mach-types.h>
#include "musb_core.h" #include "musb_core.h"
...@@ -47,6 +49,9 @@ ...@@ -47,6 +49,9 @@
#include "cppi_dma.h" #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 /* 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 * of the time (24 MHZ oscillator and PLL off, etc) by setting POWER.D0
* and, when in host mode, autosuspending idle root ports... PHYPLLON * and, when in host mode, autosuspending idle root ports... PHYPLLON
...@@ -55,20 +60,26 @@ ...@@ -55,20 +60,26 @@
static inline void phy_on(void) static inline void phy_on(void)
{ {
/* start the on-chip PHY and its PLL */ u32 phy_ctrl = __raw_readl(USB_PHY_CTRL);
__raw_writel(USBPHY_SESNDEN | USBPHY_VBDTCTEN | USBPHY_PHYPLLON,
(void __force __iomem *) IO_ADDRESS(USBPHY_CTL_PADDR)); /* power everything up; start the on-chip PHY and its PLL */
while ((__raw_readl((void __force __iomem *) phy_ctrl &= ~(USBPHY_OSCPDWN | USBPHY_OTGPDWN | USBPHY_PHYPDWN);
IO_ADDRESS(USBPHY_CTL_PADDR)) phy_ctrl |= USBPHY_SESNDEN | USBPHY_VBDTCTEN | USBPHY_PHYPLLON;
& USBPHY_PHYCLKGD) == 0) __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(); cpu_relax();
} }
static inline void phy_off(void) static inline void phy_off(void)
{ {
/* powerdown the on-chip PHY and its oscillator */ u32 phy_ctrl = __raw_readl(USB_PHY_CTRL);
__raw_writel(USBPHY_OSCPDWN | USBPHY_PHYPDWN, (void __force __iomem *)
IO_ADDRESS(USBPHY_CTL_PADDR)); /* 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; static int dma_off = 1;
...@@ -125,10 +136,6 @@ void musb_platform_disable(struct musb *musb) ...@@ -125,10 +136,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 #ifdef CONFIG_USB_MUSB_HDRC_HCD
#define portstate(stmt) stmt #define portstate(stmt) stmt
#else #else
...@@ -136,10 +143,19 @@ static int vbus_state = -1; ...@@ -136,10 +143,19 @@ static int vbus_state = -1;
#endif #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 #ifdef CONFIG_MACH_DAVINCI_EVM
static int vbus_state = -1;
/* I2C operations are always synchronous, and require a task context. /* I2C operations are always synchronous, and require a task context.
* With unloaded systems, using the shared workqueue seems to suffice * With unloaded systems, using the shared workqueue seems to suffice
* to satisfy the 100msec A_WAIT_VRISE timeout... * to satisfy the 100msec A_WAIT_VRISE timeout...
...@@ -149,12 +165,12 @@ static void evm_deferred_drvvbus(struct work_struct *ignored) ...@@ -149,12 +165,12 @@ static void evm_deferred_drvvbus(struct work_struct *ignored)
gpio_set_value_cansleep(GPIO_nVBUS_DRV, vbus_state); gpio_set_value_cansleep(GPIO_nVBUS_DRV, vbus_state);
vbus_state = !vbus_state; vbus_state = !vbus_state;
} }
static DECLARE_WORK(evm_vbus_work, evm_deferred_drvvbus);
#endif /* EVM */ #endif /* EVM */
static void davinci_source_power(struct musb *musb, int is_on, int immediate) static void davinci_source_power(struct musb *musb, int is_on, int immediate)
{ {
#ifdef CONFIG_MACH_DAVINCI_EVM
if (is_on) if (is_on)
is_on = 1; is_on = 1;
...@@ -162,16 +178,17 @@ static void davinci_source_power(struct musb *musb, int is_on, int immediate) ...@@ -162,16 +178,17 @@ static void davinci_source_power(struct musb *musb, int is_on, int immediate)
return; return;
vbus_state = !is_on; /* 0/1 vs "-1 == unknown/init" */ vbus_state = !is_on; /* 0/1 vs "-1 == unknown/init" */
#ifdef CONFIG_MACH_DAVINCI_EVM
if (machine_is_davinci_evm()) { if (machine_is_davinci_evm()) {
static DECLARE_WORK(evm_vbus_work, evm_deferred_drvvbus);
if (immediate) if (immediate)
gpio_set_value_cansleep(GPIO_nVBUS_DRV, vbus_state); gpio_set_value_cansleep(GPIO_nVBUS_DRV, vbus_state);
else else
schedule_work(&evm_vbus_work); schedule_work(&evm_vbus_work);
} }
#endif
if (immediate) if (immediate)
vbus_state = is_on; vbus_state = is_on;
#endif
} }
static void davinci_set_vbus(struct musb *musb, int is_on) static void davinci_set_vbus(struct musb *musb, int is_on)
...@@ -376,18 +393,8 @@ int __init musb_platform_init(struct musb *musb) ...@@ -376,18 +393,8 @@ int __init musb_platform_init(struct musb *musb)
u32 revision; u32 revision;
musb->mregs += DAVINCI_BASE_OFFSET; musb->mregs += DAVINCI_BASE_OFFSET;
#if 0
/* REVISIT there's something odd about clocking, this
* didn't appear do the job ...
*/
musb->clock = clk_get(pDevice, "usb");
if (IS_ERR(musb->clock))
return PTR_ERR(musb->clock);
status = clk_enable(musb->clock); clk_enable(musb->clock);
if (status < 0)
return -ENODEV;
#endif
/* returns zero if e.g. not clocked */ /* returns zero if e.g. not clocked */
revision = musb_readl(tibase, DAVINCI_USB_VERSION_REG); revision = musb_readl(tibase, DAVINCI_USB_VERSION_REG);
...@@ -400,6 +407,32 @@ int __init musb_platform_init(struct musb *musb) ...@@ -400,6 +407,32 @@ int __init musb_platform_init(struct musb *musb)
musb->board_set_vbus = davinci_set_vbus; musb->board_set_vbus = davinci_set_vbus;
davinci_source_power(musb, 0, 1); 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);
}
/* On dm355, the default-A state machine needs DRVVBUS control.
* If we won't be a host, there's no need to turn it on.
*/
if (cpu_is_davinci_dm355()) {
u32 deepsleep = __raw_readl(DM355_DEEPSLEEP);
if (is_host_enabled(musb)) {
deepsleep &= ~DRVVBUS_OVERRIDE;
} else {
deepsleep &= ~DRVVBUS_FORCE;
deepsleep |= DRVVBUS_OVERRIDE;
}
__raw_writel(deepsleep, DM355_DEEPSLEEP);
}
/* reset the controller */ /* reset the controller */
musb_writel(tibase, DAVINCI_USB_CTRL_REG, 0x1); musb_writel(tibase, DAVINCI_USB_CTRL_REG, 0x1);
...@@ -410,8 +443,7 @@ int __init musb_platform_init(struct musb *musb) ...@@ -410,8 +443,7 @@ int __init musb_platform_init(struct musb *musb)
/* NOTE: irqs are in mixed mode, not bypass to pure-musb */ /* NOTE: irqs are in mixed mode, not bypass to pure-musb */
pr_debug("DaVinci OTG revision %08x phy %03x control %02x\n", pr_debug("DaVinci OTG revision %08x phy %03x control %02x\n",
revision, __raw_readl((void __force __iomem *) revision, __raw_readl(USB_PHY_CTRL),
IO_ADDRESS(USBPHY_CTL_PADDR)),
musb_readb(tibase, DAVINCI_USB_CTRL_REG)); musb_readb(tibase, DAVINCI_USB_CTRL_REG));
musb->isr = davinci_interrupt; musb->isr = davinci_interrupt;
...@@ -423,6 +455,15 @@ int musb_platform_exit(struct musb *musb) ...@@ -423,6 +455,15 @@ int musb_platform_exit(struct musb *musb)
if (is_host_enabled(musb)) if (is_host_enabled(musb))
del_timer_sync(&otg_workaround); del_timer_sync(&otg_workaround);
/* force VBUS off */
if (cpu_is_davinci_dm355()) {
u32 deepsleep = __raw_readl(DM355_DEEPSLEEP);
deepsleep &= ~DRVVBUS_FORCE;
deepsleep |= DRVVBUS_OVERRIDE;
__raw_writel(deepsleep, DM355_DEEPSLEEP);
}
davinci_source_power(musb, 0 /*off*/, 1); davinci_source_power(musb, 0 /*off*/, 1);
/* delay, to avoid problems with module reload */ /* delay, to avoid problems with module reload */
...@@ -452,5 +493,8 @@ int musb_platform_exit(struct musb *musb) ...@@ -452,5 +493,8 @@ int musb_platform_exit(struct musb *musb)
} }
phy_off(); phy_off();
clk_disable(musb->clock);
return 0; return 0;
} }
...@@ -15,14 +15,21 @@ ...@@ -15,14 +15,21 @@
*/ */
/* Integrated highspeed/otg PHY */ /* Integrated highspeed/otg PHY */
#define USBPHY_CTL_PADDR (DAVINCI_SYSTEM_MODULE_BASE + 0x34) #define USBPHY_CTL_PADDR (DAVINCI_SYSTEM_MODULE_BASE + 0x34)
#define USBPHY_PHYCLKGD (1 << 8) #define USBPHY_DATAPOL BIT(11) /* (dm355) switch D+/D- */
#define USBPHY_SESNDEN (1 << 7) /* v(sess_end) comparator */ #define USBPHY_PHYCLKGD BIT(8)
#define USBPHY_VBDTCTEN (1 << 6) /* v(bus) comparator */ #define USBPHY_SESNDEN BIT(7) /* v(sess_end) comparator */
#define USBPHY_PHYPLLON (1 << 4) /* override pll suspend */ #define USBPHY_VBDTCTEN BIT(6) /* v(bus) comparator */
#define USBPHY_CLKO1SEL (1 << 3) #define USBPHY_VBUSSENS BIT(5) /* (dm355,ro) is vbus > 0.5V */
#define USBPHY_OSCPDWN (1 << 2) #define USBPHY_PHYPLLON BIT(4) /* override pll suspend */
#define USBPHY_PHYPDWN (1 << 0) #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 */ /* For now include usb OTG module registers here */
#define DAVINCI_USB_VERSION_REG 0x00 #define DAVINCI_USB_VERSION_REG 0x00
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment