|
18 | 18 | #include <linux/of_reserved_mem.h>
|
19 | 19 | #include <linux/platform_device.h>
|
20 | 20 | #include <linux/pm_domain.h>
|
| 21 | +#include <linux/reboot.h> |
21 | 22 | #include <linux/regmap.h>
|
22 | 23 | #include <linux/remoteproc.h>
|
23 | 24 | #include <linux/workqueue.h>
|
@@ -333,6 +334,7 @@ static const struct imx_rproc_dcfg imx_rproc_cfg_imx7ulp = {
|
333 | 334 | .att = imx_rproc_att_imx7ulp,
|
334 | 335 | .att_size = ARRAY_SIZE(imx_rproc_att_imx7ulp),
|
335 | 336 | .method = IMX_RPROC_NONE,
|
| 337 | + .flags = IMX_RPROC_NEED_SYSTEM_OFF, |
336 | 338 | };
|
337 | 339 |
|
338 | 340 | static const struct imx_rproc_dcfg imx_rproc_cfg_imx7d = {
|
@@ -1050,6 +1052,22 @@ static int imx_rproc_clk_enable(struct imx_rproc *priv)
|
1050 | 1052 | return 0;
|
1051 | 1053 | }
|
1052 | 1054 |
|
| 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 | + |
1053 | 1071 | static int imx_rproc_probe(struct platform_device *pdev)
|
1054 | 1072 | {
|
1055 | 1073 | struct device *dev = &pdev->dev;
|
@@ -1104,6 +1122,30 @@ static int imx_rproc_probe(struct platform_device *pdev)
|
1104 | 1122 | if (rproc->state != RPROC_DETACHED)
|
1105 | 1123 | rproc->auto_boot = of_property_read_bool(np, "fsl,auto-boot");
|
1106 | 1124 |
|
| 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 | + |
1107 | 1149 | ret = rproc_add(rproc);
|
1108 | 1150 | if (ret) {
|
1109 | 1151 | dev_err(dev, "rproc_add failed\n");
|
|
0 commit comments