2005-04-17 02:20:36 +04:00
/*
* wakeup . c - support wakeup devices
* Copyright ( C ) 2004 Li Shaohua < shaohua . li @ intel . com >
*/
# include <linux/init.h>
# include <linux/acpi.h>
# include <acpi/acpi_drivers.h>
# include <linux/kernel.h>
# include <linux/types.h>
2009-03-13 21:08:26 +03:00
# include "internal.h"
2005-04-17 02:20:36 +04:00
# include "sleep.h"
2009-04-07 06:24:29 +04:00
/*
* 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
* */
2005-04-17 02:20:36 +04:00
# define _COMPONENT ACPI_SYSTEM_COMPONENT
2005-08-05 08:44:28 +04:00
ACPI_MODULE_NAME ( " wakeup_devices " )
2005-04-17 02:20:36 +04:00
/**
2010-02-18 01:41:07 +03:00
* acpi_enable_wakeup_device_prep - Prepare wake - up devices .
* @ sleep_state : ACPI system sleep state .
*
* Enable all wake - up devices ' power , unless the requested system sleep state is
* too deep .
2005-04-17 02:20:36 +04:00
*/
2005-08-05 08:44:28 +04:00
void acpi_enable_wakeup_device_prep ( u8 sleep_state )
2005-04-17 02:20:36 +04:00
{
2005-08-05 08:44:28 +04:00
struct list_head * node , * next ;
2005-04-17 02:20:36 +04:00
list_for_each_safe ( node , next , & acpi_wakeup_device_list ) {
2005-08-05 08:44:28 +04:00
struct acpi_device * dev = container_of ( node ,
struct acpi_device ,
wakeup_list ) ;
2010-02-18 01:41:07 +03:00
if ( ! dev - > wakeup . flags . valid | | ! dev - > wakeup . state . enabled
| | ( sleep_state > ( u32 ) dev - > wakeup . sleep_state ) )
2005-04-17 02:20:36 +04:00
continue ;
2008-07-07 05:33:34 +04:00
acpi_enable_wakeup_device_power ( dev , sleep_state ) ;
2005-04-17 02:20:36 +04:00
}
}
/**
2010-02-18 01:41:07 +03:00
* acpi_enable_wakeup_device - Enable wake - up device GPEs .
* @ sleep_state : ACPI system sleep state .
*
* Enable all wake - up devices ' GPEs , with the assumption that
* acpi_disable_all_gpes ( ) was executed before , so we don ' t need to disable any
* GPEs here .
2005-04-17 02:20:36 +04:00
*/
2005-08-05 08:44:28 +04:00
void acpi_enable_wakeup_device ( u8 sleep_state )
2005-04-17 02:20:36 +04:00
{
2005-08-05 08:44:28 +04:00
struct list_head * node , * next ;
2005-04-17 02:20:36 +04:00
/*
* Caution : this routine must be invoked when interrupt is disabled
* Refer ACPI2 .0 : P212
*/
list_for_each_safe ( node , next , & acpi_wakeup_device_list ) {
2007-09-26 19:47:30 +04:00
struct acpi_device * dev =
container_of ( node , struct acpi_device , wakeup_list ) ;
2008-07-07 05:34:48 +04:00
2010-06-17 19:40:57 +04:00
if ( ! dev - > wakeup . flags . valid | | ! dev - > wakeup . state . enabled
2010-02-18 01:41:07 +03:00
| | sleep_state > ( u32 ) dev - > wakeup . sleep_state )
2005-04-17 02:20:36 +04:00
continue ;
2010-02-18 01:41:07 +03:00
/* The wake-up power should have been enabled already. */
2010-06-17 19:40:57 +04:00
acpi_enable_gpe ( dev - > wakeup . gpe_device , dev - > wakeup . gpe_number ,
ACPI_GPE_TYPE_WAKE ) ;
2005-04-17 02:20:36 +04:00
}
}
/**
2010-02-18 01:41:07 +03:00
* acpi_disable_wakeup_device - Disable devices ' wakeup capability .
* @ sleep_state : ACPI system sleep state .
*
* This function only affects devices with wakeup . state . enabled set , which means
* that it reverses the changes made by acpi_enable_wakeup_device_prep ( ) .
2005-04-17 02:20:36 +04:00
*/
2005-08-05 08:44:28 +04:00
void acpi_disable_wakeup_device ( u8 sleep_state )
2005-04-17 02:20:36 +04:00
{
2005-08-05 08:44:28 +04:00
struct list_head * node , * next ;
2005-04-17 02:20:36 +04:00
list_for_each_safe ( node , next , & acpi_wakeup_device_list ) {
2007-09-26 19:47:30 +04:00
struct acpi_device * dev =
container_of ( node , struct acpi_device , wakeup_list ) ;
2005-04-17 02:20:36 +04:00
2010-02-18 01:41:07 +03:00
if ( ! dev - > wakeup . flags . valid | | ! dev - > wakeup . state . enabled
| | ( sleep_state > ( u32 ) dev - > wakeup . sleep_state ) )
2005-04-17 02:20:36 +04:00
continue ;
2010-06-17 19:40:57 +04:00
acpi_disable_gpe ( dev - > wakeup . gpe_device , dev - > wakeup . gpe_number ,
ACPI_GPE_TYPE_WAKE ) ;
2005-04-17 02:20:36 +04:00
acpi_disable_wakeup_device_power ( dev ) ;
}
}
2009-03-25 01:50:19 +03:00
int __init acpi_wakeup_device_init ( void )
2005-04-17 02:20:36 +04:00
{
2005-08-05 08:44:28 +04:00
struct list_head * node , * next ;
2005-04-17 02:20:36 +04:00
2009-04-07 06:24:29 +04:00
mutex_lock ( & acpi_device_lock ) ;
2005-04-17 02:20:36 +04:00
list_for_each_safe ( node , next , & acpi_wakeup_device_list ) {
2005-08-05 08:44:28 +04:00
struct acpi_device * dev = container_of ( node ,
struct acpi_device ,
wakeup_list ) ;
2010-06-17 19:40:57 +04:00
if ( dev - > wakeup . flags . always_enabled )
dev - > wakeup . state . enabled = 1 ;
2005-04-17 02:20:36 +04:00
}
2009-04-07 06:24:29 +04:00
mutex_unlock ( & acpi_device_lock ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
}