[RFC,4/4] power: reset: Implement a PSCI SYSTEM_RESET2 reboot-mode driver

Message ID 20230724223057.1208122-5-quic_eberman@quicinc.com
State New
Headers
Series Implement a PSCI SYSTEM_RESET2 reboot-mode driver |

Commit Message

Elliot Berman July 24, 2023, 10:30 p.m. UTC
  PSCI implements a restart notifier for architectural defined resets.
The SYSTEM_RESET2 allows vendor firmware to define additional reset
types which could be mapped to the reboot reason.

Implement a driver to wire the reboot-mode framework to make vendor
SYSTEM_RESET2 calls on reboot.

Signed-off-by: Elliot Berman <quic_eberman@quicinc.com>
---
 MAINTAINERS                             |  1 +
 drivers/firmware/psci/psci.c            |  9 +++++
 drivers/power/reset/Kconfig             |  9 +++++
 drivers/power/reset/Makefile            |  1 +
 drivers/power/reset/psci-vendor-reset.c | 49 +++++++++++++++++++++++++
 include/linux/psci.h                    |  2 +
 6 files changed, 71 insertions(+)
 create mode 100644 drivers/power/reset/psci-vendor-reset.c
  

Comments

Krzysztof Kozlowski July 25, 2023, 5:44 a.m. UTC | #1
On 25/07/2023 00:30, Elliot Berman wrote:
> PSCI implements a restart notifier for architectural defined resets.
> The SYSTEM_RESET2 allows vendor firmware to define additional reset
> types which could be mapped to the reboot reason.
> 


> +
> +static const struct of_device_id psci_vendor_reset_id_table[] = {
> +	{ .compatible = "arm,psci-vendor-reset" },
> +	{ }
> +};
> +MODULE_DEVICE_TABLE(of, psci_vendor_reset_id_table);
> +
> +static struct platform_driver psci_vendor_reset_driver = {
> +	.probe = psci_vendor_reset_probe,
> +	.driver = {
> +		.name = "psci-vendor-reset",
> +		.of_match_table = of_match_ptr(psci_vendor_reset_id_table),

Drop of_match_ptr() - it is useless and if used, then it must be
balanced with conditional table.

> +	},
> +};
> +module_platform_driver(psci_vendor_reset_driver);
> +

Best regards,
Krzysztof
  
Pavan Kondeti July 26, 2023, 10:41 a.m. UTC | #2
On Mon, Jul 24, 2023 at 03:30:54PM -0700, Elliot Berman wrote:
> PSCI implements a restart notifier for architectural defined resets.
> The SYSTEM_RESET2 allows vendor firmware to define additional reset
> types which could be mapped to the reboot reason.
> 
> Implement a driver to wire the reboot-mode framework to make vendor
> SYSTEM_RESET2 calls on reboot.
> 
> Signed-off-by: Elliot Berman <quic_eberman@quicinc.com>

Do we need to skip the PSCI call from the existing PSCI restart notifier
which gets called after your newly introduced callback from reboot mode
notifier?

Thanks,
Pavan
  
Elliot Berman July 26, 2023, 5:19 p.m. UTC | #3
On 7/26/2023 3:41 AM, Pavan Kondeti wrote:
> On Mon, Jul 24, 2023 at 03:30:54PM -0700, Elliot Berman wrote:
>> PSCI implements a restart notifier for architectural defined resets.
>> The SYSTEM_RESET2 allows vendor firmware to define additional reset
>> types which could be mapped to the reboot reason.
>>
>> Implement a driver to wire the reboot-mode framework to make vendor
>> SYSTEM_RESET2 calls on reboot.
>>
>> Signed-off-by: Elliot Berman <quic_eberman@quicinc.com>
> 
> Do we need to skip the PSCI call from the existing PSCI restart notifier
> which gets called after your newly introduced callback from reboot mode
> notifier?
> 

No need, the vendor SYSTEM_RESET2 call shouldn't return if the call worked.

> Thanks,
> Pavan
  
Pavan Kondeti July 27, 2023, 3 a.m. UTC | #4
On Wed, Jul 26, 2023 at 10:19:01AM -0700, Elliot Berman wrote:
> 
> 
> On 7/26/2023 3:41 AM, Pavan Kondeti wrote:
> > On Mon, Jul 24, 2023 at 03:30:54PM -0700, Elliot Berman wrote:
> > > PSCI implements a restart notifier for architectural defined resets.
> > > The SYSTEM_RESET2 allows vendor firmware to define additional reset
> > > types which could be mapped to the reboot reason.
> > > 
> > > Implement a driver to wire the reboot-mode framework to make vendor
> > > SYSTEM_RESET2 calls on reboot.
> > > 
> > > Signed-off-by: Elliot Berman <quic_eberman@quicinc.com>
> > 
> > Do we need to skip the PSCI call from the existing PSCI restart notifier
> > which gets called after your newly introduced callback from reboot mode
> > notifier?
> > 
> 
> No need, the vendor SYSTEM_RESET2 call shouldn't return if the call worked.
> 

From the documentation of restart handlers, restarting from reboot
notifiers may not be correct. Since you hooked it up with reboot-mode
driver framework, you may restart the system much early before the
actual machine restart kicks in. Pls check. 

Thanks,
Pavan
  

Patch

diff --git a/MAINTAINERS b/MAINTAINERS
index 2da4c5f1917b..214b14c1da63 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -16984,6 +16984,7 @@  L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:	Maintained
 F:	Documentation/devicetree/bindings/power/reset/arm,psci-vendor-reset.yaml
 F:	drivers/firmware/psci/
+F:	drivers/power/reset/psci-vendor-reset.c
 F:	include/linux/psci.h
 F:	include/uapi/linux/psci.h
 
diff --git a/drivers/firmware/psci/psci.c b/drivers/firmware/psci/psci.c
index d9629ff87861..6db73f9d2304 100644
--- a/drivers/firmware/psci/psci.c
+++ b/drivers/firmware/psci/psci.c
@@ -328,6 +328,15 @@  static struct notifier_block psci_sys_reset_nb = {
 	.priority = 129,
 };
 
+void psci_vendor_sys_reset2(u32 reset_type, u32 cookie)
+{
+	if (psci_system_reset2_supported)
+		invoke_psci_fn(PSCI_FN_NATIVE(1_1, SYSTEM_RESET2),
+			reset_type | BIT_ULL(31),
+			cookie, 0);
+}
+EXPORT_SYMBOL_GPL(psci_vendor_sys_reset2);
+
 static void psci_sys_poweroff(void)
 {
 	invoke_psci_fn(PSCI_0_2_FN_SYSTEM_OFF, 0, 0, 0);
diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig
index fff07b2bd77b..1474b9d51089 100644
--- a/drivers/power/reset/Kconfig
+++ b/drivers/power/reset/Kconfig
@@ -311,4 +311,13 @@  config POWER_MLXBF
 	help
 	  This driver supports reset or low power mode handling for Mellanox BlueField.
 
+config POWER_RESET_PSCI_VENDOR_RESET
+	tristate "PSCI Vendor SYSTEM_RESET2 driver"
+	depends on ARM64 || ARM || COMPILE_TEST
+	select ARM_PSCI_FW
+	select REBOOT_MODE
+	help
+	  Say y/m here to enable driver to use Vendor SYSTEM_RESET2 types on
+	  chips which have firmware implementing custom SYSTEM_RESET2 types.
+
 endif
diff --git a/drivers/power/reset/Makefile b/drivers/power/reset/Makefile
index d763e6735ee3..d09243966b74 100644
--- a/drivers/power/reset/Makefile
+++ b/drivers/power/reset/Makefile
@@ -37,3 +37,4 @@  obj-$(CONFIG_SYSCON_REBOOT_MODE) += syscon-reboot-mode.o
 obj-$(CONFIG_POWER_RESET_SC27XX) += sc27xx-poweroff.o
 obj-$(CONFIG_NVMEM_REBOOT_MODE) += nvmem-reboot-mode.o
 obj-$(CONFIG_POWER_MLXBF) += pwr-mlxbf.o
+obj-$(CONFIG_POWER_RESET_PSCI_VENDOR_RESET) += psci-vendor-reset.o
diff --git a/drivers/power/reset/psci-vendor-reset.c b/drivers/power/reset/psci-vendor-reset.c
new file mode 100644
index 000000000000..95d027225185
--- /dev/null
+++ b/drivers/power/reset/psci-vendor-reset.c
@@ -0,0 +1,49 @@ 
+// SPDX-License-Identifier: GPL-2.0-only
+/**
+ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/reboot-mode.h>
+#include <linux/psci.h>
+
+static int psci_vendor_system_reset2(struct reboot_mode_driver *reboot, unsigned int magic)
+{
+	psci_vendor_sys_reset2(magic, 0);
+
+	return NOTIFY_DONE;
+}
+
+static int psci_vendor_reset_probe(struct platform_device *pdev)
+{
+	struct reboot_mode_driver *reboot;
+
+	reboot = devm_kzalloc(&pdev->dev, sizeof(*reboot), GFP_KERNEL);
+	if (!reboot)
+		return -ENOMEM;
+
+	reboot->write = psci_vendor_system_reset2;
+
+	return devm_reboot_mode_register(&pdev->dev, reboot);
+}
+
+static const struct of_device_id psci_vendor_reset_id_table[] = {
+	{ .compatible = "arm,psci-vendor-reset" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, psci_vendor_reset_id_table);
+
+static struct platform_driver psci_vendor_reset_driver = {
+	.probe = psci_vendor_reset_probe,
+	.driver = {
+		.name = "psci-vendor-reset",
+		.of_match_table = of_match_ptr(psci_vendor_reset_id_table),
+	},
+};
+module_platform_driver(psci_vendor_reset_driver);
+
+MODULE_DESCRIPTION("PSCI Vendor SYSTEM_RESET2 Driver");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/psci.h b/include/linux/psci.h
index 4ca0060a3fc4..0c652c12e0a8 100644
--- a/include/linux/psci.h
+++ b/include/linux/psci.h
@@ -21,6 +21,8 @@  bool psci_power_state_is_valid(u32 state);
 int psci_set_osi_mode(bool enable);
 bool psci_has_osi_support(void);
 
+void psci_vendor_sys_reset2(u32 reset_type, u32 cookie);
+
 struct psci_operations {
 	u32 (*get_version)(void);
 	int (*cpu_suspend)(u32 state, unsigned long entry_point);