aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc/modem_if/modem_modemctl_device_xmm6262.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/misc/modem_if/modem_modemctl_device_xmm6262.c')
-rw-r--r--drivers/misc/modem_if/modem_modemctl_device_xmm6262.c92
1 files changed, 88 insertions, 4 deletions
diff --git a/drivers/misc/modem_if/modem_modemctl_device_xmm6262.c b/drivers/misc/modem_if/modem_modemctl_device_xmm6262.c
index 4d0b69c..5473aad 100644
--- a/drivers/misc/modem_if/modem_modemctl_device_xmm6262.c
+++ b/drivers/misc/modem_if/modem_modemctl_device_xmm6262.c
@@ -24,9 +24,11 @@
#include <linux/platform_device.h>
#include <linux/cma.h>
#include <plat/devs.h>
-#include <linux/platform_data/modem.h>
+#include "modem.h"
#include "modem_prj.h"
-
+#ifdef CONFIG_FAST_BOOT
+#include <linux/fake_shut_down.h>
+#endif
static int xmm6262_on(struct modem_ctl *mc)
{
mif_info("\n");
@@ -59,11 +61,13 @@ static int xmm6262_on(struct modem_ctl *mc)
udelay(60);
gpio_set_value(mc->gpio_cp_on, 0);
msleep(20);
+
+ mc->phone_state = STATE_BOOTING;
+
if (mc->gpio_revers_bias_restore)
mc->gpio_revers_bias_restore();
gpio_set_value(mc->gpio_pda_active, 1);
- mc->phone_state = STATE_BOOTING;
return 0;
}
@@ -120,6 +124,20 @@ static int xmm6262_reset(struct modem_ctl *mc)
return 0;
}
+static int xmm6262_force_crash_exit(struct modem_ctl *mc)
+{
+ mif_info("\n");
+
+ if (!mc->gpio_ap_dump_int)
+ return -ENXIO;
+
+ gpio_set_value(mc->gpio_ap_dump_int, 1);
+ mif_info("set ap_dump_int(%d) to high=%d\n",
+ mc->gpio_ap_dump_int, gpio_get_value(mc->gpio_ap_dump_int));
+ return 0;
+}
+
+
static irqreturn_t phone_active_irq_handler(int irq, void *_mc)
{
int phone_reset = 0;
@@ -172,14 +190,72 @@ static irqreturn_t phone_active_irq_handler(int irq, void *_mc)
return IRQ_HANDLED;
}
+#ifdef CONFIG_FAST_BOOT
+#include <linux/reboot.h>
+
+static void mif_sim_detect_complete(struct modem_ctl *mc)
+{
+ if (mc->sim_shutdown_req) {
+ mif_info("fake shutdown sim changed shutdown\n");
+ kernel_power_off();
+ /*kernel_restart(NULL);*/
+ mc->sim_shutdown_req = false;
+ }
+}
+
+static int mif_init_sim_shutdown(struct modem_ctl *mc)
+{
+ mc->sim_shutdown_req = false;
+ mc->modem_complete = mif_sim_detect_complete;
+
+ return 0;
+}
+
+static void mif_check_fake_shutdown(struct modem_ctl *mc, bool online)
+{
+ if (fake_shut_down && mc->sim_state.online != online)
+ mc->sim_shutdown_req = true;
+}
+
+#else
+static inline int mif_init_sim_shutdown(struct modem_ctl *mc) { return 0; }
+#define mif_check_fake_shutdown(a, b) do {} while (0)
+#endif
+
+
+#define SIM_DETECT_DEBUG
static irqreturn_t sim_detect_irq_handler(int irq, void *_mc)
{
struct modem_ctl *mc = (struct modem_ctl *)_mc;
+#ifdef SIM_DETECT_DEBUG
+ int val = gpio_get_value(mc->gpio_sim_detect);
+ static int unchange;
+ static int prev_val;
+
+ if (mc->phone_state == STATE_BOOTING) {
+ mif_info("BOOTING, reset unchange\n");
+ unchange = 0;
+ }
- if (mc->iod && mc->iod->sim_state_changed)
+ if (prev_val == val) {
+ if (unchange++ > 50) {
+ mif_err("Abnormal SIM detect GPIO irqs");
+ disable_irq_nosync(mc->gpio_sim_detect);
+ panic("SIM detect IRQ Error");
+ }
+ } else {
+ unchange = 0;
+ }
+ prev_val = val;
+#endif
+ if (mc->iod && mc->iod->sim_state_changed) {
+ mif_check_fake_shutdown(mc,
+ gpio_get_value(mc->gpio_sim_detect) == mc->sim_polarity
+ );
mc->iod->sim_state_changed(mc->iod,
gpio_get_value(mc->gpio_sim_detect) == mc->sim_polarity
);
+ }
return IRQ_HANDLED;
}
@@ -189,6 +265,7 @@ static void xmm6262_get_ops(struct modem_ctl *mc)
mc->ops.modem_on = xmm6262_on;
mc->ops.modem_off = xmm6262_off;
mc->ops.modem_reset = xmm6262_reset;
+ mc->ops.modem_force_crash_exit = xmm6262_force_crash_exit;
}
int xmm6262_init_modemctl_device(struct modem_ctl *mc,
@@ -218,6 +295,7 @@ int xmm6262_init_modemctl_device(struct modem_ctl *mc,
mc->gpio_cp_ctrl2 = pdata->gpio_cp_ctrl2;
#endif
+
pdev = to_platform_device(mc->dev);
mc->irq_phone_active = gpio_to_irq(mc->gpio_phone_active);
@@ -261,6 +339,12 @@ int xmm6262_init_modemctl_device(struct modem_ctl *mc,
/* initialize sim_state => insert: gpio=0, remove: gpio=1 */
mc->sim_state.online =
gpio_get_value(mc->gpio_sim_detect) == mc->sim_polarity;
+
+ ret = mif_init_sim_shutdown(mc);
+ if (ret) {
+ mif_err("failed to sim fake shutdown init: %d\n", ret);
+ goto err_sim_detect_set_wake_irq;
+ }
}
return ret;