mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2026-03-03 18:28:01 +01:00
While binding drivers directly to struct acpi_device objects allows basic functionality to be provided, at least in the majority of cases, there are some problems with it, related to general consistency, sysfs layout, power management operation ordering, and code cleanliness. Overall, it is better to bind drivers to platform devices than to their ACPI companions, so convert the ACPI tiny-power-button driver to a platform one. While this is not expected to alter functionality, it changes sysfs layout and so it will be visible to user space. Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> [ rjw: White space fixup ] Link: https://patch.msgid.link/5629403.Sb9uPGUboI@rafael.j.wysocki Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
84 lines
2.4 KiB
C
84 lines
2.4 KiB
C
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
#include <linux/acpi.h>
|
|
#include <linux/module.h>
|
|
#include <linux/platform_device.h>
|
|
#include <linux/sched/signal.h>
|
|
#include <acpi/button.h>
|
|
|
|
MODULE_AUTHOR("Josh Triplett");
|
|
MODULE_DESCRIPTION("ACPI Tiny Power Button Driver");
|
|
MODULE_LICENSE("GPL");
|
|
|
|
static int power_signal __read_mostly = CONFIG_ACPI_TINY_POWER_BUTTON_SIGNAL;
|
|
module_param(power_signal, int, 0644);
|
|
MODULE_PARM_DESC(power_signal, "Power button sends this signal to init");
|
|
|
|
static const struct acpi_device_id tiny_power_button_device_ids[] = {
|
|
{ ACPI_BUTTON_HID_POWER, 0 },
|
|
{ ACPI_BUTTON_HID_POWERF, 0 },
|
|
{ "", 0 },
|
|
};
|
|
MODULE_DEVICE_TABLE(acpi, tiny_power_button_device_ids);
|
|
|
|
static void acpi_tiny_power_button_notify(acpi_handle handle, u32 event, void *data)
|
|
{
|
|
kill_cad_pid(power_signal, 1);
|
|
}
|
|
|
|
static void acpi_tiny_power_button_notify_run(void *not_used)
|
|
{
|
|
acpi_tiny_power_button_notify(NULL, ACPI_FIXED_HARDWARE_EVENT, NULL);
|
|
}
|
|
|
|
static u32 acpi_tiny_power_button_event(void *not_used)
|
|
{
|
|
acpi_os_execute(OSL_NOTIFY_HANDLER, acpi_tiny_power_button_notify_run, NULL);
|
|
return ACPI_INTERRUPT_HANDLED;
|
|
}
|
|
|
|
static int acpi_tiny_power_button_probe(struct platform_device *pdev)
|
|
{
|
|
struct acpi_device *device = ACPI_COMPANION(&pdev->dev);
|
|
acpi_status status;
|
|
|
|
if (device->device_type == ACPI_BUS_TYPE_POWER_BUTTON) {
|
|
status = acpi_install_fixed_event_handler(ACPI_EVENT_POWER_BUTTON,
|
|
acpi_tiny_power_button_event,
|
|
NULL);
|
|
} else {
|
|
status = acpi_install_notify_handler(device->handle,
|
|
ACPI_DEVICE_NOTIFY,
|
|
acpi_tiny_power_button_notify,
|
|
NULL);
|
|
}
|
|
if (ACPI_FAILURE(status))
|
|
return -ENODEV;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void acpi_tiny_power_button_remove(struct platform_device *pdev)
|
|
{
|
|
struct acpi_device *device = ACPI_COMPANION(&pdev->dev);
|
|
|
|
if (device->device_type == ACPI_BUS_TYPE_POWER_BUTTON) {
|
|
acpi_remove_fixed_event_handler(ACPI_EVENT_POWER_BUTTON,
|
|
acpi_tiny_power_button_event);
|
|
} else {
|
|
acpi_remove_notify_handler(device->handle, ACPI_DEVICE_NOTIFY,
|
|
acpi_tiny_power_button_notify);
|
|
}
|
|
acpi_os_wait_events_complete();
|
|
}
|
|
|
|
static struct platform_driver acpi_tiny_power_button_driver = {
|
|
.probe = acpi_tiny_power_button_probe,
|
|
.remove = acpi_tiny_power_button_remove,
|
|
.driver = {
|
|
.name = "acpi-tiny-power-button",
|
|
.acpi_match_table = tiny_power_button_device_ids,
|
|
},
|
|
};
|
|
|
|
module_platform_driver(acpi_tiny_power_button_driver);
|