📄 wakeup.c
字号:
/* * 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>#include <acpi/acevents.h>#include "sleep.h"#define _COMPONENT ACPI_SYSTEM_COMPONENTACPI_MODULE_NAME("wakeup_devices")extern struct list_head acpi_wakeup_device_list;extern spinlock_t acpi_device_lock;#ifdef CONFIG_ACPI_SLEEP/** * acpi_enable_wakeup_device_prep - prepare wakeup devices * @sleep_state: ACPI state * Enable all wakup devices power if the devices' wakeup level * is higher than requested sleep level */void acpi_enable_wakeup_device_prep(u8 sleep_state){ struct list_head *node, *next; ACPI_FUNCTION_TRACE("acpi_enable_wakeup_device_prep"); spin_lock(&acpi_device_lock); list_for_each_safe(node, next, &acpi_wakeup_device_list) { struct acpi_device *dev = container_of(node, struct acpi_device, wakeup_list); if (!dev->wakeup.flags.valid || !dev->wakeup.state.enabled || (sleep_state > (u32) dev->wakeup.sleep_state)) continue; spin_unlock(&acpi_device_lock); acpi_enable_wakeup_device_power(dev); spin_lock(&acpi_device_lock); } spin_unlock(&acpi_device_lock);}/** * acpi_enable_wakeup_device - enable wakeup devices * @sleep_state: ACPI state * Enable all wakup devices's GPE */void acpi_enable_wakeup_device(u8 sleep_state){ struct list_head *node, *next; /* * Caution: this routine must be invoked when interrupt is disabled * Refer ACPI2.0: P212 */ ACPI_FUNCTION_TRACE("acpi_enable_wakeup_device"); spin_lock(&acpi_device_lock); list_for_each_safe(node, next, &acpi_wakeup_device_list) { struct acpi_device *dev = container_of(node, struct acpi_device, wakeup_list); /* If users want to disable run-wake GPE, * we only disable it for wake and leave it for runtime */ if (dev->wakeup.flags.run_wake && !dev->wakeup.state.enabled) { spin_unlock(&acpi_device_lock); acpi_set_gpe_type(dev->wakeup.gpe_device, dev->wakeup.gpe_number, ACPI_GPE_TYPE_RUNTIME); /* Re-enable it, since set_gpe_type will disable it */ acpi_enable_gpe(dev->wakeup.gpe_device, dev->wakeup.gpe_number, ACPI_ISR); spin_lock(&acpi_device_lock); continue; } if (!dev->wakeup.flags.valid || !dev->wakeup.state.enabled || (sleep_state > (u32) dev->wakeup.sleep_state)) continue; spin_unlock(&acpi_device_lock); /* run-wake GPE has been enabled */ if (!dev->wakeup.flags.run_wake) acpi_enable_gpe(dev->wakeup.gpe_device, dev->wakeup.gpe_number, ACPI_ISR); dev->wakeup.state.active = 1; spin_lock(&acpi_device_lock); } spin_unlock(&acpi_device_lock);}/** * acpi_disable_wakeup_device - disable devices' wakeup capability * @sleep_state: ACPI state * Disable all wakup devices's GPE and wakeup capability */void acpi_disable_wakeup_device(u8 sleep_state){ struct list_head *node, *next; ACPI_FUNCTION_TRACE("acpi_disable_wakeup_device"); spin_lock(&acpi_device_lock); list_for_each_safe(node, next, &acpi_wakeup_device_list) { struct acpi_device *dev = container_of(node, struct acpi_device, wakeup_list); if (dev->wakeup.flags.run_wake && !dev->wakeup.state.enabled) { spin_unlock(&acpi_device_lock); acpi_set_gpe_type(dev->wakeup.gpe_device, dev->wakeup.gpe_number, ACPI_GPE_TYPE_WAKE_RUN); /* Re-enable it, since set_gpe_type will disable it */ acpi_enable_gpe(dev->wakeup.gpe_device, dev->wakeup.gpe_number, ACPI_NOT_ISR); spin_lock(&acpi_device_lock); continue; } if (!dev->wakeup.flags.valid || !dev->wakeup.state.active || (sleep_state > (u32) dev->wakeup.sleep_state)) continue; spin_unlock(&acpi_device_lock); acpi_disable_wakeup_device_power(dev); /* Never disable run-wake GPE */ if (!dev->wakeup.flags.run_wake) { acpi_disable_gpe(dev->wakeup.gpe_device, dev->wakeup.gpe_number, ACPI_NOT_ISR); acpi_clear_gpe(dev->wakeup.gpe_device, dev->wakeup.gpe_number, ACPI_NOT_ISR); } dev->wakeup.state.active = 0; spin_lock(&acpi_device_lock); } spin_unlock(&acpi_device_lock);}static int __init acpi_wakeup_device_init(void){ struct list_head *node, *next; if (acpi_disabled) return 0; printk("ACPI wakeup devices: \n"); spin_lock(&acpi_device_lock); list_for_each_safe(node, next, &acpi_wakeup_device_list) { struct acpi_device *dev = container_of(node, struct acpi_device, wakeup_list); /* In case user doesn't load button driver */ if (dev->wakeup.flags.run_wake && !dev->wakeup.state.enabled) { spin_unlock(&acpi_device_lock); acpi_set_gpe_type(dev->wakeup.gpe_device, dev->wakeup.gpe_number, ACPI_GPE_TYPE_WAKE_RUN); acpi_enable_gpe(dev->wakeup.gpe_device, dev->wakeup.gpe_number, ACPI_NOT_ISR); dev->wakeup.state.enabled = 1; spin_lock(&acpi_device_lock); } printk("%4s ", dev->pnp.bus_id); } spin_unlock(&acpi_device_lock); printk("\n"); return 0;}late_initcall(acpi_wakeup_device_init);#endif/* * Disable all wakeup GPEs before power off. * * Since acpi_enter_sleep_state() will disable all * RUNTIME GPEs, we simply mark all GPES that * are not enabled for wakeup from S5 as RUNTIME. */void acpi_wakeup_gpe_poweroff_prepare(void){ struct list_head *node, *next; list_for_each_safe(node, next, &acpi_wakeup_device_list) { struct acpi_device *dev = container_of(node, struct acpi_device, wakeup_list); /* The GPE can wakeup system from S5, don't touch it */ if ((u32) dev->wakeup.sleep_state == ACPI_STATE_S5) continue; /* acpi_set_gpe_type will automatically disable GPE */ acpi_set_gpe_type(dev->wakeup.gpe_device, dev->wakeup.gpe_number, ACPI_GPE_TYPE_RUNTIME); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -