diff options
author | Robin Gong <yibin.gong@nxp.com> | 2019-01-09 22:59:01 +0800 |
---|---|---|
committer | Jason Liu <jason.hui.liu@nxp.com> | 2019-02-12 10:35:52 +0800 |
commit | aa619cf5b4836de66738cf876c8335508e052dc4 (patch) | |
tree | 8059e1798e45e6fd4b843ed9b21a7b2298a65271 /drivers/rpmsg | |
parent | ac10d4fb898113e0c8de7fe567f2ac0a6d50eb6c (diff) |
MLK-20691-3 rpmsg: imx_rpmsg: add partition reset support
unregister all rpmsg devices and kick off ready notifyication
again to restore back rpmsg communications after M4 partion
reset.
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.c | 46 |
1 files changed, 46 insertions, 0 deletions
diff --git a/drivers/rpmsg/imx_rpmsg.c b/drivers/rpmsg/imx_rpmsg.c index 3312a9aaaf84..ced9c664af9d 100644 --- a/drivers/rpmsg/imx_rpmsg.c +++ b/drivers/rpmsg/imx_rpmsg.c @@ -13,6 +13,7 @@ */ #include <linux/clk.h> +#include <linux/delay.h> #include <linux/err.h> #include <linux/init.h> #include <linux/interrupt.h> @@ -34,6 +35,7 @@ #include <linux/mx8_mu.h> #include <soc/imx8/sc/sci.h> #include <soc/imx8/sc/svc/irq/api.h> +#include "rpmsg_internal.h" enum imx_rpmsg_variants { IMX6SX, @@ -486,6 +488,48 @@ static int imx_rpmsg_mu_init(struct imx_rpmsg_vproc *rpdev) return ret; } +static int imx_unregister_rpmsg(struct device *dev, + void *data) +{ + struct rpmsg_device *rpdev = to_rpmsg_device(dev); + struct rpmsg_channel_info chinfo; + int ret; + struct virtio_device *vdev = (struct virtio_device *)data; + + chinfo.src = rpdev->src; + chinfo.dst = rpdev->dst; + strncpy(chinfo.name, rpdev->id.name, RPMSG_NAME_SIZE); + rpdev->announce = rpdev->src != RPMSG_ADDR_ANY; + + ret = rpmsg_unregister_device(&vdev->dev, &chinfo); + if (ret) + dev_err(dev, "rpmsg_destroy_channel failed: %d\n", ret); + + return ret; +} + +void imx_rpmsg_restore(struct imx_rpmsg_vproc *rpdev) +{ + int i; + unsigned int mu_rpmsg = 0; + int vdev_nums = rpdev->vdev_nums; + + for (i = 0; i < vdev_nums; i++) { + /* unregister all rpmsg channels */ + device_for_each_child(&rpdev->ivdev[i].vdev.dev, + &rpdev->ivdev[i].vdev, + imx_unregister_rpmsg); + + /* Wait a while for remote bootup */ + if (!i) + usleep_range(10000, 20000); + + /* Kick-off remote again */ + MU_SendMessageTimeout(rpdev->mu_base, 1, mu_rpmsg << 16, 200); + mu_rpmsg += 2; + } +} + static int imx_rpmsg_partion_notify0(struct notifier_block *nb, unsigned long event, void *group) { @@ -496,6 +540,7 @@ static int imx_rpmsg_partion_notify0(struct notifier_block *nb, (*(sc_irq_group_t *)group == SC_IRQ_GROUP_REBOOTED))) return 0; + imx_rpmsg_restore(rpdev); pr_info("Patition%d reset!\n", rpdev->mub_partition); return 0; @@ -511,6 +556,7 @@ static int imx_rpmsg_partion_notify1(struct notifier_block *nb, (*(sc_irq_group_t *)group == SC_IRQ_GROUP_REBOOTED))) return 0; + imx_rpmsg_restore(rpdev); pr_info("Patition%d reset!\n", rpdev->mub_partition); return 0; |