Esempio n. 1
0
static void mdm_status_fn(struct work_struct *work)
{
	struct mdm_ctrl *mdm =
		container_of(work, struct mdm_ctrl, mdm_status_work);
	struct device *dev = mdm->dev;
	int value = gpio_get_value(MDM_GPIO(mdm, MDM2AP_STATUS));

	dev_info(dev, "%s: status:%d\n", __func__, value);
	/* Update gpio configuration to "running" config. */
	mdm_update_gpio_configs(mdm, GPIO_UPDATE_RUNNING_CONFIG);
}
Esempio n. 2
0
static void mdm_status_fn(struct work_struct *work)
{
	int value = gpio_get_value(mdm_drv->mdm2ap_status_gpio);

	pr_debug("%s: status:%d\n", __func__, value);
	if (mdm_drv->mdm_ready && mdm_drv->ops->status_cb)
		mdm_drv->ops->status_cb(mdm_drv, value);

	/* Update gpio configuration to "running" config. */
	mdm_update_gpio_configs(GPIO_UPDATE_RUNNING_CONFIG);
}
static void mdm_status_fn(struct work_struct *work)
{
	struct mdm_ctrl *mdm =
		container_of(work, struct mdm_ctrl, mdm_status_work);
	struct device *dev = mdm->dev;
	int value = gpio_get_value(MDM_GPIO(mdm, MDM2AP_STATUS));

	dev_info(dev, "%s: status:%d\n", __func__, value);
#if defined(CONFIG_MDM_HSIC_PM)
	request_active_lock_set(rmnet_pm_dev);
#endif
	/* Update gpio configuration to "running" config. */
	mdm_update_gpio_configs(mdm, GPIO_UPDATE_RUNNING_CONFIG);
}
Esempio n. 4
0
static void mdm_notify(enum esoc_notify notify, struct esoc_clink *esoc)
{
	bool status_down;
	uint64_t timeout;
	uint64_t now;
	struct mdm_ctrl *mdm = get_esoc_clink_data(esoc);
	struct device *dev = mdm->dev;

	switch (notify) {
	case ESOC_IMG_XFER_DONE:
		dev_info(dev, "%s ESOC_IMG_XFER_DONE\n", __func__);
		if (gpio_get_value(MDM_GPIO(mdm, MDM2AP_STATUS)) ==  0)
			schedule_delayed_work(&mdm->mdm2ap_status_check_work,
				msecs_to_jiffies(MDM2AP_STATUS_TIMEOUT_MS));
		break;
	case ESOC_BOOT_DONE:
		esoc_clink_evt_notify(ESOC_RUN_STATE, esoc);
		break;
	case ESOC_IMG_XFER_RETRY:
		mdm->init = 1;
		mdm_toggle_soft_reset(mdm);
		break;
	case ESOC_IMG_XFER_FAIL:
		esoc_clink_evt_notify(ESOC_BOOT_FAIL, esoc);
		break;
	case ESOC_UPGRADE_AVAILABLE:
		break;
	case ESOC_DEBUG_DONE:
		mdm->debug_fail = false;
		mdm_update_gpio_configs(mdm, GPIO_UPDATE_BOOTING_CONFIG);
		complete(&mdm->debug_done);
		break;
	case ESOC_DEBUG_FAIL:
		mdm->debug_fail = true;
		complete(&mdm->debug_done);
		break;
	case ESOC_PRIMARY_CRASH:
		mdm_disable_irqs(mdm);
		status_down = false;
		dev_info(dev, "signal apq err fatal for graceful restart\n");
		gpio_set_value(MDM_GPIO(mdm, AP2MDM_ERRFATAL), 1);
		timeout = local_clock();
		do_div(timeout, NSEC_PER_MSEC);
		timeout += MDM_MODEM_TIMEOUT;
		do {
			if (gpio_get_value(MDM_GPIO(mdm,
						MDM2AP_STATUS)) == 0) {
				status_down = true;
				break;
			}
			now = local_clock();
			do_div(now, NSEC_PER_MSEC);
		} while (!time_after64(now, timeout));

		if (!status_down) {
			dev_err(mdm->dev, "%s MDM2AP status did not go low\n",
								__func__);
			gpio_direction_output(MDM_GPIO(mdm, AP2MDM_SOFT_RESET),
					      !!mdm->soft_reset_inverted);
			/*
			 * allow PS hold assert to be detected.
			 * pmic requires 6ms for crash reset case.
			 */
			mdelay(6);
			gpio_direction_output(MDM_GPIO(mdm, AP2MDM_SOFT_RESET),
					      !mdm->soft_reset_inverted);
		}
		break;
	case ESOC_PRIMARY_REBOOT:
		dev_info(mdm->dev, "Triggering mdm cold reset");
		mdm->ready = 0;
		gpio_direction_output(MDM_GPIO(mdm, AP2MDM_SOFT_RESET),
				!!mdm->soft_reset_inverted);
		mdelay(300);
		gpio_direction_output(MDM_GPIO(mdm, AP2MDM_SOFT_RESET),
				!mdm->soft_reset_inverted);
		break;
	};
	return;
}
Esempio n. 5
0
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;
}
static void mdm_notify(enum esoc_notify notify, struct esoc_clink *esoc)
{
	bool status_down;
	uint64_t timeout;
	uint64_t now;
	struct mdm_ctrl *mdm = get_esoc_clink_data(esoc);
	struct device *dev = mdm->dev;
	int ret;
	int max_spin = 20;

	switch (notify) {
	case ESOC_IMG_XFER_DONE:
		dev_info(dev, "%s ESOC_IMG_XFER_DONE\n", __func__);
		if (gpio_get_value(MDM_GPIO(mdm, MDM2AP_STATUS)) ==  0)
			schedule_delayed_work(&mdm->mdm2ap_status_check_work,
				msecs_to_jiffies(MDM2AP_STATUS_TIMEOUT_MS));
		break;
	case ESOC_BOOT_DONE:
		esoc_clink_evt_notify(ESOC_RUN_STATE, esoc);
		break;
	case ESOC_IMG_XFER_RETRY:
		mdm->init = 1;
		mdm_toggle_soft_reset(mdm);
		break;
	case ESOC_IMG_XFER_FAIL:
		esoc_clink_evt_notify(ESOC_INVALID_STATE, esoc);
		break;
	case ESOC_BOOT_FAIL:
		esoc_clink_evt_notify(ESOC_INVALID_STATE, esoc);
		break;
	case ESOC_UPGRADE_AVAILABLE:
		break;
	case ESOC_DEBUG_DONE:
		mdm->debug_fail = false;
		mdm_update_gpio_configs(mdm, GPIO_UPDATE_BOOTING_CONFIG);
		complete(&mdm->debug_done);
		break;
	case ESOC_DEBUG_FAIL:
		mdm->debug_fail = true;
		complete(&mdm->debug_done);
		break;
	case ESOC_PRIMARY_CRASH:
		mdm_disable_irqs(mdm);
		status_down = false;
		dev_info(dev, "signal apq err fatal for graceful restart\n");
		gpio_set_value(MDM_GPIO(mdm, AP2MDM_ERRFATAL), 1);
		gpio_set_value(MDM_GPIO(mdm, AP2MDM_VDDMIN), 1);
		timeout = local_clock();
		do_div(timeout, NSEC_PER_MSEC);
		timeout += MDM_MODEM_TIMEOUT;
		do {
			if (gpio_get_value(MDM_GPIO(mdm,
						MDM2AP_STATUS)) == 0) {
				status_down = true;
				break;
			}
			now = local_clock();
			do_div(now, NSEC_PER_MSEC);
		} while (!time_after64(now, timeout));

		if (!status_down) {
			dev_err(mdm->dev, "%s MDM2AP status did not go low\n",
								__func__);
			gpio_direction_output(MDM_GPIO(mdm, AP2MDM_SOFT_RESET),
					      !!mdm->soft_reset_inverted);
			/*
			 * allow PS hold assert to be detected.
			 * pmic requires 6ms for crash reset case.
			 */
			mdelay(6);
			gpio_direction_output(MDM_GPIO(mdm, AP2MDM_SOFT_RESET),
					      !mdm->soft_reset_inverted);
		}
		break;
	case ESOC_PRIMARY_REBOOT:
		exynos_pcie_disable_irq(0);
		mdm_disable_irqs(mdm);
		dev_info(mdm->dev, "Triggering mdm cold reset");
		mdm->ready = 0;
		while (gpio_get_value(MDM_GPIO(mdm, MDM2AP_STATUS)) && max_spin--) {
			msleep(100);
			dev_info(mdm->dev, "gpio_get_value(MDM2AP_STATUS) : %d\n",
					gpio_get_value(MDM_GPIO(mdm, MDM2AP_STATUS)));
		}
		gpio_direction_output(MDM_GPIO(mdm, AP2MDM_SOFT_RESET),
				!!mdm->soft_reset_inverted);
		mdelay(300);
		gpio_direction_output(MDM_GPIO(mdm, AP2MDM_SOFT_RESET),
				!mdm->soft_reset_inverted);
		break;
	case ESOC_DIAG_DISABLE:
		dev_info(mdm->dev, "Send diag_disable noti\n");
		ret = sysmon_send_diag_disable_noti(mdm->sysmon_subsys_id);
		if (ret < 0)
			dev_err(mdm->dev, "sending diag_disable noti is failed, ret = %d\n", ret);
		else
			dev_info(mdm->dev, "sending diag_disable noti is succeed.\n");
		break;
	case ESOC_FORCE_CPCRASH:
		dev_err(mdm->dev, "Force CP Crash\n");
		gpio_set_value(MDM_GPIO(mdm, AP2MDM_ERRFATAL), 1);
		gpio_set_value(MDM_GPIO(mdm, AP2MDM_VDDMIN), 1);
		break;
	case ESOC_CP_SILENT_RESET:
		dev_err(mdm->dev, "Force CP Silent Reset\n");
		set_silent_reset();
		gpio_set_value(MDM_GPIO(mdm, AP2MDM_ERRFATAL), 1);
		gpio_set_value(MDM_GPIO(mdm, AP2MDM_VDDMIN), 1);
		break;
	};
	return;
}