msm: mdm: change the gpio pull value of mdm2ap_status after bootup

The mdm2ap_status gpio has been known to fluctuate in
its value during mdm bootup if set to PULL_NONE, so set
it to PULL_DOWN when the gpiomux is initialliy installed.
However, it needs to be reset to PULL_NONE after the mdm
is booted up in order to reduce leakage current.

CRs-Fixed: 368433
CRs-Fixed: 379343
Change-Id: Ia5a9046ed1ed98854750e8f4ae8d08e32ff427a9
Signed-off-by: Joel King <joelking@codeaurora.org>
diff --git a/arch/arm/mach-msm/board-8064-gpiomux.c b/arch/arm/mach-msm/board-8064-gpiomux.c
index 1c19442..7898cf6 100644
--- a/arch/arm/mach-msm/board-8064-gpiomux.c
+++ b/arch/arm/mach-msm/board-8064-gpiomux.c
@@ -788,7 +788,7 @@
 static struct gpiomux_setting mdm2ap_status_cfg = {
 	.func = GPIOMUX_FUNC_GPIO,
 	.drv = GPIOMUX_DRV_8MA,
-	.pull = GPIOMUX_PULL_NONE,
+	.pull = GPIOMUX_PULL_DOWN,
 };
 
 static struct gpiomux_setting mdm2ap_errfatal_cfg = {
@@ -828,6 +828,7 @@
 	{
 		.gpio = 49,
 		.settings = {
+			[GPIOMUX_ACTIVE] = &mdm2ap_status_cfg,
 			[GPIOMUX_SUSPENDED] = &mdm2ap_status_cfg,
 		}
 	},
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index 90563ad..0fad463 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -1727,6 +1727,12 @@
 	.mdm2ap_vddmin_gpio = 80,
 };
 
+static struct gpiomux_setting mdm2ap_status_gpio_run_cfg = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv = GPIOMUX_DRV_8MA,
+	.pull = GPIOMUX_PULL_NONE,
+};
+
 static struct mdm_platform_data mdm_platform_data = {
 	.mdm_version = "3.0",
 	.ramdump_delay_ms = 2000,
@@ -1735,6 +1741,7 @@
 	.vddmin_resource = &mdm_vddmin_rscs,
 	.peripheral_platform_device = &apq8064_device_hsic_host,
 	.ramdump_timeout_ms = 120000,
+	.mdm2ap_status_gpio_run_cfg = &mdm2ap_status_gpio_run_cfg,
 };
 
 static struct tsens_platform_data apq_tsens_pdata  = {
diff --git a/arch/arm/mach-msm/include/mach/mdm2.h b/arch/arm/mach-msm/include/mach/mdm2.h
index c4877cc..6ec12c1 100644
--- a/arch/arm/mach-msm/include/mach/mdm2.h
+++ b/arch/arm/mach-msm/include/mach/mdm2.h
@@ -32,6 +32,7 @@
 	struct platform_device *peripheral_platform_device;
 	const unsigned int ramdump_timeout_ms;
 	int image_upgrade_supported;
+	struct gpiomux_setting *mdm2ap_status_gpio_run_cfg;
 };
 
 #endif
diff --git a/arch/arm/mach-msm/mdm_common.c b/arch/arm/mach-msm/mdm_common.c
index 6b40cda..d1865e4 100644
--- a/arch/arm/mach-msm/mdm_common.c
+++ b/arch/arm/mach-msm/mdm_common.c
@@ -30,6 +30,7 @@
 #include <linux/workqueue.h>
 #include <linux/clk.h>
 #include <linux/mfd/pmic8058.h>
+#include <linux/msm_charm.h>
 #include <asm/mach-types.h>
 #include <asm/uaccess.h>
 #include <mach/mdm2.h>
@@ -37,7 +38,7 @@
 #include <mach/subsystem_notif.h>
 #include <mach/subsystem_restart.h>
 #include <mach/rpm.h>
-#include <linux/msm_charm.h>
+#include <mach/gpiomux.h>
 #include "msm_watchdog.h"
 #include "mdm_private.h"
 #include "sysmon.h"
@@ -68,6 +69,13 @@
 #define SFR_MAX_RETRIES		10
 #define SFR_RETRY_INTERVAL	1000
 
+enum gpio_update_config {
+	GPIO_UPDATE_BOOTING_CONFIG = 1,
+	GPIO_UPDATE_RUNNING_CONFIG,
+};
+static int mdm2ap_status_valid_old_config;
+static struct gpiomux_setting mdm2ap_status_old_config;
+
 static irqreturn_t mdm_vddmin_change(int irq, void *dev_id)
 {
 	int value = gpio_get_value(
@@ -163,6 +171,37 @@
 
 static DECLARE_DELAYED_WORK(mdm2ap_status_check_work, mdm2ap_status_check);
 
+static void mdm_update_gpio_configs(enum gpio_update_config gpio_config)
+{
+	/* Some gpio configuration may need updating after modem bootup.*/
+	switch (gpio_config) {
+	case GPIO_UPDATE_RUNNING_CONFIG:
+		if (mdm_drv->pdata->mdm2ap_status_gpio_run_cfg) {
+			if (msm_gpiomux_write(mdm_drv->mdm2ap_status_gpio,
+				GPIOMUX_ACTIVE,
+				mdm_drv->pdata->mdm2ap_status_gpio_run_cfg,
+				&mdm2ap_status_old_config))
+				pr_err("%s: failed updating running gpio config\n",
+					   __func__);
+			else
+				mdm2ap_status_valid_old_config = 1;
+		}
+		break;
+	case GPIO_UPDATE_BOOTING_CONFIG:
+		if (mdm2ap_status_valid_old_config) {
+			msm_gpiomux_write(mdm_drv->mdm2ap_status_gpio,
+					GPIOMUX_ACTIVE,
+					&mdm2ap_status_old_config,
+					NULL);
+			mdm2ap_status_valid_old_config = 0;
+		}
+		break;
+	default:
+		pr_err("%s: called with no config\n", __func__);
+		break;
+	}
+}
+
 long mdm_modem_ioctl(struct file *filp, unsigned int cmd,
 				unsigned long arg)
 {
@@ -205,11 +244,10 @@
 		else
 			first_boot = 0;
 
-		/* Start a timer to check that the mdm2ap_status gpio
-		 * goes high.
+		/* If successful, start a timer to check that the mdm2ap_status
+		 * gpio goes high.
 		 */
-
-		if (gpio_get_value(mdm_drv->mdm2ap_status_gpio) == 0)
+		if (!status && gpio_get_value(mdm_drv->mdm2ap_status_gpio) == 0)
 			schedule_delayed_work(&mdm2ap_status_check_work,
 				msecs_to_jiffies(MDM2AP_STATUS_TIMEOUT_MS));
 		break;
@@ -266,6 +304,9 @@
 	pr_debug("%s: status:%d\n", __func__, value);
 	if (mdm_drv->mdm_ready && mdm_drv->ops->status_cb)
 		mdm_drv->ops->status_cb(mdm_drv, value);
+
+	/* Update gpio configuration to "running" config. */
+	mdm_update_gpio_configs(GPIO_UPDATE_RUNNING_CONFIG);
 }
 
 static DECLARE_WORK(mdm_status_work, mdm_status_fn);
@@ -364,6 +405,7 @@
 static int mdm_subsys_shutdown(const struct subsys_desc *crashed_subsys)
 {
 	mdm_drv->mdm_ready = 0;
+	cancel_delayed_work(&mdm2ap_status_check_work);
 	gpio_direction_output(mdm_drv->ap2mdm_errfatal_gpio, 1);
 	if (mdm_drv->pdata->ramdump_delay_ms > 0) {
 		/* Wait for the external modem to complete
@@ -371,10 +413,13 @@
 		 */
 		msleep(mdm_drv->pdata->ramdump_delay_ms);
 	}
-	if (!mdm_drv->mdm_unexpected_reset_occurred)
+	if (!mdm_drv->mdm_unexpected_reset_occurred) {
 		mdm_drv->ops->reset_mdm_cb(mdm_drv);
-	else
+		/* Update gpio configuration to "booting" config. */
+		mdm_update_gpio_configs(GPIO_UPDATE_BOOTING_CONFIG);
+	} else {
 		mdm_drv->mdm_unexpected_reset_occurred = 0;
+	}
 	return 0;
 }
 
@@ -404,6 +449,7 @@
 				const struct subsys_desc *crashed_subsys)
 {
 	mdm_drv->mdm_ram_dump_status = 0;
+	cancel_delayed_work(&mdm2ap_status_check_work);
 	if (want_dumps) {
 		mdm_drv->boot_type = CHARM_RAM_DUMPS;
 		complete(&mdm_needs_reload);
@@ -416,8 +462,11 @@
 			pr_info("%s: mdm modem ramdumps completed.\n",
 					__func__);
 		INIT_COMPLETION(mdm_ram_dumps);
-		if (!mdm_drv->pdata->no_powerdown_after_ramdumps)
+		if (!mdm_drv->pdata->no_powerdown_after_ramdumps) {
 			mdm_drv->ops->power_down_mdm_cb(mdm_drv);
+			/* Update gpio configuration to "booting" config. */
+			mdm_update_gpio_configs(GPIO_UPDATE_BOOTING_CONFIG);
+		}
 	}
 	return mdm_drv->mdm_ram_dump_status;
 }