Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

remoteproc: imx_rproc: support i.MX8MN/P

Add i.MX8MN/P remote processor(Cortex-M7) support, we are using ARM
SMCCC to start/stop M core, not using regmap interface.

Reviewed-by: Mathieu Poirier <mathieu.poirier@linaro.org>
Signed-off-by: Peng Fan <peng.fan@nxp.com>
Link: https://lore.kernel.org/r/1620274123-1461-9-git-send-email-peng.fan@oss.nxp.com
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>

authored by

Peng Fan and committed by
Bjorn Andersson
79806d32 c8a1a56d

+80 -7
+80 -7
drivers/remoteproc/imx_rproc.c
··· 3 3 * Copyright (c) 2017 Pengutronix, Oleksij Rempel <kernel@pengutronix.de> 4 4 */ 5 5 6 + #include <linux/arm-smccc.h> 6 7 #include <linux/clk.h> 7 8 #include <linux/err.h> 8 9 #include <linux/interrupt.h> ··· 50 49 | IMX6SX_SW_M4C_RST) 51 50 52 51 #define IMX_RPROC_MEM_MAX 32 52 + 53 + #define IMX_SIP_RPROC 0xC2000005 54 + #define IMX_SIP_RPROC_START 0x00 55 + #define IMX_SIP_RPROC_STARTED 0x01 56 + #define IMX_SIP_RPROC_STOP 0x02 53 57 54 58 /** 55 59 * struct imx_rproc_mem - slim internal memory structure ··· 112 106 struct work_struct rproc_work; 113 107 struct workqueue_struct *workqueue; 114 108 void __iomem *rsc_table; 109 + }; 110 + 111 + static const struct imx_rproc_att imx_rproc_att_imx8mn[] = { 112 + /* dev addr , sys addr , size , flags */ 113 + /* ITCM */ 114 + { 0x00000000, 0x007E0000, 0x00020000, ATT_OWN }, 115 + /* OCRAM_S */ 116 + { 0x00180000, 0x00180000, 0x00009000, 0 }, 117 + /* OCRAM */ 118 + { 0x00900000, 0x00900000, 0x00020000, 0 }, 119 + /* OCRAM */ 120 + { 0x00920000, 0x00920000, 0x00020000, 0 }, 121 + /* OCRAM */ 122 + { 0x00940000, 0x00940000, 0x00050000, 0 }, 123 + /* QSPI Code - alias */ 124 + { 0x08000000, 0x08000000, 0x08000000, 0 }, 125 + /* DDR (Code) - alias */ 126 + { 0x10000000, 0x40000000, 0x0FFE0000, 0 }, 127 + /* DTCM */ 128 + { 0x20000000, 0x00800000, 0x00020000, ATT_OWN }, 129 + /* OCRAM_S - alias */ 130 + { 0x20180000, 0x00180000, 0x00008000, ATT_OWN }, 131 + /* OCRAM */ 132 + { 0x20200000, 0x00900000, 0x00020000, ATT_OWN }, 133 + /* OCRAM */ 134 + { 0x20220000, 0x00920000, 0x00020000, ATT_OWN }, 135 + /* OCRAM */ 136 + { 0x20240000, 0x00940000, 0x00040000, ATT_OWN }, 137 + /* DDR (Data) */ 138 + { 0x40000000, 0x40000000, 0x80000000, 0 }, 115 139 }; 116 140 117 141 static const struct imx_rproc_att imx_rproc_att_imx8mq[] = { ··· 230 194 { 0x80000000, 0x80000000, 0x60000000, 0 }, 231 195 }; 232 196 197 + static const struct imx_rproc_dcfg imx_rproc_cfg_imx8mn = { 198 + .att = imx_rproc_att_imx8mn, 199 + .att_size = ARRAY_SIZE(imx_rproc_att_imx8mn), 200 + .method = IMX_RPROC_SMC, 201 + }; 202 + 233 203 static const struct imx_rproc_dcfg imx_rproc_cfg_imx8mq = { 234 204 .src_reg = IMX7D_SRC_SCR, 235 205 .src_mask = IMX7D_M4_RST_MASK, ··· 277 235 struct imx_rproc *priv = rproc->priv; 278 236 const struct imx_rproc_dcfg *dcfg = priv->dcfg; 279 237 struct device *dev = priv->dev; 238 + struct arm_smccc_res res; 280 239 int ret; 281 240 282 - ret = regmap_update_bits(priv->regmap, dcfg->src_reg, 283 - dcfg->src_mask, dcfg->src_start); 241 + switch (dcfg->method) { 242 + case IMX_RPROC_MMIO: 243 + ret = regmap_update_bits(priv->regmap, dcfg->src_reg, dcfg->src_mask, 244 + dcfg->src_start); 245 + break; 246 + case IMX_RPROC_SMC: 247 + arm_smccc_smc(IMX_SIP_RPROC, IMX_SIP_RPROC_START, 0, 0, 0, 0, 0, 0, &res); 248 + ret = res.a0; 249 + break; 250 + default: 251 + return -EOPNOTSUPP; 252 + } 253 + 284 254 if (ret) 285 - dev_err(dev, "Failed to enable M4!\n"); 255 + dev_err(dev, "Failed to enable remote core!\n"); 286 256 287 257 return ret; 288 258 } ··· 304 250 struct imx_rproc *priv = rproc->priv; 305 251 const struct imx_rproc_dcfg *dcfg = priv->dcfg; 306 252 struct device *dev = priv->dev; 253 + struct arm_smccc_res res; 307 254 int ret; 308 255 309 - if (dcfg->method == IMX_RPROC_NONE) 256 + switch (dcfg->method) { 257 + case IMX_RPROC_MMIO: 258 + ret = regmap_update_bits(priv->regmap, dcfg->src_reg, dcfg->src_mask, 259 + dcfg->src_stop); 260 + break; 261 + case IMX_RPROC_SMC: 262 + arm_smccc_smc(IMX_SIP_RPROC, IMX_SIP_RPROC_STOP, 0, 0, 0, 0, 0, 0, &res); 263 + ret = res.a0; 264 + if (res.a1) 265 + dev_info(dev, "Not in wfi, force stopped\n"); 266 + break; 267 + default: 310 268 return -EOPNOTSUPP; 269 + } 311 270 312 - ret = regmap_update_bits(priv->regmap, dcfg->src_reg, 313 - dcfg->src_mask, dcfg->src_stop); 314 271 if (ret) 315 - dev_err(dev, "Failed to stop M4!\n"); 272 + dev_err(dev, "Failed to stop remote core\n"); 316 273 317 274 return ret; 318 275 } ··· 659 594 const struct imx_rproc_dcfg *dcfg = priv->dcfg; 660 595 struct device *dev = priv->dev; 661 596 struct regmap *regmap; 597 + struct arm_smccc_res res; 662 598 int ret; 663 599 u32 val; 664 600 665 601 switch (dcfg->method) { 666 602 case IMX_RPROC_NONE: 667 603 priv->rproc->state = RPROC_DETACHED; 604 + return 0; 605 + case IMX_RPROC_SMC: 606 + arm_smccc_smc(IMX_SIP_RPROC, IMX_SIP_RPROC_STARTED, 0, 0, 0, 0, 0, 0, &res); 607 + if (res.a0) 608 + priv->rproc->state = RPROC_DETACHED; 668 609 return 0; 669 610 default: 670 611 break; ··· 822 751 { .compatible = "fsl,imx6sx-cm4", .data = &imx_rproc_cfg_imx6sx }, 823 752 { .compatible = "fsl,imx8mq-cm4", .data = &imx_rproc_cfg_imx8mq }, 824 753 { .compatible = "fsl,imx8mm-cm4", .data = &imx_rproc_cfg_imx8mq }, 754 + { .compatible = "fsl,imx8mn-cm7", .data = &imx_rproc_cfg_imx8mn }, 755 + { .compatible = "fsl,imx8mp-cm7", .data = &imx_rproc_cfg_imx8mn }, 825 756 {}, 826 757 }; 827 758 MODULE_DEVICE_TABLE(of, imx_rproc_of_match);