forked from torvalds/linux
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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 <[email protected]> Signed-off-by: Peng Fan <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Bjorn Andersson <[email protected]>
- Loading branch information
Showing
1 changed file
with
80 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,6 +3,7 @@ | |
* Copyright (c) 2017 Pengutronix, Oleksij Rempel <[email protected]> | ||
*/ | ||
|
||
#include <linux/arm-smccc.h> | ||
#include <linux/clk.h> | ||
#include <linux/err.h> | ||
#include <linux/interrupt.h> | ||
|
@@ -50,6 +51,11 @@ | |
|
||
#define IMX_RPROC_MEM_MAX 32 | ||
|
||
#define IMX_SIP_RPROC 0xC2000005 | ||
#define IMX_SIP_RPROC_START 0x00 | ||
#define IMX_SIP_RPROC_STARTED 0x01 | ||
#define IMX_SIP_RPROC_STOP 0x02 | ||
|
||
/** | ||
* struct imx_rproc_mem - slim internal memory structure | ||
* @cpu_addr: MPU virtual address of the memory region | ||
|
@@ -108,6 +114,36 @@ struct imx_rproc { | |
void __iomem *rsc_table; | ||
}; | ||
|
||
static const struct imx_rproc_att imx_rproc_att_imx8mn[] = { | ||
/* dev addr , sys addr , size , flags */ | ||
/* ITCM */ | ||
{ 0x00000000, 0x007E0000, 0x00020000, ATT_OWN }, | ||
/* OCRAM_S */ | ||
{ 0x00180000, 0x00180000, 0x00009000, 0 }, | ||
/* OCRAM */ | ||
{ 0x00900000, 0x00900000, 0x00020000, 0 }, | ||
/* OCRAM */ | ||
{ 0x00920000, 0x00920000, 0x00020000, 0 }, | ||
/* OCRAM */ | ||
{ 0x00940000, 0x00940000, 0x00050000, 0 }, | ||
/* QSPI Code - alias */ | ||
{ 0x08000000, 0x08000000, 0x08000000, 0 }, | ||
/* DDR (Code) - alias */ | ||
{ 0x10000000, 0x40000000, 0x0FFE0000, 0 }, | ||
/* DTCM */ | ||
{ 0x20000000, 0x00800000, 0x00020000, ATT_OWN }, | ||
/* OCRAM_S - alias */ | ||
{ 0x20180000, 0x00180000, 0x00008000, ATT_OWN }, | ||
/* OCRAM */ | ||
{ 0x20200000, 0x00900000, 0x00020000, ATT_OWN }, | ||
/* OCRAM */ | ||
{ 0x20220000, 0x00920000, 0x00020000, ATT_OWN }, | ||
/* OCRAM */ | ||
{ 0x20240000, 0x00940000, 0x00040000, ATT_OWN }, | ||
/* DDR (Data) */ | ||
{ 0x40000000, 0x40000000, 0x80000000, 0 }, | ||
}; | ||
|
||
static const struct imx_rproc_att imx_rproc_att_imx8mq[] = { | ||
/* dev addr , sys addr , size , flags */ | ||
/* TCML - alias */ | ||
|
@@ -194,6 +230,12 @@ static const struct imx_rproc_att imx_rproc_att_imx6sx[] = { | |
{ 0x80000000, 0x80000000, 0x60000000, 0 }, | ||
}; | ||
|
||
static const struct imx_rproc_dcfg imx_rproc_cfg_imx8mn = { | ||
.att = imx_rproc_att_imx8mn, | ||
.att_size = ARRAY_SIZE(imx_rproc_att_imx8mn), | ||
.method = IMX_RPROC_SMC, | ||
}; | ||
|
||
static const struct imx_rproc_dcfg imx_rproc_cfg_imx8mq = { | ||
.src_reg = IMX7D_SRC_SCR, | ||
.src_mask = IMX7D_M4_RST_MASK, | ||
|
@@ -235,12 +277,24 @@ static int imx_rproc_start(struct rproc *rproc) | |
struct imx_rproc *priv = rproc->priv; | ||
const struct imx_rproc_dcfg *dcfg = priv->dcfg; | ||
struct device *dev = priv->dev; | ||
struct arm_smccc_res res; | ||
int ret; | ||
|
||
ret = regmap_update_bits(priv->regmap, dcfg->src_reg, | ||
dcfg->src_mask, dcfg->src_start); | ||
switch (dcfg->method) { | ||
case IMX_RPROC_MMIO: | ||
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); | ||
ret = res.a0; | ||
break; | ||
default: | ||
return -EOPNOTSUPP; | ||
} | ||
|
||
if (ret) | ||
dev_err(dev, "Failed to enable M4!\n"); | ||
dev_err(dev, "Failed to enable remote core!\n"); | ||
|
||
return ret; | ||
} | ||
|
@@ -250,15 +304,26 @@ static int imx_rproc_stop(struct rproc *rproc) | |
struct imx_rproc *priv = rproc->priv; | ||
const struct imx_rproc_dcfg *dcfg = priv->dcfg; | ||
struct device *dev = priv->dev; | ||
struct arm_smccc_res res; | ||
int ret; | ||
|
||
if (dcfg->method == IMX_RPROC_NONE) | ||
switch (dcfg->method) { | ||
case IMX_RPROC_MMIO: | ||
ret = regmap_update_bits(priv->regmap, dcfg->src_reg, dcfg->src_mask, | ||
dcfg->src_stop); | ||
break; | ||
case IMX_RPROC_SMC: | ||
arm_smccc_smc(IMX_SIP_RPROC, IMX_SIP_RPROC_STOP, 0, 0, 0, 0, 0, 0, &res); | ||
ret = res.a0; | ||
if (res.a1) | ||
dev_info(dev, "Not in wfi, force stopped\n"); | ||
break; | ||
default: | ||
return -EOPNOTSUPP; | ||
} | ||
|
||
ret = regmap_update_bits(priv->regmap, dcfg->src_reg, | ||
dcfg->src_mask, dcfg->src_stop); | ||
if (ret) | ||
dev_err(dev, "Failed to stop M4!\n"); | ||
dev_err(dev, "Failed to stop remote core\n"); | ||
|
||
return ret; | ||
} | ||
|
@@ -594,13 +659,19 @@ static int imx_rproc_detect_mode(struct imx_rproc *priv) | |
const struct imx_rproc_dcfg *dcfg = priv->dcfg; | ||
struct device *dev = priv->dev; | ||
struct regmap *regmap; | ||
struct arm_smccc_res res; | ||
int ret; | ||
u32 val; | ||
|
||
switch (dcfg->method) { | ||
case IMX_RPROC_NONE: | ||
priv->rproc->state = RPROC_DETACHED; | ||
return 0; | ||
case IMX_RPROC_SMC: | ||
arm_smccc_smc(IMX_SIP_RPROC, IMX_SIP_RPROC_STARTED, 0, 0, 0, 0, 0, 0, &res); | ||
if (res.a0) | ||
priv->rproc->state = RPROC_DETACHED; | ||
return 0; | ||
default: | ||
break; | ||
} | ||
|
@@ -751,6 +822,8 @@ static const struct of_device_id imx_rproc_of_match[] = { | |
{ .compatible = "fsl,imx6sx-cm4", .data = &imx_rproc_cfg_imx6sx }, | ||
{ .compatible = "fsl,imx8mq-cm4", .data = &imx_rproc_cfg_imx8mq }, | ||
{ .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 }, | ||
{}, | ||
}; | ||
MODULE_DEVICE_TABLE(of, imx_rproc_of_match); | ||
|