Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions Documentation/ABI/testing/sysfs-class-reboot-mode-reboot_modes
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
What: /sys/class/reboot-mode/<driver>/reboot_modes
Date: August 2025
KernelVersion: 6.17.0-rc1
Contact: linux-pm@vger.kernel.org
Description:
This interface exposes the reboot-mode arguments
registered with the reboot-mode framework. It is
a read-only interface and provides a space
separated list of reboot-mode arguments supported
on the current platform.
Example:
recovery fastboot bootloader

The exact sysfs path may vary depending on the
name of the driver that registers the arguments.
Example:
/sys/class/reboot-mode/nvmem-reboot-mode/reboot_modes
/sys/class/reboot-mode/syscon-reboot-mode/reboot_modes
/sys/class/reboot-mode/qcom-pon/reboot_modes

The supported arguments can be used by userspace
to invoke device reset using the reboot() system
call, with the "argument" as string to "*arg"
parameter along with LINUX_REBOOT_CMD_RESTART2.
Example:
reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
LINUX_REBOOT_CMD_RESTART2, "bootloader");

A driver can expose the supported arguments by
registering them with the reboot-mode framework
using the property names that follow the
mode-<argument> format.
Example:
mode-bootloader, mode-recovery.

This attribute is useful for scripts or initramfs
logic that need to programmatically determine
which reboot-mode arguments are valid before
triggering a reboot.
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,15 @@ properties:
- qcom,sm8650-pdc
- qcom,sm8750-pdc
- qcom,x1e80100-pdc
- qcom,x1p42100-pdc
- const: qcom,pdc

reg:
minItems: 1
items:
- description: PDC base register region
- description: Edge or Level config register for SPI interrupts
- description: PDC config for pass through or secondary IRQ mode for GPIOs

'#interrupt-cells':
const: 2
Expand All @@ -81,6 +83,10 @@ properties:
The tuples indicates the valid mapping of valid PDC ports
and their hwirq mapping.

qcom,qmp:
$ref: /schemas/types.yaml#/definitions/phandle
description: Reference to the AOSS side-channel message RAM.

required:
- compatible
- reg
Expand Down
3 changes: 3 additions & 0 deletions drivers/cpuidle/cpuidle.c
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,9 @@ noinstr int cpuidle_enter_state(struct cpuidle_device *dev,
bool broadcast = !!(target_state->flags & CPUIDLE_FLAG_TIMER_STOP);
ktime_t time_start, time_end;

if (cpus_peek_for_pending_ipi(cpumask_of(dev->cpu)))
return -EBUSY;

instrumentation_begin();

/*
Expand Down
2 changes: 2 additions & 0 deletions drivers/firmware/psci/Kconfig
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# SPDX-License-Identifier: GPL-2.0-only
config ARM_PSCI_FW
bool
select POWER_RESET
select REBOOT_MODE

config ARM_PSCI_CHECKER
bool "ARM PSCI checker"
Expand Down
92 changes: 91 additions & 1 deletion drivers/firmware/psci/psci.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,18 @@

#include <linux/acpi.h>
#include <linux/arm-smccc.h>
#include <linux/bitops.h>
#include <linux/cpuidle.h>
#include <linux/debugfs.h>
#include <linux/errno.h>
#include <linux/linkage.h>
#include <linux/of.h>
#include <linux/panic_notifier.h>
#include <linux/pm.h>
#include <linux/printk.h>
#include <linux/psci.h>
#include <linux/reboot.h>
#include <linux/reboot-mode.h>
#include <linux/slab.h>
#include <linux/suspend.h>

Expand Down Expand Up @@ -51,6 +54,24 @@ static int resident_cpu = -1;
struct psci_operations psci_ops;
static enum arm_smccc_conduit psci_conduit = SMCCC_CONDUIT_NONE;

struct psci_vendor_sysreset2 {
u32 reset_type;
u32 cookie;
bool valid;
};

static struct psci_vendor_sysreset2 vendor_reset;

static int psci_panic_event(struct notifier_block *nb, unsigned long v, void *p)
{
vendor_reset.valid = false;
return NOTIFY_DONE;
}

static struct notifier_block psci_panic_block = {
.notifier_call = psci_panic_event
};

bool psci_tos_resident_on(int cpu)
{
return cpu == resident_cpu;
Expand Down Expand Up @@ -309,7 +330,10 @@ static int get_set_conduit_method(const struct device_node *np)
static int psci_sys_reset(struct notifier_block *nb, unsigned long action,
void *data)
{
if ((reboot_mode == REBOOT_WARM || reboot_mode == REBOOT_SOFT) &&
if (vendor_reset.valid && psci_system_reset2_supported) {
invoke_psci_fn(PSCI_FN_NATIVE(1_1, SYSTEM_RESET2), vendor_reset.reset_type,
vendor_reset.cookie, 0);
} else if ((reboot_mode == REBOOT_WARM || reboot_mode == REBOOT_SOFT) &&
psci_system_reset2_supported) {
/*
* reset_type[31] = 0 (architectural)
Expand Down Expand Up @@ -547,6 +571,72 @@ static const struct platform_suspend_ops psci_suspend_ops = {
.enter = psci_system_suspend_enter,
};

static int psci_set_vendor_sys_reset2(struct reboot_mode_driver *reboot, u64 magic)
{
u32 magic_32;

if (psci_system_reset2_supported) {
magic_32 = magic & GENMASK(31, 0);
vendor_reset.reset_type = PSCI_1_1_RESET_TYPE_VENDOR_START | magic_32;
vendor_reset.cookie = (magic >> 32) & GENMASK(31, 0);
vendor_reset.valid = true;
}

return NOTIFY_DONE;
}

static int __init psci_init_vendor_reset(void)
{
struct reboot_mode_driver *reboot;
struct device_node *psci_np;
struct device_node *np;
int ret;

if (!psci_system_reset2_supported)
return -EINVAL;

psci_np = of_find_compatible_node(NULL, NULL, "arm,psci-1.0");
if (!psci_np)
return -ENODEV;

np = of_find_node_by_name(psci_np, "reboot-mode");
if (!np) {
of_node_put(psci_np);
return -ENODEV;
}

ret = atomic_notifier_chain_register(&panic_notifier_list, &psci_panic_block);
if (ret)
goto err_notifier;

reboot = kzalloc(sizeof(*reboot), GFP_KERNEL);
if (!reboot) {
ret = -ENOMEM;
goto err_kzalloc;
}

reboot->write = psci_set_vendor_sys_reset2;
reboot->driver_name = "psci";

ret = reboot_mode_register(reboot, of_fwnode_handle(np));
if (ret)
goto err_register;

of_node_put(psci_np);
of_node_put(np);
return 0;

err_register:
kfree(reboot);
err_kzalloc:
atomic_notifier_chain_unregister(&panic_notifier_list, &psci_panic_block);
err_notifier:
of_node_put(psci_np);
of_node_put(np);
return ret;
}
late_initcall(psci_init_vendor_reset)

static void __init psci_init_system_reset2(void)
{
int ret;
Expand Down
1 change: 1 addition & 0 deletions drivers/irqchip/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -508,6 +508,7 @@ config GOLDFISH_PIC
config QCOM_PDC
tristate "QCOM PDC"
depends on ARCH_QCOM
depends on QCOM_AOSS_QMP
select IRQ_DOMAIN_HIERARCHY
help
Power Domain Controller driver to manage and configure wakeup
Expand Down
Loading