11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * wakeup.c - support wakeup devices 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 2004 Li Shaohua <shaohua.li@intel.com> 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/acpi.h> 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h> 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/types.h> 10e60cc7a6f02598fc23c68a656fe9c263d6531ca0Bjorn Helgaas 11e60cc7a6f02598fc23c68a656fe9c263d6531ca0Bjorn Helgaas#include "internal.h" 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "sleep.h" 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 149090589d87506c578ea1523ffd7ae7fd9424fb28Shaohua Li/* 159090589d87506c578ea1523ffd7ae7fd9424fb28Shaohua Li * We didn't lock acpi_device_lock in the file, because it invokes oops in 169090589d87506c578ea1523ffd7ae7fd9424fb28Shaohua Li * suspend/resume and isn't really required as this is called in S-state. At 179090589d87506c578ea1523ffd7ae7fd9424fb28Shaohua Li * that time, there is no device hotplug 189090589d87506c578ea1523ffd7ae7fd9424fb28Shaohua Li **/ 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define _COMPONENT ACPI_SYSTEM_COMPONENT 204be44fcd3bf648b782f4460fd06dfae6c42ded4bLen BrownACPI_MODULE_NAME("wakeup_devices") 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 2378f5f023167813130d2cf657d1b9eadc32f0e992Rafael J. Wysocki * acpi_enable_wakeup_devices - Enable wake-up device GPEs. 249630bdd9b15d2f489c646d8bc04b60e53eb5ec78Rafael J. Wysocki * @sleep_state: ACPI system sleep state. 259630bdd9b15d2f489c646d8bc04b60e53eb5ec78Rafael J. Wysocki * 2678f5f023167813130d2cf657d1b9eadc32f0e992Rafael J. Wysocki * Enable wakeup device power of devices with the state.enable flag set and set 2778f5f023167813130d2cf657d1b9eadc32f0e992Rafael J. Wysocki * the wakeup enable mask bits in the GPE registers that correspond to wakeup 2878f5f023167813130d2cf657d1b9eadc32f0e992Rafael J. Wysocki * devices. 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3078f5f023167813130d2cf657d1b9eadc32f0e992Rafael J. Wysockivoid acpi_enable_wakeup_devices(u8 sleep_state) 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 324be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown struct list_head *node, *next; 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds list_for_each_safe(node, next, &acpi_wakeup_device_list) { 359b039330808b83acac3597535da26f47ad1862ceAlexey Starikovskiy struct acpi_device *dev = 369b039330808b83acac3597535da26f47ad1862ceAlexey Starikovskiy container_of(node, struct acpi_device, wakeup_list); 37eb9d0fe40e313c0a74115ef456a2e43a6c8da72fRafael J. Wysocki 38e8b6f970107cfc9c00cdcdb12ec6c7e135cf379fRafael J. Wysocki if (!dev->wakeup.flags.valid 39f2b56bc808addb908a5bf435d9b942c02af9a7c4Rafael J. Wysocki || sleep_state > (u32) dev->wakeup.sleep_state 40f2b56bc808addb908a5bf435d9b942c02af9a7c4Rafael J. Wysocki || !(device_may_wakeup(&dev->dev) 41f2b56bc808addb908a5bf435d9b942c02af9a7c4Rafael J. Wysocki || dev->wakeup.prepare_count)) 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continue; 439630bdd9b15d2f489c646d8bc04b60e53eb5ec78Rafael J. Wysocki 44f2b56bc808addb908a5bf435d9b942c02af9a7c4Rafael J. Wysocki if (device_may_wakeup(&dev->dev)) 4578f5f023167813130d2cf657d1b9eadc32f0e992Rafael J. Wysocki acpi_enable_wakeup_device_power(dev, sleep_state); 4678f5f023167813130d2cf657d1b9eadc32f0e992Rafael J. Wysocki 479630bdd9b15d2f489c646d8bc04b60e53eb5ec78Rafael J. Wysocki /* The wake-up power should have been enabled already. */ 483a37898d507794cfc68a092303e02651d3f01308Lin Ming acpi_set_gpe_wake_mask(dev->wakeup.gpe_device, dev->wakeup.gpe_number, 49e8b6f970107cfc9c00cdcdb12ec6c7e135cf379fRafael J. Wysocki ACPI_GPE_ENABLE); 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 5478f5f023167813130d2cf657d1b9eadc32f0e992Rafael J. Wysocki * acpi_disable_wakeup_devices - Disable devices' wakeup capability. 559630bdd9b15d2f489c646d8bc04b60e53eb5ec78Rafael J. Wysocki * @sleep_state: ACPI system sleep state. 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5778f5f023167813130d2cf657d1b9eadc32f0e992Rafael J. Wysockivoid acpi_disable_wakeup_devices(u8 sleep_state) 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 594be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown struct list_head *node, *next; 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds list_for_each_safe(node, next, &acpi_wakeup_device_list) { 629b039330808b83acac3597535da26f47ad1862ceAlexey Starikovskiy struct acpi_device *dev = 639b039330808b83acac3597535da26f47ad1862ceAlexey Starikovskiy container_of(node, struct acpi_device, wakeup_list); 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 65e8b6f970107cfc9c00cdcdb12ec6c7e135cf379fRafael J. Wysocki if (!dev->wakeup.flags.valid 66f2b56bc808addb908a5bf435d9b942c02af9a7c4Rafael J. Wysocki || sleep_state > (u32) dev->wakeup.sleep_state 67f2b56bc808addb908a5bf435d9b942c02af9a7c4Rafael J. Wysocki || !(device_may_wakeup(&dev->dev) 68f2b56bc808addb908a5bf435d9b942c02af9a7c4Rafael J. Wysocki || dev->wakeup.prepare_count)) 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continue; 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 713a37898d507794cfc68a092303e02651d3f01308Lin Ming acpi_set_gpe_wake_mask(dev->wakeup.gpe_device, dev->wakeup.gpe_number, 72e8b6f970107cfc9c00cdcdb12ec6c7e135cf379fRafael J. Wysocki ACPI_GPE_DISABLE); 73e8b6f970107cfc9c00cdcdb12ec6c7e135cf379fRafael J. Wysocki 74f2b56bc808addb908a5bf435d9b942c02af9a7c4Rafael J. Wysocki if (device_may_wakeup(&dev->dev)) 75e8b6f970107cfc9c00cdcdb12ec6c7e135cf379fRafael J. Wysocki acpi_disable_wakeup_device_power(dev); 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 79201b8c655f7a48563f6a0b66f9e388460a1ea611Bjorn Helgaasint __init acpi_wakeup_device_init(void) 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 814be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown struct list_head *node, *next; 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 839090589d87506c578ea1523ffd7ae7fd9424fb28Shaohua Li mutex_lock(&acpi_device_lock); 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds list_for_each_safe(node, next, &acpi_wakeup_device_list) { 854be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown struct acpi_device *dev = container_of(node, 864be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown struct acpi_device, 874be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown wakeup_list); 882a5d24286e8bdafdc272b37ec5bdd9e977b3767cRafael J. Wysocki if (device_can_wakeup(&dev->dev)) { 892a5d24286e8bdafdc272b37ec5bdd9e977b3767cRafael J. Wysocki /* Button GPEs are supposed to be always enabled. */ 902a5d24286e8bdafdc272b37ec5bdd9e977b3767cRafael J. Wysocki acpi_enable_gpe(dev->wakeup.gpe_device, 912a5d24286e8bdafdc272b37ec5bdd9e977b3767cRafael J. Wysocki dev->wakeup.gpe_number); 92f2b56bc808addb908a5bf435d9b942c02af9a7c4Rafael J. Wysocki device_set_wakeup_enable(&dev->dev, true); 932a5d24286e8bdafdc272b37ec5bdd9e977b3767cRafael J. Wysocki } 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 959090589d87506c578ea1523ffd7ae7fd9424fb28Shaohua Li mutex_unlock(&acpi_device_lock); 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 98