linux/drivers/acpi/wakeup.c
<<
>>
Prefs
   1/*
   2 * wakeup.c - support wakeup devices
   3 * Copyright (C) 2004 Li Shaohua <shaohua.li@intel.com>
   4 */
   5
   6#include <linux/init.h>
   7#include <linux/acpi.h>
   8#include <acpi/acpi_drivers.h>
   9#include <linux/kernel.h>
  10#include <linux/types.h>
  11
  12#include "internal.h"
  13#include "sleep.h"
  14
  15/*
  16 * We didn't lock acpi_device_lock in the file, because it invokes oops in
  17 * suspend/resume and isn't really required as this is called in S-state. At
  18 * that time, there is no device hotplug
  19 **/
  20#define _COMPONENT              ACPI_SYSTEM_COMPONENT
  21ACPI_MODULE_NAME("wakeup_devices")
  22
  23/**
  24 * acpi_enable_wakeup_device_prep - prepare wakeup devices
  25 *      @sleep_state:   ACPI state
  26 * Enable all wakup devices power if the devices' wakeup level
  27 * is higher than requested sleep level
  28 */
  29
  30void acpi_enable_wakeup_device_prep(u8 sleep_state)
  31{
  32        struct list_head *node, *next;
  33
  34        list_for_each_safe(node, next, &acpi_wakeup_device_list) {
  35                struct acpi_device *dev = container_of(node,
  36                                                       struct acpi_device,
  37                                                       wakeup_list);
  38
  39                if (!dev->wakeup.flags.valid ||
  40                    !dev->wakeup.state.enabled ||
  41                    (sleep_state > (u32) dev->wakeup.sleep_state))
  42                        continue;
  43
  44                acpi_enable_wakeup_device_power(dev, sleep_state);
  45        }
  46}
  47
  48/**
  49 * acpi_enable_wakeup_device - enable wakeup devices
  50 *      @sleep_state:   ACPI state
  51 * Enable all wakup devices's GPE
  52 */
  53void acpi_enable_wakeup_device(u8 sleep_state)
  54{
  55        struct list_head *node, *next;
  56
  57        /* 
  58         * Caution: this routine must be invoked when interrupt is disabled 
  59         * Refer ACPI2.0: P212
  60         */
  61        list_for_each_safe(node, next, &acpi_wakeup_device_list) {
  62                struct acpi_device *dev =
  63                        container_of(node, struct acpi_device, wakeup_list);
  64
  65                if (!dev->wakeup.flags.valid)
  66                        continue;
  67
  68                /* If users want to disable run-wake GPE,
  69                 * we only disable it for wake and leave it for runtime
  70                 */
  71                if ((!dev->wakeup.state.enabled && !dev->wakeup.prepare_count)
  72                    || sleep_state > (u32) dev->wakeup.sleep_state) {
  73                        if (dev->wakeup.flags.run_wake) {
  74                                /* set_gpe_type will disable GPE, leave it like that */
  75                                acpi_set_gpe_type(dev->wakeup.gpe_device,
  76                                                  dev->wakeup.gpe_number,
  77                                                  ACPI_GPE_TYPE_RUNTIME);
  78                        }
  79                        continue;
  80                }
  81                if (!dev->wakeup.flags.run_wake)
  82                        acpi_enable_gpe(dev->wakeup.gpe_device,
  83                                        dev->wakeup.gpe_number);
  84        }
  85}
  86
  87/**
  88 * acpi_disable_wakeup_device - disable devices' wakeup capability
  89 *      @sleep_state:   ACPI state
  90 * Disable all wakup devices's GPE and wakeup capability
  91 */
  92void acpi_disable_wakeup_device(u8 sleep_state)
  93{
  94        struct list_head *node, *next;
  95
  96        list_for_each_safe(node, next, &acpi_wakeup_device_list) {
  97                struct acpi_device *dev =
  98                        container_of(node, struct acpi_device, wakeup_list);
  99
 100                if (!dev->wakeup.flags.valid)
 101                        continue;
 102
 103                if ((!dev->wakeup.state.enabled && !dev->wakeup.prepare_count)
 104                    || sleep_state > (u32) dev->wakeup.sleep_state) {
 105                        if (dev->wakeup.flags.run_wake) {
 106                                acpi_set_gpe_type(dev->wakeup.gpe_device,
 107                                                  dev->wakeup.gpe_number,
 108                                                  ACPI_GPE_TYPE_WAKE_RUN);
 109                                /* Re-enable it, since set_gpe_type will disable it */
 110                                acpi_enable_gpe(dev->wakeup.gpe_device,
 111                                                dev->wakeup.gpe_number);
 112                        }
 113                        continue;
 114                }
 115
 116                acpi_disable_wakeup_device_power(dev);
 117                /* Never disable run-wake GPE */
 118                if (!dev->wakeup.flags.run_wake) {
 119                        acpi_disable_gpe(dev->wakeup.gpe_device,
 120                                         dev->wakeup.gpe_number);
 121                        acpi_clear_gpe(dev->wakeup.gpe_device,
 122                                       dev->wakeup.gpe_number, ACPI_NOT_ISR);
 123                }
 124        }
 125}
 126
 127int __init acpi_wakeup_device_init(void)
 128{
 129        struct list_head *node, *next;
 130
 131        mutex_lock(&acpi_device_lock);
 132        list_for_each_safe(node, next, &acpi_wakeup_device_list) {
 133                struct acpi_device *dev = container_of(node,
 134                                                       struct acpi_device,
 135                                                       wakeup_list);
 136                /* In case user doesn't load button driver */
 137                if (!dev->wakeup.flags.run_wake || dev->wakeup.state.enabled)
 138                        continue;
 139                acpi_set_gpe_type(dev->wakeup.gpe_device,
 140                                  dev->wakeup.gpe_number,
 141                                  ACPI_GPE_TYPE_WAKE_RUN);
 142                acpi_enable_gpe(dev->wakeup.gpe_device,
 143                                dev->wakeup.gpe_number);
 144                dev->wakeup.state.enabled = 1;
 145        }
 146        mutex_unlock(&acpi_device_lock);
 147        return 0;
 148}
 149