Skip to content

Commit c94ea66

Browse files
MrVanmathieupoirier
authored andcommitted
remoteproc: imx_rproc: Support kicking Mcore from Linux for i.MX8QXP
When M4 is in the same hardware partition with Cortex-A, it could be start/stop by Linux. Added power domain to make sure M4 could run, it requires several power domains to work. Make clock always optional for i.MX8QXP, because SCFW handles it when power up M4 core. Signed-off-by: Peng Fan <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Mathieu Poirier <[email protected]>
1 parent 5e50aef commit c94ea66

File tree

1 file changed

+93
-3
lines changed

1 file changed

+93
-3
lines changed

drivers/remoteproc/imx_rproc.c

Lines changed: 93 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include <linux/of_reserved_mem.h>
1717
#include <linux/of_device.h>
1818
#include <linux/platform_device.h>
19+
#include <linux/pm_domain.h>
1920
#include <linux/regmap.h>
2021
#include <linux/remoteproc.h>
2122
#include <linux/workqueue.h>
@@ -79,6 +80,8 @@ struct imx_rproc_mem {
7980
#define ATT_OWN BIT(1)
8081
#define ATT_IOMEM BIT(2)
8182

83+
static int imx_rproc_detach_pd(struct rproc *rproc);
84+
8285
struct imx_rproc {
8386
struct device *dev;
8487
struct regmap *regmap;
@@ -96,6 +99,10 @@ struct imx_rproc {
9699
struct notifier_block rproc_nb;
97100
u32 rproc_pt; /* partition id */
98101
u32 rsrc_id; /* resource id */
102+
u32 entry; /* cpu start address */
103+
int num_pd;
104+
struct device **pd_dev;
105+
struct device_link **pd_dev_link;
99106
};
100107

101108
static const struct imx_rproc_att imx_rproc_att_imx93[] = {
@@ -335,6 +342,9 @@ static int imx_rproc_start(struct rproc *rproc)
335342
arm_smccc_smc(IMX_SIP_RPROC, IMX_SIP_RPROC_START, 0, 0, 0, 0, 0, 0, &res);
336343
ret = res.a0;
337344
break;
345+
case IMX_RPROC_SCU_API:
346+
ret = imx_sc_pm_cpu_start(priv->ipc_handle, priv->rsrc_id, true, priv->entry);
347+
break;
338348
default:
339349
return -EOPNOTSUPP;
340350
}
@@ -364,6 +374,9 @@ static int imx_rproc_stop(struct rproc *rproc)
364374
if (res.a1)
365375
dev_info(dev, "Not in wfi, force stopped\n");
366376
break;
377+
case IMX_RPROC_SCU_API:
378+
ret = imx_sc_pm_cpu_start(priv->ipc_handle, priv->rsrc_id, false, priv->entry);
379+
break;
367380
default:
368381
return -EOPNOTSUPP;
369382
}
@@ -713,8 +726,10 @@ static void imx_rproc_put_scu(struct rproc *rproc)
713726
if (dcfg->method != IMX_RPROC_SCU_API)
714727
return;
715728

716-
if (imx_sc_rm_is_resource_owned(priv->ipc_handle, priv->rsrc_id))
729+
if (imx_sc_rm_is_resource_owned(priv->ipc_handle, priv->rsrc_id)) {
730+
imx_rproc_detach_pd(rproc);
717731
return;
732+
}
718733

719734
imx_scu_irq_group_enable(IMX_SC_IRQ_GROUP_REBOOTED, BIT(priv->rproc_pt), false);
720735
imx_scu_irq_unregister_notifier(&priv->rproc_nb);
@@ -736,6 +751,77 @@ static int imx_rproc_partition_notify(struct notifier_block *nb,
736751
return 0;
737752
}
738753

754+
static int imx_rproc_attach_pd(struct imx_rproc *priv)
755+
{
756+
struct device *dev = priv->dev;
757+
int ret, i;
758+
759+
/*
760+
* If there is only one power-domain entry, the platform driver framework
761+
* will handle it, no need handle it in this driver.
762+
*/
763+
priv->num_pd = of_count_phandle_with_args(dev->of_node, "power-domains",
764+
"#power-domain-cells");
765+
if (priv->num_pd <= 1)
766+
return 0;
767+
768+
priv->pd_dev = devm_kmalloc_array(dev, priv->num_pd, sizeof(*priv->pd_dev), GFP_KERNEL);
769+
if (!priv->pd_dev)
770+
return -ENOMEM;
771+
772+
priv->pd_dev_link = devm_kmalloc_array(dev, priv->num_pd, sizeof(*priv->pd_dev_link),
773+
GFP_KERNEL);
774+
775+
if (!priv->pd_dev_link)
776+
return -ENOMEM;
777+
778+
for (i = 0; i < priv->num_pd; i++) {
779+
priv->pd_dev[i] = dev_pm_domain_attach_by_id(dev, i);
780+
if (IS_ERR(priv->pd_dev[i])) {
781+
ret = PTR_ERR(priv->pd_dev[i]);
782+
goto detach_pd;
783+
}
784+
785+
priv->pd_dev_link[i] = device_link_add(dev, priv->pd_dev[i], DL_FLAG_STATELESS |
786+
DL_FLAG_PM_RUNTIME | DL_FLAG_RPM_ACTIVE);
787+
if (!priv->pd_dev_link[i]) {
788+
dev_pm_domain_detach(priv->pd_dev[i], false);
789+
ret = -EINVAL;
790+
goto detach_pd;
791+
}
792+
}
793+
794+
return 0;
795+
796+
detach_pd:
797+
while (--i >= 0) {
798+
device_link_del(priv->pd_dev_link[i]);
799+
dev_pm_domain_detach(priv->pd_dev[i], false);
800+
}
801+
802+
return ret;
803+
}
804+
805+
static int imx_rproc_detach_pd(struct rproc *rproc)
806+
{
807+
struct imx_rproc *priv = rproc->priv;
808+
int i;
809+
810+
/*
811+
* If there is only one power-domain entry, the platform driver framework
812+
* will handle it, no need handle it in this driver.
813+
*/
814+
if (priv->num_pd <= 1)
815+
return 0;
816+
817+
for (i = 0; i < priv->num_pd; i++) {
818+
device_link_del(priv->pd_dev_link[i]);
819+
dev_pm_domain_detach(priv->pd_dev[i], false);
820+
}
821+
822+
return 0;
823+
}
824+
739825
static int imx_rproc_detect_mode(struct imx_rproc *priv)
740826
{
741827
struct regmap_config config = { .name = "imx-rproc" };
@@ -770,8 +856,12 @@ static int imx_rproc_detect_mode(struct imx_rproc *priv)
770856
* If Mcore resource is not owned by Acore partition, It is kicked by ROM,
771857
* and Linux could only do IPC with Mcore and nothing else.
772858
*/
773-
if (imx_sc_rm_is_resource_owned(priv->ipc_handle, priv->rsrc_id))
774-
return 0;
859+
if (imx_sc_rm_is_resource_owned(priv->ipc_handle, priv->rsrc_id)) {
860+
if (of_property_read_u32(dev->of_node, "fsl,entry-address", &priv->entry))
861+
return -EINVAL;
862+
863+
return imx_rproc_attach_pd(priv);
864+
}
775865

776866
priv->rproc->state = RPROC_DETACHED;
777867
priv->rproc->recovery_disabled = true;

0 commit comments

Comments
 (0)