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

Reply via email to