summaryrefslogtreecommitdiff
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
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>
-rw-r--r--arch/arm/mach-tegra/board-enterprise.c3
-rw-r--r--arch/arm/mach-tegra/board-whistler.c2
-rw-r--r--arch/arm/mach-tegra/tegra_usb_phy.h1
-rw-r--r--arch/arm/mach-tegra/usb_phy.c48
-rw-r--r--drivers/usb/otg/tegra-otg.c2
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: