diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2026-08-24 08:46:03 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2026-08-24 08:46:03 -0700 |
| commit | cf9610f9116d55c5a66ef9f1faecacabd93a9322 (patch) | |
| tree | 757a3d280760c654767631cab5ad8af2d86d1848 /drivers/acpi/wakeup.c | |
| download | linux-stable-cf9610f9116d55c5a66ef9f1faecacabd93a9322.tar.gz linux-stable-cf9610f9116d55c5a66ef9f1faecacabd93a9322.zip | |
Merge tag 'pinctrl-v7.3-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrlgrafted
Pull pin control updates from Linus Walleij:
"Core changes:
- Use the non-blocking mux_state_try_select() in the generic MUX pin
control back-end
- Free pin maps on pinctrl_generic_to_map() failure in the core
helpers
New hardware pin control:
- Qualcomm Maili TLMM SoC, PMG1110 PMIC, and Eliza LPASS LPI TLMM SoC
(this is for the low power audio, LPASS = Low Power Audio SubSystem
portions)
- Upboard support on top of the Intel pin controller
- Apple T6030 and T6031 support (just compatible strings)
- Samsung Exynos 8855 SoC
- Mediatek MT6858 SoC
- Rockchip RK3308B and RV1106 SoCs
- Airoha EN7523 and AN7563 SoCs
Improvements:
- Qualcomm TLMM GPIOs are unconditionally marked as wakeup capable
- Qualcomm improvements on top of the Qualcomm PDC (power domain
controller) irqchip improvements from tglx:s tree
- Qualcomm IPQ806x and IPQ9650 non-urgent pin grop fixups
- The NPCM8xx driver has been put into shape fixing many pin and
group definitions
- Some non-urgent Tegra 264 pin assignments are fixed up
- Some non-urgent fixups to Airoha AN7581 and AN7583 registers and
pin assignments, missing features etc"
* tag 'pinctrl-v7.3-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl: (130 commits)
dt-bindings: pinctrl: Convert TI DA850 pupd to DT schema
pinctrl: meson: sync some modify from A4
pinctrl: meson: a4: Add input enable pin configuration
pinctrl: realtek: rtd1625: remove unused group name spdif_sel
pinctrl: realtek: rtd1625: fix base_bit for VE4 GPIO 13
dt-bindings: pinctrl: microchip,pic32mzda-pinctrl: Convert to DT schema
Revert "Merge branch 'ib-rsk7204' into devel"
pinctrl: rockchip: Add RV1106 pinctrl support
dt-bindings: pinctrl: rockchip: Add RV1106 compatible
pinctrl: rockchip: Decode drive strength in the get function
pinctrl: fix PINCTRL_GENERIC_MUX not always being selectable
pinctrl: airoha: add support of an7563 SoC
dt-bindings: pinctrl: airoha: add support of an7563 pin controller
pinctrl: airoha: try to find chip scu node by phandle first
pinctrl: airoha: add support of en7523 SoC
dt-bindings: pinctrl: airoha: add support of en7523 pin controller
pinctrl: airoha: an7583: add support for olt pinmux
pinctrl: airoha: an7583: add support for pon_alt pinmux
pinctrl: airoha: an7583: add support for npu_uart pinmux
dt-bindings: pinctrl: airoha: an7583: add missed features
...
Diffstat (limited to 'drivers/acpi/wakeup.c')
| -rw-r--r-- | drivers/acpi/wakeup.c | 171 |
1 files changed, 171 insertions, 0 deletions
diff --git a/drivers/acpi/wakeup.c b/drivers/acpi/wakeup.c new file mode 100644 index 000000000..0cbee0f06 --- /dev/null +++ b/drivers/acpi/wakeup.c @@ -0,0 +1,171 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * wakeup.c - support wakeup devices + * Copyright (C) 2004 Li Shaohua <shaohua.li@intel.com> + */ + +#include <linux/init.h> +#include <linux/acpi.h> +#include <linux/kernel.h> +#include <linux/types.h> + +#include "internal.h" +#include "sleep.h" + +struct acpi_wakeup_handler { + struct list_head list_node; + bool (*wakeup)(void *context); + void *context; +}; + +static LIST_HEAD(acpi_wakeup_handler_head); +static DEFINE_MUTEX(acpi_wakeup_handler_mutex); + +/* + * We didn't lock acpi_device_lock in the file, because it invokes oops in + * suspend/resume and isn't really required as this is called in S-state. At + * that time, there is no device hotplug + **/ + +/** + * acpi_enable_wakeup_devices - Enable wake-up device GPEs. + * @sleep_state: ACPI system sleep state. + * + * Enable wakeup device power of devices with the state.enable flag set and set + * the wakeup enable mask bits in the GPE registers that correspond to wakeup + * devices. + */ +void acpi_enable_wakeup_devices(u8 sleep_state) +{ + struct acpi_device *dev, *tmp; + + list_for_each_entry_safe(dev, tmp, &acpi_wakeup_device_list, + wakeup_list) { + if (!dev->wakeup.flags.valid + || sleep_state > dev->wakeup.sleep_state + || !(device_may_wakeup(&dev->dev) + || dev->wakeup.prepare_count)) + continue; + + if (device_may_wakeup(&dev->dev)) + acpi_enable_wakeup_device_power(dev, sleep_state); + + /* The wake-up power should have been enabled already. */ + acpi_set_gpe_wake_mask(dev->wakeup.gpe_device, dev->wakeup.gpe_number, + ACPI_GPE_ENABLE); + } +} + +/** + * acpi_disable_wakeup_devices - Disable devices' wakeup capability. + * @sleep_state: ACPI system sleep state. + */ +void acpi_disable_wakeup_devices(u8 sleep_state) +{ + struct acpi_device *dev, *tmp; + + list_for_each_entry_safe(dev, tmp, &acpi_wakeup_device_list, + wakeup_list) { + if (!dev->wakeup.flags.valid + || sleep_state > dev->wakeup.sleep_state + || !(device_may_wakeup(&dev->dev) + || dev->wakeup.prepare_count)) + continue; + + acpi_set_gpe_wake_mask(dev->wakeup.gpe_device, dev->wakeup.gpe_number, + ACPI_GPE_DISABLE); + + if (device_may_wakeup(&dev->dev)) + acpi_disable_wakeup_device_power(dev); + } +} + +int __init acpi_wakeup_device_init(void) +{ + struct acpi_device *dev, *tmp; + + mutex_lock(&acpi_device_lock); + list_for_each_entry_safe(dev, tmp, &acpi_wakeup_device_list, + wakeup_list) { + if (device_can_wakeup(&dev->dev)) { + /* Button GPEs are supposed to be always enabled. */ + acpi_enable_gpe(dev->wakeup.gpe_device, + dev->wakeup.gpe_number); + device_set_wakeup_enable(&dev->dev, true); + } + } + mutex_unlock(&acpi_device_lock); + return 0; +} + +/** + * acpi_register_wakeup_handler - Register wakeup handler + * @wake_irq: The IRQ through which the device may receive wakeups + * @wakeup: Wakeup-handler to call when the SCI has triggered a wakeup + * @context: Context to pass to the handler when calling it + * + * Drivers which may share an IRQ with the SCI can use this to register + * a handler which returns true when the device they are managing wants + * to trigger a wakeup. + */ +int acpi_register_wakeup_handler(int wake_irq, bool (*wakeup)(void *context), + void *context) +{ + struct acpi_wakeup_handler *handler; + + /* + * If the device is not sharing its IRQ with the SCI, there is no + * need to register the handler. + */ + if (!acpi_sci_irq_valid() || wake_irq != acpi_sci_irq) + return 0; + + handler = kmalloc_obj(*handler); + if (!handler) + return -ENOMEM; + + handler->wakeup = wakeup; + handler->context = context; + + mutex_lock(&acpi_wakeup_handler_mutex); + list_add(&handler->list_node, &acpi_wakeup_handler_head); + mutex_unlock(&acpi_wakeup_handler_mutex); + + return 0; +} +EXPORT_SYMBOL_GPL(acpi_register_wakeup_handler); + +/** + * acpi_unregister_wakeup_handler - Unregister wakeup handler + * @wakeup: Wakeup-handler passed to acpi_register_wakeup_handler() + * @context: Context passed to acpi_register_wakeup_handler() + */ +void acpi_unregister_wakeup_handler(bool (*wakeup)(void *context), + void *context) +{ + struct acpi_wakeup_handler *handler; + + mutex_lock(&acpi_wakeup_handler_mutex); + list_for_each_entry(handler, &acpi_wakeup_handler_head, list_node) { + if (handler->wakeup == wakeup && handler->context == context) { + list_del(&handler->list_node); + kfree(handler); + break; + } + } + mutex_unlock(&acpi_wakeup_handler_mutex); +} +EXPORT_SYMBOL_GPL(acpi_unregister_wakeup_handler); + +bool acpi_check_wakeup_handlers(void) +{ + struct acpi_wakeup_handler *handler; + + /* No need to lock, nothing else is running when we're called. */ + list_for_each_entry(handler, &acpi_wakeup_handler_head, list_node) { + if (handler->wakeup(handler->context)) + return true; + } + + return false; +} |
