Skip to content

Commit 49f80a7

Browse files
Marek Vasutmathieupoirier
authored andcommitted
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: Marek Vasut <marex@denx.de> Reviewed-by: Peng Fan <peng.fan@nxp.com> Link: https://lore.kernel.org/r/20230724222418.163220-2-marex@denx.de Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
1 parent 05117ba commit 49f80a7

File tree

2 files changed

+58
-2
lines changed

2 files changed

+58
-2
lines changed

drivers/remoteproc/imx_rproc.c

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,12 @@
4040
#define IMX7D_M4_STOP (IMX7D_ENABLE_M4 | IMX7D_SW_M4C_RST | \
4141
IMX7D_SW_M4C_NON_SCLR_RST)
4242

43+
#define IMX8M_M7_STOP (IMX7D_ENABLE_M4 | IMX7D_SW_M4C_RST)
44+
#define IMX8M_M7_POLL IMX7D_ENABLE_M4
45+
46+
#define IMX8M_GPR22 0x58
47+
#define IMX8M_GPR22_CM7_CPUWAIT BIT(0)
48+
4349
/* Address: 0x020D8000 */
4450
#define IMX6SX_SRC_SCR 0x00
4551
#define IMX6SX_ENABLE_M4 BIT(22)
@@ -91,6 +97,7 @@ static int imx_rproc_detach_pd(struct rproc *rproc);
9197
struct imx_rproc {
9298
struct device *dev;
9399
struct regmap *regmap;
100+
struct regmap *gpr;
94101
struct rproc *rproc;
95102
const struct imx_rproc_dcfg *dcfg;
96103
struct imx_rproc_mem mem[IMX_RPROC_MEM_MAX];
@@ -285,6 +292,18 @@ static const struct imx_rproc_att imx_rproc_att_imx6sx[] = {
285292
{ 0x80000000, 0x80000000, 0x60000000, 0 },
286293
};
287294

295+
static const struct imx_rproc_dcfg imx_rproc_cfg_imx8mn_mmio = {
296+
.src_reg = IMX7D_SRC_SCR,
297+
.src_mask = IMX7D_M4_RST_MASK,
298+
.src_start = IMX7D_M4_START,
299+
.src_stop = IMX8M_M7_STOP,
300+
.gpr_reg = IMX8M_GPR22,
301+
.gpr_wait = IMX8M_GPR22_CM7_CPUWAIT,
302+
.att = imx_rproc_att_imx8mn,
303+
.att_size = ARRAY_SIZE(imx_rproc_att_imx8mn),
304+
.method = IMX_RPROC_MMIO,
305+
};
306+
288307
static const struct imx_rproc_dcfg imx_rproc_cfg_imx8mn = {
289308
.att = imx_rproc_att_imx8mn,
290309
.att_size = ARRAY_SIZE(imx_rproc_att_imx8mn),
@@ -365,8 +384,14 @@ static int imx_rproc_start(struct rproc *rproc)
365384

366385
switch (dcfg->method) {
367386
case IMX_RPROC_MMIO:
368-
ret = regmap_update_bits(priv->regmap, dcfg->src_reg, dcfg->src_mask,
369-
dcfg->src_start);
387+
if (priv->gpr) {
388+
ret = regmap_clear_bits(priv->gpr, dcfg->gpr_reg,
389+
dcfg->gpr_wait);
390+
} else {
391+
ret = regmap_update_bits(priv->regmap, dcfg->src_reg,
392+
dcfg->src_mask,
393+
dcfg->src_start);
394+
}
370395
break;
371396
case IMX_RPROC_SMC:
372397
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)
395420

396421
switch (dcfg->method) {
397422
case IMX_RPROC_MMIO:
423+
if (priv->gpr) {
424+
ret = regmap_set_bits(priv->gpr, dcfg->gpr_reg,
425+
dcfg->gpr_wait);
426+
if (ret) {
427+
dev_err(priv->dev,
428+
"Failed to quiescence M4 platform!\n");
429+
return ret;
430+
}
431+
}
432+
398433
ret = regmap_update_bits(priv->regmap, dcfg->src_reg, dcfg->src_mask,
399434
dcfg->src_stop);
400435
break;
@@ -992,6 +1027,10 @@ static int imx_rproc_detect_mode(struct imx_rproc *priv)
9921027
break;
9931028
}
9941029

1030+
priv->gpr = syscon_regmap_lookup_by_phandle(dev->of_node, "fsl,iomuxc-gpr");
1031+
if (IS_ERR(priv->gpr))
1032+
priv->gpr = NULL;
1033+
9951034
regmap = syscon_regmap_lookup_by_phandle(dev->of_node, "syscon");
9961035
if (IS_ERR(regmap)) {
9971036
dev_err(dev, "failed to find syscon\n");
@@ -1001,6 +1040,19 @@ static int imx_rproc_detect_mode(struct imx_rproc *priv)
10011040
priv->regmap = regmap;
10021041
regmap_attach_dev(dev, regmap, &config);
10031042

1043+
if (priv->gpr) {
1044+
ret = regmap_read(priv->gpr, dcfg->gpr_reg, &val);
1045+
if (val & dcfg->gpr_wait) {
1046+
/*
1047+
* After cold boot, the CM indicates its in wait
1048+
* state, but not fully powered off. Power it off
1049+
* fully so firmware can be loaded into it.
1050+
*/
1051+
imx_rproc_stop(priv->rproc);
1052+
return 0;
1053+
}
1054+
}
1055+
10041056
ret = regmap_read(regmap, dcfg->src_reg, &val);
10051057
if (ret) {
10061058
dev_err(dev, "Failed to read src\n");
@@ -1142,6 +1194,8 @@ static const struct of_device_id imx_rproc_of_match[] = {
11421194
{ .compatible = "fsl,imx8mm-cm4", .data = &imx_rproc_cfg_imx8mq },
11431195
{ .compatible = "fsl,imx8mn-cm7", .data = &imx_rproc_cfg_imx8mn },
11441196
{ .compatible = "fsl,imx8mp-cm7", .data = &imx_rproc_cfg_imx8mn },
1197+
{ .compatible = "fsl,imx8mn-cm7-mmio", .data = &imx_rproc_cfg_imx8mn_mmio },
1198+
{ .compatible = "fsl,imx8mp-cm7-mmio", .data = &imx_rproc_cfg_imx8mn_mmio },
11451199
{ .compatible = "fsl,imx8qxp-cm4", .data = &imx_rproc_cfg_imx8qxp },
11461200
{ .compatible = "fsl,imx8qm-cm4", .data = &imx_rproc_cfg_imx8qm },
11471201
{ .compatible = "fsl,imx8ulp-cm33", .data = &imx_rproc_cfg_imx8ulp },

drivers/remoteproc/imx_rproc.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ struct imx_rproc_dcfg {
3131
u32 src_mask;
3232
u32 src_start;
3333
u32 src_stop;
34+
u32 gpr_reg;
35+
u32 gpr_wait;
3436
const struct imx_rproc_att *att;
3537
size_t att_size;
3638
enum imx_rproc_method method;

0 commit comments

Comments
 (0)