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 | |
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>
-rw-r--r-- | arch/arm/mach-tegra/board-enterprise.c | 3 | ||||
-rw-r--r-- | arch/arm/mach-tegra/board-whistler.c | 2 | ||||
-rw-r--r-- | arch/arm/mach-tegra/tegra_usb_phy.h | 1 | ||||
-rw-r--r-- | arch/arm/mach-tegra/usb_phy.c | 48 | ||||
-rw-r--r-- | drivers/usb/otg/tegra-otg.c | 2 |
5 files changed, 50 insertions, 6 deletions
diff --git a/arch/arm/mach-tegra/board-enterprise.c b/arch/arm/mach-tegra/board-enterprise.c index d92ac57dd054..e23a9a468081 100644 --- a/arch/arm/mach-tegra/board-enterprise.c +++ b/arch/arm/mach-tegra/board-enterprise.c @@ -684,7 +684,8 @@ static struct tegra_usb_platform_data tegra_udc_pdata = { .phy_intf = TEGRA_USB_PHY_INTF_UTMI, .op_mode = TEGRA_USB_OPMODE_DEVICE, .u_data.dev = { - .vbus_pmu_irq = 0, + .vbus_pmu_irq = ENT_TPS80031_IRQ_BASE + + TPS80031_INT_VBUS_DET, .vbus_gpio = -1, .charging_supported = false, .remote_wakeup_supported = false, diff --git a/arch/arm/mach-tegra/board-whistler.c b/arch/arm/mach-tegra/board-whistler.c index 874ef18900e7..6156c8a8e51d 100644 --- a/arch/arm/mach-tegra/board-whistler.c +++ b/arch/arm/mach-tegra/board-whistler.c @@ -441,7 +441,7 @@ static struct tegra_usb_platform_data tegra_udc_pdata = { .phy_intf = TEGRA_USB_PHY_INTF_UTMI, .op_mode = TEGRA_USB_OPMODE_DEVICE, .u_data.dev = { - .vbus_pmu_irq = 0, + .vbus_pmu_irq = MAX8907C_INT_BASE + MAX8907C_IRQ_VCHG_DC_R, .vbus_gpio = -1, .charging_supported = false, .remote_wakeup_supported = false, diff --git a/arch/arm/mach-tegra/tegra_usb_phy.h b/arch/arm/mach-tegra/tegra_usb_phy.h index 36b88db94f52..0375b5aac812 100644 --- a/arch/arm/mach-tegra/tegra_usb_phy.h +++ b/arch/arm/mach-tegra/tegra_usb_phy.h @@ -89,6 +89,7 @@ struct tegra_usb_phy { void __iomem *regs; int inst; bool phy_clk_on; + bool ctrl_clk_on; /* used only for pmu irq */ 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 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); diff --git a/drivers/usb/otg/tegra-otg.c b/drivers/usb/otg/tegra-otg.c index 5258b3ec8992..f91a8f8f78e7 100644 --- a/drivers/usb/otg/tegra-otg.c +++ b/drivers/usb/otg/tegra-otg.c @@ -465,6 +465,8 @@ static int tegra_otg_probe(struct platform_device *pdev) goto err_irq; } + clk_disable(tegra->clk); + return 0; err_irq: |