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

Commit 52a31374 authored by Satya Durga Srinivasu Prabhala's avatar Satya Durga Srinivasu Prabhala Committed by Raghavendra Rao Ananta
Browse files

esoc: Add support for SDX50



Add basic operations to support sdx50 in esoc driver that includes
compatibility, initializations and power control operations (reset,
shutdown, and so on).

Change-Id: Ia53a128b0259d0fc7680bc9452ceaead7b286ca8
Signed-off-by: default avatarSatya Durga Srinivasu Prabhala <satyap@codeaurora.org>
parent 66f22056
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -6,7 +6,7 @@ to be reset.

Required Properties:
- compatible:	The bus devices need to be compatible with
		"qcom,ext-mdm9x55"
		"qcom,ext-mdm9x55", qcom,ext-sdx50m.

Required named gpio properties:
- qcom,mdm2ap-errfatal-gpio: gpio for the external modem to indicate to the apps processor
+131 −0
Original line number Diff line number Diff line
@@ -760,6 +760,27 @@ static int mdm_pinctrl_init(struct mdm_ctrl *mdm)
	return retval;
}

static void mdm_release_ipc_gpio(struct mdm_ctrl *mdm)
{
	int i;

	if (!mdm)
		return;

	for (i = 0; i < NUM_GPIOS; ++i)
		if (gpio_is_valid(MDM_GPIO(mdm, i)))
			gpio_free(MDM_GPIO(mdm, i));
}

static void mdm_free_irq(struct mdm_ctrl *mdm)
{
	if (!mdm)
		return;

	free_irq(mdm->errfatal_irq, mdm);
	free_irq(mdm->status_irq, mdm);
}

static int mdm9x55_setup_hw(struct mdm_ctrl *mdm,
					const struct mdm_ops *ops,
					struct platform_device *pdev)
@@ -851,6 +872,108 @@ static int mdm9x55_setup_hw(struct mdm_ctrl *mdm,
	return 0;
}

static int sdx50m_setup_hw(struct mdm_ctrl *mdm,
					const struct mdm_ops *ops,
					struct platform_device *pdev)
{
	int ret;
	struct device_node *node;
	struct esoc_clink *esoc;
	const struct esoc_clink_ops *const clink_ops = ops->clink_ops;
	const struct mdm_pon_ops *pon_ops = ops->pon_ops;

	mdm->dev = &pdev->dev;
	mdm->pon_ops = pon_ops;
	node = pdev->dev.of_node;

	esoc = devm_kzalloc(mdm->dev, sizeof(*esoc), GFP_KERNEL);
	if (IS_ERR_OR_NULL(esoc)) {
		dev_err(mdm->dev, "cannot allocate esoc device\n");
		return PTR_ERR(esoc);
	}
	esoc->pdev = pdev;

	mdm->mdm_queue = alloc_workqueue("mdm_queue", 0, 0);
	if (!mdm->mdm_queue) {
		dev_err(mdm->dev, "could not create mdm_queue\n");
		return -ENOMEM;
	}

	mdm->irq_mask = 0;
	mdm->ready = false;

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

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

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

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

	ret = mdm_configure_ipc(mdm, pdev);
	if (ret) {
		dev_err(mdm->dev, "Failed to configure the ipc\n");
		goto err_release_ipc;
	}

	esoc->name = SDX50M_LABEL;
	mdm->dual_interface = of_property_read_bool(node,
						"qcom,mdm-dual-link");
	esoc->link_name = SDX50M_PCIE;
	ret = of_property_read_string(node, "qcom,mdm-link-info",
					&esoc->link_info);
	if (ret)
		dev_info(mdm->dev, "esoc link info missing\n");

	esoc->clink_ops = clink_ops;
	esoc->parent = mdm->dev;
	esoc->owner = THIS_MODULE;
	esoc->np = pdev->dev.of_node;
	set_esoc_clink_data(esoc, mdm);

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

	init_completion(&mdm->debug_done);
	INIT_WORK(&mdm->mdm_status_work, mdm_status_fn);
	INIT_WORK(&mdm->restart_reason_work, mdm_get_restart_reason);
	INIT_DELAYED_WORK(&mdm->mdm2ap_status_check_work, mdm2ap_status_check);
	mdm->get_restart_reason = false;
	mdm->debug_fail = false;
	mdm->esoc = esoc;
	mdm->init = 0;

	return 0;

err_free_irq:
	mdm_free_irq(mdm);
err_release_ipc:
	mdm_release_ipc_gpio(mdm);
err_destroy_wrkq:
	destroy_workqueue(mdm->mdm_queue);
	return ret;
}

static struct esoc_clink_ops mdm_cops = {
	.cmd_exe = mdm_cmd_exe,
	.get_status = mdm_get_status,
@@ -864,9 +987,17 @@ static struct mdm_ops mdm9x55_ops = {
	.pon_ops = &mdm9x55_pon_ops,
};

static struct mdm_ops sdx50m_ops = {
	.clink_ops = &mdm_cops,
	.config_hw = sdx50m_setup_hw,
	.pon_ops = &sdx50m_pon_ops,
};

static const struct of_device_id mdm_dt_match[] = {
	{ .compatible = "qcom,ext-mdm9x55",
		.data = &mdm9x55_ops, },
	{ .compatible = "qcom,ext-sdx50m",
		.data = &sdx50m_ops, },
	{},
};
MODULE_DEVICE_TABLE(of, mdm_dt_match);
+4 −0
Original line number Diff line number Diff line
@@ -301,6 +301,10 @@ static struct esoc_compat compat_table[] = {
		.name = "MDM9x55",
		.data = NULL,
	},
	{
		.name = "SDX50M",
		.data = NULL,
	},
};

static struct esoc_drv esoc_ssr_drv = {
+89 −0
Original line number Diff line number Diff line
@@ -41,6 +41,34 @@ static int mdm9x55_toggle_soft_reset(struct mdm_ctrl *mdm, bool atomic)
	return 0;
}

/* This function can be called from atomic context. */
static int sdx50m_toggle_soft_reset(struct mdm_ctrl *mdm, bool atomic)
{
	int soft_reset_direction_assert = 0,
	    soft_reset_direction_de_assert = 1;

	if (mdm->soft_reset_inverted) {
		soft_reset_direction_assert = 1;
		soft_reset_direction_de_assert = 0;
	}
	gpio_direction_output(MDM_GPIO(mdm, AP2MDM_SOFT_RESET),
			soft_reset_direction_assert);
	/*
	 * Allow PS hold assert to be detected
	 */
	if (!atomic)
		usleep_range(203000, 300000);
	else
		/*
		 * The flow falls through this path as a part of the
		 * panic handler, which has to executed atomically.
		 */
		mdelay(203);
	gpio_direction_output(MDM_GPIO(mdm, AP2MDM_SOFT_RESET),
			soft_reset_direction_de_assert);
	return 0;
}

static int mdm4x_do_first_power_on(struct mdm_ctrl *mdm)
{
	int i;
@@ -101,6 +129,26 @@ static int mdm9x55_power_down(struct mdm_ctrl *mdm)
	return 0;
}

static int sdx50m_power_down(struct mdm_ctrl *mdm)
{
	struct device *dev = mdm->dev;
	int soft_reset_direction = mdm->soft_reset_inverted ? 1 : 0;
	/* Assert the soft reset line whether mdm2ap_status went low or not */
	gpio_direction_output(MDM_GPIO(mdm, AP2MDM_SOFT_RESET),
					soft_reset_direction);
	dev_dbg(dev, "Doing a hard reset\n");
	gpio_direction_output(MDM_GPIO(mdm, AP2MDM_SOFT_RESET),
						soft_reset_direction);
	/*
	 * Currently, there is a debounce timer on the charm PMIC. It is
	 * necessary to hold the PMIC RESET low for 406ms
	 * for the reset to fully take place. Sleep here to ensure the
	 * reset has occurred before the function exits.
	 */
	msleep(406);
	return 0;
}

static void mdm9x55_cold_reset(struct mdm_ctrl *mdm)
{
	dev_dbg(mdm->dev, "Triggering mdm cold reset");
@@ -117,6 +165,22 @@ static void mdm9x55_cold_reset(struct mdm_ctrl *mdm)
			!mdm->soft_reset_inverted);
}

static void sdx50m_cold_reset(struct mdm_ctrl *mdm)
{
	dev_dbg(mdm->dev, "Triggering mdm cold reset");
	gpio_direction_output(MDM_GPIO(mdm, AP2MDM_SOFT_RESET),
			!!mdm->soft_reset_inverted);

	/*
	 * The function is executed as a part of the atomic reboot handler.
	 * Hence, go with a busy loop instead of sleep.
	 */
	mdelay(334);

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

static int mdm9x55_pon_dt_init(struct mdm_ctrl *mdm)
{
	int val;
@@ -140,6 +204,23 @@ static int mdm9x55_pon_dt_init(struct mdm_ctrl *mdm)
		return -EIO;
}

static int mdm4x_pon_dt_init(struct mdm_ctrl *mdm)
{
	int val;
	struct device_node *node = mdm->dev->of_node;
	enum of_gpio_flags flags = OF_GPIO_ACTIVE_LOW;

	val = of_get_named_gpio_flags(node, "qcom,ap2mdm-soft-reset-gpio",
						0, &flags);
	if (val >= 0) {
		MDM_GPIO(mdm, AP2MDM_SOFT_RESET) = val;
		if (flags & OF_GPIO_ACTIVE_LOW)
			mdm->soft_reset_inverted = 1;
		return 0;
	} else
		return -EIO;
}

static int mdm4x_pon_setup(struct mdm_ctrl *mdm)
{
	struct device *dev = mdm->dev;
@@ -163,3 +244,11 @@ struct mdm_pon_ops mdm9x55_pon_ops = {
	.setup = mdm4x_pon_setup,
};

struct mdm_pon_ops sdx50m_pon_ops = {
	.pon = mdm4x_do_first_power_on,
	.soft_reset = sdx50m_toggle_soft_reset,
	.poff_force = sdx50m_power_down,
	.cold_reset = sdx50m_cold_reset,
	.dt_init = mdm4x_pon_dt_init,
	.setup = mdm4x_pon_setup,
};
+3 −0
Original line number Diff line number Diff line
@@ -29,6 +29,8 @@
#define MDM_GPIO(mdm, i)		(mdm->gpios[i])
#define MDM9x55_LABEL			"MDM9x55"
#define MDM9x55_PCIE			"PCIe"
#define SDX50M_LABEL			"SDX50M"
#define SDX50M_PCIE			"PCIe"
#define MDM2AP_STATUS_TIMEOUT_MS	120000L
#define MDM_MODEM_TIMEOUT		3000
#define DEF_RAMDUMP_TIMEOUT		120000
@@ -146,4 +148,5 @@ static inline int mdm_pon_setup(struct mdm_ctrl *mdm)
}

extern struct mdm_pon_ops mdm9x55_pon_ops;
extern struct mdm_pon_ops sdx50m_pon_ops;
#endif