summaryrefslogtreecommitdiff
path: root/arch/arm/mach-tegra/usb_phy.c
diff options
context:
space:
mode:
authorKrishna Yarlagadda <kyarlagadda@nvidia.com>2012-05-29 20:09:34 +0530
committerRohan Somvanshi <rsomvanshi@nvidia.com>2012-05-31 05:45:34 -0700
commitd9391d9c6e6ab412e9326cf33cca802e58820f2a (patch)
treee557c5252cc9e81c58753d2b64c7efff8b4bd595 /arch/arm/mach-tegra/usb_phy.c
parent4c15f4cbfcd668c4a7c22f0cc31282f358e176b4 (diff)
ARM: tegra: usb: enable pmu vbus interrupts
Enable pmu vbus interrupt for Enterprise and Whistler to save power by turning off controller clock Change-Id: I691bdd76ca71d63d98f83e2a3a18bbfcfc16a473 Signed-off-by: Krishna Yarlagadda <kyarlagadda@nvidia.com> Reviewed-on: http://git-master/r/105150 Reviewed-by: Rohan Somvanshi <rsomvanshi@nvidia.com> Tested-by: Rohan Somvanshi <rsomvanshi@nvidia.com>
Diffstat (limited to 'arch/arm/mach-tegra/usb_phy.c')
-rw-r--r--arch/arm/mach-tegra/usb_phy.c48
1 files changed, 44 insertions, 4 deletions
diff --git a/arch/arm/mach-tegra/usb_phy.c b/arch/arm/mach-tegra/usb_phy.c
index 6f568fd2cd29..3074dcfa7ca5 100644
--- a/arch/arm/mach-tegra/usb_phy.c
+++ b/arch/arm/mach-tegra/usb_phy.c
@@ -131,15 +131,24 @@ int tegra_usb_phy_init_ops(struct tegra_usb_phy *phy)
static irqreturn_t usb_phy_dev_vbus_pmu_irq_thr(int irq, void *pdata)
{
- /* FIXME : Need to enable pmu vbus handling */
+ struct tegra_usb_phy *phy = pdata;
- return IRQ_NONE;
+ /* clk is disabled during phy power off and not here*/
+ if (!phy->ctrl_clk_on) {
+ clk_enable(phy->ctrlr_clk);
+ phy->ctrl_clk_on = true;
+ }
+
+ return IRQ_HANDLED;
}
static void tegra_usb_phy_release_clocks(struct tegra_usb_phy *phy)
{
clk_put(phy->emc_clk);
clk_put(phy->sys_clk);
+ if (phy->pdata->op_mode == TEGRA_USB_OPMODE_HOST &&
+ phy->pdata->u_data.host.hot_plug)
+ clk_disable(phy->ctrlr_clk);
clk_put(phy->ctrlr_clk);
clk_disable(phy->pllu_clk);
clk_put(phy->pllu_clk);
@@ -164,6 +173,10 @@ static int tegra_usb_phy_get_clocks(struct tegra_usb_phy *phy)
goto fail_ctrlr_clk;
}
+ if (phy->pdata->op_mode == TEGRA_USB_OPMODE_HOST &&
+ phy->pdata->u_data.host.hot_plug)
+ clk_enable(phy->ctrlr_clk);
+
phy->sys_clk = clk_get(&phy->pdev->dev, "sclk");
if (IS_ERR(phy->sys_clk)) {
dev_err(&phy->pdev->dev, "Can't get sclk clock\n");
@@ -273,6 +286,8 @@ struct tegra_usb_phy *tegra_usb_phy_open(struct platform_device *pdev)
phy->inst);
goto fail_init;
}
+ } else {
+ clk_enable(phy->ctrlr_clk);
}
} else {
if (phy->pdata->u_data.host.vbus_reg) {
@@ -365,6 +380,8 @@ void tegra_usb_phy_close(struct tegra_usb_phy *phy)
if (phy->pdata->op_mode == TEGRA_USB_OPMODE_DEVICE) {
if (phy->pdata->u_data.dev.vbus_pmu_irq)
free_irq(phy->pdata->u_data.dev.vbus_pmu_irq, phy);
+ else
+ clk_disable(phy->ctrlr_clk);
} else {
usb_host_vbus_enable(phy, false);
@@ -439,7 +456,18 @@ int tegra_usb_phy_power_off(struct tegra_usb_phy *phy)
clk_disable(phy->emc_clk);
clk_disable(phy->sys_clk);
- clk_disable(phy->ctrlr_clk);
+ if (phy->pdata->op_mode == TEGRA_USB_OPMODE_HOST) {
+ if (!phy->pdata->u_data.host.hot_plug)
+ clk_disable(phy->ctrlr_clk);
+ } else {
+ /* In device mode clock is turned on by pmu irq handler
+ * if pmu irq is not available clocks will not be turned off/on
+ */
+ if (phy->pdata->u_data.dev.vbus_pmu_irq) {
+ clk_disable(phy->ctrlr_clk);
+ phy->ctrl_clk_on = false;
+ }
+ }
phy->phy_power_on = false;
@@ -455,7 +483,19 @@ int tegra_usb_phy_power_on(struct tegra_usb_phy *phy)
if (phy->phy_power_on)
return status;
- clk_enable(phy->ctrlr_clk);
+ /* In device mode clock is turned on by pmu irq handler
+ * if pmu irq is not available clocks will not be turned off/on
+ */
+ if (phy->pdata->op_mode == TEGRA_USB_OPMODE_HOST) {
+ if (!phy->pdata->u_data.host.hot_plug)
+ clk_enable(phy->ctrlr_clk);
+ } else {
+ if (phy->pdata->u_data.dev.vbus_pmu_irq &&
+ !phy->ctrl_clk_on) {
+ clk_enable(phy->ctrlr_clk);
+ phy->ctrl_clk_on = true;
+ }
+ }
clk_enable(phy->sys_clk);
clk_enable(phy->emc_clk);