Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 117b43f3 authored by qctecmdr Service's avatar qctecmdr Service Committed by Gerrit - the friendly Code Review server
Browse files

Merge "esoc: Add IPC logging support"

parents aad1c5d0 52cf7a40
Loading
Loading
Loading
Loading
+107 −5
Original line number Original line Diff line number Diff line
@@ -55,6 +55,8 @@ static const int required_gpios[] = {
	AP2MDM_STATUS,
	AP2MDM_STATUS,
};
};


void *ipc_log;

static void mdm_debug_gpio_show(struct mdm_ctrl *mdm)
static void mdm_debug_gpio_show(struct mdm_ctrl *mdm)
{
{
	struct device *dev = mdm->dev;
	struct device *dev = mdm->dev;
@@ -83,10 +85,25 @@ static void mdm_debug_gpio_show(struct mdm_ctrl *mdm)
			 __func__, MDM_GPIO(mdm, MDM2AP_VDDMIN));
			 __func__, MDM_GPIO(mdm, MDM2AP_VDDMIN));
}
}


static void mdm_debug_gpio_ipc_log(struct mdm_ctrl *mdm)
{
	esoc_mdm_log("MDM2AP_ERRFATAL gpio = %d\n",
			MDM_GPIO(mdm, MDM2AP_ERRFATAL));
	esoc_mdm_log("AP2MDM_ERRFATAL gpio = %d\n",
			MDM_GPIO(mdm, AP2MDM_ERRFATAL));
	esoc_mdm_log("MDM2AP_STATUS gpio = %d\n",
			MDM_GPIO(mdm, MDM2AP_STATUS));
	esoc_mdm_log("AP2MDM_STATUS gpio = %d\n",
			MDM_GPIO(mdm, AP2MDM_STATUS));
	esoc_mdm_log("AP2MDM_SOFT_RESET gpio = %d\n",
			MDM_GPIO(mdm, AP2MDM_SOFT_RESET));
}

static void mdm_enable_irqs(struct mdm_ctrl *mdm)
static void mdm_enable_irqs(struct mdm_ctrl *mdm)
{
{
	if (!mdm)
	if (!mdm)
		return;
		return;
	esoc_mdm_log("Enabling the interrupts\n");
	if (mdm->irq_mask & IRQ_ERRFATAL) {
	if (mdm->irq_mask & IRQ_ERRFATAL) {
		enable_irq(mdm->errfatal_irq);
		enable_irq(mdm->errfatal_irq);
		mdm->irq_mask &= ~IRQ_ERRFATAL;
		mdm->irq_mask &= ~IRQ_ERRFATAL;
@@ -105,6 +122,7 @@ void mdm_disable_irqs(struct mdm_ctrl *mdm)
{
{
	if (!mdm)
	if (!mdm)
		return;
		return;
	esoc_mdm_log("Disabling the interrupts\n");
	if (!(mdm->irq_mask & IRQ_ERRFATAL)) {
	if (!(mdm->irq_mask & IRQ_ERRFATAL)) {
		disable_irq_nosync(mdm->errfatal_irq);
		disable_irq_nosync(mdm->errfatal_irq);
		mdm->irq_mask |= IRQ_ERRFATAL;
		mdm->irq_mask |= IRQ_ERRFATAL;
@@ -192,6 +210,7 @@ static int mdm_cmd_exe(enum esoc_cmd cmd, struct esoc_clink *esoc)
				esoc->clink_ops->notify(ESOC_BOOT_DONE, esoc);
				esoc->clink_ops->notify(ESOC_BOOT_DONE, esoc);
			}
			}
		}
		}
		esoc_mdm_log("ESOC_PWR_ON: Setting AP2MDM_ERRFATAL = 0\n");
		gpio_set_value(MDM_GPIO(mdm, AP2MDM_ERRFATAL), 0);
		gpio_set_value(MDM_GPIO(mdm, AP2MDM_ERRFATAL), 0);
		mdm->init = 1;
		mdm->init = 1;
		mdm_do_first_power_on(mdm);
		mdm_do_first_power_on(mdm);
@@ -206,11 +225,17 @@ static int mdm_cmd_exe(enum esoc_cmd cmd, struct esoc_clink *esoc)
			break;
			break;
		graceful_shutdown = true;
		graceful_shutdown = true;
		if (!esoc->userspace_handle_shutdown) {
		if (!esoc->userspace_handle_shutdown) {
			esoc_mdm_log(
			"ESOC_PWR_OFF: sending sysmon-shutdown to modem\n");
			ret = sysmon_send_shutdown(&esoc->subsys);
			ret = sysmon_send_shutdown(&esoc->subsys);
			if (ret) {
			if (ret) {
				esoc_mdm_log(
			"ESOC_PWR_OFF: sysmon-shutdown failed: %d\n", ret);
				dev_err(mdm->dev,
				dev_err(mdm->dev,
				 "sysmon shutdown fail, ret = %d\n", ret);
				 "sysmon shutdown fail, ret = %d\n", ret);
				graceful_shutdown = false;
				graceful_shutdown = false;
				esoc_mdm_log(
			"ESOC_PWR_OFF: forcefully powering-off modem\n");
			}
			}
		} else {
		} else {
			esoc_clink_queue_request(ESOC_REQ_SEND_SHUTDOWN, esoc);
			esoc_clink_queue_request(ESOC_REQ_SEND_SHUTDOWN, esoc);
@@ -236,13 +261,19 @@ static int mdm_cmd_exe(enum esoc_cmd cmd, struct esoc_clink *esoc)
		 * monitored by multiple mdms(might be wrongly interpreted as
		 * monitored by multiple mdms(might be wrongly interpreted as
		 * a primary crash).
		 * a primary crash).
		 */
		 */
		if (esoc->statusline_not_a_powersource == false)
		if (esoc->statusline_not_a_powersource == false) {
			esoc_mdm_log(
			"ESOC_FORCE_PWR_OFF: setting AP2MDM_STATUS = 0\n");
			gpio_set_value(MDM_GPIO(mdm, AP2MDM_STATUS), 0);
			gpio_set_value(MDM_GPIO(mdm, AP2MDM_STATUS), 0);
		}
		esoc_mdm_log(
		"ESOC_FORCE_PWR_OFF: Queueing request: ESOC_REQ_SHUTDOWN\n");
		esoc_clink_queue_request(ESOC_REQ_SHUTDOWN, esoc);
		esoc_clink_queue_request(ESOC_REQ_SHUTDOWN, esoc);
		mdm_power_down(mdm);
		mdm_power_down(mdm);
		mdm_update_gpio_configs(mdm, GPIO_UPDATE_BOOTING_CONFIG);
		mdm_update_gpio_configs(mdm, GPIO_UPDATE_BOOTING_CONFIG);
		break;
		break;
	case ESOC_RESET:
	case ESOC_RESET:
		esoc_mdm_log("ESOC_RESET: Resetting the modem\n");
		mdm_toggle_soft_reset(mdm, false);
		mdm_toggle_soft_reset(mdm, false);
		break;
		break;
	case ESOC_PREPARE_DEBUG:
	case ESOC_PREPARE_DEBUG:
@@ -252,8 +283,12 @@ static int mdm_cmd_exe(enum esoc_cmd cmd, struct esoc_clink *esoc)
		 * an APQ crash, wait till mdm is ready for ramdumps.
		 * an APQ crash, wait till mdm is ready for ramdumps.
		 */
		 */
		mdm->ready = false;
		mdm->ready = false;
		esoc_mdm_log(
		"ESOC_PREPARE_DEBUG: Cancelling the status check work\n");
		cancel_delayed_work(&mdm->mdm2ap_status_check_work);
		cancel_delayed_work(&mdm->mdm2ap_status_check_work);
		if (!mdm->esoc->auto_boot) {
		if (!mdm->esoc->auto_boot) {
			esoc_mdm_log(
			"ESOC_PREPARE_DEBUG: setting AP2MDM_ERRFATAL = 1\n");
			gpio_set_value(MDM_GPIO(mdm, AP2MDM_ERRFATAL), 1);
			gpio_set_value(MDM_GPIO(mdm, AP2MDM_ERRFATAL), 1);
			dev_dbg(mdm->dev,
			dev_dbg(mdm->dev,
				"set ap2mdm errfatal to force reset\n");
				"set ap2mdm errfatal to force reset\n");
@@ -266,6 +301,7 @@ static int mdm_cmd_exe(enum esoc_cmd cmd, struct esoc_clink *esoc)
		if (mdm->skip_restart_for_mdm_crash)
		if (mdm->skip_restart_for_mdm_crash)
			break;
			break;


		esoc_mdm_log("ESOC_EXE_DEBUG: Resetting the modem\n");
		mdm->debug = 1;
		mdm->debug = 1;
		mdm_toggle_soft_reset(mdm, false);
		mdm_toggle_soft_reset(mdm, false);
		/*
		/*
@@ -273,8 +309,12 @@ static int mdm_cmd_exe(enum esoc_cmd cmd, struct esoc_clink *esoc)
		 * then power down the mdm and switch gpios to booting
		 * then power down the mdm and switch gpios to booting
		 * config
		 * config
		 */
		 */
		esoc_mdm_log(
		"ESOC_EXE_DEBUG: Waiting for ramdumps to be collected\n");
		wait_for_completion(&mdm->debug_done);
		wait_for_completion(&mdm->debug_done);
		if (mdm->debug_fail) {
		if (mdm->debug_fail) {
			esoc_mdm_log(
			"ESOC_EXE_DEBUG: Failed to collect the ramdumps\n");
			dev_err(mdm->dev, "unable to collect ramdumps\n");
			dev_err(mdm->dev, "unable to collect ramdumps\n");
			mdm->debug = 0;
			mdm->debug = 0;
			return -EIO;
			return -EIO;
@@ -288,11 +328,13 @@ static int mdm_cmd_exe(enum esoc_cmd cmd, struct esoc_clink *esoc)
		 * Deassert APQ to mdm err fatal
		 * Deassert APQ to mdm err fatal
		 * Power on the mdm
		 * Power on the mdm
		 */
		 */
		esoc_mdm_log("ESOC_EXIT_DEBUG: Setting AP2MDM_ERRFATAL = 0\n");
		gpio_set_value(MDM_GPIO(mdm, AP2MDM_ERRFATAL), 0);
		gpio_set_value(MDM_GPIO(mdm, AP2MDM_ERRFATAL), 0);
		dev_dbg(mdm->dev, "exiting debug state after power on\n");
		dev_dbg(mdm->dev, "exiting debug state after power on\n");
		mdm->get_restart_reason = true;
		mdm->get_restart_reason = true;
		break;
		break;
	default:
	default:
		esoc_mdm_log("Invalid command\n");
		return -EINVAL;
		return -EINVAL;
	};
	};
	return 0;
	return 0;
@@ -306,7 +348,11 @@ static void mdm2ap_status_check(struct work_struct *work)
	struct device *dev = mdm->dev;
	struct device *dev = mdm->dev;
	struct esoc_clink *esoc = mdm->esoc;
	struct esoc_clink *esoc = mdm->esoc;


	esoc_mdm_log(
	"Powerup timer expired after images are transferred to modem\n");

	if (gpio_get_value(MDM_GPIO(mdm, MDM2AP_STATUS)) == 0) {
	if (gpio_get_value(MDM_GPIO(mdm, MDM2AP_STATUS)) == 0) {
		esoc_mdm_log("MDM2AP_STATUS did not go high\n");
		dev_dbg(dev, "MDM2AP_STATUS did not go high\n");
		dev_dbg(dev, "MDM2AP_STATUS did not go high\n");
		esoc_clink_evt_notify(ESOC_UNEXPECTED_RESET, esoc);
		esoc_clink_evt_notify(ESOC_UNEXPECTED_RESET, esoc);
	}
	}
@@ -336,14 +382,17 @@ static void mdm_get_restart_reason(struct work_struct *work)
		ret = sysmon_get_reason(&mdm->esoc->subsys, sfr_buf,
		ret = sysmon_get_reason(&mdm->esoc->subsys, sfr_buf,
							sizeof(sfr_buf));
							sizeof(sfr_buf));
		if (!ret) {
		if (!ret) {
			esoc_mdm_log("restart reason is %s\n", sfr_buf);
			dev_err(dev, "mdm restart reason is %s\n", sfr_buf);
			dev_err(dev, "mdm restart reason is %s\n", sfr_buf);
			break;
			break;
		}
		}
		msleep(SFR_RETRY_INTERVAL);
		msleep(SFR_RETRY_INTERVAL);
	} while (++ntries < SFR_MAX_RETRIES);
	} while (++ntries < SFR_MAX_RETRIES);
	if (ntries == SFR_MAX_RETRIES)
	if (ntries == SFR_MAX_RETRIES) {
		esoc_mdm_log("restart reason not obtained. err: %d\n", ret);
		dev_dbg(dev, "%s: Error retrieving restart reason: %d\n",
		dev_dbg(dev, "%s: Error retrieving restart reason: %d\n",
						__func__, ret);
						__func__, ret);
	}
	mdm->get_restart_reason = false;
	mdm->get_restart_reason = false;
}
}


@@ -355,36 +404,53 @@ static void mdm_notify(enum esoc_notify notify, struct esoc_clink *esoc)
	struct mdm_ctrl *mdm = get_esoc_clink_data(esoc);
	struct mdm_ctrl *mdm = get_esoc_clink_data(esoc);
	struct device *dev = mdm->dev;
	struct device *dev = mdm->dev;


	esoc_mdm_log("Notification: %d\n", notify);

	switch (notify) {
	switch (notify) {
	case ESOC_IMG_XFER_DONE:
	case ESOC_IMG_XFER_DONE:
		if (gpio_get_value(MDM_GPIO(mdm, MDM2AP_STATUS)) ==  0)
		if (gpio_get_value(MDM_GPIO(mdm, MDM2AP_STATUS)) ==  0) {
			esoc_mdm_log(
		"ESOC_IMG_XFER_DONE: Begin timeout of %lu ms for modem_status\n",
			MDM2AP_STATUS_TIMEOUT_MS);
			schedule_delayed_work(&mdm->mdm2ap_status_check_work,
			schedule_delayed_work(&mdm->mdm2ap_status_check_work,
				msecs_to_jiffies(MDM2AP_STATUS_TIMEOUT_MS));
				msecs_to_jiffies(MDM2AP_STATUS_TIMEOUT_MS));
		}
		break;
		break;
	case ESOC_BOOT_DONE:
	case ESOC_BOOT_DONE:
		esoc_mdm_log(
		"ESOC_BOOT_DONE: Sending the notification: ESOC_RUN_STATE\n");
		esoc_clink_evt_notify(ESOC_RUN_STATE, esoc);
		esoc_clink_evt_notify(ESOC_RUN_STATE, esoc);
		break;
		break;
	case ESOC_IMG_XFER_RETRY:
	case ESOC_IMG_XFER_RETRY:
		esoc_mdm_log("ESOC_IMG_XFER_RETRY: Resetting the device\n");
		mdm->init = 1;
		mdm->init = 1;
		mdm_toggle_soft_reset(mdm, false);
		mdm_toggle_soft_reset(mdm, false);
		break;
		break;
	case ESOC_IMG_XFER_FAIL:
	case ESOC_IMG_XFER_FAIL:
		esoc_mdm_log(
		"ESOC_IMG_XFER_FAIL: Send notification: ESOC_INVALID_STATE\n");
		esoc_clink_evt_notify(ESOC_INVALID_STATE, esoc);
		esoc_clink_evt_notify(ESOC_INVALID_STATE, esoc);
		break;
		break;
	case ESOC_BOOT_FAIL:
	case ESOC_BOOT_FAIL:
		esoc_mdm_log(
		"ESOC_BOOT_FAIL: Send notification: ESOC_INVALID_STATE\n");
		esoc_clink_evt_notify(ESOC_INVALID_STATE, esoc);
		esoc_clink_evt_notify(ESOC_INVALID_STATE, esoc);
		break;
		break;
	case ESOC_PON_RETRY:
	case ESOC_PON_RETRY:
		esoc_mdm_log(
		"ESOC_PON_RETRY: Send notification: ESOC_RETRY_PON_EVT\n");
		esoc_clink_evt_notify(ESOC_RETRY_PON_EVT, esoc);
		esoc_clink_evt_notify(ESOC_RETRY_PON_EVT, esoc);
		break;
		break;
	case ESOC_UPGRADE_AVAILABLE:
	case ESOC_UPGRADE_AVAILABLE:
		break;
		break;
	case ESOC_DEBUG_DONE:
	case ESOC_DEBUG_DONE:
		esoc_mdm_log("ESOC_DEBUG_DONE: Ramdumps collection done\n");
		mdm->debug_fail = false;
		mdm->debug_fail = false;
		mdm_update_gpio_configs(mdm, GPIO_UPDATE_BOOTING_CONFIG);
		mdm_update_gpio_configs(mdm, GPIO_UPDATE_BOOTING_CONFIG);
		complete(&mdm->debug_done);
		complete(&mdm->debug_done);
		break;
		break;
	case ESOC_DEBUG_FAIL:
	case ESOC_DEBUG_FAIL:
		esoc_mdm_log("ESOC_DEBUG_FAIL: Ramdumps collection failed\n");
		mdm->debug_fail = true;
		mdm->debug_fail = true;
		complete(&mdm->debug_done);
		complete(&mdm->debug_done);
		break;
		break;
@@ -392,9 +458,13 @@ static void mdm_notify(enum esoc_notify notify, struct esoc_clink *esoc)
		mdm_disable_irqs(mdm);
		mdm_disable_irqs(mdm);
		status_down = false;
		status_down = false;
		dev_dbg(dev, "signal apq err fatal for graceful restart\n");
		dev_dbg(dev, "signal apq err fatal for graceful restart\n");
		esoc_mdm_log(
		"ESOC_PRIMARY_CRASH: Setting AP2MDM_ERRFATAL = 1\n");
		gpio_set_value(MDM_GPIO(mdm, AP2MDM_ERRFATAL), 1);
		gpio_set_value(MDM_GPIO(mdm, AP2MDM_ERRFATAL), 1);
		if (esoc->primary)
		if (esoc->primary)
			break;
			break;
		esoc_mdm_log(
		"ESOC_PRIMARY_CRASH: Waiting for MDM2AP_STATUS to go LOW\n");
		timeout = local_clock();
		timeout = local_clock();
		do_div(timeout, NSEC_PER_MSEC);
		do_div(timeout, NSEC_PER_MSEC);
		timeout += MDM_MODEM_TIMEOUT;
		timeout += MDM_MODEM_TIMEOUT;
@@ -409,6 +479,8 @@ static void mdm_notify(enum esoc_notify notify, struct esoc_clink *esoc)
		} while (!time_after64(now, timeout));
		} while (!time_after64(now, timeout));


		if (!status_down) {
		if (!status_down) {
			esoc_mdm_log(
	"ESOC_PRIMARY_CRASH: MDM2AP_STATUS didn't go LOW. Resetting modem\n");
			dev_err(mdm->dev, "%s MDM2AP status did not go low\n",
			dev_err(mdm->dev, "%s MDM2AP status did not go low\n",
								__func__);
								__func__);
			mdm_toggle_soft_reset(mdm, true);
			mdm_toggle_soft_reset(mdm, true);
@@ -418,6 +490,8 @@ static void mdm_notify(enum esoc_notify notify, struct esoc_clink *esoc)
		mdm_disable_irqs(mdm);
		mdm_disable_irqs(mdm);
		mdm->debug = 0;
		mdm->debug = 0;
		mdm->ready = false;
		mdm->ready = false;
		esoc_mdm_log(
		"ESOC_PRIMARY_REBOOT: Powering down the modem\n");
		mdm_power_down(mdm);
		mdm_power_down(mdm);
		break;
		break;
	};
	};
@@ -435,6 +509,7 @@ static irqreturn_t mdm_errfatal(int irq, void *dev_id)
	if (!mdm->ready)
	if (!mdm->ready)
		goto mdm_pwroff_irq;
		goto mdm_pwroff_irq;
	esoc = mdm->esoc;
	esoc = mdm->esoc;
	esoc_mdm_log("MDM2AP_ERRFATAL IRQ received!\n");
	dev_err(dev, "%s: mdm sent errfatal interrupt\n",
	dev_err(dev, "%s: mdm sent errfatal interrupt\n",
					__func__);
					__func__);
	subsys_set_crash_status(esoc->subsys_dev, true);
	subsys_set_crash_status(esoc->subsys_dev, true);
@@ -442,6 +517,8 @@ static irqreturn_t mdm_errfatal(int irq, void *dev_id)
	esoc_clink_evt_notify(ESOC_ERR_FATAL, esoc);
	esoc_clink_evt_notify(ESOC_ERR_FATAL, esoc);
	return IRQ_HANDLED;
	return IRQ_HANDLED;
mdm_pwroff_irq:
mdm_pwroff_irq:
	esoc_mdm_log(
	"MDM2AP_ERRFATAL IRQ received before modem booted. Ignoring.\n");
	dev_info(dev, "errfatal irq when in pwroff\n");
	dev_info(dev, "errfatal irq when in pwroff\n");
no_mdm_irq:
no_mdm_irq:
	return IRQ_HANDLED;
	return IRQ_HANDLED;
@@ -458,15 +535,19 @@ static irqreturn_t mdm_status_change(int irq, void *dev_id)
		return IRQ_HANDLED;
		return IRQ_HANDLED;
	dev = mdm->dev;
	dev = mdm->dev;
	esoc = mdm->esoc;
	esoc = mdm->esoc;
	esoc_mdm_log("MDM2AP_STATUS IRQ received!\n");
	/*
	/*
	 * On auto boot devices, there is a possibility of receiving
	 * On auto boot devices, there is a possibility of receiving
	 * status change interrupt before esoc_clink structure is
	 * status change interrupt before esoc_clink structure is
	 * initialized. Ignore them.
	 * initialized. Ignore them.
	 */
	 */
	if (!esoc)
	if (!esoc) {
		esoc_mdm_log("Unexpected IRQ. Ignoring.\n");
		return IRQ_HANDLED;
		return IRQ_HANDLED;
	}
	value = gpio_get_value(MDM_GPIO(mdm, MDM2AP_STATUS));
	value = gpio_get_value(MDM_GPIO(mdm, MDM2AP_STATUS));
	if (value == 0 && mdm->ready) {
	if (value == 0 && mdm->ready) {
		esoc_mdm_log("Unexpected reset of external modem\n");
		dev_err(dev, "unexpected reset external modem\n");
		dev_err(dev, "unexpected reset external modem\n");
		subsys_set_crash_status(esoc->subsys_dev, true);
		subsys_set_crash_status(esoc->subsys_dev, true);
		esoc_clink_evt_notify(ESOC_UNEXPECTED_RESET, esoc);
		esoc_clink_evt_notify(ESOC_UNEXPECTED_RESET, esoc);
@@ -478,6 +559,8 @@ static irqreturn_t mdm_status_change(int irq, void *dev_id)
		if (esoc->auto_boot && mdm->ready)
		if (esoc->auto_boot && mdm->ready)
			return IRQ_HANDLED;
			return IRQ_HANDLED;


		esoc_mdm_log(
		"Modem ready. Cancelling the the status_check work\n");
		cancel_delayed_work(&mdm->mdm2ap_status_check_work);
		cancel_delayed_work(&mdm->mdm2ap_status_check_work);
		dev_dbg(dev, "status = 1: mdm is now ready\n");
		dev_dbg(dev, "status = 1: mdm is now ready\n");
		mdm->ready = true;
		mdm->ready = true;
@@ -887,30 +970,35 @@ static int sdx50m_setup_hw(struct mdm_ctrl *mdm,


	ret = mdm_dt_parse_gpios(mdm);
	ret = mdm_dt_parse_gpios(mdm);
	if (ret) {
	if (ret) {
		esoc_mdm_log("Failed to parse DT gpios\n");
		dev_err(mdm->dev, "Failed to parse DT gpios\n");
		dev_err(mdm->dev, "Failed to parse DT gpios\n");
		goto err_destroy_wrkq;
		goto err_destroy_wrkq;
	}
	}


	ret = mdm_pon_dt_init(mdm);
	ret = mdm_pon_dt_init(mdm);
	if (ret) {
	if (ret) {
		esoc_mdm_log("Failed to parse PON DT gpios\n");
		dev_err(mdm->dev, "Failed to parse PON DT gpio\n");
		dev_err(mdm->dev, "Failed to parse PON DT gpio\n");
		goto err_destroy_wrkq;
		goto err_destroy_wrkq;
	}
	}


	ret = mdm_pinctrl_init(mdm);
	ret = mdm_pinctrl_init(mdm);
	if (ret) {
	if (ret) {
		esoc_mdm_log("Failed to init pinctrl\n");
		dev_err(mdm->dev, "Failed to init pinctrl\n");
		dev_err(mdm->dev, "Failed to init pinctrl\n");
		goto err_destroy_wrkq;
		goto err_destroy_wrkq;
	}
	}


	ret = mdm_pon_setup(mdm);
	ret = mdm_pon_setup(mdm);
	if (ret) {
	if (ret) {
		esoc_mdm_log("Failed to setup PON\n");
		dev_err(mdm->dev, "Failed to setup PON\n");
		dev_err(mdm->dev, "Failed to setup PON\n");
		goto err_destroy_wrkq;
		goto err_destroy_wrkq;
	}
	}


	ret = mdm_configure_ipc(mdm, pdev);
	ret = mdm_configure_ipc(mdm, pdev);
	if (ret) {
	if (ret) {
		esoc_mdm_log("Failed to configure the ipc\n");
		dev_err(mdm->dev, "Failed to configure the ipc\n");
		dev_err(mdm->dev, "Failed to configure the ipc\n");
		goto err_release_ipc;
		goto err_release_ipc;
	}
	}
@@ -935,10 +1023,12 @@ static int sdx50m_setup_hw(struct mdm_ctrl *mdm,


	ret = esoc_clink_register(esoc);
	ret = esoc_clink_register(esoc);
	if (ret) {
	if (ret) {
		esoc_mdm_log("esoc registration failed\n");
		dev_err(mdm->dev, "esoc registration failed\n");
		dev_err(mdm->dev, "esoc registration failed\n");
		goto err_free_irq;
		goto err_free_irq;
	}
	}
	dev_dbg(mdm->dev, "esoc registration done\n");
	dev_dbg(mdm->dev, "esoc registration done\n");
	esoc_mdm_log("Done configuring the GPIOs and esoc registration\n");


	init_completion(&mdm->debug_done);
	init_completion(&mdm->debug_done);
	INIT_WORK(&mdm->mdm_status_work, mdm_status_fn);
	INIT_WORK(&mdm->mdm_status_work, mdm_status_fn);
@@ -949,6 +1039,8 @@ static int sdx50m_setup_hw(struct mdm_ctrl *mdm,
	mdm->esoc = esoc;
	mdm->esoc = esoc;
	mdm->init = 0;
	mdm->init = 0;


	mdm_debug_gpio_ipc_log(mdm);

	return 0;
	return 0;


err_free_irq:
err_free_irq:
@@ -994,6 +1086,7 @@ static int mdm_probe(struct platform_device *pdev)
	const struct mdm_ops *mdm_ops;
	const struct mdm_ops *mdm_ops;
	struct device_node *node = pdev->dev.of_node;
	struct device_node *node = pdev->dev.of_node;
	struct mdm_ctrl *mdm;
	struct mdm_ctrl *mdm;
	int ret;


	match = of_match_node(mdm_dt_match, node);
	match = of_match_node(mdm_dt_match, node);
	if (IS_ERR_OR_NULL(match))
	if (IS_ERR_OR_NULL(match))
@@ -1002,7 +1095,16 @@ static int mdm_probe(struct platform_device *pdev)
	mdm = devm_kzalloc(&pdev->dev, sizeof(*mdm), GFP_KERNEL);
	mdm = devm_kzalloc(&pdev->dev, sizeof(*mdm), GFP_KERNEL);
	if (IS_ERR_OR_NULL(mdm))
	if (IS_ERR_OR_NULL(mdm))
		return PTR_ERR(mdm);
		return PTR_ERR(mdm);
	return mdm_ops->config_hw(mdm, mdm_ops, pdev);

	ipc_log = ipc_log_context_create(ESOC_MDM_IPC_PAGES, "esoc-mdm", 0);
	if (!ipc_log)
		dev_err(&pdev->dev, "Failed to setup IPC logging\n");

	ret = mdm_ops->config_hw(mdm, mdm_ops, pdev);
	if (ret)
		ipc_log_context_destroy(ipc_log);

	return ret;
}
}


static struct platform_driver mdm_driver = {
static struct platform_driver mdm_driver = {
+131 −9
Original line number Original line Diff line number Diff line
@@ -19,8 +19,25 @@
#include "esoc-mdm.h"
#include "esoc-mdm.h"
#include "mdm-dbg.h"
#include "mdm-dbg.h"


/* Maximum number of powerup trial requests per session */
/* Default number of powerup trial requests per session */
#define ESOC_MAX_PON_REQ	2
#define ESOC_DEF_PON_REQ	2
static unsigned int n_pon_tries = ESOC_DEF_PON_REQ;
module_param(n_pon_tries, uint, 0644);
MODULE_PARM_DESC(n_pon_tries,
"Number of power-on retrials allowed upon boot failure");

enum esoc_boot_fail_action {
	BOOT_FAIL_ACTION_RETRY,
	BOOT_FAIL_ACTION_COLD_RESET,
	BOOT_FAIL_ACTION_SHUTDOWN,
	BOOT_FAIL_ACTION_PANIC,
	BOOT_FAIL_ACTION_NOP,
};

static unsigned int boot_fail_action = BOOT_FAIL_ACTION_NOP;
module_param(boot_fail_action, uint, 0644);
MODULE_PARM_DESC(boot_fail_action,
"Actions: 0:Retry PON; 1:Cold reset; 2:Power-down; 3:APQ Panic; 4:No action");


enum esoc_pon_state {
enum esoc_pon_state {
	PON_INIT,
	PON_INIT,
@@ -65,6 +82,8 @@ static int esoc_msm_restart_handler(struct notifier_block *nb,
	if (action == SYS_RESTART) {
	if (action == SYS_RESTART) {
		if (mdm_dbg_stall_notify(ESOC_PRIMARY_REBOOT))
		if (mdm_dbg_stall_notify(ESOC_PRIMARY_REBOOT))
			return NOTIFY_OK;
			return NOTIFY_OK;
		esoc_mdm_log(
			"Reboot notifier: Notifying esoc of cold reboot\n");
		dev_dbg(&esoc_clink->dev, "Notifying esoc of cold reboot\n");
		dev_dbg(&esoc_clink->dev, "Notifying esoc of cold reboot\n");
		clink_ops->notify(ESOC_PRIMARY_REBOOT, esoc_clink);
		clink_ops->notify(ESOC_PRIMARY_REBOOT, esoc_clink);
	}
	}
@@ -74,23 +93,35 @@ static void mdm_handle_clink_evt(enum esoc_evt evt,
					struct esoc_eng *eng)
					struct esoc_eng *eng)
{
{
	struct mdm_drv *mdm_drv = to_mdm_drv(eng);
	struct mdm_drv *mdm_drv = to_mdm_drv(eng);
	bool unexpected_state = false;


	switch (evt) {
	switch (evt) {
	case ESOC_INVALID_STATE:
	case ESOC_INVALID_STATE:
		esoc_mdm_log(
		"ESOC_INVALID_STATE: Calling complete with state: PON_FAIL\n");
		mdm_drv->pon_state = PON_FAIL;
		mdm_drv->pon_state = PON_FAIL;
		complete(&mdm_drv->pon_done);
		complete(&mdm_drv->pon_done);
		break;
		break;
	case ESOC_RUN_STATE:
	case ESOC_RUN_STATE:
		esoc_mdm_log(
		"ESOC_RUN_STATE: Calling complete with state: PON_SUCCESS\n");
		mdm_drv->pon_state = PON_SUCCESS;
		mdm_drv->pon_state = PON_SUCCESS;
		mdm_drv->mode = RUN,
		mdm_drv->mode = RUN,
		complete(&mdm_drv->pon_done);
		complete(&mdm_drv->pon_done);
		break;
		break;
	case ESOC_RETRY_PON_EVT:
	case ESOC_RETRY_PON_EVT:
		esoc_mdm_log(
		"ESOC_RETRY_PON_EVT: Calling complete with state: PON_RETRY\n");
		mdm_drv->pon_state = PON_RETRY;
		mdm_drv->pon_state = PON_RETRY;
		complete(&mdm_drv->pon_done);
		complete(&mdm_drv->pon_done);
		break;
		break;
	case ESOC_UNEXPECTED_RESET:
	case ESOC_UNEXPECTED_RESET:
		esoc_mdm_log("evt_state: ESOC_UNEXPECTED_RESET\n");
		unexpected_state = true;
	case ESOC_ERR_FATAL:
	case ESOC_ERR_FATAL:
		if (!unexpected_state)
			esoc_mdm_log("evt_state: ESOC_ERR_FATAL\n");

		/*
		/*
		 * Modem can crash while we are waiting for pon_done during
		 * Modem can crash while we are waiting for pon_done during
		 * a subsystem_get(). Setting mode to CRASH will prevent a
		 * a subsystem_get(). Setting mode to CRASH will prevent a
@@ -98,12 +129,20 @@ static void mdm_handle_clink_evt(enum esoc_evt evt,
		 * this by seting mode to CRASH only if device was up and
		 * this by seting mode to CRASH only if device was up and
		 * running.
		 * running.
		 */
		 */
		if (mdm_drv->mode == CRASH)
			esoc_mdm_log(
			"Modem in crash state already. Ignoring.\n");
		if (mdm_drv->mode != RUN)
			esoc_mdm_log("Modem not up. Ignoring.\n");
		if (mdm_drv->mode == CRASH || mdm_drv->mode != RUN)
		if (mdm_drv->mode == CRASH || mdm_drv->mode != RUN)
			return;
			return;
		mdm_drv->mode = CRASH;
		mdm_drv->mode = CRASH;
		esoc_mdm_log("Starting SSR work\n");
		queue_work(mdm_drv->mdm_queue, &mdm_drv->ssr_work);
		queue_work(mdm_drv->mdm_queue, &mdm_drv->ssr_work);
		break;
		break;
	case ESOC_REQ_ENG_ON:
	case ESOC_REQ_ENG_ON:
		esoc_mdm_log(
		"evt_state: ESOC_REQ_ENG_ON; Registered a req engine\n");
		complete(&mdm_drv->req_eng_wait);
		complete(&mdm_drv->req_eng_wait);
		break;
		break;
	default:
	default:
@@ -128,6 +167,8 @@ static void esoc_client_link_power_on(struct esoc_clink *esoc_clink,
	struct esoc_client_hook *client_hook;
	struct esoc_client_hook *client_hook;


	dev_dbg(&esoc_clink->dev, "Calling power_on hooks\n");
	dev_dbg(&esoc_clink->dev, "Calling power_on hooks\n");
	esoc_mdm_log(
	"Calling power_on hooks with crash state: %d\n", mdm_crashed);


	for (i = 0; i < ESOC_MAX_HOOKS; i++) {
	for (i = 0; i < ESOC_MAX_HOOKS; i++) {
		client_hook = esoc_clink->client_hook[i];
		client_hook = esoc_clink->client_hook[i];
@@ -144,6 +185,8 @@ static void esoc_client_link_power_off(struct esoc_clink *esoc_clink,
	struct esoc_client_hook *client_hook;
	struct esoc_client_hook *client_hook;


	dev_dbg(&esoc_clink->dev, "Calling power_off hooks\n");
	dev_dbg(&esoc_clink->dev, "Calling power_off hooks\n");
	esoc_mdm_log(
	"Calling power_off hooks with crash state: %d\n", mdm_crashed);


	for (i = 0; i < ESOC_MAX_HOOKS; i++) {
	for (i = 0; i < ESOC_MAX_HOOKS; i++) {
		client_hook = esoc_clink->client_hook[i];
		client_hook = esoc_clink->client_hook[i];
@@ -162,6 +205,8 @@ static void mdm_crash_shutdown(const struct subsys_desc *mdm_subsys)
								subsys);
								subsys);
	const struct esoc_clink_ops * const clink_ops = esoc_clink->clink_ops;
	const struct esoc_clink_ops * const clink_ops = esoc_clink->clink_ops;


	esoc_mdm_log("MDM crashed notification from SSR\n");

	if (mdm_dbg_stall_notify(ESOC_PRIMARY_CRASH))
	if (mdm_dbg_stall_notify(ESOC_PRIMARY_CRASH))
		return;
		return;
	clink_ops->notify(ESOC_PRIMARY_CRASH, esoc_clink);
	clink_ops->notify(ESOC_PRIMARY_CRASH, esoc_clink);
@@ -176,7 +221,10 @@ static int mdm_subsys_shutdown(const struct subsys_desc *crashed_subsys,
	struct mdm_drv *mdm_drv = esoc_get_drv_data(esoc_clink);
	struct mdm_drv *mdm_drv = esoc_get_drv_data(esoc_clink);
	const struct esoc_clink_ops * const clink_ops = esoc_clink->clink_ops;
	const struct esoc_clink_ops * const clink_ops = esoc_clink->clink_ops;


	esoc_mdm_log("Shutdown request from SSR\n");

	if (mdm_drv->mode == CRASH || mdm_drv->mode == PEER_CRASH) {
	if (mdm_drv->mode == CRASH || mdm_drv->mode == PEER_CRASH) {
		esoc_mdm_log("Shutdown in crash mode\n");
		if (mdm_dbg_stall_cmd(ESOC_PREPARE_DEBUG))
		if (mdm_dbg_stall_cmd(ESOC_PREPARE_DEBUG))
			/* We want to mask debug command.
			/* We want to mask debug command.
			 * In this case return success
			 * In this case return success
@@ -187,18 +235,23 @@ static int mdm_subsys_shutdown(const struct subsys_desc *crashed_subsys,
		esoc_clink_queue_request(ESOC_REQ_CRASH_SHUTDOWN, esoc_clink);
		esoc_clink_queue_request(ESOC_REQ_CRASH_SHUTDOWN, esoc_clink);
		esoc_client_link_power_off(esoc_clink, true);
		esoc_client_link_power_off(esoc_clink, true);


		esoc_mdm_log("Executing the ESOC_PREPARE_DEBUG command\n");
		ret = clink_ops->cmd_exe(ESOC_PREPARE_DEBUG,
		ret = clink_ops->cmd_exe(ESOC_PREPARE_DEBUG,
							esoc_clink);
							esoc_clink);
		if (ret) {
		if (ret) {
			esoc_mdm_log("ESOC_PREPARE_DEBUG command failed\n");
			dev_err(&esoc_clink->dev, "failed to enter debug\n");
			dev_err(&esoc_clink->dev, "failed to enter debug\n");
			return ret;
			return ret;
		}
		}
		mdm_drv->mode = IN_DEBUG;
		mdm_drv->mode = IN_DEBUG;
	} else if (!force_stop) {
	} else if (!force_stop) {
		if (esoc_clink->subsys.sysmon_shutdown_ret)
		esoc_mdm_log("Graceful shutdown mode\n");
		if (esoc_clink->subsys.sysmon_shutdown_ret) {
			esoc_mdm_log(
			"Executing the ESOC_FORCE_PWR_OFF command\n");
			ret = clink_ops->cmd_exe(ESOC_FORCE_PWR_OFF,
			ret = clink_ops->cmd_exe(ESOC_FORCE_PWR_OFF,
							esoc_clink);
							esoc_clink);
		else {
		} else {
			if (mdm_dbg_stall_cmd(ESOC_PWR_OFF))
			if (mdm_dbg_stall_cmd(ESOC_PWR_OFF))
				/* Since power off command is masked
				/* Since power off command is masked
				 * we return success, and leave the state
				 * we return success, and leave the state
@@ -206,9 +259,12 @@ static int mdm_subsys_shutdown(const struct subsys_desc *crashed_subsys,
				 */
				 */
				return 0;
				return 0;
			dev_dbg(&esoc_clink->dev, "Sending sysmon-shutdown\n");
			dev_dbg(&esoc_clink->dev, "Sending sysmon-shutdown\n");
			esoc_mdm_log("Executing the ESOC_PWR_OFF command\n");
			ret = clink_ops->cmd_exe(ESOC_PWR_OFF, esoc_clink);
			ret = clink_ops->cmd_exe(ESOC_PWR_OFF, esoc_clink);
		}
		}
		if (ret) {
		if (ret) {
			esoc_mdm_log(
			"Executing the ESOC_PWR_OFF command failed\n");
			dev_err(&esoc_clink->dev, "failed to exe power off\n");
			dev_err(&esoc_clink->dev, "failed to exe power off\n");
			return ret;
			return ret;
		}
		}
@@ -217,6 +273,7 @@ static int mdm_subsys_shutdown(const struct subsys_desc *crashed_subsys,
		clink_ops->cmd_exe(ESOC_FORCE_PWR_OFF, esoc_clink);
		clink_ops->cmd_exe(ESOC_FORCE_PWR_OFF, esoc_clink);
		mdm_drv->mode = PWR_OFF;
		mdm_drv->mode = PWR_OFF;
	}
	}
	esoc_mdm_log("Shutdown completed\n");
	return 0;
	return 0;
}
}


@@ -225,6 +282,8 @@ static void mdm_subsys_retry_powerup_cleanup(struct esoc_clink *esoc_clink)
	struct mdm_ctrl *mdm = get_esoc_clink_data(esoc_clink);
	struct mdm_ctrl *mdm = get_esoc_clink_data(esoc_clink);
	struct mdm_drv *mdm_drv = esoc_get_drv_data(esoc_clink);
	struct mdm_drv *mdm_drv = esoc_get_drv_data(esoc_clink);


	esoc_mdm_log("Doing cleanup\n");

	esoc_client_link_power_off(esoc_clink, false);
	esoc_client_link_power_off(esoc_clink, false);
	mdm_disable_irqs(mdm);
	mdm_disable_irqs(mdm);
	mdm_drv->pon_state = PON_INIT;
	mdm_drv->pon_state = PON_INIT;
@@ -232,6 +291,46 @@ static void mdm_subsys_retry_powerup_cleanup(struct esoc_clink *esoc_clink)
	reinit_completion(&mdm_drv->req_eng_wait);
	reinit_completion(&mdm_drv->req_eng_wait);
}
}


/* Returns 0 to proceed towards another retry, or an error code to quit */
static int mdm_handle_boot_fail(struct esoc_clink *esoc_clink, u8 *pon_trial)
{
	struct mdm_ctrl *mdm = get_esoc_clink_data(esoc_clink);

	switch (boot_fail_action) {
	case BOOT_FAIL_ACTION_RETRY:
		mdm_subsys_retry_powerup_cleanup(esoc_clink);
		esoc_mdm_log("Request to retry a warm reset\n");
		(*pon_trial)++;
		break;
	/*
	 * Issue a shutdown here and rerun the powerup again.
	 * This way it becomes a cold reset. Else, we end up
	 * issuing a cold reset & a warm reset back to back.
	 */
	case BOOT_FAIL_ACTION_COLD_RESET:
		mdm_subsys_retry_powerup_cleanup(esoc_clink);
		esoc_mdm_log("Doing cold reset by power-down and warm reset\n");
		(*pon_trial)++;
		mdm_power_down(mdm);
		break;
	case BOOT_FAIL_ACTION_PANIC:
		esoc_mdm_log("Calling panic!!\n");
		panic("Panic requested on external modem boot failure\n");
		break;
	case BOOT_FAIL_ACTION_NOP:
		esoc_mdm_log("Leaving the modem in its curent state\n");
		return -EIO;
	case BOOT_FAIL_ACTION_SHUTDOWN:
	default:
		mdm_subsys_retry_powerup_cleanup(esoc_clink);
		esoc_mdm_log("Shutdown the modem and quit\n");
		mdm_power_down(mdm);
		return -EIO;
	}

	return 0;
}

static int mdm_subsys_powerup(const struct subsys_desc *crashed_subsys)
static int mdm_subsys_powerup(const struct subsys_desc *crashed_subsys)
{
{
	int ret;
	int ret;
@@ -240,34 +339,46 @@ static int mdm_subsys_powerup(const struct subsys_desc *crashed_subsys)
								subsys);
								subsys);
	struct mdm_drv *mdm_drv = esoc_get_drv_data(esoc_clink);
	struct mdm_drv *mdm_drv = esoc_get_drv_data(esoc_clink);
	const struct esoc_clink_ops * const clink_ops = esoc_clink->clink_ops;
	const struct esoc_clink_ops * const clink_ops = esoc_clink->clink_ops;
	struct mdm_ctrl *mdm = get_esoc_clink_data(esoc_clink);
	int timeout = INT_MAX;
	int timeout = INT_MAX;
	u8 pon_trial = 1;
	u8 pon_trial = 1;


	esoc_mdm_log("Powerup request from SSR\n");

	do {
	do {
		esoc_mdm_log("Boot trial: %d\n", pon_trial);
		if (!esoc_clink->auto_boot &&
		if (!esoc_clink->auto_boot &&
			!esoc_req_eng_enabled(esoc_clink)) {
			!esoc_req_eng_enabled(esoc_clink)) {
			esoc_mdm_log("Wait for req eng registration\n");
			dev_dbg(&esoc_clink->dev,
			dev_dbg(&esoc_clink->dev,
					"Wait for req eng registration\n");
					"Wait for req eng registration\n");
			wait_for_completion(&mdm_drv->req_eng_wait);
			wait_for_completion(&mdm_drv->req_eng_wait);
		}
		}
		esoc_mdm_log("Req eng available\n");
		if (mdm_drv->mode == PWR_OFF) {
		if (mdm_drv->mode == PWR_OFF) {
			esoc_mdm_log("In normal power-on mode\n");
			if (mdm_dbg_stall_cmd(ESOC_PWR_ON))
			if (mdm_dbg_stall_cmd(ESOC_PWR_ON))
				return -EBUSY;
				return -EBUSY;
			esoc_mdm_log("Executing the ESOC_PWR_ON command\n");
			ret = clink_ops->cmd_exe(ESOC_PWR_ON, esoc_clink);
			ret = clink_ops->cmd_exe(ESOC_PWR_ON, esoc_clink);
			if (ret) {
			if (ret) {
				esoc_mdm_log("ESOC_PWR_ON command failed\n");
				dev_err(&esoc_clink->dev, "pwr on fail\n");
				dev_err(&esoc_clink->dev, "pwr on fail\n");
				return ret;
				return ret;
			}
			}
			esoc_client_link_power_on(esoc_clink, false);
			esoc_client_link_power_on(esoc_clink, false);
		} else if (mdm_drv->mode == IN_DEBUG) {
		} else if (mdm_drv->mode == IN_DEBUG) {
			esoc_mdm_log("In SSR power-on mode\n");
			esoc_mdm_log("Executing the ESOC_EXIT_DEBUG command\n");
			ret = clink_ops->cmd_exe(ESOC_EXIT_DEBUG, esoc_clink);
			ret = clink_ops->cmd_exe(ESOC_EXIT_DEBUG, esoc_clink);
			if (ret) {
			if (ret) {
				esoc_mdm_log(
				"ESOC_EXIT_DEBUG command failed\n");
				dev_err(&esoc_clink->dev,
				dev_err(&esoc_clink->dev,
						"cannot exit debug mode\n");
						"cannot exit debug mode\n");
				return ret;
				return ret;
			}
			}
			mdm_drv->mode = PWR_OFF;
			mdm_drv->mode = PWR_OFF;
			esoc_mdm_log("Executing the ESOC_PWR_ON command\n");
			ret = clink_ops->cmd_exe(ESOC_PWR_ON, esoc_clink);
			ret = clink_ops->cmd_exe(ESOC_PWR_ON, esoc_clink);
			if (ret) {
			if (ret) {
				dev_err(&esoc_clink->dev, "pwr on fail\n");
				dev_err(&esoc_clink->dev, "pwr on fail\n");
@@ -285,19 +396,24 @@ static int mdm_subsys_powerup(const struct subsys_desc *crashed_subsys)
		 */
		 */
		if (esoc_clink->auto_boot)
		if (esoc_clink->auto_boot)
			timeout = 10 * HZ;
			timeout = 10 * HZ;
		esoc_mdm_log(
		"Modem turned-on. Waiting for pon_done notification..\n");
		ret = wait_for_completion_timeout(&mdm_drv->pon_done, timeout);
		ret = wait_for_completion_timeout(&mdm_drv->pon_done, timeout);
		if (mdm_drv->pon_state == PON_FAIL || ret <= 0) {
		if (mdm_drv->pon_state == PON_FAIL || ret <= 0) {
			dev_err(&esoc_clink->dev, "booting failed\n");
			dev_err(&esoc_clink->dev, "booting failed\n");
			mdm_subsys_retry_powerup_cleanup(esoc_clink);
			esoc_mdm_log("booting failed\n");
			mdm_power_down(mdm);
			ret = mdm_handle_boot_fail(esoc_clink, &pon_trial);
			return -EIO;
			if (ret)
				return ret;
		} else if (mdm_drv->pon_state == PON_RETRY) {
		} else if (mdm_drv->pon_state == PON_RETRY) {
			esoc_mdm_log(
			"Boot failed. Doing cleanup and attempting to retry\n");
			pon_trial++;
			pon_trial++;
			mdm_subsys_retry_powerup_cleanup(esoc_clink);
			mdm_subsys_retry_powerup_cleanup(esoc_clink);
		} else if (mdm_drv->pon_state == PON_SUCCESS) {
		} else if (mdm_drv->pon_state == PON_SUCCESS) {
			break;
			break;
		}
		}
	} while (pon_trial <= ESOC_MAX_PON_REQ);
	} while (pon_trial <= n_pon_tries);


	return 0;
	return 0;
}
}
@@ -311,9 +427,14 @@ static int mdm_subsys_ramdumps(int want_dumps,
								subsys);
								subsys);
	const struct esoc_clink_ops * const clink_ops = esoc_clink->clink_ops;
	const struct esoc_clink_ops * const clink_ops = esoc_clink->clink_ops;


	esoc_mdm_log("Ramdumps called from SSR\n");

	if (want_dumps) {
	if (want_dumps) {
		esoc_mdm_log("Executing the ESOC_EXE_DEBUG command\n");
		ret = clink_ops->cmd_exe(ESOC_EXE_DEBUG, esoc_clink);
		ret = clink_ops->cmd_exe(ESOC_EXE_DEBUG, esoc_clink);
		if (ret) {
		if (ret) {
			esoc_mdm_log(
			"Failed executing the ESOC_EXE_DEBUG command\n");
			dev_err(&esoc_clink->dev, "debugging failed\n");
			dev_err(&esoc_clink->dev, "debugging failed\n");
			return ret;
			return ret;
		}
		}
@@ -375,6 +496,7 @@ int esoc_ssr_probe(struct esoc_clink *esoc_clink, struct esoc_drv *drv)
		dev_dbg(&esoc_clink->dev, "dbg engine initialized\n");
		dev_dbg(&esoc_clink->dev, "dbg engine initialized\n");
		debug_init_done = true;
		debug_init_done = true;
	}
	}

	return 0;
	return 0;
queue_err:
queue_err:
	esoc_clink_unregister_ssr(esoc_clink);
	esoc_clink_unregister_ssr(esoc_clink);
+19 −1
Original line number Original line Diff line number Diff line
@@ -51,6 +51,11 @@ static int sdx50m_toggle_soft_reset(struct mdm_ctrl *mdm, bool atomic)
		soft_reset_direction_assert = 1;
		soft_reset_direction_assert = 1;
		soft_reset_direction_de_assert = 0;
		soft_reset_direction_de_assert = 0;
	}
	}

	esoc_mdm_log("RESET GPIO value (before doing a reset): %d\n",
			gpio_get_value(MDM_GPIO(mdm, AP2MDM_SOFT_RESET)));
	esoc_mdm_log("Setting AP2MDM_SOFT_RESET = %d\n",
				soft_reset_direction_assert);
	gpio_direction_output(MDM_GPIO(mdm, AP2MDM_SOFT_RESET),
	gpio_direction_output(MDM_GPIO(mdm, AP2MDM_SOFT_RESET),
			soft_reset_direction_assert);
			soft_reset_direction_assert);
	/*
	/*
@@ -64,6 +69,9 @@ static int sdx50m_toggle_soft_reset(struct mdm_ctrl *mdm, bool atomic)
		 * panic handler, which has to executed atomically.
		 * panic handler, which has to executed atomically.
		 */
		 */
		mdelay(100);
		mdelay(100);

	esoc_mdm_log("Setting AP2MDM_SOFT_RESET = %d\n",
				soft_reset_direction_de_assert);
	gpio_direction_output(MDM_GPIO(mdm, AP2MDM_SOFT_RESET),
	gpio_direction_output(MDM_GPIO(mdm, AP2MDM_SOFT_RESET),
			soft_reset_direction_de_assert);
			soft_reset_direction_de_assert);
	return 0;
	return 0;
@@ -75,6 +83,7 @@ static int mdm4x_do_first_power_on(struct mdm_ctrl *mdm)
	int pblrdy;
	int pblrdy;
	struct device *dev = mdm->dev;
	struct device *dev = mdm->dev;


	esoc_mdm_log("Powering on modem for the first time\n");
	dev_dbg(dev, "Powering on modem for the first time\n");
	dev_dbg(dev, "Powering on modem for the first time\n");
	if (mdm->esoc->auto_boot)
	if (mdm->esoc->auto_boot)
		return 0;
		return 0;
@@ -82,6 +91,7 @@ static int mdm4x_do_first_power_on(struct mdm_ctrl *mdm)
	mdm_toggle_soft_reset(mdm, false);
	mdm_toggle_soft_reset(mdm, false);
	/* Add a delay to allow PON sequence to complete*/
	/* Add a delay to allow PON sequence to complete*/
	msleep(150);
	msleep(150);
	esoc_mdm_log("Setting AP2MDM_STATUS = 1\n");
	gpio_direction_output(MDM_GPIO(mdm, AP2MDM_STATUS), 1);
	gpio_direction_output(MDM_GPIO(mdm, AP2MDM_STATUS), 1);
	if (gpio_is_valid(MDM_GPIO(mdm, MDM2AP_PBLRDY))) {
	if (gpio_is_valid(MDM_GPIO(mdm, MDM2AP_PBLRDY))) {
		for (i = 0; i  < MDM_PBLRDY_CNT; i++) {
		for (i = 0; i  < MDM_PBLRDY_CNT; i++) {
@@ -98,8 +108,10 @@ static int mdm4x_do_first_power_on(struct mdm_ctrl *mdm)
	 * Send request for image. Let userspace confirm establishment of
	 * Send request for image. Let userspace confirm establishment of
	 * link to external modem.
	 * link to external modem.
	 */
	 */
	else
	else {
		esoc_mdm_log("Queueing the request: ESOC_REQ_IMG\n");
		esoc_clink_queue_request(ESOC_REQ_IMG, mdm->esoc);
		esoc_clink_queue_request(ESOC_REQ_IMG, mdm->esoc);
	}
	return 0;
	return 0;
}
}


@@ -134,6 +146,7 @@ static int sdx50m_power_down(struct mdm_ctrl *mdm)
	struct device *dev = mdm->dev;
	struct device *dev = mdm->dev;
	int soft_reset_direction = mdm->soft_reset_inverted ? 1 : 0;
	int soft_reset_direction = mdm->soft_reset_inverted ? 1 : 0;
	/* Assert the soft reset line whether mdm2ap_status went low or not */
	/* Assert the soft reset line whether mdm2ap_status went low or not */
	esoc_mdm_log("Setting AP2MDM_SOFT_RESET = %d\n", soft_reset_direction);
	gpio_direction_output(MDM_GPIO(mdm, AP2MDM_SOFT_RESET),
	gpio_direction_output(MDM_GPIO(mdm, AP2MDM_SOFT_RESET),
					soft_reset_direction);
					soft_reset_direction);
	dev_dbg(dev, "Doing a hard reset\n");
	dev_dbg(dev, "Doing a hard reset\n");
@@ -152,6 +165,7 @@ static int sdx50m_power_down(struct mdm_ctrl *mdm)
static void mdm9x55_cold_reset(struct mdm_ctrl *mdm)
static void mdm9x55_cold_reset(struct mdm_ctrl *mdm)
{
{
	dev_dbg(mdm->dev, "Triggering mdm cold reset");
	dev_dbg(mdm->dev, "Triggering mdm cold reset");

	gpio_direction_output(MDM_GPIO(mdm, AP2MDM_SOFT_RESET),
	gpio_direction_output(MDM_GPIO(mdm, AP2MDM_SOFT_RESET),
			!!mdm->soft_reset_inverted);
			!!mdm->soft_reset_inverted);


@@ -168,6 +182,8 @@ static void mdm9x55_cold_reset(struct mdm_ctrl *mdm)
static void sdx50m_cold_reset(struct mdm_ctrl *mdm)
static void sdx50m_cold_reset(struct mdm_ctrl *mdm)
{
{
	dev_dbg(mdm->dev, "Triggering mdm cold reset");
	dev_dbg(mdm->dev, "Triggering mdm cold reset");
	esoc_mdm_log("Setting AP2MDM_SOFT_RESET = %d\n",
					!!mdm->soft_reset_inverted);
	gpio_direction_output(MDM_GPIO(mdm, AP2MDM_SOFT_RESET),
	gpio_direction_output(MDM_GPIO(mdm, AP2MDM_SOFT_RESET),
			!!mdm->soft_reset_inverted);
			!!mdm->soft_reset_inverted);


@@ -177,6 +193,8 @@ static void sdx50m_cold_reset(struct mdm_ctrl *mdm)
	 */
	 */
	mdelay(600);
	mdelay(600);


	esoc_mdm_log("Setting AP2MDM_SOFT_RESET = %d\n",
					!!mdm->soft_reset_inverted);
	gpio_direction_output(MDM_GPIO(mdm, AP2MDM_SOFT_RESET),
	gpio_direction_output(MDM_GPIO(mdm, AP2MDM_SOFT_RESET),
			!mdm->soft_reset_inverted);
			!mdm->soft_reset_inverted);
}
}
+12 −0
Original line number Original line Diff line number Diff line
@@ -23,6 +23,18 @@
#include <linux/spinlock.h>
#include <linux/spinlock.h>
#include <soc/qcom/subsystem_restart.h>
#include <soc/qcom/subsystem_restart.h>
#include <soc/qcom/subsystem_notif.h>
#include <soc/qcom/subsystem_notif.h>
#include <linux/ipc_logging.h>

#define ESOC_MDM_IPC_PAGES	10

extern void *ipc_log;

#define esoc_mdm_log(__msg, ...) \
do { \
	if (ipc_log) \
		ipc_log_string(ipc_log, \
			"[%s]: "__msg, __func__, ##__VA_ARGS__); \
} while (0)


#define ESOC_DEV_MAX		4
#define ESOC_DEV_MAX		4
#define ESOC_NAME_LEN		20
#define ESOC_NAME_LEN		20
+58 −8

File changed.

Preview size limit exceeded, changes collapsed.