Skip to content

Commit ff555fc

Browse files
MrVanmathieupoirier
authored andcommitted
remoteproc: imx_rproc: Add support for poweroff and reboot
On some NXP platforms (e.g i.MX7ULP) the poweroff and reboot operations are done via a separate remote core. Typically Linux needs to send a message to the remote core and requests for poweroff or reboot. By default the communication between Linux core and the remote core is is done via a blocking mailbox mechanism but Linux doesn't allow blocking operations in the system off (reboot, power off) handlers. So, we need to make sure the mailbox message send operations do not block for this specific operations. Fortunately, Linux allows us to register handlers that are called in preparation of the system off operations. Thus, before carrying the power off or reboot preparations, just destroy the existing mailboxes and create them as non-blocking. Note that power off and restart are totally different operations and are not complementary. We introduce a new flag in the imx remoteproc per device data which tells us when a device needs this special setup. For now, only imx7ulp needs it. Signed-off-by: Peng Fan <[email protected]> Reviewed-by: Daniel Baluta <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Mathieu Poirier <[email protected]>
1 parent d9dbd71 commit ff555fc

File tree

2 files changed

+46
-0
lines changed

2 files changed

+46
-0
lines changed

drivers/remoteproc/imx_rproc.c

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <linux/of_reserved_mem.h>
1919
#include <linux/platform_device.h>
2020
#include <linux/pm_domain.h>
21+
#include <linux/reboot.h>
2122
#include <linux/regmap.h>
2223
#include <linux/remoteproc.h>
2324
#include <linux/workqueue.h>
@@ -333,6 +334,7 @@ static const struct imx_rproc_dcfg imx_rproc_cfg_imx7ulp = {
333334
.att = imx_rproc_att_imx7ulp,
334335
.att_size = ARRAY_SIZE(imx_rproc_att_imx7ulp),
335336
.method = IMX_RPROC_NONE,
337+
.flags = IMX_RPROC_NEED_SYSTEM_OFF,
336338
};
337339

338340
static const struct imx_rproc_dcfg imx_rproc_cfg_imx7d = {
@@ -1050,6 +1052,22 @@ static int imx_rproc_clk_enable(struct imx_rproc *priv)
10501052
return 0;
10511053
}
10521054

1055+
static int imx_rproc_sys_off_handler(struct sys_off_data *data)
1056+
{
1057+
struct rproc *rproc = data->cb_data;
1058+
int ret;
1059+
1060+
imx_rproc_free_mbox(rproc);
1061+
1062+
ret = imx_rproc_xtr_mbox_init(rproc, false);
1063+
if (ret) {
1064+
dev_err(&rproc->dev, "Failed to request non-blocking mbox\n");
1065+
return NOTIFY_BAD;
1066+
}
1067+
1068+
return NOTIFY_DONE;
1069+
}
1070+
10531071
static int imx_rproc_probe(struct platform_device *pdev)
10541072
{
10551073
struct device *dev = &pdev->dev;
@@ -1104,6 +1122,30 @@ static int imx_rproc_probe(struct platform_device *pdev)
11041122
if (rproc->state != RPROC_DETACHED)
11051123
rproc->auto_boot = of_property_read_bool(np, "fsl,auto-boot");
11061124

1125+
if (dcfg->flags & IMX_RPROC_NEED_SYSTEM_OFF) {
1126+
/*
1127+
* setup mailbox to non-blocking mode in
1128+
* [SYS_OFF_MODE_POWER_OFF_PREPARE, SYS_OFF_MODE_RESTART_PREPARE]
1129+
* phase before invoking [SYS_OFF_MODE_POWER_OFF, SYS_OFF_MODE_RESTART]
1130+
* atomic chain, see kernel/reboot.c.
1131+
*/
1132+
ret = devm_register_sys_off_handler(dev, SYS_OFF_MODE_POWER_OFF_PREPARE,
1133+
SYS_OFF_PRIO_DEFAULT,
1134+
imx_rproc_sys_off_handler, rproc);
1135+
if (ret) {
1136+
dev_err(dev, "register power off handler failure\n");
1137+
goto err_put_clk;
1138+
}
1139+
1140+
ret = devm_register_sys_off_handler(dev, SYS_OFF_MODE_RESTART_PREPARE,
1141+
SYS_OFF_PRIO_DEFAULT,
1142+
imx_rproc_sys_off_handler, rproc);
1143+
if (ret) {
1144+
dev_err(dev, "register restart handler failure\n");
1145+
goto err_put_clk;
1146+
}
1147+
}
1148+
11071149
ret = rproc_add(rproc);
11081150
if (ret) {
11091151
dev_err(dev, "rproc_add failed\n");

drivers/remoteproc/imx_rproc.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ enum imx_rproc_method {
2626
IMX_RPROC_SCU_API,
2727
};
2828

29+
/* dcfg flags */
30+
#define IMX_RPROC_NEED_SYSTEM_OFF BIT(0)
31+
2932
struct imx_rproc_dcfg {
3033
u32 src_reg;
3134
u32 src_mask;
@@ -36,6 +39,7 @@ struct imx_rproc_dcfg {
3639
const struct imx_rproc_att *att;
3740
size_t att_size;
3841
enum imx_rproc_method method;
42+
u32 flags;
3943
};
4044

4145
#endif /* _IMX_RPROC_H */

0 commit comments

Comments
 (0)