diff options
author | Krishna Yarlagadda <kyarlagadda@nvidia.com> | 2012-05-29 20:09:34 +0530 |
---|---|---|
committer | Rohan Somvanshi <rsomvanshi@nvidia.com> | 2012-05-31 05:45:34 -0700 |
commit | d9391d9c6e6ab412e9326cf33cca802e58820f2a (patch) | |
tree | e557c5252cc9e81c58753d2b64c7efff8b4bd595 /arch/arm/mach-tegra/usb_phy.c | |
parent | 4c15f4cbfcd668c4a7c22f0cc31282f358e176b4 (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.c | 48 |
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); |