Commit 49f80a7a authored by Marek Vasut's avatar Marek Vasut Committed by Mathieu Poirier
Browse files

remoteproc: imx_rproc: Switch iMX8MN/MP from SMCCC to MMIO



The MX8M CM7 boot via SMC call is problematic, since not all versions
of ATF support this interface. Extend the MMIO support so it can boot
the CM7 on MX8MN/MP instead and discern the two alternatives using DT
compatible strings.

Signed-off-by: default avatarMarek Vasut <marex@denx.de>
Reviewed-by: default avatarPeng Fan <peng.fan@nxp.com>
Link: https://lore.kernel.org/r/20230724222418.163220-2-marex@denx.de


Signed-off-by: default avatarMathieu Poirier <mathieu.poirier@linaro.org>
parent 05117baf
Loading
Loading
Loading
Loading
+56 −2
Original line number Diff line number Diff line
@@ -40,6 +40,12 @@
#define IMX7D_M4_STOP			(IMX7D_ENABLE_M4 | IMX7D_SW_M4C_RST | \
					 IMX7D_SW_M4C_NON_SCLR_RST)

#define IMX8M_M7_STOP			(IMX7D_ENABLE_M4 | IMX7D_SW_M4C_RST)
#define IMX8M_M7_POLL			IMX7D_ENABLE_M4

#define IMX8M_GPR22			0x58
#define IMX8M_GPR22_CM7_CPUWAIT		BIT(0)

/* Address: 0x020D8000 */
#define IMX6SX_SRC_SCR			0x00
#define IMX6SX_ENABLE_M4		BIT(22)
@@ -91,6 +97,7 @@ static int imx_rproc_detach_pd(struct rproc *rproc);
struct imx_rproc {
	struct device			*dev;
	struct regmap			*regmap;
	struct regmap			*gpr;
	struct rproc			*rproc;
	const struct imx_rproc_dcfg	*dcfg;
	struct imx_rproc_mem		mem[IMX_RPROC_MEM_MAX];
@@ -285,6 +292,18 @@ static const struct imx_rproc_att imx_rproc_att_imx6sx[] = {
	{ 0x80000000, 0x80000000, 0x60000000, 0 },
};

static const struct imx_rproc_dcfg imx_rproc_cfg_imx8mn_mmio = {
	.src_reg	= IMX7D_SRC_SCR,
	.src_mask	= IMX7D_M4_RST_MASK,
	.src_start	= IMX7D_M4_START,
	.src_stop	= IMX8M_M7_STOP,
	.gpr_reg	= IMX8M_GPR22,
	.gpr_wait	= IMX8M_GPR22_CM7_CPUWAIT,
	.att		= imx_rproc_att_imx8mn,
	.att_size	= ARRAY_SIZE(imx_rproc_att_imx8mn),
	.method		= IMX_RPROC_MMIO,
};

static const struct imx_rproc_dcfg imx_rproc_cfg_imx8mn = {
	.att		= imx_rproc_att_imx8mn,
	.att_size	= ARRAY_SIZE(imx_rproc_att_imx8mn),
@@ -365,8 +384,14 @@ static int imx_rproc_start(struct rproc *rproc)

	switch (dcfg->method) {
	case IMX_RPROC_MMIO:
		ret = regmap_update_bits(priv->regmap, dcfg->src_reg, dcfg->src_mask,
		if (priv->gpr) {
			ret = regmap_clear_bits(priv->gpr, dcfg->gpr_reg,
						dcfg->gpr_wait);
		} else {
			ret = regmap_update_bits(priv->regmap, dcfg->src_reg,
						 dcfg->src_mask,
						 dcfg->src_start);
		}
		break;
	case IMX_RPROC_SMC:
		arm_smccc_smc(IMX_SIP_RPROC, IMX_SIP_RPROC_START, 0, 0, 0, 0, 0, 0, &res);
@@ -395,6 +420,16 @@ static int imx_rproc_stop(struct rproc *rproc)

	switch (dcfg->method) {
	case IMX_RPROC_MMIO:
		if (priv->gpr) {
			ret = regmap_set_bits(priv->gpr, dcfg->gpr_reg,
					      dcfg->gpr_wait);
			if (ret) {
				dev_err(priv->dev,
					"Failed to quiescence M4 platform!\n");
				return ret;
			}
		}

		ret = regmap_update_bits(priv->regmap, dcfg->src_reg, dcfg->src_mask,
					 dcfg->src_stop);
		break;
@@ -992,6 +1027,10 @@ static int imx_rproc_detect_mode(struct imx_rproc *priv)
		break;
	}

	priv->gpr = syscon_regmap_lookup_by_phandle(dev->of_node, "fsl,iomuxc-gpr");
	if (IS_ERR(priv->gpr))
		priv->gpr = NULL;

	regmap = syscon_regmap_lookup_by_phandle(dev->of_node, "syscon");
	if (IS_ERR(regmap)) {
		dev_err(dev, "failed to find syscon\n");
@@ -1001,6 +1040,19 @@ static int imx_rproc_detect_mode(struct imx_rproc *priv)
	priv->regmap = regmap;
	regmap_attach_dev(dev, regmap, &config);

	if (priv->gpr) {
		ret = regmap_read(priv->gpr, dcfg->gpr_reg, &val);
		if (val & dcfg->gpr_wait) {
			/*
			 * After cold boot, the CM indicates its in wait
			 * state, but not fully powered off. Power it off
			 * fully so firmware can be loaded into it.
			 */
			imx_rproc_stop(priv->rproc);
			return 0;
		}
	}

	ret = regmap_read(regmap, dcfg->src_reg, &val);
	if (ret) {
		dev_err(dev, "Failed to read src\n");
@@ -1142,6 +1194,8 @@ static const struct of_device_id imx_rproc_of_match[] = {
	{ .compatible = "fsl,imx8mm-cm4", .data = &imx_rproc_cfg_imx8mq },
	{ .compatible = "fsl,imx8mn-cm7", .data = &imx_rproc_cfg_imx8mn },
	{ .compatible = "fsl,imx8mp-cm7", .data = &imx_rproc_cfg_imx8mn },
	{ .compatible = "fsl,imx8mn-cm7-mmio", .data = &imx_rproc_cfg_imx8mn_mmio },
	{ .compatible = "fsl,imx8mp-cm7-mmio", .data = &imx_rproc_cfg_imx8mn_mmio },
	{ .compatible = "fsl,imx8qxp-cm4", .data = &imx_rproc_cfg_imx8qxp },
	{ .compatible = "fsl,imx8qm-cm4", .data = &imx_rproc_cfg_imx8qm },
	{ .compatible = "fsl,imx8ulp-cm33", .data = &imx_rproc_cfg_imx8ulp },
+2 −0
Original line number Diff line number Diff line
@@ -31,6 +31,8 @@ struct imx_rproc_dcfg {
	u32				src_mask;
	u32				src_start;
	u32				src_stop;
	u32				gpr_reg;
	u32				gpr_wait;
	const struct imx_rproc_att	*att;
	size_t				att_size;
	enum imx_rproc_method		method;