2020-02-11 15:38:06 -08:00
// SPDX-License-Identifier: GPL-2.0-or-later
# include <linux/module.h>
# include <linux/sched/signal.h>
# include <linux/acpi.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 ) ;
2023-06-04 17:22:48 +02:00
static void acpi_tiny_power_button_notify ( acpi_handle handle , u32 event , void * data )
2020-02-11 15:38:06 -08:00
{
2023-06-04 17:22:48 +02:00
kill_cad_pid ( power_signal , 1 ) ;
2020-02-11 15:38:06 -08:00
}
2023-06-04 17:22:48 +02:00
static void acpi_tiny_power_button_notify_run ( void * not_used )
2022-11-14 00:26:09 +08:00
{
2023-06-04 17:22:48 +02:00
acpi_tiny_power_button_notify ( NULL , ACPI_FIXED_HARDWARE_EVENT , NULL ) ;
2022-11-14 00:26:09 +08:00
}
2023-06-04 17:22:48 +02:00
static u32 acpi_tiny_power_button_event ( void * not_used )
2020-02-11 15:38:06 -08:00
{
2023-06-04 17:22:48 +02:00
acpi_os_execute ( OSL_NOTIFY_HANDLER , acpi_tiny_power_button_notify_run , NULL ) ;
return ACPI_INTERRUPT_HANDLED ;
}
static int acpi_tiny_power_button_add ( struct acpi_device * device )
{
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 acpi_device * device )
{
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 ( ) ;
2020-02-11 15:38:06 -08:00
}
static struct acpi_driver acpi_tiny_power_button_driver = {
. name = " tiny-power-button " ,
. class = " tiny-power-button " ,
. ids = tiny_power_button_device_ids ,
. ops = {
2023-06-04 17:22:48 +02:00
. add = acpi_tiny_power_button_add ,
. remove = acpi_tiny_power_button_remove ,
2020-02-11 15:38:06 -08:00
} ,
} ;
2020-11-13 10:26:44 +08:00
module_acpi_driver ( acpi_tiny_power_button_driver ) ;