mirror of
https://github.com/torvalds/linux.git
synced 2024-11-23 20:51:44 +00:00
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>
This commit is contained in:
parent
743821717c
commit
a227fd7db7
@ -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"
|
||||
|
@ -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;
|
||||
|
@ -16,13 +16,20 @@
|
||||
|
||||
/* 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_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
|
||||
|
Loading…
Reference in New Issue
Block a user