[PATCH 3/4] microblaze: reset: Provide a power off handler through an unaligned PC

Thomas Weißschuh <[email protected]>
Newsgroups org.kernel.vger.linux-kernel,org.kernel.vger.linux-kselftest
Message-ID <[email protected]>
microblaze is missing a generic architecture-wide power off mechanism.

To enable KUnit for microblaze it is necessary for KUnit to shut down
the machine in a way that QEMU will recognize. The machines emulated by
QEMU do not provide machine-specific power off functionality which could
be used.
However at least the petalogix-s3adsp1800 machine will abort if an
unaligned instruction is executed. An ugly message will be printed but
that is not an issue for KUnit.

Make use of this to provide a power off handler.

Signed-off-by: Thomas Weißschuh <[email protected]>

---
This is quite hacky. But I didn't find a better solution.
---
 arch/microblaze/Kconfig        |  9 +++++++++
 arch/microblaze/kernel/reset.c | 21 +++++++++++++++++++++
 2 files changed, 30 insertions(+)

diff --git a/arch/microblaze/Kconfig b/arch/microblaze/Kconfig
index 484ebb3baedf..0ca8999dd770 100644
--- a/arch/microblaze/Kconfig
+++ b/arch/microblaze/Kconfig
@@ -216,3 +216,12 @@ config MB_MANAGER
 	  Say N here unless you know what you are doing.
 
 endmenu
+
+config MB_POWER_OFF_THROUGH_UNALIGNED_PC
+	bool "Power off through unaligned PC"
+	help
+	  This options adds a power off handler which executes an unaligned PC
+	  so the machine resets in a generic way. This works for the
+	  petalogix-s3adsp1800 QEMU machine.
+
+	  Say N here unless you know what you are doing.
diff --git a/arch/microblaze/kernel/reset.c b/arch/microblaze/kernel/reset.c
index 3612a20ca16d..4af660deed3b 100644
--- a/arch/microblaze/kernel/reset.c
+++ b/arch/microblaze/kernel/reset.c
@@ -41,3 +41,24 @@ void machine_restart(char *cmd)
 	pr_emerg("Reboot failed -- System halted\n");
 	while (1);
 }
+
+#ifdef CONFIG_MB_POWER_OFF_THROUGH_UNALIGNED_PC
+static int unaligned_pc_sys_off(struct sys_off_data *data)
+{
+	__asm__(
+		"bri 1\n"
+	);
+
+	return NOTIFY_DONE;
+}
+
+static int __init register_unaligned_pc_sys_off(void)
+{
+	struct sys_off_handler *sys_off;
+
+	sys_off = register_sys_off_handler(SYS_OFF_MODE_POWER_OFF, SYS_OFF_PRIO_LOW,
+					   unaligned_pc_sys_off, NULL);
+	return PTR_ERR_OR_ZERO(sys_off);
+}
+device_initcall(register_unaligned_pc_sys_off);
+#endif /* CONFIG_MB_POWER_OFF_THROUGH_UNALIGNED_PC */

-- 
2.55.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.