summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-tegra/tegra_usb_phy.h5
-rw-r--r--arch/arm/mach-tegra/usb_phy.c34
-rw-r--r--drivers/usb/host/ehci-tegra.c22
3 files changed, 40 insertions, 21 deletions
diff --git a/arch/arm/mach-tegra/tegra_usb_phy.h b/arch/arm/mach-tegra/tegra_usb_phy.h
index c399c31b18ae..0dc4cd73c5e7 100644
--- a/arch/arm/mach-tegra/tegra_usb_phy.h
+++ b/arch/arm/mach-tegra/tegra_usb_phy.h
@@ -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;
diff --git a/arch/arm/mach-tegra/usb_phy.c b/arch/arm/mach-tegra/usb_phy.c
index b072283da294..f6e64f08c30a 100644
--- a/arch/arm/mach-tegra/usb_phy.c
+++ b/arch/arm/mach-tegra/usb_phy.c
@@ -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
*/
diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c
index c0574ee8642d..2b9cd1a9ab4b 100644
--- a/drivers/usb/host/ehci-tegra.c
+++ b/drivers/usb/host/ehci-tegra.c
@@ -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,
}
};