David Brownell <[email protected]> writes:
> From: David Brownell <[email protected]>
>
> 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: David Brownell <[email protected]>
Thanks, pushing today.
Kevin
> ---
> Depends on arch/arm/mach-davinci updates which aren't yet queued
> for mainline: <mach/cpu.h>, and USB clock setup. Otherwise this
> could go to mainline.
>
> drivers/usb/musb/Kconfig | 6 +-
> drivers/usb/musb/davinci.c | 104 ++++++++++++++++++++++++++++++-------------
> drivers/usb/musb/davinci.h | 23 ++++++---
> 3 files changed, 92 insertions(+), 41 deletions(-)
>
> --- 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.
>
> If you do not know what this is, please say N.
>
> @@ -35,7 +35,7 @@ config USB_MUSB_SOC
> default y if ARCH_OMAP2430
> default y if ARCH_OMAP34XX
>
> -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"
> --- a/drivers/usb/musb/davinci.c
> +++ b/drivers/usb/musb/davinci.c
> @@ -35,6 +35,8 @@
> #include <mach/hardware.h>
> #include <mach/memory.h>
> #include <mach/gpio.h>
> +#include <mach/cpu.h>
> +
> #include <asm/mach-types.h>
>
> #include "musb_core.h"
> @@ -47,6 +49,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
> @@ -55,20 +60,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;
> @@ -125,10 +136,6 @@ void musb_platform_disable(struct 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
> @@ -136,10 +143,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...
> @@ -149,12 +165,12 @@ static void evm_deferred_drvvbus(struct
> 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;
>
> @@ -162,16 +178,17 @@ static void davinci_source_power(struct
> 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)
> @@ -376,18 +393,8 @@ int __init musb_platform_init(struct mus
> u32 revision;
>
> 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);
> - if (status < 0)
> - return -ENODEV;
> -#endif
> + clk_enable(musb->clock);
>
> /* returns zero if e.g. not clocked */
> revision = musb_readl(tibase, DAVINCI_USB_VERSION_REG);
> @@ -400,6 +407,32 @@ int __init musb_platform_init(struct mus
> 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);
> + }
> +
> + /* 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 */
> musb_writel(tibase, DAVINCI_USB_CTRL_REG, 0x1);
>
> @@ -410,8 +443,7 @@ int __init musb_platform_init(struct mus
>
> /* 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;
> @@ -423,6 +455,15 @@ int musb_platform_exit(struct musb *musb
> if (is_host_enabled(musb))
> 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);
>
> /* delay, to avoid problems with module reload */
> @@ -452,5 +493,8 @@ int musb_platform_exit(struct musb *musb
> }
>
> phy_off();
> +
> + clk_disable(musb->clock);
> +
> return 0;
> }
> --- 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
>
> _______________________________________________
> Davinci-linux-open-source mailing list
> [email protected]
> http://linux.davincidsp.com/mailman/listinfo/davinci-linux-open-source
_______________________________________________
Davinci-linux-open-source mailing list
[email protected]
http://linux.davincidsp.com/mailman/listinfo/davinci-linux-open-source