arm: tegra: enterprise: disable dsi_csi_rail in LP0
Vinayak Pane [Sat, 14 Apr 2012 00:13:15 +0000 (17:13 -0700)]
AVDD_DSI_CSI is shared by modem and dsi. If DSI turns
off this rail then HSIC fails after wakeup from modem.
This patch provides a way to turn on this rail from
modem as well as from DSI. Create two virtual power rails
from avdd_csi_dsi to control it from both the drivers separately.
This is enterprise specific change as per the power rail layout.

Bug 920881

(cherry picked from commit ab52b51c59f776ae770d48a28a2744e2db2e5d2f)
Reviewed-on: http://git-master/r/85656

Change-Id: I2e9c04a8f4e8d6fd20584b4e75657c1cb6d5c8bd
Signed-off-by: Vinayak Pane <vpane@nvidia.com>
Reviewed-on: http://git-master/r/89134
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Puneet Saxena <puneets@nvidia.com>
Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com>

arch/arm/mach-tegra/baseband-xmm-power.c
arch/arm/mach-tegra/board-enterprise-panel.c
arch/arm/mach-tegra/board-enterprise-power.c

index 0e642d8..2d41abc 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/suspend.h>
 #include <mach/usb_phy.h>
 #include "board.h"
+#include "board-enterprise.h"
 #include "devices.h"
 #include "gpio-names.h"
 #include "baseband-xmm-power.h"
@@ -107,11 +108,70 @@ static bool modem_sleep_flag;
 static spinlock_t xmm_lock;
 static DEFINE_MUTEX(xmm_onoff_mutex);
 static bool system_suspending;
+static struct regulator *enterprise_hsic_reg;
+static bool _hsic_reg_status;
 
 static void baseband_xmm_power_L2_resume(void);
 static int baseband_xmm_power_driver_handle_resume(
                        struct baseband_power_platform_data *data);
 
+static int tegra_baseband_rail_on(void)
+{
+       int ret;
+       struct board_info bi;
+       tegra_get_board_info(&bi);
+
+       /* only applicable to enterprise */
+       if (bi.board_id != BOARD_E1197)
+               return 0;
+
+       if (_hsic_reg_status == true)
+               return 0;
+
+       if (enterprise_hsic_reg == NULL) {
+               enterprise_hsic_reg = regulator_get(NULL, "avdd_hsic");
+               if (IS_ERR_OR_NULL(enterprise_hsic_reg)) {
+                       pr_err("xmm: could not get regulator vddio_hsic\n");
+                       enterprise_hsic_reg = NULL;
+                       return PTR_ERR(enterprise_hsic_reg);
+               }
+       }
+       ret = regulator_enable(enterprise_hsic_reg);
+       if (ret < 0) {
+               pr_err("xmm: failed to enable regulator\n");
+               return ret;
+       }
+       _hsic_reg_status = true;
+       return 0;
+}
+
+static int tegra_baseband_rail_off(void)
+{
+       int ret;
+       struct board_info bi;
+       tegra_get_board_info(&bi);
+
+       /* only applicable to enterprise */
+       if (bi.board_id != BOARD_E1197)
+               return 0;
+
+       if (_hsic_reg_status == false)
+               return 0;
+
+       if (IS_ERR_OR_NULL(enterprise_hsic_reg)) {
+               pr_err("xmm: unbalanced disable on vddio_hsic regulator\n");
+               enterprise_hsic_reg = NULL;
+               return PTR_ERR(enterprise_hsic_reg);
+       }
+       ret = regulator_disable(enterprise_hsic_reg);
+       if (ret < 0) {
+               pr_err("xmm: failed to disable regulator\n");
+               return ret;
+       }
+       _hsic_reg_status = false;
+       return 0;
+}
+
 static int baseband_modem_power_on(struct baseband_power_platform_data *data)
 {
        /* set IPC_HSIC_ACTIVE active */
@@ -146,6 +206,8 @@ static int baseband_xmm_power_on(struct platform_device *device)
        if (baseband_xmm_powerstate != BBXMM_PS_UNINIT)
                return -EINVAL;
 
+       tegra_baseband_rail_on();
+
        /* reset the state machine */
        baseband_xmm_powerstate = BBXMM_PS_INIT;
        modem_sleep_flag = false;
@@ -245,6 +307,8 @@ static int baseband_xmm_power_off(struct platform_device *device)
        spin_unlock_irqrestore(&xmm_lock, flags);
        /* start registration process once again on xmm on */
        register_hsic_device = true;
+
+       tegra_baseband_rail_off();
        pr_debug("%s }\n", __func__);
 
        return 0;
@@ -358,6 +422,10 @@ void baseband_xmm_set_power_status(unsigned int status)
                        }
                }
                pr_info("L3\n");
+               /* system is going to suspend */
+               if (baseband_xmm_powerstate == BBXMM_PS_L2)
+                       tegra_baseband_rail_off();
+
                baseband_xmm_powerstate = status;
                spin_lock_irqsave(&xmm_lock, flags);
                system_suspending = false;
@@ -383,6 +451,12 @@ void baseband_xmm_set_power_status(unsigned int status)
                }
                baseband_xmm_powerstate = status;
                break;
+       case BBXMM_PS_L3TOL0:
+               /* poweron rail for L3 -> L0 (system resume) */
+               pr_debug("L3 -> L0, turning on power rail.\n");
+               tegra_baseband_rail_on();
+               baseband_xmm_powerstate = status;
+               break;
        default:
                baseband_xmm_powerstate = status;
                break;
index 913a577..dbc1c48 100644 (file)
@@ -63,6 +63,7 @@
 
 #ifdef CONFIG_TEGRA_DC
 static struct regulator *enterprise_dsi_reg;
+static bool dsi_regulator_status;
 static struct regulator *enterprise_lcd_reg;
 
 static struct regulator *enterprise_hdmi_reg;
@@ -454,27 +455,61 @@ static struct tegra_dc_platform_data enterprise_disp2_pdata = {
        .emc_clk_rate   = 300000000,
 };
 
-static int enterprise_dsi_panel_enable(void)
+static int avdd_dsi_csi_rail_enable(void)
 {
        int ret;
-       struct board_info board_info;
 
-       tegra_get_board_info(&board_info);
+       if (dsi_regulator_status == true)
+               return 0;
 
        if (enterprise_dsi_reg == NULL) {
                enterprise_dsi_reg = regulator_get(NULL, "avdd_dsi_csi");
                if (IS_ERR_OR_NULL(enterprise_dsi_reg)) {
                        pr_err("dsi: Could not get regulator avdd_dsi_csi\n");
-                               enterprise_dsi_reg = NULL;
-                               return PTR_ERR(enterprise_dsi_reg);
+                       enterprise_dsi_reg = NULL;
+                       return PTR_ERR(enterprise_dsi_reg);
                }
        }
        ret = regulator_enable(enterprise_dsi_reg);
        if (ret < 0) {
-               printk(KERN_ERR
-                       "DSI regulator avdd_dsi_csi could not be enabled\n");
+               pr_err("DSI regulator avdd_dsi_csi could not be enabled\n");
+               return ret;
+       }
+       dsi_regulator_status = true;
+       return 0;
+}
+
+static int avdd_dsi_csi_rail_disable(void)
+{
+       int ret;
+
+       if (dsi_regulator_status == false)
+               return 0;
+
+       if (enterprise_dsi_reg == NULL) {
+               pr_warn("%s: unbalanced disable\n", __func__);
+               return -EIO;
+       }
+
+       ret = regulator_disable(enterprise_dsi_reg);
+       if (ret < 0) {
+               pr_err("DSI regulator avdd_dsi_csi cannot be disabled\n");
                return ret;
        }
+       dsi_regulator_status = false;
+       return 0;
+}
+
+static int enterprise_dsi_panel_enable(void)
+{
+       int ret;
+       struct board_info board_info;
+
+       tegra_get_board_info(&board_info);
+
+       ret = avdd_dsi_csi_rail_enable();
+       if (ret)
+               return ret;
 
 #if DSI_PANEL_RESET
 
@@ -562,8 +597,8 @@ static void enterprise_stereo_set_orientation(int mode)
 #ifdef CONFIG_TEGRA_DC
 static int enterprise_dsi_panel_postsuspend(void)
 {
-       /* Do nothing for enterprise dsi panel */
-       return 0;
+       /* Disable enterprise dsi rail */
+       return avdd_dsi_csi_rail_disable();
 }
 #endif
 
index 9d7a4d6..c17c3ea 100644 (file)
@@ -147,6 +147,7 @@ static struct regulator_consumer_supply tps80031_vana_supply_common[] = {
 
 static struct regulator_consumer_supply tps80031_ldo1_supply_a02[] = {
        REGULATOR_SUPPLY("avdd_dsi_csi", NULL),
+       REGULATOR_SUPPLY("avdd_hsic", NULL),
        REGULATOR_SUPPLY("pwrdet_mipi", NULL),
 };