ARM: tegra: usb: turn off power during suspend
Rohan Somvanshi [Wed, 4 Jul 2012 10:43:10 +0000 (10:43 +0000)]
Turn off regulators along with clocks during suspend

Bug 991262

Reviewed-on: http://git-master/r/108820
(cherry picked from commit 41ae7ac21a2c08da0e4312b8395b380a704fa16c)

Change-Id: Ib49eec5d91571d75881f4d252d956dece1d37d60
Signed-off-by: Rakesh Bodla <rbodla@nvidia.com>
Reviewed-on: http://git-master/r/105364
Reviewed-by: Rohan Somvanshi <rsomvanshi@nvidia.com>
Tested-by: Rohan Somvanshi <rsomvanshi@nvidia.com>
Reviewed-by: Automatic_Commit_Validation_User

arch/arm/mach-tegra/tegra_usb_phy.h
arch/arm/mach-tegra/usb_phy.c
drivers/usb/host/ehci-tegra.c

index c399c31..0dc4cd7 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * arch/arm/mach-tegra/include/mach/tegra_usb_phy.h
  *
- * Copyright (c) 2011-2012, NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -89,7 +89,8 @@ struct tegra_usb_phy {
        void __iomem *regs;
        int inst;
        bool phy_clk_on;
-       bool ctrl_clk_on; /* used only for pmu irq */
+       bool ctrl_clk_on;
+       bool vdd_reg_on;
        bool phy_power_on;
        bool remote_wakeup;
        bool hw_accessible;
index b072283..f6e64f0 100644 (file)
@@ -2,7 +2,7 @@
  * arch/arm/mach-tegra/usb_phy.c
  *
  * Copyright (C) 2010 Google, Inc.
- * Copyright (C) 2010 - 2011 NVIDIA Corporation
+ * Copyright (c) 2010-2012, NVIDIA CORPORATION.  All rights reserved.
  *
  * Author:
  *     Erik Gilling <konkers@google.com>
@@ -32,6 +32,7 @@
 #include <linux/platform_data/tegra_usb.h>
 #include "tegra_usb_phy.h"
 #include <mach/iomap.h>
+#include <fuse.h>
 
 #define ERR(stuff...)          pr_err("usb_phy: " stuff)
 #define WARNING(stuff...)      pr_warning("usb_phy: " stuff)
@@ -133,6 +134,16 @@ static irqreturn_t usb_phy_dev_vbus_pmu_irq_thr(int irq, void *pdata)
 {
        struct tegra_usb_phy *phy = pdata;
 
+       if (phy->vdd_reg && !phy->vdd_reg_on) {
+               regulator_enable(phy->vdd_reg);
+               phy->vdd_reg_on = 1;
+               /*
+                * Optimal time to get the regulator turned on
+                * before detecting vbus interrupt.
+                */
+               mdelay(15);
+       }
+
        /* clk is disabled during phy power off and not here*/
        if (!phy->ctrl_clk_on) {
                clk_enable(phy->ctrlr_clk);
@@ -339,9 +350,6 @@ struct tegra_usb_phy *tegra_usb_phy_open(struct platform_device *pdev)
                }
        }
 
-       if (phy->vdd_reg)
-               regulator_enable(phy->vdd_reg);
-
        return phy;
 
 fail_init:
@@ -405,7 +413,6 @@ void tegra_usb_phy_close(struct tegra_usb_phy *phy)
        }
 
        if (phy->vdd_reg) {
-               regulator_disable(phy->vdd_reg);
                regulator_put(phy->vdd_reg);
        }
 
@@ -473,6 +480,18 @@ int tegra_usb_phy_power_off(struct tegra_usb_phy *phy)
                }
        }
 
+       if (phy->vdd_reg && phy->vdd_reg_on) {
+#ifndef CONFIG_ARCH_TEGRA_2x_SOC
+               regulator_disable(phy->vdd_reg);
+               phy->vdd_reg_on = false;
+#else
+               if (tegra_get_revision() >= TEGRA_REVISION_A03) {
+                       regulator_disable(phy->vdd_reg);
+                       phy->vdd_reg_on = false;
+               }
+#endif
+       }
+
        phy->phy_power_on = false;
 
        return err;
@@ -487,6 +506,11 @@ int tegra_usb_phy_power_on(struct tegra_usb_phy *phy)
        if (phy->phy_power_on)
                return status;
 
+       if (phy->vdd_reg && !phy->vdd_reg_on) {
+               regulator_enable(phy->vdd_reg);
+               phy->vdd_reg_on = true;
+       }
+
        /* In device mode clock is turned on by pmu irq handler
         * if pmu irq is not available clocks will not be turned off/on
         */
index c0574ee..2b9cd1a 100644 (file)
@@ -1,8 +1,8 @@
 /*
  * EHCI-compliant USB host controller driver for NVIDIA Tegra SoCs
  *
- * Copyright (C) 2010 Google, Inc.
- * Copyright (C) 2009 - 2011 NVIDIA Corporation
+ * Copyright (c) 2010 Google, Inc.
+ * Copyright (c) 2009-2012 NVIDIA CORPORATION. All rights reserved.
  *
  * 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 the
@@ -512,17 +512,15 @@ fail_hcd:
 
 
 #ifdef CONFIG_PM
-static int tegra_ehci_resume_noirq(struct device *dev)
+static int tegra_ehci_resume(struct platform_device *pdev)
 {
-       struct platform_device *pdev = to_platform_device(dev);
        struct tegra_ehci_hcd *tegra = platform_get_drvdata(pdev);
 
        return tegra_usb_phy_power_on(tegra->phy);
 }
 
-static int tegra_ehci_suspend_noirq(struct device *dev)
+static int tegra_ehci_suspend(struct platform_device *pdev, pm_message_t state)
 {
-       struct platform_device *pdev = to_platform_device(dev);
        struct tegra_ehci_hcd *tegra = platform_get_drvdata(pdev);
 
        /* bus suspend could have failed because of remote wakeup resume */
@@ -531,11 +529,6 @@ static int tegra_ehci_suspend_noirq(struct device *dev)
        else
                return tegra_usb_phy_power_off(tegra->phy);
 }
-
-static struct dev_pm_ops tegra_ehci_dev_pm_ops = {
-       .suspend_noirq = tegra_ehci_suspend_noirq,
-       .resume_noirq = tegra_ehci_resume_noirq,
-};
 #endif
 
 static int tegra_ehci_remove(struct platform_device *pdev)
@@ -578,10 +571,11 @@ static struct platform_driver tegra_ehci_driver = {
        .probe          = tegra_ehci_probe,
        .remove = tegra_ehci_remove,
        .shutdown       = tegra_ehci_hcd_shutdown,
-       .driver = {
-               .name   = driver_name,
 #ifdef CONFIG_PM
-               .pm = &tegra_ehci_dev_pm_ops,
+       .suspend = tegra_ehci_suspend,
+       .resume  = tegra_ehci_resume,
 #endif
+       .driver = {
+               .name   = driver_name,
        }
 };