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

Commit 884142dd authored by Akash Asthana's avatar Akash Asthana
Browse files

msm: msm-geni-se: Add proxy votes to fix earlycon crash



QUP core clock is shared among all the SE drivers present on particular
QUP wrapper, the system will reset(unclocked access) if earlycon used after
QUP core clock is put to 0 from other SE drivers before real console comes
up.

As earlycon can't vote for it's QUP core need, to fix this put vote for
QUP core from common driver probe on behalf of earlycon and remove vote
during real console probe after uart_add_one_port call because by this
time real console is up and voted for it's resources.

Change-Id: I4362fec8ef798de30beae4d608626ae409607b84
Signed-off-by: default avatarAkash Asthana <akashast@codeaurora.org>
parent 4fc723f7
Loading
Loading
Loading
Loading
+54 −0
Original line number Diff line number Diff line
@@ -103,6 +103,7 @@ struct geni_se_device {
	struct bus_vectors *vectors;
	int num_paths;
	bool vote_for_bw;
	struct se_geni_rsc wrapper_rsc;
};

#define HW_VER_MAJOR_MASK GENMASK(31, 28)
@@ -1642,6 +1643,34 @@ static struct bus_vectors *get_icc_paths(struct platform_device *pdev,
	return NULL;
}

void geni_se_remove_earlycon_icc_vote(struct device *dev)
{
	struct platform_device *pdev;
	struct device_node *parent;
	struct device_node *child;
	struct geni_se_device *geni_se_dev;
	int ret;

	parent = of_get_next_parent(dev->of_node);
	for_each_child_of_node(parent, child) {
		if (!of_device_is_compatible(child, "qcom,qupv3-geni-se"))
			continue;

		pdev = of_find_device_by_node(child);
		if (!pdev)
			continue;

		geni_se_dev = platform_get_drvdata(pdev);
		ret = geni_se_rmv_ab_ib(geni_se_dev, &geni_se_dev->wrapper_rsc);

		if (ret)
			dev_err(dev, "%s: Error %d during bus_bw_update\n", __func__,
					ret);
	}
	of_node_put(parent);
}
EXPORT_SYMBOL(geni_se_remove_earlycon_icc_vote);

static int geni_se_iommu_probe(struct device *dev)
{
	struct geni_se_device *geni_se_dev;
@@ -1731,6 +1760,31 @@ static int geni_se_probe(struct platform_device *pdev)

	dev_set_drvdata(dev, geni_se_dev);

	/*
	 * TBD: Proxy vote on QUP core path on behalf of earlycon.
	 * Once the ICC sync state feature is implemented, we can make
	 * console UART as dummy consumer of ICC to get rid of this HACK
	 */
#if IS_ENABLED(CONFIG_SERIAL_MSM_GENI_CONSOLE)
	geni_se_dev->wrapper_rsc.wrapper_dev = dev;
	geni_se_dev->wrapper_rsc.ctrl_dev = dev;

	ret = geni_se_resources_init(&geni_se_dev->wrapper_rsc,
					UART_CONSOLE_CORE2X_VOTE,
					(DEFAULT_SE_CLK * DEFAULT_BUS_WIDTH));
	if (ret) {
		dev_err(dev, "Resources init failed: %d\n", ret);
		return ret;
	}

	ret = geni_se_add_ab_ib(geni_se_dev, &geni_se_dev->wrapper_rsc);
	if (ret) {
		dev_err(dev, "%s: Error %d during bus_bw_update\n", __func__,
				ret);
		return ret;
	}
#endif

	ret = of_platform_populate(dev->of_node, geni_se_dt_match, NULL, dev);
	if (ret) {
		dev_err(dev, "%s: Error populating children\n", __func__);
+10 −0
Original line number Diff line number Diff line
@@ -3168,6 +3168,16 @@ static int msm_geni_serial_probe(struct platform_device *pdev)
	}

	ret = uart_add_one_port(drv, uport);
	if (ret)
		dev_err(&pdev->dev, "Failed to register uart_port: %d\n",
				ret);
	/*
	 * Remove proxy vote from QUP core which was kept from common driver
	 * probe on behalf of earlycon
	 */
	if (uart_console(uport))
		geni_se_remove_earlycon_icc_vote(dev_port->wrapper_dev);

exit_geni_serial_probe:
	IPC_LOG_MSG(dev_port->ipc_log_misc, "%s: ret:%d\n",
		    __func__, ret);
+6 −0
Original line number Diff line number Diff line
@@ -823,6 +823,12 @@ int geni_se_iommu_free_buf(struct device *wrapper_dev, dma_addr_t *iova,
 */
void geni_se_dump_dbg_regs(struct se_geni_rsc *rsc, void __iomem *base,
				void *ipc);

/*
 * This function is used to remove proxy ICC BW vote put from common driver
 * probe on behalf of earlycon usecase.
 */
void geni_se_remove_earlycon_icc_vote(struct device *dev);
#else
static inline unsigned int geni_read_reg_nolog(void __iomem *base, int offset)
{