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]>
---
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

Reply via email to