diff options
Diffstat (limited to 'drivers/misc/modem_if/modem_modemctl_device_mdm6600.c')
-rw-r--r-- | drivers/misc/modem_if/modem_modemctl_device_mdm6600.c | 307 |
1 files changed, 268 insertions, 39 deletions
diff --git a/drivers/misc/modem_if/modem_modemctl_device_mdm6600.c b/drivers/misc/modem_if/modem_modemctl_device_mdm6600.c index 6f1807e..2706e5e 100644 --- a/drivers/misc/modem_if/modem_modemctl_device_mdm6600.c +++ b/drivers/misc/modem_if/modem_modemctl_device_mdm6600.c @@ -258,14 +258,72 @@ int mdm6600_init_modemctl_device(struct modem_ctl *mc, struct modem_data *pdata) } #endif /* CONFIG_MACH_U1_KOR_LGT */ -#if defined(CONFIG_MACH_C1CTC) || defined(CONFIG_MACH_M0_CTC) +#if defined(CONFIG_MACH_M0_CTC) || defined(CONFIG_MACH_T0_CHN_CTC) + +#if defined(CONFIG_LINK_DEVICE_DPRAM) #include "modem_link_device_dpram.h" +#elif defined(CONFIG_LINK_DEVICE_PLD) +#include "modem_link_device_pld.h" +#endif #define PIF_TIMEOUT (180 * HZ) #define DPRAM_INIT_TIMEOUT (30 * HZ) +#if defined(CONFIG_MACH_M0_DUOSCTC) || defined(CONFIG_MACH_M0_GRANDECTC) || \ + defined(CONFIG_MACH_T0_CHN_CTC) +static void mdm6600_vbus_on(void) +{ + struct regulator *regulator; + + pr_info("[MSM] <%s>\n", __func__); + +#if defined(CONFIG_MACH_T0_CHN_CTC) + if (system_rev == 4) + regulator = regulator_get(NULL, "vcc_1.8v_lcd"); + else + regulator = regulator_get(NULL, "vcc_1.8v_usb"); +#else + regulator = regulator_get(NULL, "vusbhub_osc_1.8v"); +#endif + if (IS_ERR(regulator)) { + pr_err("[MSM] error getting regulator_get <%s>\n", __func__); + return ; + } + regulator_enable(regulator); + regulator_put(regulator); + + pr_info("[MSM] <%s> enable\n", __func__); +} + +static void mdm6600_vbus_off(void) +{ + struct regulator *regulator; + + pr_info("[MSM] <%s>\n", __func__); + +#if defined(CONFIG_MACH_T0_CHN_CTC) + if (system_rev == 4) + regulator = regulator_get(NULL, "vcc_1.8v_lcd"); + else + regulator = regulator_get(NULL, "vcc_1.8v_usb"); +#else + regulator = regulator_get(NULL, "vusbhub_osc_1.8v"); +#endif + if (IS_ERR(regulator)) { + pr_err("[MSM] error getting regulator_get <%s>\n", __func__); + return ; + } + regulator_disable(regulator); + regulator_put(regulator); + + pr_info("[MSM] <%s> disable\n", __func__); +} +#endif + static int mdm6600_on(struct modem_ctl *mc) { + struct link_device *ld = get_current_link(mc->iod); + pr_info("[MSM] <%s>\n", __func__); if (!mc->gpio_reset_req_n || !mc->gpio_cp_reset @@ -274,20 +332,28 @@ static int mdm6600_on(struct modem_ctl *mc) return -ENXIO; } - gpio_set_value(mc->gpio_reset_req_n, 1); - - gpio_set_value(mc->gpio_cp_reset, 1); - msleep(30); + gpio_set_value(mc->gpio_pda_active, 0); gpio_set_value(mc->gpio_cp_on, 1); msleep(500); + gpio_set_value(mc->gpio_reset_req_n, 1); + msleep(50); + + gpio_set_value(mc->gpio_cp_reset, 1); + msleep(50); + gpio_set_value(mc->gpio_cp_on, 0); msleep(500); gpio_set_value(mc->gpio_pda_active, 1); +#if defined(CONFIG_LINK_DEVICE_PLD) + gpio_set_value(mc->gpio_fpga_cs_n, 1); +#endif + mc->iod->modem_state_changed(mc->iod, STATE_BOOTING); + ld->mode = LINK_MODE_BOOT; return 0; } @@ -302,8 +368,11 @@ static int mdm6600_off(struct modem_ctl *mc) } gpio_set_value(mc->gpio_cp_reset, 0); + gpio_set_value(mc->gpio_reset_req_n, 0); gpio_set_value(mc->gpio_cp_on, 0); + msleep(200); + mc->iod->modem_state_changed(mc->iod, STATE_OFFLINE); return 0; @@ -312,26 +381,46 @@ static int mdm6600_off(struct modem_ctl *mc) static int mdm6600_reset(struct modem_ctl *mc) { int ret = 0; + struct link_device *ld = get_current_link(mc->iod); pr_info("[MSM] <%s>\n", __func__); - ret = mdm6600_off(mc); - if (ret) + if (!mc->gpio_reset_req_n || !mc->gpio_cp_reset + || !mc->gpio_cp_on || !mc->gpio_pda_active) { + pr_err("[MSM] no gpio data\n"); return -ENXIO; + } + + gpio_set_value(mc->gpio_cp_reset, 0); + gpio_set_value(mc->gpio_reset_req_n, 0); + gpio_set_value(mc->gpio_cp_on, 0); -#if 0 msleep(100); -#endif - ret = mdm6600_on(mc); - if (ret) - return -ENXIO; + gpio_set_value(mc->gpio_cp_on, 1); + msleep(300); + + gpio_set_value(mc->gpio_reset_req_n, 1); + msleep(50); + + gpio_set_value(mc->gpio_cp_reset, 1); + msleep(50); + + gpio_set_value(mc->gpio_cp_on, 0); + msleep(100); + + gpio_set_value(mc->gpio_pda_active, 1); + + mc->iod->modem_state_changed(mc->iod, STATE_BOOTING); + ld->mode = LINK_MODE_BOOT; return 0; } static int mdm6600_boot_on(struct modem_ctl *mc) { + struct regulator *regulator; + pr_info("[MSM] <%s>\n", __func__); if (!mc->gpio_flm_uart_sel) { @@ -339,62 +428,106 @@ static int mdm6600_boot_on(struct modem_ctl *mc) return -ENXIO; } - pr_info("[MSM] <%s> %s\n", __func__, "USB_BOOT_EN initializing"); +#if defined(CONFIG_MACH_M0_DUOSCTC) || defined(CONFIG_MACH_T0_CHN_CTC) + mdm6600_vbus_on(); +#elif defined(CONFIG_MACH_M0_GRANDECTC) + if (system_rev >= 14) + mdm6600_vbus_on(); +#endif + pr_info("[MSM] <%s> %s\n", __func__, "USB_BOOT_EN initializing"); if (system_rev < 11) { gpio_direction_output(GPIO_USB_BOOT_EN, 0); s3c_gpio_setpull(GPIO_USB_BOOT_EN, S3C_GPIO_PULL_NONE); gpio_set_value(GPIO_USB_BOOT_EN, 0); + gpio_direction_output(GPIO_BOOT_SW_SEL, 0); + s3c_gpio_setpull(GPIO_BOOT_SW_SEL, S3C_GPIO_PULL_NONE); + gpio_set_value(GPIO_BOOT_SW_SEL, 0); + + msleep(100); + gpio_direction_output(GPIO_USB_BOOT_EN, 1); gpio_set_value(GPIO_USB_BOOT_EN, 1); pr_info("[MSM] <%s> USB_BOOT_EN:[%d]\n", __func__, gpio_get_value(GPIO_USB_BOOT_EN)); + + gpio_direction_output(GPIO_BOOT_SW_SEL, 1); + gpio_set_value(GPIO_BOOT_SW_SEL, 1); + + pr_info("[MSM] <%s> BOOT_SW_SEL : [%d]\n", __func__, + gpio_get_value(GPIO_BOOT_SW_SEL)); } else if (system_rev == 11) { gpio_direction_output(GPIO_USB_BOOT_EN, 0); s3c_gpio_setpull(GPIO_USB_BOOT_EN, S3C_GPIO_PULL_NONE); gpio_set_value(GPIO_USB_BOOT_EN, 0); + gpio_direction_output(GPIO_USB_BOOT_EN_REV06, 0); + s3c_gpio_setpull(GPIO_USB_BOOT_EN_REV06, S3C_GPIO_PULL_NONE); + gpio_set_value(GPIO_USB_BOOT_EN_REV06, 0); + + msleep(100); + gpio_direction_output(GPIO_USB_BOOT_EN, 1); gpio_set_value(GPIO_USB_BOOT_EN, 1); pr_info("[MSM] <%s> USB_BOOT_EN:[%d]\n", __func__, gpio_get_value(GPIO_USB_BOOT_EN)); - gpio_direction_output(GPIO_USB_BOOT_EN_REV06, 0); - s3c_gpio_setpull(GPIO_USB_BOOT_EN_REV06, S3C_GPIO_PULL_NONE); - gpio_set_value(GPIO_USB_BOOT_EN_REV06, 0); - gpio_direction_output(GPIO_USB_BOOT_EN_REV06, 1); gpio_set_value(GPIO_USB_BOOT_EN_REV06, 1); - pr_info("[MSM] <%s> USB_BOOT_EN:[%d]\n", __func__, - gpio_get_value(GPIO_USB_BOOT_EN_REV06)); + pr_info("[MSM(%d)] <%s> USB_BOOT_EN:[%d]\n", system_rev, + __func__, gpio_get_value(GPIO_USB_BOOT_EN_REV06)); + + gpio_direction_output(GPIO_BOOT_SW_SEL, 0); + s3c_gpio_setpull(GPIO_BOOT_SW_SEL, S3C_GPIO_PULL_NONE); + gpio_set_value(GPIO_BOOT_SW_SEL, 0); + + gpio_direction_output(GPIO_BOOT_SW_SEL_REV06, 0); + s3c_gpio_setpull(GPIO_BOOT_SW_SEL_REV06, S3C_GPIO_PULL_NONE); + gpio_set_value(GPIO_BOOT_SW_SEL_REV06, 0); + + msleep(100); + + gpio_direction_output(GPIO_BOOT_SW_SEL, 1); + gpio_set_value(GPIO_BOOT_SW_SEL, 1); + + pr_info("[MSM] <%s> BOOT_SW_SEL : [%d]\n", __func__, + gpio_get_value(GPIO_BOOT_SW_SEL)); + + gpio_direction_output(GPIO_BOOT_SW_SEL_REV06, 1); + gpio_set_value(GPIO_BOOT_SW_SEL_REV06, 1); + + pr_info("[MSM(%d)] <%s> BOOT_SW_SEL : [%d]\n", system_rev, + __func__, gpio_get_value(GPIO_BOOT_SW_SEL_REV06)); } else { /* system_rev>11 */ gpio_direction_output(GPIO_USB_BOOT_EN_REV06, 0); s3c_gpio_setpull(GPIO_USB_BOOT_EN_REV06, S3C_GPIO_PULL_NONE); gpio_set_value(GPIO_USB_BOOT_EN_REV06, 0); + gpio_direction_output(GPIO_BOOT_SW_SEL_REV06, 0); + s3c_gpio_setpull(GPIO_BOOT_SW_SEL_REV06, S3C_GPIO_PULL_NONE); + gpio_set_value(GPIO_BOOT_SW_SEL_REV06, 0); + + msleep(100); + gpio_direction_output(GPIO_USB_BOOT_EN_REV06, 1); gpio_set_value(GPIO_USB_BOOT_EN_REV06, 1); pr_info("[MSM] <%s> USB_BOOT_EN:[%d]\n", __func__, gpio_get_value(GPIO_USB_BOOT_EN_REV06)); - } - - gpio_direction_output(mc->gpio_flm_uart_sel, 0); - s3c_gpio_setpull(mc->gpio_flm_uart_sel, S3C_GPIO_PULL_NONE); - gpio_set_value(mc->gpio_flm_uart_sel, 0); - - gpio_direction_output(mc->gpio_flm_uart_sel, 1); - gpio_set_value(mc->gpio_flm_uart_sel, 1); + gpio_direction_output(GPIO_BOOT_SW_SEL_REV06, 1); + gpio_set_value(GPIO_BOOT_SW_SEL_REV06, 1); pr_info("[MSM] <%s> BOOT_SW_SEL : [%d]\n", __func__, - gpio_get_value(mc->gpio_flm_uart_sel)); + gpio_get_value(GPIO_BOOT_SW_SEL_REV06)); + + } mc->iod->modem_state_changed(mc->iod, STATE_BOOTING); @@ -405,11 +538,22 @@ static int mdm6600_boot_off(struct modem_ctl *mc) { pr_info("[MSM] <%s>\n", __func__); - if (!mc->gpio_flm_uart_sel || !mc->gpio_flm_uart_sel_rev06) { + if (!mc->gpio_flm_uart_sel +#if defined(CONFIG_MACH_M0_CTC) + || !mc->gpio_flm_uart_sel_rev06 +#endif + ) { pr_err("[MSM] no gpio data\n"); return -ENXIO; } +#if defined(CONFIG_MACH_M0_DUOSCTC) || defined(CONFIG_MACH_T0_CHN_CTC) + mdm6600_vbus_off(); +#elif defined(CONFIG_MACH_M0_GRANDECTC) + if (system_rev >= 14) + mdm6600_vbus_off(); +#endif + if (system_rev < 11) { gpio_direction_output(GPIO_USB_BOOT_EN, 0); s3c_gpio_setpull(GPIO_USB_BOOT_EN, S3C_GPIO_PULL_NONE); @@ -422,19 +566,23 @@ static int mdm6600_boot_off(struct modem_ctl *mc) gpio_direction_output(GPIO_USB_BOOT_EN, 0); s3c_gpio_setpull(GPIO_USB_BOOT_EN, S3C_GPIO_PULL_NONE); gpio_set_value(GPIO_USB_BOOT_EN, 0); - gpio_direction_output(GPIO_USB_BOOT_EN_REV06, 0); - s3c_gpio_setpull(GPIO_USB_BOOT_EN_REV06, S3C_GPIO_PULL_NONE); - gpio_set_value(GPIO_USB_BOOT_EN_REV06, 0); gpio_direction_output(GPIO_BOOT_SW_SEL, 0); s3c_gpio_setpull(GPIO_BOOT_SW_SEL, S3C_GPIO_PULL_NONE); gpio_set_value(GPIO_BOOT_SW_SEL, 0); +#if defined(CONFIG_MACH_M0_CTC) + gpio_direction_output(GPIO_USB_BOOT_EN_REV06, 0); + s3c_gpio_setpull(GPIO_USB_BOOT_EN_REV06, S3C_GPIO_PULL_NONE); + gpio_set_value(GPIO_USB_BOOT_EN_REV06, 0); + gpio_direction_output(GPIO_BOOT_SW_SEL_REV06, 0); s3c_gpio_setpull(GPIO_BOOT_SW_SEL_REV06, S3C_GPIO_PULL_NONE); gpio_set_value(GPIO_BOOT_SW_SEL_REV06, 0); +#endif } else { /* system_rev>11 */ +#if defined(CONFIG_MACH_M0_CTC) gpio_direction_output(GPIO_USB_BOOT_EN_REV06, 0); s3c_gpio_setpull(GPIO_USB_BOOT_EN_REV06, S3C_GPIO_PULL_NONE); gpio_set_value(GPIO_USB_BOOT_EN_REV06, 0); @@ -442,9 +590,10 @@ static int mdm6600_boot_off(struct modem_ctl *mc) gpio_direction_output(GPIO_BOOT_SW_SEL_REV06, 0); s3c_gpio_setpull(GPIO_BOOT_SW_SEL_REV06, S3C_GPIO_PULL_NONE); gpio_set_value(GPIO_BOOT_SW_SEL_REV06, 0); - +#endif } +#if defined(CONFIG_MACH_M0_CTC) if (max7693_muic_cp_usb_state()) { msleep(30); gpio_direction_output(GPIO_USB_BOOT_EN, 1); @@ -454,8 +603,29 @@ static int mdm6600_boot_off(struct modem_ctl *mc) s3c_gpio_setpull(GPIO_USB_BOOT_EN_REV06, S3C_GPIO_PULL_NONE); gpio_set_value(GPIO_USB_BOOT_EN_REV06, 1); } +#endif + + gpio_set_value(GPIO_BOOT_SW_SEL, 0); + + return 0; +} + + +static int mdm6600_force_crash_exit(struct modem_ctl *mc) +{ + pr_info("[MSM] <%s>\n", __func__); + + if (!mc->gpio_cp_reset || !mc->gpio_cp_on) { + pr_err("[MSM] no gpio data\n"); + return -ENXIO; + } + + s3c_gpio_cfgpin(mc->gpio_cp_dump_int, S3C_GPIO_OUTPUT); + gpio_direction_output(mc->gpio_cp_dump_int, 1); - gpio_set_value(mc->gpio_flm_uart_sel, 0); + gpio_set_value(mc->gpio_cp_reset, 0); + gpio_set_value(mc->gpio_cp_on, 0); + gpio_set_value(mc->gpio_cp_reset, 1); return 0; } @@ -466,16 +636,20 @@ static irqreturn_t phone_active_irq_handler(int irq, void *arg) int phone_reset = 0; int phone_active = 0; int phone_state = 0; + int cp_dump_int = 0; - if (!mc->gpio_cp_reset || !mc->gpio_phone_active) { + if (!mc->gpio_cp_reset || + !mc->gpio_phone_active || !mc->gpio_cp_dump_int) { pr_err("[MSM] no gpio data\n"); return IRQ_HANDLED; } phone_reset = gpio_get_value(mc->gpio_cp_reset); phone_active = gpio_get_value(mc->gpio_phone_active); - pr_info("[MSM] <%s> phone_reset = %d, phone_active = %d\n", - __func__, phone_reset, phone_active); + cp_dump_int = gpio_get_value(mc->gpio_cp_dump_int); + + pr_info("[MSM] <%s> phone_reset=%d, phone_active=%d, cp_dump_int=%d\n", + __func__, phone_reset, phone_active, cp_dump_int); if (phone_reset && phone_active) { phone_state = STATE_ONLINE; @@ -483,7 +657,10 @@ static irqreturn_t phone_active_irq_handler(int irq, void *arg) mc->iod->modem_state_changed(mc->iod, phone_state); } else if (phone_reset && !phone_active) { if (mc->phone_state == STATE_ONLINE) { - phone_state = STATE_CRASH_EXIT; + if (cp_dump_int) + phone_state = STATE_CRASH_EXIT; + else + phone_state = STATE_CRASH_RESET; if (mc->iod && mc->iod->modem_state_changed) mc->iod->modem_state_changed(mc->iod, phone_state); @@ -504,6 +681,22 @@ static irqreturn_t phone_active_irq_handler(int irq, void *arg) return IRQ_HANDLED; } +#if defined(CONFIG_SIM_DETECT) +static irqreturn_t sim_detect_irq_handler(int irq, void *_mc) +{ + struct modem_ctl *mc = (struct modem_ctl *)_mc; + + pr_info("[MSM] <%s> gpio_sim_detect = %d\n", + __func__, gpio_get_value(mc->gpio_sim_detect)); + + if (mc->iod && mc->iod->sim_state_changed) + mc->iod->sim_state_changed(mc->iod, + !gpio_get_value(mc->gpio_sim_detect)); + + return IRQ_HANDLED; +} +#endif + static void mdm6600_get_ops(struct modem_ctl *mc) { mc->ops.modem_on = mdm6600_on; @@ -511,6 +704,7 @@ static void mdm6600_get_ops(struct modem_ctl *mc) mc->ops.modem_reset = mdm6600_reset; mc->ops.modem_boot_on = mdm6600_boot_on; mc->ops.modem_boot_off = mdm6600_boot_off; + mc->ops.modem_force_crash_exit = mdm6600_force_crash_exit; } int mdm6600_init_modemctl_device(struct modem_ctl *mc, struct modem_data *pdata) @@ -525,10 +719,15 @@ int mdm6600_init_modemctl_device(struct modem_ctl *mc, struct modem_data *pdata) mc->gpio_phone_active = pdata->gpio_phone_active; mc->gpio_cp_dump_int = pdata->gpio_cp_dump_int; mc->gpio_flm_uart_sel = pdata->gpio_flm_uart_sel; -#if 1 +#if defined(CONFIG_MACH_M0_CTC) mc->gpio_flm_uart_sel_rev06 = pdata->gpio_flm_uart_sel_rev06; #endif mc->gpio_cp_warm_reset = pdata->gpio_cp_warm_reset; + mc->gpio_sim_detect = pdata->gpio_sim_detect; + +#if defined(CONFIG_LINK_DEVICE_PLD) + mc->gpio_fpga_cs_n = pdata->gpio_fpga2_cs_n; +#endif gpio_set_value(mc->gpio_cp_reset, 0); gpio_set_value(mc->gpio_cp_on, 0); @@ -557,6 +756,36 @@ int mdm6600_init_modemctl_device(struct modem_ctl *mc, struct modem_data *pdata) return ret; } +#if defined(CONFIG_SIM_DETECT) + mc->irq_sim_detect = platform_get_irq_byname(pdev, "sim_irq"); + pr_info("[MSM] <%s> SIM_DECTCT IRQ# = %d\n", + __func__, mc->irq_sim_detect); + + if (mc->irq_sim_detect) { + ret = request_irq(mc->irq_sim_detect, sim_detect_irq_handler, + IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, + "msm_sim_detect", mc); + if (ret) { + mif_err("[MSM] failed to request_irq: %d\n", ret); + mc->sim_state.online = false; + mc->sim_state.changed = false; + return ret; + } + + ret = enable_irq_wake(mc->irq_sim_detect); + if (ret) { + mif_err("[MSM] failed to enable_irq_wake: %d\n", ret); + free_irq(mc->irq_sim_detect, mc); + mc->sim_state.online = false; + mc->sim_state.changed = false; + return ret; + } + + /* initialize sim_state => insert: gpio=0, remove: gpio=1 */ + mc->sim_state.online = !gpio_get_value(mc->gpio_sim_detect); + } +#endif + return ret; } #endif |