include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit...
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / usb / host / ehci-omap.c
index 74d07f4e8b7d48d74f9ea119d350ab6aed8a2dd1..a67a0030dd57f8a44ec8c26a5478a8cdd2531065 100644 (file)
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  *
- * TODO (last updated Feb 23rd, 2009):
+ * TODO (last updated Feb 12, 2010):
  *     - add kernel-doc
  *     - enable AUTOIDLE
- *     - move DPLL5 programming to clock fw
  *     - add suspend/resume
  *     - move workarounds to board-files
  */
@@ -37,6 +36,8 @@
 #include <linux/platform_device.h>
 #include <linux/clk.h>
 #include <linux/gpio.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
 #include <plat/usb.h>
 
 /*
@@ -178,6 +179,11 @@ struct ehci_hcd_omap {
        void __iomem            *uhh_base;
        void __iomem            *tll_base;
        void __iomem            *ehci_base;
+
+       /* Regulators for USB PHYs.
+        * Each PHY can have a seperate regulator.
+        */
+       struct regulator        *regulator[OMAP3_HS_USB_PORTS];
 };
 
 /*-------------------------------------------------------------------------*/
@@ -546,6 +552,8 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
 
        int irq = platform_get_irq(pdev, 0);
        int ret = -ENODEV;
+       int i;
+       char supply[7];
 
        if (!pdata) {
                dev_dbg(&pdev->dev, "missing platform_data\n");
@@ -613,6 +621,21 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
                goto err_tll_ioremap;
        }
 
+       /* get ehci regulator and enable */
+       for (i = 0 ; i < OMAP3_HS_USB_PORTS ; i++) {
+               if (omap->port_mode[i] != EHCI_HCD_OMAP_MODE_PHY) {
+                       omap->regulator[i] = NULL;
+                       continue;
+               }
+               snprintf(supply, sizeof(supply), "hsusb%d", i);
+               omap->regulator[i] = regulator_get(omap->dev, supply);
+               if (IS_ERR(omap->regulator[i]))
+                       dev_dbg(&pdev->dev,
+                       "failed to get ehci port%d regulator\n", i);
+               else
+                       regulator_enable(omap->regulator[i]);
+       }
+
        ret = omap_start_ehc(omap, hcd);
        if (ret) {
                dev_dbg(&pdev->dev, "failed to start ehci\n");
@@ -622,13 +645,12 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
        omap->ehci->regs = hcd->regs
                + HC_LENGTH(readl(&omap->ehci->caps->hc_capbase));
 
+       dbg_hcs_params(omap->ehci, "reset");
+       dbg_hcc_params(omap->ehci, "reset");
+
        /* cache this readonly data; minimize chip reads */
        omap->ehci->hcs_params = readl(&omap->ehci->caps->hcs_params);
 
-       /* SET 1 micro-frame Interrupt interval */
-       writel(readl(&omap->ehci->regs->command) | (1 << 16),
-                       &omap->ehci->regs->command);
-
        ret = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED);
        if (ret) {
                dev_dbg(&pdev->dev, "failed to add hcd with err %d\n", ret);
@@ -641,6 +663,12 @@ err_add_hcd:
        omap_stop_ehc(omap, hcd);
 
 err_start:
+       for (i = 0 ; i < OMAP3_HS_USB_PORTS ; i++) {
+               if (omap->regulator[i]) {
+                       regulator_disable(omap->regulator[i]);
+                       regulator_put(omap->regulator[i]);
+               }
+       }
        iounmap(omap->tll_base);
 
 err_tll_ioremap:
@@ -674,13 +702,21 @@ static int ehci_hcd_omap_remove(struct platform_device *pdev)
 {
        struct ehci_hcd_omap *omap = platform_get_drvdata(pdev);
        struct usb_hcd *hcd = ehci_to_hcd(omap->ehci);
+       int i;
 
        usb_remove_hcd(hcd);
        omap_stop_ehc(omap, hcd);
        iounmap(hcd->regs);
+       for (i = 0 ; i < OMAP3_HS_USB_PORTS ; i++) {
+               if (omap->regulator[i]) {
+                       regulator_disable(omap->regulator[i]);
+                       regulator_put(omap->regulator[i]);
+               }
+       }
        iounmap(omap->tll_base);
        iounmap(omap->uhh_base);
        usb_put_hcd(hcd);
+       kfree(omap);
 
        return 0;
 }