[go: nahoru, domu]

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