]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/usb/host/ehci-omap.c
ehci-omap: (mostly) cosmetic cleanups
[linux-2.6-omap-h63xx.git] / drivers / usb / host / ehci-omap.c
index 21deda12bbbecda588326fa3dbd59c83fe2d880e..419e70ab0ba9b1b4ecee37f06a88f262b6f16bb5 100644 (file)
@@ -5,9 +5,9 @@
  * Tested on OMAP3430 ES2.0 SDP
  *
  * Copyright (C) 2007-2008 Texas Instruments, Inc.
- * Copyright (C) 2007-2008 Vikram Pandita <vikram.pandita@ti.com>
- * Based on "ehci-fsl.c" by David Brownell and
- *         "ehci-au1xxx.c" by K.Boge <karsten.boge@amd.com>
+ *     Author: Vikram Pandita <vikram.pandita@ti.com>
+ *
+ * Based on "ehci-fsl.c" and "ehci-au1xxx.c" ehci glue layers
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -27,7 +27,7 @@
 
 #include <linux/platform_device.h>
 #include <linux/clk.h>
-#include <asm/arch/gpio.h>
+#include <mach/gpio.h>
 
 #include "ehci-omap.h"
 
 
 /* ISSUE1:
  *      ISP1504 for input clocking mode needs special reset handling
- *     Hold the PHY in reset by asserting RESET_N signal
- *     Then start the 60Mhz clock input to PHY
- *     Release the reset after a delay -
- *             to get the PHY state machine in working state
+ *     Hold the PHY in reset by asserting RESET_N signal
+ *     Then start the 60Mhz clock input to PHY
+ *     Release the reset after a delay -
+ *             to get the PHY state machine in working state
  */
 #define EXTERNAL_PHY_RESET
 #define        EXT_PHY_RESET_GPIO_PORT1        (57)
@@ -73,21 +73,91 @@ struct ehci_omap_clock_defs {
 };
 
 /* Clock names as per clock framework: May change so keep as #defs */
-#define USBHOST_ICKL   "usbhost_l4_ick"
+#define USBHOST_ICKL           "usbhost_ick"
 #define USBHOST_120M_FCLK      "usbhost_120m_fck"
 #define USBHOST_48M_FCLK       "usbhost_48m_fck"
 #define USBHOST_TLL_ICKL       "usbtll_ick"
 #define USBHOST_TLL_FCLK       "usbtll_fck"
 /*-------------------------------------------------------------------------*/
 
+
+#ifndef CONFIG_OMAP_EHCI_PHY_MODE
+
+static void omap_usb_utmi_init(struct usb_hcd *hcd, u8 tll_channel_mask)
+{
+       int i;
+
+       /* Use UTMI Ports of TLL */
+       omap_writel((1 << OMAP_UHH_HOSTCONFIG_ULPI_BYPASS_SHIFT)|
+                       (1<<OMAP_UHH_HOSTCONFIG_INCR4_BURST_EN_SHIFT)|
+                       (1<<OMAP_UHH_HOSTCONFIG_INCR8_BURST_EN_SHIFT)|
+                       (1<<OMAP_UHH_HOSTCONFIG_INCR16_BURST_EN_SHIFT)|
+                       (0<<OMAP_UHH_HOSTCONFIG_INCRX_ALIGN_EN_SHIFT),
+                                               OMAP_UHH_HOSTCONFIG);
+       /* Enusre bit is set */
+       while (!(omap_readl(OMAP_UHH_HOSTCONFIG)
+                       & (1 << OMAP_UHH_HOSTCONFIG_ULPI_BYPASS_SHIFT)))
+               cpu_relax();
+
+       dev_dbg(hcd->self.controller, "\nEntered UTMI MODE: success\n");
+
+       /* Program the 3 TLL channels upfront */
+
+       for (i = 0; i < OMAP_TLL_CHANNEL_COUNT; i++) {
+
+               /* Disable AutoIdle */
+               omap_writel(omap_readl(OMAP_TLL_CHANNEL_CONF(i)) &
+                           ~(1<<OMAP_TLL_CHANNEL_CONF_UTMIAUTOIDLE_SHIFT),
+                           OMAP_TLL_CHANNEL_CONF(i));
+               /* Disable BitStuffing */
+               omap_writel(omap_readl(OMAP_TLL_CHANNEL_CONF(i)) &
+                           ~(1<<OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF_SHIFT),
+                           OMAP_TLL_CHANNEL_CONF(i));
+               /* SDR Mode */
+               omap_writel(omap_readl(OMAP_TLL_CHANNEL_CONF(i)) &
+                           ~(1<<OMAP_TLL_CHANNEL_CONF_ULPIDDRMODE_SHIFT),
+                           OMAP_TLL_CHANNEL_CONF(i));
+
+       }
+
+       /* Program Common TLL register */
+       omap_writel((1 << OMAP_TLL_SHARED_CONF_FCLK_IS_ON_SHIFT) |
+                       (1 << OMAP_TLL_SHARED_CONF_USB_DIVRATION_SHIFT) |
+                       (0 << OMAP_TLL_SHARED_CONF_USB_180D_SDR_EN_SHIFT) |
+                       (0 << OMAP_TLL_SHARED_CONF_USB_90D_DDR_EN_SHFT),
+                               OMAP_TLL_SHARED_CONF);
+
+       /* Enable channels now */
+       for (i = 0; i < OMAP_TLL_CHANNEL_COUNT; i++) {
+
+               /* Enable only the channel that is needed */
+               if (!(tll_channel_mask & 1<<i))
+                       continue;
+
+               omap_writel(omap_readl(OMAP_TLL_CHANNEL_CONF(i)) |
+                           (1<<OMAP_TLL_CHANNEL_CONF_CHANEN_SHIFT),
+                           OMAP_TLL_CHANNEL_CONF(i));
+
+               omap_writeb(0xBE, OMAP_TLL_ULPI_SCRATCH_REGISTER(i));
+               dev_dbg(hcd->self.controller, "\nULPI_SCRATCH_REG[ch=%d]"
+                       "= 0x%02x\n",
+                       i+1, omap_readb(OMAP_TLL_ULPI_SCRATCH_REGISTER(i)));
+       }
+}
+
+#else
+# define omap_usb_utmi_init(x, y)      0
+#endif
+
+
 /* omap_start_ehc
- *     - Start the TI USBHOST controller
+ *     - Start the TI USBHOST controller
  */
 static int omap_start_ehc(struct platform_device *dev, struct usb_hcd *hcd)
 {
        struct ehci_omap_clock_defs *ehci_clocks;
 
-       dev_dbg(hcd->self.controller, "starting TI EHCI USB Controller\n");
+       dev_dbg(hcd->self.controller, "starting TI EHCI USB Controller\n");
 
        ehci_clocks = (struct ehci_omap_clock_defs *)(
                                ((char *)hcd_to_ehci(hcd)) +
@@ -110,7 +180,7 @@ static int omap_start_ehc(struct platform_device *dev, struct usb_hcd *hcd)
                        PLL_MOD, OMAP3430ES2_CM_CLKEN2);
 
        while (!(cm_read_mod_reg(PLL_MOD, CM_IDLEST2) &
-                               OMAP3430_ST_PERIPH2_CLK))
+                               OMAP3430ES2_ST_PERIPH2_CLK_MASK))
                dev_dbg(hcd->self.controller,
                        "idlest2 = 0x%x\n",
                        cm_read_mod_reg(PLL_MOD, CM_IDLEST2));
@@ -177,25 +247,30 @@ static int omap_start_ehc(struct platform_device *dev, struct usb_hcd *hcd)
        clk_enable(ehci_clocks->usbtll_ick_clk);
 
        /* Disable Auto Idle of USBTLL */
-       cm_write_mod_reg((0 << OMAP3430_AUTO_USBTLL_SHIFT),
-                               CORE_MOD, OMAP3430_CM_AUTOIDLE3_CORE);
+       cm_write_mod_reg((0 << OMAP3430ES2_AUTO_USBTLL_SHIFT),
+                               CORE_MOD, CM_AUTOIDLE3);
 
        /* Wait for TLL to be Active */
-       while ((cm_read_mod_reg(CORE_MOD, OMAP3430_CM_IDLEST3_CORE) &
-               (1 << OMAP3430_ST_USBTLL_SHIFT)));
+       while ((cm_read_mod_reg(CORE_MOD, OMAP2430_CM_IDLEST3)
+                       & (1 << OMAP3430ES2_ST_USBTLL_SHIFT)))
+               cpu_relax();
 
        /* perform TLL soft reset, and wait until reset is complete */
+       omap_writel(1 << OMAP_USBTLL_SYSCONFIG_SOFTRESET_SHIFT,
+                       OMAP_USBTLL_SYSCONFIG);
+       /* Wait for TLL reset to complete */
+       while (!(omap_readl(OMAP_USBTLL_SYSSTATUS)
+                       & (1 << OMAP_USBTLL_SYSSTATUS_RESETDONE_SHIFT)))
+               cpu_relax();
+
+       dev_dbg(hcd->self.controller, "TLL RESET DONE\n");
+
        /* (1<<3) = no idle mode only for initial debugging */
-       omap_writel((1 << OMAP_USBTLL_SYSCONFIG_SOFTRESET_SHIFT) |
-                       (1 << OMAP_USBTLL_SYSCONFIG_ENAWAKEUP_SHIFT) |
+       omap_writel((1 << OMAP_USBTLL_SYSCONFIG_ENAWAKEUP_SHIFT) |
                        (1 << OMAP_USBTLL_SYSCONFIG_SIDLEMODE_SHIFT) |
                        (1 << OMAP_USBTLL_SYSCONFIG_CACTIVITY_SHIFT),
                        OMAP_USBTLL_SYSCONFIG);
-       /* Wait for TLL reset to complete */
-       while (!(omap_readl(OMAP_USBTLL_SYSSTATUS) &
-               (1 << OMAP_USBTLL_SYSSTATUS_RESETDONE_SHIFT)));
 
-       dev_dbg(hcd->self.controller, "\n TLL RESET DONE");
 
        /* Put UHH in NoIdle/NoStandby mode */
        omap_writel((0 << OMAP_UHH_SYSCONFIG_AUTOIDLE_SHIFT) |
@@ -207,93 +282,26 @@ static int omap_start_ehc(struct platform_device *dev, struct usb_hcd *hcd)
 
 #ifdef CONFIG_OMAP_EHCI_PHY_MODE
        /* Bypass the TLL module for PHY mode operation */
-       omap_writel((0 << OMAP_UHH_HOSTCONFIG_ULPI_BYPASS_SHIFT),
+       omap_writel((0 << OMAP_UHH_HOSTCONFIG_ULPI_BYPASS_SHIFT)|
+                       (1<<OMAP_UHH_HOSTCONFIG_INCR4_BURST_EN_SHIFT)|
+                       (1<<OMAP_UHH_HOSTCONFIG_INCR8_BURST_EN_SHIFT)|
+                       (1<<OMAP_UHH_HOSTCONFIG_INCR16_BURST_EN_SHIFT)|
+                       (0<<OMAP_UHH_HOSTCONFIG_INCRX_ALIGN_EN_SHIFT),
                                                OMAP_UHH_HOSTCONFIG);
        /* Ensure that BYPASS is set */
-       while (omap_readl(OMAP_UHH_HOSTCONFIG) &
-               (1 << OMAP_UHH_HOSTCONFIG_ULPI_BYPASS_SHIFT));
+       while (omap_readl(OMAP_UHH_HOSTCONFIG)
+                       & (1 << OMAP_UHH_HOSTCONFIG_ULPI_BYPASS_SHIFT))
+               cpu_relax();
 
-       dev_dbg(hcd->self.controller, "Entered ULPI PHY MODE: success");
+       dev_dbg(hcd->self.controller, "Entered ULPI PHY MODE: success\n");
 
 #else
-       /* Use UTMI Ports of TLL */
-       omap_writel((1 << OMAP_UHH_HOSTCONFIG_ULPI_BYPASS_SHIFT),
-                                               OMAP_UHH_HOSTCONFIG);
-       /* Enusre bit is set */
-       while (!(omap_readl(OMAP_UHH_HOSTCONFIG) &
-               (1 << OMAP_UHH_HOSTCONFIG_ULPI_BYPASS_SHIFT)));
-
-       dev_dbg(hcd->self.controller, "Entered UTMI MODE: success");
-
-       /* Program the 3 TLL channels upfront */
-
-       /* CHANNEL-1 */
-       /* Disable AutoIdle */
-       omap_writel(omap_readl(OMAP_TLL_CHANNEL_CONF(0)) &
-                       ~(1<<OMAP_TLL_CHANNEL_CONF_UTMIAUTOIDLE_SHIFT),
-                       OMAP_TLL_CHANNEL_CONF(0));
-       /* Disable BitStuffing */
-       omap_writel(omap_readl(OMAP_TLL_CHANNEL_CONF(0)) &
-                       ~(1<<OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF_SHIFT),
-                       OMAP_TLL_CHANNEL_CONF(0));
-       /* SDR Mode */
-       omap_writel(omap_readl(OMAP_TLL_CHANNEL_CONF(0)) &
-                       ~(1<<OMAP_TLL_CHANNEL_CONF_ULPIDDRMODE_SHIFT),
-                       OMAP_TLL_CHANNEL_CONF(0));
-
-       /* CHANNEL-2 */
-       /* Disable AutoIdle */
-       omap_writel(omap_readl(OMAP_TLL_CHANNEL_CONF(1)) &
-                       ~(1<<OMAP_TLL_CHANNEL_CONF_UTMIAUTOIDLE_SHIFT),
-                       OMAP_TLL_CHANNEL_CONF(1));
-       /* Disable BitStuffing */
-       omap_writel(omap_readl(OMAP_TLL_CHANNEL_CONF(1)) &
-                       ~(1<<OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF_SHIFT),
-                       OMAP_TLL_CHANNEL_CONF(1));
-       /* SDR Mode */
-       omap_writel(omap_readl(OMAP_TLL_CHANNEL_CONF(1)) &
-                       ~(1<<OMAP_TLL_CHANNEL_CONF_ULPIDDRMODE_SHIFT),
-                       OMAP_TLL_CHANNEL_CONF(1));
-
-       /* CHANNEL-3 */
-       /* Disable AutoIdle */
-       omap_writel(omap_readl(OMAP_TLL_CHANNEL_CONF(2)) &
-                       ~(1<<OMAP_TLL_CHANNEL_CONF_UTMIAUTOIDLE_SHIFT),
-                       OMAP_TLL_CHANNEL_CONF(2));
-       /* Disable BitStuffing */
-       omap_writel(omap_readl(OMAP_TLL_CHANNEL_CONF(2)) &
-                       ~(1<<OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF_SHIFT),
-                       OMAP_TLL_CHANNEL_CONF(2));
-       /* SDR Mode */
-       omap_writel(omap_readl(OMAP_TLL_CHANNEL_CONF(2)) &
-                       ~(1<<OMAP_TLL_CHANNEL_CONF_ULPIDDRMODE_SHIFT),
-                       OMAP_TLL_CHANNEL_CONF(2));
-
-       /* Program Common TLL register */
-       omap_writel((1 << OMAP_TLL_SHARED_CONF_FCLK_IS_ON_SHIFT) |
-                       (1 << OMAP_TLL_SHARED_CONF_USB_DIVRATION_SHIFT) |
-                       (1 << OMAP_TLL_SHARED_CONF_USB_180D_SDR_EN_SHIFT) |
-                       (1 << OMAP_TLL_SHARED_CONF_USB_90D_DDR_EN_SHFT),
-                               OMAP_TLL_SHARED_CONF);
-
-       /* Enable All 3 channels now */
-       omap_writel(omap_readl(OMAP_TLL_CHANNEL_CONF(0)) |
-                       (1<<OMAP_TLL_CHANNEL_CONF_CHANEN_SHIFT),
-                       OMAP_TLL_CHANNEL_CONF(0));
-
-       omap_writel(omap_readl(OMAP_TLL_CHANNEL_CONF(1)) |
-                       (1<<OMAP_TLL_CHANNEL_CONF_CHANEN_SHIFT),
-                       OMAP_TLL_CHANNEL_CONF(1));
-
-       omap_writel(omap_readl(OMAP_TLL_CHANNEL_CONF(2)) |
-                       (1<<OMAP_TLL_CHANNEL_CONF_CHANEN_SHIFT),
-                       OMAP_TLL_CHANNEL_CONF(2));
-
-       /* test writing to ulpi scratch register */
-       omap_writeb(0xBE, OMAP_TLL_ULPI_SCRATCH_REGISTER);
-       dev_dbg(hcd->self.controller, "\nULPI_SCRATCH_REG 0x%02x\n",
-                       omap_readb(OMAP_TLL_ULPI_SCRATCH_REGISTER));
-
+       /* Enable UTMI mode for all 3 TLL channels */
+       omap_usb_utmi_init(hcd,
+               OMAP_TLL_CHANNEL_1_EN_MASK |
+               OMAP_TLL_CHANNEL_2_EN_MASK |
+               OMAP_TLL_CHANNEL_3_EN_MASK
+               );
 #endif
 
 #ifdef EXTERNAL_PHY_RESET
@@ -309,7 +317,7 @@ static int omap_start_ehc(struct platform_device *dev, struct usb_hcd *hcd)
        /* Refer ISSUE2: LINK assumes external charge pump */
 
        /* use Port1 VBUS to charge externally Port2:
-        *      So for PHY mode operation use Port2 only
+        *      So for PHY mode operation use Port2 only
         */
        omap_writel((0xA << EHCI_INSNREG05_ULPI_REGADD_SHIFT) |/* OTG ctrl reg*/
                        (2 << EHCI_INSNREG05_ULPI_OPSEL_SHIFT) |/*   Write */
@@ -318,8 +326,9 @@ static int omap_start_ehc(struct platform_device *dev, struct usb_hcd *hcd)
                        (0x26),
                        EHCI_INSNREG05_ULPI);
 
-       while (!(omap_readl(EHCI_INSNREG05_ULPI) &
-               (1<<EHCI_INSNREG05_ULPI_CONTROL_SHIFT)));
+       while (!(omap_readl(EHCI_INSNREG05_ULPI)
+                       & (1<<EHCI_INSNREG05_ULPI_CONTROL_SHIFT)))
+               cpu_relax();
 
 #endif
 
@@ -335,20 +344,24 @@ static void omap_stop_ehc(struct platform_device *dev, struct usb_hcd *hcd)
        ehci_clocks = (struct ehci_omap_clock_defs *)
                        (((char *)hcd_to_ehci(hcd)) + sizeof(struct ehci_hcd));
 
-       dev_dbg(hcd->self.controller, "stopping TI EHCI USB Controller\n");
+       dev_dbg(hcd->self.controller, "stopping TI EHCI USB Controller\n");
 
        /* Reset OMAP modules for insmod/rmmod to work */
        omap_writel((1<<1), OMAP_UHH_SYSCONFIG);
-       while (!(omap_readl(OMAP_UHH_SYSSTATUS) & (1<<0)));
-       while (!(omap_readl(OMAP_UHH_SYSSTATUS) & (1<<1)));
-       while (!(omap_readl(OMAP_UHH_SYSSTATUS) & (1<<2)));
+       while (!(omap_readl(OMAP_UHH_SYSSTATUS) & (1<<0)))
+               cpu_relax();
+       while (!(omap_readl(OMAP_UHH_SYSSTATUS) & (1<<1)))
+               cpu_relax();
+       while (!(omap_readl(OMAP_UHH_SYSSTATUS) & (1<<2)))
+               cpu_relax();
        dev_dbg(hcd->self.controller,
                "UHH RESET DONE OMAP_UHH_SYSSTATUS %x !!\n",
                        omap_readl(OMAP_UHH_SYSSTATUS));
 
        omap_writel((1<<1), OMAP_USBTLL_SYSCONFIG);
-       while (!(omap_readl(OMAP_USBTLL_SYSSTATUS) & (1<<0)));
-       dev_dbg(hcd->self.controller, ":TLL RESEET DONE");
+       while (!(omap_readl(OMAP_USBTLL_SYSSTATUS) & (1<<0)))
+               cpu_relax();
+       dev_dbg(hcd->self.controller, "TLL RESET DONE\n");
 
        if (ehci_clocks->usbtll_fck_clk != NULL) {
                clk_disable(ehci_clocks->usbtll_fck_clk);
@@ -387,7 +400,7 @@ static void omap_stop_ehc(struct platform_device *dev, struct usb_hcd *hcd)
 #endif
 
        dev_dbg(hcd->self.controller,
-               "Clock to USB host has been disabled\n");
+               "Clock to USB host has been disabled\n");
 }
 
 static const struct hc_driver ehci_omap_hc_driver;
@@ -411,13 +424,13 @@ static int ehci_hcd_omap_drv_probe(struct platform_device *dev)
        struct usb_hcd *hcd;
        struct ehci_hcd *ehci;
 
-       dev_dbg(&dev->dev, "ehci_hcd_omap_drv_probe()");
+       dev_dbg(&dev->dev, "ehci_hcd_omap_drv_probe()\n");
 
        if (usb_disabled())
                return -ENODEV;
 
        if (dev->resource[1].flags != IORESOURCE_IRQ) {
-               dev_dbg(&dev->dev, "resource[1] is not IORESOURCE_IRQ");
+               dev_dbg(&dev->dev, "resource[1] is not IORESOURCE_IRQ\n");
                retval = -ENOMEM;
        }
 
@@ -434,11 +447,17 @@ static int ehci_hcd_omap_drv_probe(struct platform_device *dev)
        hcd->rsrc_start = dev->resource[0].start;
        hcd->rsrc_len = dev->resource[0].end - dev->resource[0].start + 1;
 
-       hcd->regs = (void __iomem *) (int) IO_ADDRESS(hcd->rsrc_start);
+       hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
+       if (!hcd->regs) {
+               dev_err(&dev->dev, "ioremap failed\n");
+               return -ENOMEM;
+       }
 
        ehci = hcd_to_ehci(hcd);
        ehci->caps = hcd->regs;
 
+       ehci->sbrn = 0x20;
+
        ehci->regs = hcd->regs + HC_LENGTH(readl(&ehci->caps->hc_capbase));
        /* cache this readonly data; minimize chip reads */
        ehci->hcs_params = readl(&ehci->caps->hcs_params);
@@ -451,10 +470,11 @@ static int ehci_hcd_omap_drv_probe(struct platform_device *dev)
        if (retval == 0)
                return retval;
 
-       dev_dbg(hcd->self.controller, "ERR: add_hcd");
+       dev_dbg(hcd->self.controller, "ERR: add_hcd\n");
        omap_stop_ehc(dev, hcd);
-
+       iounmap(hcd->regs);
        usb_put_hcd(hcd);
+
        return retval;
 }
 
@@ -477,8 +497,9 @@ static int ehci_hcd_omap_drv_remove(struct platform_device *dev)
 {
        struct usb_hcd *hcd = platform_get_drvdata(dev);
 
-       dev_dbg(&dev->dev, "ehci_hcd_omap_drv_remove()");
+       dev_dbg(&dev->dev, "ehci_hcd_omap_drv_remove()\n");
 
+       iounmap(hcd->regs);
        usb_remove_hcd(hcd);
        usb_put_hcd(hcd);
        omap_stop_ehc(dev, hcd);
@@ -544,7 +565,7 @@ static const struct hc_driver ehci_omap_hc_driver = {
 };
 
 /*-------------------------------------------------------------------------*/
-MODULE_ALIAS("omap-ehci");
+MODULE_ALIAS("platform:omap-ehci");
 static struct platform_driver ehci_hcd_omap_driver = {
        .probe = ehci_hcd_omap_drv_probe,
        .remove = ehci_hcd_omap_drv_remove,