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");