long mdm_modem_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { int status, ret = 0; if (_IOC_TYPE(cmd) != CHARM_CODE) { pr_err("%s: invalid ioctl code\n", __func__); return -EINVAL; } pr_debug("%s: Entering ioctl cmd = %d\n", __func__, _IOC_NR(cmd)); switch (cmd) { case WAKE_CHARM: pr_info("%s: Powering on mdm\n", __func__); mdm_drv->ops->power_on_mdm_cb(mdm_drv); break; case CHECK_FOR_BOOT: if (gpio_get_value(mdm_drv->mdm2ap_status_gpio) == 0) put_user(1, (unsigned long __user *) arg); else put_user(0, (unsigned long __user *) arg); break; case NORMAL_BOOT_DONE: pr_debug("%s: check if mdm is booted up\n", __func__); get_user(status, (unsigned long __user *) arg); if (status) { pr_debug("%s: normal boot failed\n", __func__); mdm_drv->mdm_boot_status = -EIO; } else { pr_info("%s: normal boot done\n", __func__); mdm_drv->mdm_boot_status = 0; } mdm_drv->mdm_ready = 1; if (mdm_drv->ops->normal_boot_done_cb != NULL) mdm_drv->ops->normal_boot_done_cb(mdm_drv); if (!first_boot) complete(&mdm_boot); else first_boot = 0; /* Start a timer to check that the mdm2ap_status gpio * goes high. */ if (gpio_get_value(mdm_drv->mdm2ap_status_gpio) == 0) schedule_delayed_work(&mdm2ap_status_check_work, msecs_to_jiffies(MDM2AP_STATUS_TIMEOUT_MS)); break; case RAM_DUMP_DONE: pr_debug("%s: mdm done collecting RAM dumps\n", __func__); get_user(status, (unsigned long __user *) arg); if (status) mdm_drv->mdm_ram_dump_status = -EIO; else { pr_info("%s: ramdump collection completed\n", __func__); mdm_drv->mdm_ram_dump_status = 0; } complete(&mdm_ram_dumps); break; case WAIT_FOR_RESTART: pr_debug("%s: wait for mdm to need images reloaded\n", __func__); ret = wait_for_completion_interruptible(&mdm_needs_reload); if (!ret) put_user(mdm_drv->boot_type, (unsigned long __user *) arg); INIT_COMPLETION(mdm_needs_reload); break; case GET_DLOAD_STATUS: pr_debug("getting status of mdm2ap_errfatal_gpio\n"); if (gpio_get_value(mdm_drv->mdm2ap_errfatal_gpio) == 1 && !mdm_drv->mdm_ready) put_user(1, (unsigned long __user *) arg); else put_user(0, (unsigned long __user *) arg); break; case SHUTDOWN_CHARM: if (!mdm_drv->pdata->send_shdn) break; mdm_drv->mdm_ready = 0; if (mdm_debug_mask & MDM_DEBUG_MASK_SHDN_LOG) pr_info("Sending shutdown request to mdm\n"); ret = sysmon_send_shutdown(SYSMON_SS_EXT_MODEM); if (ret) pr_err("%s: Graceful shutdown of the external modem failed, ret = %d\n", __func__, ret); put_user(ret, (unsigned long __user *) arg); break; default: pr_err("%s: invalid ioctl cmd = %d\n", __func__, _IOC_NR(cmd)); ret = -EINVAL; break; } return ret; }
static int mdm_cmd_exe(enum esoc_cmd cmd, struct esoc_clink *esoc) { int ret; unsigned long end_time; bool status_down = false; struct mdm_ctrl *mdm = get_esoc_clink_data(esoc); struct device *dev = mdm->dev; switch (cmd) { case ESOC_PWR_ON: gpio_set_value(MDM_GPIO(mdm, AP2MDM_ERRFATAL), 0); mdm_enable_irqs(mdm); mdm->init = 1; mdm_do_first_power_on(mdm); break; case ESOC_PWR_OFF: mdm_disable_irqs(mdm); mdm->debug = 0; mdm->ready = false; ret = sysmon_send_shutdown(mdm->sysmon_subsys_id); device_lock(dev); if (ret) dev_err(mdm->dev, "Graceful shutdown fail, ret = %d\n", ret); else { dev_info(mdm->dev, "Waiting for status gpio go low\n"); status_down = false; end_time = jiffies + msecs_to_jiffies(10000); while (time_before(jiffies, end_time)) { if (gpio_get_value(MDM_GPIO(mdm, MDM2AP_STATUS)) == 0) { dev_dbg(dev, "Status went low\n"); status_down = true; break; } msleep(100); } if (status_down) dev_info(dev, "shutdown successful\n"); else dev_err(mdm->dev, "graceful poff ipc fail\n"); } /* * Force a shutdown of the mdm. This is required in order * to prevent the mdm from immediately powering back on * after the shutdown */ gpio_set_value(MDM_GPIO(mdm, AP2MDM_STATUS), 0); esoc_clink_queue_request(ESOC_REQ_SHUTDOWN, esoc); mdm_power_down(mdm); mdm_update_gpio_configs(mdm, GPIO_UPDATE_BOOTING_CONFIG); device_unlock(dev); break; case ESOC_RESET: mdm_toggle_soft_reset(mdm); break; case ESOC_PREPARE_DEBUG: /* * disable all irqs except request irq (pblrdy) * force a reset of the mdm by signaling * an APQ crash, wait till mdm is ready for ramdumps. */ mdm->ready = false; cancel_delayed_work(&mdm->mdm2ap_status_check_work); gpio_set_value(MDM_GPIO(mdm, AP2MDM_ERRFATAL), 1); dev_info(mdm->dev, "set ap2mdm errfatal to force reset\n"); msleep(mdm->ramdump_delay_ms); break; case ESOC_EXE_DEBUG: mdm->debug = 1; mdm_toggle_soft_reset(mdm); /* * wait for ramdumps to be collected * then power down the mdm and switch gpios to booting * config */ if (!wait_for_completion_timeout(&mdm->debug_done, msecs_to_jiffies(mdm->dump_timeout_ms))) { dev_err(mdm->dev, "ramdump collection timedout\n"); mdm->debug = 0; return -ETIMEDOUT; } if (mdm->debug_fail) { dev_err(mdm->dev, "unable to collect ramdumps\n"); mdm->debug = 0; return -EIO; } dev_dbg(mdm->dev, "ramdump collection done\n"); mdm->debug = 0; init_completion(&mdm->debug_done); break; case ESOC_EXIT_DEBUG: /* * Deassert APQ to mdm err fatal * Power on the mdm */ gpio_set_value(MDM_GPIO(mdm, AP2MDM_ERRFATAL), 0); dev_dbg(mdm->dev, "exiting debug state after power on\n"); mdm->get_restart_reason = true; break; default: return -EINVAL; }; return 0; }
long qsc_modem_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { int status, ret = 0, retry = 0; if (_IOC_TYPE(cmd) != CHARM_CODE) { pr_err("%s: invalid ioctl code\n", __func__); return -EINVAL; } pr_debug("%s: Entering ioctl cmd = %d\n", __func__, _IOC_NR(cmd)); switch (cmd) { case WAKE_CHARM: if( qsc_bootup_state == QSC_BOOT_MDM_BOOTLOAER_IRQ_REGISTERED || qsc_bootup_state == QSC_BOOT_MDM_BOOTLOAER_IRQ_RECEIVED ) { do { retry++; ret = wait_for_completion_interruptible_timeout(&qsc_boot_after_mdm_booloader_irq, msecs_to_jiffies(10000)); } while ( ret == -ERESTARTSYS && retry <= 3); /* interrupted, need retry */ } if( qsc_bootup_state == QSC_BOOT_MDM_BOOTLOAER_IRQ_RECEIVED || qsc_bootup_state == QSC_BOOT_MDM_BOOTLOAER_IRQ_BOOTED ) { retry = 0; while( qsc_bootup_state != QSC_BOOT_MDM_BOOTLOAER_IRQ_BOOTED && retry < QSC_POWON_MDM_HELPER_DELAY_TIMES ) { retry++; msleep(QSC_POWON_MDM_HELPER_DELAY_INTERVAL_MS); } if( qsc_bootup_state == QSC_BOOT_MDM_BOOTLOAER_IRQ_RECEIVED ) { pr_err("%s: QSC boot by mdm bootloader irq took too long time.\n", __func__); } else { pr_info("%s: QSC has been booted by mdm bootloader irq.\n", __func__); } } else { qsc_bootup_state = QSC_BOOT_MDM_HELPER_BOOTING; pr_info("%s: Powering on qsc by WAKE_CHARM\n", __func__); mdm_drv->ops->power_on_mdm_cb(mdm_drv); qsc_bootup_state = QSC_BOOT_MDM_HELPER_BOOTED; } INIT_COMPLETION(qsc_boot_after_mdm_booloader_irq); break; case CHECK_FOR_BOOT: if (gpio_get_value(mdm_drv->mdm2ap_status_gpio) == 0) put_user(1, (unsigned long __user *) arg); else put_user(0, (unsigned long __user *) arg); break; case NORMAL_BOOT_DONE: pr_debug("%s: check if qsc is booted up\n", __func__); get_user(status, (unsigned long __user *) arg); if (status) { pr_debug("%s: normal boot failed\n", __func__); mdm_drv->mdm_boot_status = -EIO; } else { pr_info("%s: normal boot done\n", __func__); mdm_drv->mdm_boot_status = 0; } mdm_drv->mdm_ready = 1; if (mdm_drv->ops->normal_boot_done_cb != NULL) mdm_drv->ops->normal_boot_done_cb(mdm_drv); if (!first_boot) complete(&qsc_boot); else first_boot = 0; /* If successful, start a timer to check that the mdm2ap_status * gpio goes high. */ if (!status && gpio_get_value(mdm_drv->mdm2ap_status_gpio) == 0) schedule_delayed_work(&qsc2ap_status_check_work, msecs_to_jiffies(MDM2AP_STATUS_TIMEOUT_MS)); break; case RAM_DUMP_DONE: pr_debug("%s: qsc done collecting RAM dumps\n", __func__); get_user(status, (unsigned long __user *) arg); if (status) mdm_drv->mdm_ram_dump_status = -EIO; else { pr_info("%s: ramdump collection completed\n", __func__); mdm_drv->mdm_ram_dump_status = 0; } complete(&qsc_ram_dumps); break; case WAIT_FOR_RESTART: pr_debug("%s: wait for qsc to need images reloaded\n", __func__); ret = wait_for_completion_interruptible(&qsc_needs_reload); if (!ret) put_user(mdm_drv->boot_type, (unsigned long __user *) arg); INIT_COMPLETION(qsc_needs_reload); break; case FORCE_DLOAD: pr_info("%s: Force QSC enter DLOAD.\n", __func__); if( gpio_get_value(mdm_drv->mdm2ap_vddmin_gpio) ) { pr_info("%s: HW Reset case, QSC already in Dload mode.\n", __func__); print_qsc_gpio(); } else { gpio_direction_output(mdm_drv->ap2mdm_vddmin_gpio, 1); print_qsc_gpio(); mdm_drv->ops->atomic_reset_mdm_cb(mdm_drv); mdelay(10); } break; case GET_DLOAD_STATUS: pr_debug("getting status of qsc2ap_errfatal_gpio\n"); if (gpio_get_value(mdm_drv->mdm2ap_errfatal_gpio) == 1 && !mdm_drv->mdm_ready) put_user(1, (unsigned long __user *) arg); else put_user(0, (unsigned long __user *) arg); break; case IMAGE_UPGRADE: pr_debug("%s Image upgrade ioctl recieved\n", __func__); if (mdm_drv->pdata->image_upgrade_supported && mdm_drv->ops->image_upgrade_cb) { get_user(status, (unsigned long __user *) arg); mdm_drv->ops->image_upgrade_cb(mdm_drv, status); } else pr_debug("%s Image upgrade not supported\n", __func__); break; case SHUTDOWN_CHARM: if (!mdm_drv->pdata->send_shdn) break; mdm_drv->mdm_ready = 0; if (qsc_debug_mask & MDM_DEBUG_MASK_SHDN_LOG) pr_info("Sending shutdown request to mdm\n"); ret = sysmon_send_shutdown(SYSMON_SS_EXT_MODEM); if (ret) pr_err("%s: Graceful shutdown of the external modem failed, ret = %d\n", __func__, ret); break; default: pr_err("%s: invalid ioctl cmd = %d\n", __func__, _IOC_NR(cmd)); ret = -EINVAL; break; } return ret; }