msm: mdm: add support for multiple external modems

The mdm driver previously assumed that it would only need to support
one external modem at a time. This is no longer true. The changes now
support a arbitrary number of modems. Each modem must have its own
platform data.

Change-Id: I43918f92935b4b447a46d02721239fed0b5e877e
Signed-off-by: Ameya Thakur <ameyat@codeaurora.org>
diff --git a/arch/arm/mach-msm/mdm2.c b/arch/arm/mach-msm/mdm2.c
index 77eeb53..a9fad9d 100644
--- a/arch/arm/mach-msm/mdm2.c
+++ b/arch/arm/mach-msm/mdm2.c
@@ -28,6 +28,7 @@
 #include <linux/debugfs.h>
 #include <linux/completion.h>
 #include <linux/workqueue.h>
+#include <linux/clk.h>
 #include <linux/mfd/pmic8058.h>
 #include <asm/mach-types.h>
 #include <asm/uaccess.h>
@@ -38,26 +39,24 @@
 #include <linux/msm_charm.h>
 #include "msm_watchdog.h"
 #include "devices.h"
+#include "clock.h"
 #include "mdm_private.h"
 #define MDM_PBLRDY_CNT		20
 
 static int mdm_debug_mask;
-static int power_on_count;
-static int hsic_peripheral_status;
-static DEFINE_MUTEX(hsic_status_lock);
 
 static void mdm_peripheral_connect(struct mdm_modem_drv *mdm_drv)
 {
 	if (!mdm_drv->pdata->peripheral_platform_device)
 		return;
 
-	mutex_lock(&hsic_status_lock);
-	if (hsic_peripheral_status)
+	mutex_lock(&mdm_drv->peripheral_status_lock);
+	if (mdm_drv->peripheral_status)
 		goto out;
 	platform_device_add(mdm_drv->pdata->peripheral_platform_device);
-	hsic_peripheral_status = 1;
+	mdm_drv->peripheral_status = 1;
 out:
-	mutex_unlock(&hsic_status_lock);
+	mutex_unlock(&mdm_drv->peripheral_status_lock);
 }
 
 static void mdm_peripheral_disconnect(struct mdm_modem_drv *mdm_drv)
@@ -65,13 +64,13 @@
 	if (!mdm_drv->pdata->peripheral_platform_device)
 		return;
 
-	mutex_lock(&hsic_status_lock);
-	if (!hsic_peripheral_status)
+	mutex_lock(&mdm_drv->peripheral_status_lock);
+	if (!mdm_drv->peripheral_status)
 		goto out;
 	platform_device_del(mdm_drv->pdata->peripheral_platform_device);
-	hsic_peripheral_status = 0;
+	mdm_drv->peripheral_status = 0;
 out:
-	mutex_unlock(&hsic_status_lock);
+	mutex_unlock(&mdm_drv->peripheral_status_lock);
 }
 
 /* This function can be called from atomic context. */
@@ -112,15 +111,15 @@
 	for (i = 20; i > 0; i--) {
 		if (gpio_get_value(mdm_drv->mdm2ap_status_gpio) == 0) {
 			if (mdm_debug_mask & MDM_DEBUG_MASK_SHDN_LOG)
-				pr_info("%s: mdm2ap_status went low, i = %d\n",
-					__func__, i);
+				pr_info("%s:id %d: mdm2ap_statuswent low, i=%d\n",
+					__func__, mdm_drv->device_id, i);
 			break;
 		}
 		msleep(100);
 	}
 	if (i == 0) {
-		pr_err("%s: MDM2AP_STATUS never went low. Doing a hard reset\n",
-			   __func__);
+		pr_err("%s:id %d: MDM2AP_STATUS never went low. Doing a hard reset\n",
+			   __func__, mdm_drv->device_id);
 		gpio_direction_output(mdm_drv->ap2mdm_soft_reset_gpio,
 					soft_reset_direction);
 		/*
@@ -137,13 +136,14 @@
 {
 	int i;
 	int pblrdy;
-	if (power_on_count != 1) {
-		pr_err("%s: Calling fn when power_on_count != 1\n",
-			   __func__);
+	if (mdm_drv->power_on_count != 1) {
+		pr_err("%s:id %d: Calling fn when power_on_count != 1\n",
+			   __func__, mdm_drv->device_id);
 		return;
 	}
 
-	pr_err("%s: Powering on modem for the first time\n", __func__);
+	pr_err("%s:id %d: Powering on modem for the first time\n",
+		   __func__, mdm_drv->device_id);
 	mdm_peripheral_disconnect(mdm_drv);
 
 	/* If this is the first power-up after a panic, the modem may still
@@ -157,7 +157,8 @@
 		/* Pull AP2MDM_KPDPWR gpio high and wait for PS_HOLD to settle,
 		 * then	pull it back low.
 		 */
-		pr_debug("%s: Pulling AP2MDM_KPDPWR gpio high\n", __func__);
+		pr_debug("%s:id %d: Pulling AP2MDM_KPDPWR gpio high\n",
+				 __func__, mdm_drv->device_id);
 		gpio_direction_output(mdm_drv->ap2mdm_kpdpwr_n_gpio, 1);
 		msleep(1000);
 		gpio_direction_output(mdm_drv->ap2mdm_kpdpwr_n_gpio, 0);
@@ -172,7 +173,8 @@
 			break;
 		usleep_range(5000, 5000);
 	}
-	pr_debug("%s: i:%d\n", __func__, i);
+	pr_debug("%s: id %d: pblrdy i:%d\n", __func__,
+			 mdm_drv->device_id, i);
 
 start_mdm_peripheral:
 	mdm_peripheral_connect(mdm_drv);
@@ -184,7 +186,8 @@
 	int i;
 	int pblrdy;
 
-	pr_err("%s: soft resetting mdm modem\n", __func__);
+	pr_err("%s: id %d:  soft resetting mdm modem\n",
+		   __func__, mdm_drv->device_id);
 	mdm_peripheral_disconnect(mdm_drv);
 	mdm_toggle_soft_reset(mdm_drv);
 
@@ -198,7 +201,8 @@
 		usleep_range(5000, 5000);
 	}
 
-	pr_debug("%s: i:%d\n", __func__, i);
+	pr_debug("%s: id %d: pblrdy i:%d\n", __func__,
+			 mdm_drv->device_id, i);
 
 start_mdm_peripheral:
 	mdm_peripheral_connect(mdm_drv);
@@ -207,7 +211,7 @@
 
 static void mdm_power_on_common(struct mdm_modem_drv *mdm_drv)
 {
-	power_on_count++;
+	mdm_drv->power_on_count++;
 
 	/* this gpio will be used to indicate apq readiness,
 	 * de-assert it now so that it can be asserted later.
@@ -222,10 +226,10 @@
 	 * user space but we're already powered on. Ignore it.
 	 */
 	if (mdm_drv->pdata->early_power_on &&
-			(power_on_count == 2))
+			(mdm_drv->power_on_count == 2))
 		return;
 
-	if (power_on_count == 1)
+	if (mdm_drv->power_on_count == 1)
 		mdm_do_first_power_on(mdm_drv);
 	else
 		mdm_do_soft_power_on(mdm_drv);
@@ -238,7 +242,8 @@
 
 static void mdm_status_changed(struct mdm_modem_drv *mdm_drv, int value)
 {
-	pr_debug("%s: value:%d\n", __func__, value);
+	pr_debug("%s: id %d: value:%d\n", __func__,
+			 value, mdm_drv->device_id);
 
 	if (value) {
 		mdm_peripheral_disconnect(mdm_drv);
@@ -252,13 +257,15 @@
 {
 	switch (type) {
 	case APQ_CONTROLLED_UPGRADE:
-		pr_debug("%s APQ controlled modem image upgrade\n", __func__);
-		mdm_drv->mdm_ready = 0;
+		pr_debug("%s: id %d: APQ controlled modem image upgrade\n",
+				 __func__, mdm_drv->device_id);
+		atomic_set(&mdm_drv->mdm_ready, 0);
 		mdm_toggle_soft_reset(mdm_drv);
 		break;
 	case MDM_CONTROLLED_UPGRADE:
-		pr_debug("%s MDM controlled modem image upgrade\n", __func__);
-		mdm_drv->mdm_ready = 0;
+		pr_debug("%s: id %d: MDM controlled modem image upgrade\n",
+				 __func__, mdm_drv->device_id);
+		atomic_set(&mdm_drv->mdm_ready, 0);
 		/*
 		 * If we have no image currently present on the modem, then we
 		 * would be in PBL, in which case the status gpio would not go
@@ -266,15 +273,19 @@
 		 */
 		mdm_drv->disable_status_check = 1;
 		if (GPIO_IS_VALID(mdm_drv->usb_switch_gpio)) {
-			pr_info("%s Switching usb control to MDM\n", __func__);
+			pr_info("%s: id %d: Switching usb control to MDM\n",
+					__func__, mdm_drv->device_id);
 			gpio_direction_output(mdm_drv->usb_switch_gpio, 1);
 		} else
-			pr_err("%s usb switch gpio unavailable\n", __func__);
+			pr_err("%s: id %d: usb switch gpio unavailable\n",
+				   __func__, mdm_drv->device_id);
 		break;
 	default:
-		pr_err("%s invalid upgrade type\n", __func__);
+		pr_err("%s: id %d: invalid upgrade type\n",
+			   __func__, mdm_drv->device_id);
 	}
 }
+
 static struct mdm_ops mdm_cb = {
 	.power_on_mdm_cb = mdm_power_on_common,
 	.reset_mdm_cb = mdm_power_on_common,
@@ -285,44 +296,10 @@
 	.image_upgrade_cb = mdm_image_upgrade,
 };
 
-static int __init mdm_modem_probe(struct platform_device *pdev)
+int mdm_get_ops(struct mdm_ops **mdm_ops)
 {
-	return mdm_common_create(pdev, &mdm_cb);
+	*mdm_ops = &mdm_cb;
+	return 0;
 }
 
-static int __devexit mdm_modem_remove(struct platform_device *pdev)
-{
-	return mdm_common_modem_remove(pdev);
-}
 
-static void mdm_modem_shutdown(struct platform_device *pdev)
-{
-	mdm_common_modem_shutdown(pdev);
-}
-
-static struct platform_driver mdm_modem_driver = {
-	.remove         = mdm_modem_remove,
-	.shutdown	= mdm_modem_shutdown,
-	.driver         = {
-		.name = "mdm2_modem",
-		.owner = THIS_MODULE
-	},
-};
-
-static int __init mdm_modem_init(void)
-{
-	return platform_driver_probe(&mdm_modem_driver, mdm_modem_probe);
-}
-
-static void __exit mdm_modem_exit(void)
-{
-	platform_driver_unregister(&mdm_modem_driver);
-}
-
-module_init(mdm_modem_init);
-module_exit(mdm_modem_exit);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("mdm modem driver");
-MODULE_VERSION("2.0");
-MODULE_ALIAS("mdm_modem");