summaryrefslogtreecommitdiff
path: root/drivers/rpmsg
diff options
context:
space:
mode:
authorRobin Gong <yibin.gong@nxp.com>2019-01-08 17:41:34 +0800
committerJason Liu <jason.hui.liu@nxp.com>2019-02-12 10:35:51 +0800
commit9abf77f37ae945dcf6236d6a2d5613a806f7e4a1 (patch)
tree0dcfc114dc134900f2a4c07c475291499e353d7f /drivers/rpmsg
parenta6624bf14422f04848c3a4da919c9e6404e907c3 (diff)
MLK-20691-1: rpmsg: imx_rpmsg: add new partition reset interrupt
Add new partition reset interrupt group to know M4 reset and restore back at rpmsg level later. Signed-off-by: Robin Gong <yibin.gong@nxp.com> Acked-by: Richard Zhu <hongxing.zhu@nxp.com>
Diffstat (limited to 'drivers/rpmsg')
-rw-r--r--drivers/rpmsg/imx_rpmsg.c84
1 files changed, 84 insertions, 0 deletions
diff --git a/drivers/rpmsg/imx_rpmsg.c b/drivers/rpmsg/imx_rpmsg.c
index 5cb97a0bb65d..3312a9aaaf84 100644
--- a/drivers/rpmsg/imx_rpmsg.c
+++ b/drivers/rpmsg/imx_rpmsg.c
@@ -32,6 +32,8 @@
#include <linux/virtio_ring.h>
#include <linux/imx_rpmsg.h>
#include <linux/mx8_mu.h>
+#include <soc/imx8/sc/sci.h>
+#include <soc/imx8/sc/svc/irq/api.h>
enum imx_rpmsg_variants {
IMX6SX,
@@ -67,6 +69,8 @@ struct imx_rpmsg_vproc {
u32 in_idx;
u32 out_idx;
u32 core_id;
+ u32 mub_partition;
+ struct notifier_block *pnotifier;
spinlock_t mu_lock;
};
@@ -102,6 +106,11 @@ struct imx_rpmsg_vq_info {
struct imx_rpmsg_vproc *rpdev;
};
+static int imx_rpmsg_partion_notify0(struct notifier_block *nb,
+ unsigned long event, void *group);
+static int imx_rpmsg_partion_notify1(struct notifier_block *nb,
+ unsigned long event, void *group);
+
static u64 imx_rpmsg_get_features(struct virtio_device *vdev)
{
/* VIRTIO_RPMSG_F_NS has been made private */
@@ -340,12 +349,23 @@ static struct virtio_config_ops imx_rpmsg_config_ops = {
.get_status = imx_rpmsg_get_status,
};
+static struct notifier_block imx_rpmsg_partion_notifier[] = {
+ {
+ .notifier_call = imx_rpmsg_partion_notify0,
+ },
+ {
+ .notifier_call = imx_rpmsg_partion_notify1,
+ },
+};
+
static struct imx_rpmsg_vproc imx_rpmsg_vprocs[] = {
{
.rproc_name = "m4",
+ .pnotifier = &imx_rpmsg_partion_notifier[0],
},
{
.rproc_name = "m4",
+ .pnotifier = &imx_rpmsg_partion_notifier[1],
},
};
@@ -465,6 +485,37 @@ static int imx_rpmsg_mu_init(struct imx_rpmsg_vproc *rpdev)
return ret;
}
+
+static int imx_rpmsg_partion_notify0(struct notifier_block *nb,
+ unsigned long event, void *group)
+{
+ struct imx_rpmsg_vproc *rpdev = &imx_rpmsg_vprocs[0];
+
+ /* Ignore other irqs */
+ if (!((event & BIT(rpdev->mub_partition)) &&
+ (*(sc_irq_group_t *)group == SC_IRQ_GROUP_REBOOTED)))
+ return 0;
+
+ pr_info("Patition%d reset!\n", rpdev->mub_partition);
+
+ return 0;
+}
+
+static int imx_rpmsg_partion_notify1(struct notifier_block *nb,
+ unsigned long event, void *group)
+{
+ struct imx_rpmsg_vproc *rpdev = &imx_rpmsg_vprocs[1];
+
+ /* Ignore other irqs */
+ if (!((event & BIT(rpdev->mub_partition)) &&
+ (*(sc_irq_group_t *)group == SC_IRQ_GROUP_REBOOTED)))
+ return 0;
+
+ pr_info("Patition%d reset!\n", rpdev->mub_partition);
+
+ return 0;
+}
+
static int imx_rpmsg_probe(struct platform_device *pdev)
{
int core_id, j, ret = 0;
@@ -589,6 +640,39 @@ static int imx_rpmsg_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, rpdev);
+ if (rpdev->variant == IMX8QXP || rpdev->variant == IMX8QM) {
+ uint32_t mu_id;
+ sc_err_t sciErr;
+ static sc_ipc_t mu_ipchandle;
+ /* Get muB partition id and enable irq in SCFW then */
+ if (of_property_read_u32(np, "mub-partition",
+ &rpdev->mub_partition))
+ rpdev->mub_partition = 3; /* default partition 3 */
+
+ sciErr = sc_ipc_getMuID(&mu_id);
+ if (sciErr != SC_ERR_NONE) {
+ pr_err("can't obtain mu id: %d\n", sciErr);
+ return sciErr;
+ }
+
+ sciErr = sc_ipc_open(&mu_ipchandle, mu_id);
+
+ if (sciErr != SC_ERR_NONE) {
+ pr_err("can't get ipc handler: %d\n", sciErr);
+ return sciErr;
+ };
+
+ /* Request for the partition reset interrupt. */
+ sciErr = sc_irq_enable(mu_ipchandle, SC_R_MU_1A,
+ SC_IRQ_GROUP_REBOOTED,
+ BIT(rpdev->mub_partition), true);
+ if (sciErr)
+ pr_info("Cannot request partition reset interrupt\n");
+
+ return register_scu_notifier(rpdev->pnotifier);
+
+ }
+
return ret;
err_out: