aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/bcm27xx/patches-4.19/950-0124-firmware-raspberrypi-Notify-firmware-of-a-reboot.patch
blob: 8539d8442162a3fe4acc45d2ceb8a67774ee1964 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
From 68aaa2f653c83f8fda6032153566b4f895dff524 Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Sat, 12 May 2018 21:35:43 +0100
Subject: [PATCH] firmware/raspberrypi: Notify firmware of a reboot

Register for reboot notifications, sending RPI_FIRMWARE_NOTIFY_REBOOT
over the mailbox interface on reception.

Signed-off-by: Phil Elwell <phil@raspberrypi.org>
---
 drivers/firmware/raspberrypi.c | 40 +++++++++++++++++++++++++++++++++-
 1 file changed, 39 insertions(+), 1 deletion(-)

--- a/drivers/firmware/raspberrypi.c
+++ b/drivers/firmware/raspberrypi.c
@@ -14,6 +14,7 @@
 #include <linux/module.h>
 #include <linux/of_platform.h>
 #include <linux/platform_device.h>
+#include <linux/reboot.h>
 #include <linux/slab.h>
 #include <soc/bcm2835/raspberrypi-firmware.h>
 
@@ -175,6 +176,26 @@ int rpi_firmware_property(struct rpi_fir
 }
 EXPORT_SYMBOL_GPL(rpi_firmware_property);
 
+static int rpi_firmware_notify_reboot(struct notifier_block *nb,
+				      unsigned long action,
+				      void *data)
+{
+	struct rpi_firmware *fw;
+	struct platform_device *pdev = g_pdev;
+
+	if (!pdev)
+		return 0;
+
+	fw = platform_get_drvdata(pdev);
+	if (!fw)
+		return 0;
+
+	(void)rpi_firmware_property(fw, RPI_FIRMWARE_NOTIFY_REBOOT,
+				    0, 0);
+
+	return 0;
+}
+
 static void
 rpi_firmware_print_firmware_revision(struct rpi_firmware *fw)
 {
@@ -285,15 +306,32 @@ static struct platform_driver rpi_firmwa
 	.remove		= rpi_firmware_remove,
 };
 
+static struct notifier_block rpi_firmware_reboot_notifier = {
+	.notifier_call = rpi_firmware_notify_reboot,
+};
+
 static int __init rpi_firmware_init(void)
 {
-	return platform_driver_register(&rpi_firmware_driver);
+	int ret = register_reboot_notifier(&rpi_firmware_reboot_notifier);
+	if (ret)
+		goto out1;
+	ret = platform_driver_register(&rpi_firmware_driver);
+	if (ret)
+		goto out2;
+
+	return 0;
+
+out2:
+	unregister_reboot_notifier(&rpi_firmware_reboot_notifier);
+out1:
+	return ret;
 }
 subsys_initcall(rpi_firmware_init);
 
 static void __init rpi_firmware_exit(void)
 {
 	platform_driver_unregister(&rpi_firmware_driver);
+	unregister_reboot_notifier(&rpi_firmware_reboot_notifier);
 }
 module_exit(rpi_firmware_exit);