arm: tegra3: usb_phy: Add support for HSIC wakeup
Venu Byravarasu [Tue, 24 Jul 2012 12:42:22 +0000 (17:42 +0530)]
As part of this patch following changes are made:
1. HSIC regulator enable/disable is added
2. HSIC phy close is added.

bug 1010916

Change-Id: I4607a3ac13417a201b62708c6fef5d1117dfdcc5
Signed-off-by: Venu Byravarasu <vbyravarasu@nvidia.com>
Reviewed-on: http://git-master/r/116984
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Venkat Moganty <vmoganty@nvidia.com>

arch/arm/mach-tegra/tegra3_usb_phy.c
arch/arm/mach-tegra/tegra_usb_phy.h

index 0b8ab07..171e2ec 100644 (file)
@@ -2065,10 +2065,58 @@ static void uhsic_phy_restore_end(struct tegra_usb_phy *phy)
        }
 }
 
+static int hsic_rail_enable(struct tegra_usb_phy *phy)
+{
+       int ret;
+
+       if (phy->hsic_reg == NULL) {
+               phy->hsic_reg = regulator_get(NULL, "avdd_hsic");
+               if (IS_ERR_OR_NULL(phy->hsic_reg)) {
+                       pr_err("HSIC: Could not get regulator avdd_hsic\n");
+                       phy->hsic_reg = NULL;
+                       return PTR_ERR(phy->hsic_reg);
+               }
+       }
+
+       ret = regulator_enable(phy->hsic_reg);
+       if (ret < 0) {
+               pr_err("%s avdd_hsic could not be enabled\n", __func__);
+               return ret;
+       }
+
+       return 0;
+}
+
+static int hsic_rail_disable(struct tegra_usb_phy *phy)
+{
+       int ret;
+
+       if (phy->hsic_reg == NULL) {
+               pr_warn("%s: unbalanced disable\n", __func__);
+               return -EIO;
+       }
+
+       ret = regulator_disable(phy->hsic_reg);
+       if (ret < 0) {
+               pr_err("HSIC regulator avdd_hsic cannot be disabled\n");
+               return ret;
+       }
+
+       return 0;
+}
+
 static int uhsic_phy_open(struct tegra_usb_phy *phy)
 {
        unsigned long parent_rate;
        int i;
+       int ret;
+
+       phy->hsic_reg = NULL;
+       ret = hsic_rail_enable(phy);
+       if (ret < 0) {
+               pr_err("%s avdd_hsic could not be enabled\n", __func__);
+               return ret;
+       }
 
        DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
        parent_rate = clk_get_rate(clk_get_parent(phy->pllu_clk));
@@ -2088,6 +2136,15 @@ static int uhsic_phy_open(struct tegra_usb_phy *phy)
        return 0;
 }
 
+static void uhsic_phy_close(struct tegra_usb_phy *phy)
+{
+       int ret;
+
+       ret = hsic_rail_disable(phy);
+       if (ret < 0)
+               pr_err("%s avdd_hsic could not be disabled\n", __func__);
+}
+
 static int uhsic_phy_irq(struct tegra_usb_phy *phy)
 {
        usb_phy_fence_read(phy);
@@ -2863,6 +2920,7 @@ static struct tegra_usb_phy_ops utmi_phy_ops = {
 
 static struct tegra_usb_phy_ops uhsic_phy_ops = {
        .open           = uhsic_phy_open,
+       .close          = uhsic_phy_close,
        .irq            = uhsic_phy_irq,
        .power_on       = uhsic_phy_power_on,
        .power_off      = uhsic_phy_power_off,
index 7e85a4b..674e8b8 100644 (file)
@@ -80,6 +80,7 @@ struct tegra_usb_phy {
        struct clk *emc_clk;
        struct clk *sys_clk;
        struct regulator *vdd_reg;
+       struct regulator *hsic_reg;
        struct regulator *vbus_reg;
        struct tegra_usb_phy_ops *ops;
        struct tegra_xtal_freq *freq;