diff options
-rw-r--r-- | arch/arm/mach-tegra/tegra_usb_phy.h | 5 | ||||
-rw-r--r-- | arch/arm/mach-tegra/usb_phy.c | 34 | ||||
-rw-r--r-- | drivers/usb/host/ehci-tegra.c | 22 |
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, } }; |