mdm: Add support for PBLRDY gpio

mdm peripheral can be added before mdm becomes ready which
can result in mdm pbl enumeration failures. To avoid such
failures, wait for mdm pbl to be ready before adding
peripheral.

Change-Id: I8a22cc93048a501bcac8aae17d7df6c3a55fedf0
Signed-off-by: Vamsi Krishna <vskrishn@codeaurora.org>
diff --git a/arch/arm/mach-msm/board-8064-gpiomux.c b/arch/arm/mach-msm/board-8064-gpiomux.c
index b941bd4..ecd4e54 100644
--- a/arch/arm/mach-msm/board-8064-gpiomux.c
+++ b/arch/arm/mach-msm/board-8064-gpiomux.c
@@ -797,6 +797,13 @@
 	.pull = GPIOMUX_PULL_DOWN,
 };
 
+static struct gpiomux_setting mdm2ap_pblrdy = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv = GPIOMUX_DRV_16MA,
+	.pull = GPIOMUX_PULL_DOWN,
+};
+
+
 static struct gpiomux_setting ap2mdm_soft_reset_cfg = {
 	.func = GPIOMUX_FUNC_GPIO,
 	.drv = GPIOMUX_DRV_8MA,
@@ -852,6 +859,13 @@
 			[GPIOMUX_SUSPENDED] = &ap2mdm_wakeup,
 		}
 	},
+	/* MDM2AP_PBL_READY*/
+	{
+		.gpio = 46,
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &mdm2ap_pblrdy,
+		}
+	},
 };
 
 static struct gpiomux_setting mi2s_act_cfg = {
diff --git a/arch/arm/mach-msm/devices-8064.c b/arch/arm/mach-msm/devices-8064.c
index 4e01899..cc3c6db 100644
--- a/arch/arm/mach-msm/devices-8064.c
+++ b/arch/arm/mach-msm/devices-8064.c
@@ -2273,6 +2273,7 @@
 #define AP2MDM_STATUS			48
 #define AP2MDM_SOFT_RESET		27
 #define AP2MDM_WAKEUP			35
+#define MDM2AP_PBLRDY			46
 
 static struct resource mdm_resources[] = {
 	{
@@ -2311,6 +2312,12 @@
 		.name	= "AP2MDM_WAKEUP",
 		.flags	= IORESOURCE_IO,
 	},
+	{
+		.start	= MDM2AP_PBLRDY,
+		.end	= MDM2AP_PBLRDY,
+		.name	= "MDM2AP_PBLRDY",
+		.flags	= IORESOURCE_IO,
+	},
 };
 
 struct platform_device mdm_8064_device = {
diff --git a/arch/arm/mach-msm/mdm2.c b/arch/arm/mach-msm/mdm2.c
index bd7bd9e..4791955 100644
--- a/arch/arm/mach-msm/mdm2.c
+++ b/arch/arm/mach-msm/mdm2.c
@@ -45,6 +45,7 @@
 #define MDM_MODEM_TIMEOUT	6000
 #define MDM_HOLD_TIME		4000
 #define MDM_MODEM_DELTA		100
+#define MDM_PBLRDY_CNT		20
 
 static int mdm_debug_on;
 static int power_on_count;
@@ -93,6 +94,8 @@
 {
 	int soft_reset_direction =
 		mdm_drv->pdata->soft_reset_inverted ? 0 : 1;
+	int i;
+	int pblrdy;
 
 	if (power_on_count != 1) {
 		pr_err("%s: Calling fn when power_on_count != 1\n",
@@ -118,7 +121,19 @@
 	pr_debug("%s: De-asserting soft reset gpio\n", __func__);
 	gpio_direction_output(mdm_drv->ap2mdm_soft_reset_gpio,
 						  soft_reset_direction);
+	if (!mdm_drv->mdm2ap_pblrdy)
+		goto start_mdm_peripheral;
 
+	for (i = 0; i  < MDM_PBLRDY_CNT; i++) {
+		pblrdy = gpio_get_value(mdm_drv->mdm2ap_pblrdy);
+		if (pblrdy)
+			break;
+		usleep_range(5000, 5000);
+	}
+
+	pr_debug("%s: i:%d\n", __func__, i);
+
+start_mdm_peripheral:
 	mdm_peripheral_connect(mdm_drv);
 	msleep(200);
 }
@@ -127,6 +142,8 @@
 {
 	int soft_reset_direction =
 		mdm_drv->pdata->soft_reset_inverted ? 0 : 1;
+	int i;
+	int pblrdy;
 
 	/* De-assert the soft reset line. */
 	pr_err("%s: soft resetting mdm modem\n", __func__);
@@ -139,6 +156,19 @@
 	gpio_direction_output(mdm_drv->ap2mdm_soft_reset_gpio,
 		soft_reset_direction == 1 ? 1 : 0);
 
+	if (!mdm_drv->mdm2ap_pblrdy)
+		goto start_mdm_peripheral;
+
+	for (i = 0; i  < MDM_PBLRDY_CNT; i++) {
+		pblrdy = gpio_get_value(mdm_drv->mdm2ap_pblrdy);
+		if (pblrdy)
+			break;
+		usleep_range(5000, 5000);
+	}
+
+	pr_debug("%s: i:%d\n", __func__, i);
+
+start_mdm_peripheral:
 	mdm_peripheral_connect(mdm_drv);
 	msleep(200);
 }
diff --git a/arch/arm/mach-msm/mdm_common.c b/arch/arm/mach-msm/mdm_common.c
index 921f062..c961731 100644
--- a/arch/arm/mach-msm/mdm_common.c
+++ b/arch/arm/mach-msm/mdm_common.c
@@ -340,6 +340,14 @@
 	return IRQ_HANDLED;
 }
 
+static irqreturn_t mdm_pblrdy_change(int irq, void *dev_id)
+{
+	pr_info("%s: pbl ready:%d\n", __func__,
+			gpio_get_value(mdm_drv->mdm2ap_pblrdy));
+
+	return IRQ_HANDLED;
+}
+
 static int mdm_subsys_shutdown(const struct subsys_data *crashed_subsys)
 {
 	gpio_direction_output(mdm_drv->ap2mdm_errfatal_gpio, 1);
@@ -497,6 +505,12 @@
 	if (pres)
 		mdm_drv->ap2mdm_pmic_pwr_en_gpio = pres->start;
 
+	/* MDM2AP_PBLRDY */
+	pres = platform_get_resource_byname(pdev, IORESOURCE_IO,
+							"MDM2AP_PBLRDY");
+	if (pres)
+		mdm_drv->mdm2ap_pblrdy = pres->start;
+
 	mdm_drv->boot_type                  = CHARM_NORMAL_BOOT;
 
 	mdm_drv->ops      = mdm_ops;
@@ -524,6 +538,8 @@
 		gpio_request(mdm_drv->ap2mdm_kpdpwr_n_gpio, "AP2MDM_KPDPWR_N");
 	gpio_request(mdm_drv->mdm2ap_status_gpio, "MDM2AP_STATUS");
 	gpio_request(mdm_drv->mdm2ap_errfatal_gpio, "MDM2AP_ERRFATAL");
+	if (mdm_drv->mdm2ap_pblrdy > 0)
+		gpio_request(mdm_drv->mdm2ap_pblrdy, "MDM2AP_PBLRDY");
 
 	if (mdm_drv->ap2mdm_pmic_pwr_en_gpio > 0)
 		gpio_request(mdm_drv->ap2mdm_pmic_pwr_en_gpio,
@@ -612,6 +628,27 @@
 	mdm_drv->mdm_status_irq = irq;
 
 status_err:
+	if (mdm_drv->mdm2ap_pblrdy > 0) {
+		irq = MSM_GPIO_TO_INT(mdm_drv->mdm2ap_pblrdy);
+		if (irq < 0) {
+			pr_err("%s: could not get MDM2AP_PBLRDY IRQ resource",
+				__func__);
+			goto pblrdy_err;
+		}
+
+		ret = request_threaded_irq(irq, NULL, mdm_pblrdy_change,
+			IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING |
+			IRQF_SHARED,
+			"mdm pbl ready", mdm_drv);
+
+		if (ret < 0) {
+			pr_err("%s: MDM2AP_PBL IRQ#%d request failed error=%d",
+				__func__, irq, ret);
+			goto pblrdy_err;
+		}
+	}
+
+pblrdy_err:
 	/*
 	 * If AP2MDM_PMIC_PWR_EN gpio is used, pull it high. It remains
 	 * high until the whole phone is shut down.
diff --git a/arch/arm/mach-msm/mdm_private.h b/arch/arm/mach-msm/mdm_private.h
index f157d88..53bfaf0 100644
--- a/arch/arm/mach-msm/mdm_private.h
+++ b/arch/arm/mach-msm/mdm_private.h
@@ -35,6 +35,7 @@
 	unsigned ap2mdm_kpdpwr_n_gpio;
 	unsigned ap2mdm_soft_reset_gpio;
 	unsigned ap2mdm_pmic_pwr_en_gpio;
+	unsigned mdm2ap_pblrdy;
 
 	int mdm_errfatal_irq;
 	int mdm_status_irq;