linux/drivers/acpi/sleep/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#include <acpi/acevents.h>
  12#include "sleep.h"
  13
  14#define _COMPONENT              ACPI_SYSTEM_COMPONENT
  15ACPI_MODULE_NAME                ("wakeup_devices")
  16
  17extern struct list_head acpi_wakeup_device_list;
  18extern spinlock_t acpi_device_lock;
  19
  20#ifdef CONFIG_ACPI_SLEEP
  21/**
  22 * acpi_enable_wakeup_device_prep - prepare wakeup devices
  23 *      @sleep_state:   ACPI state
  24 * Enable all wakup devices power if the devices' wakeup level
  25 * is higher than requested sleep level
  26 */
  27
  28void
  29acpi_enable_wakeup_device_prep(
  30        u8              sleep_state)
  31{
  32        struct list_head * node, * next;
  33
  34        ACPI_FUNCTION_TRACE("acpi_enable_wakeup_device_prep");
  35
  36        spin_lock(&acpi_device_lock);
  37        list_for_each_safe(node, next, &acpi_wakeup_device_list) {
  38                struct acpi_device * dev = container_of(node, 
  39                        struct acpi_device, wakeup_list);
  40                
  41                if (!dev->wakeup.flags.valid || 
  42                        !dev->wakeup.state.enabled ||
  43                        (sleep_state > (u32) dev->wakeup.sleep_state))
  44                        continue;
  45
  46                spin_unlock(&acpi_device_lock);
  47                acpi_enable_wakeup_device_power(dev);
  48                spin_lock(&acpi_device_lock);
  49        }
  50        spin_unlock(&acpi_device_lock);
  51}
  52
  53/**
  54 * acpi_enable_wakeup_device - enable wakeup devices
  55 *      @sleep_state:   ACPI state
  56 * Enable all wakup devices's GPE
  57 */
  58void
  59acpi_enable_wakeup_device(
  60        u8              sleep_state)
  61{
  62        struct list_head * node, * next;
  63
  64        /* 
  65         * Caution: this routine must be invoked when interrupt is disabled 
  66         * Refer ACPI2.0: P212
  67         */
  68        ACPI_FUNCTION_TRACE("acpi_enable_wakeup_device");
  69        spin_lock(&acpi_device_lock);
  70        list_for_each_safe(node, next, &acpi_wakeup_device_list) {
  71                struct acpi_device * dev = container_of(node, 
  72                        struct acpi_device, wakeup_list);
  73
  74                /* If users want to disable run-wake GPE,
  75                 * we only disable it for wake and leave it for runtime
  76                 */
  77                if (dev->wakeup.flags.run_wake && !dev->wakeup.state.enabled) {
  78                        spin_unlock(&acpi_device_lock);
  79                        acpi_set_gpe_type(dev->wakeup.gpe_device, 
  80                                dev->wakeup.gpe_number, ACPI_GPE_TYPE_RUNTIME);
  81                        /* Re-enable it, since set_gpe_type will disable it */
  82                        acpi_enable_gpe(dev->wakeup.gpe_device, 
  83                                dev->wakeup.gpe_number, ACPI_ISR);
  84                        spin_lock(&acpi_device_lock);
  85                        continue;
  86                }
  87
  88                if (!dev->wakeup.flags.valid ||
  89                        !dev->wakeup.state.enabled ||
  90                        (sleep_state > (u32) dev->wakeup.sleep_state))
  91                        continue;
  92
  93                spin_unlock(&acpi_device_lock);
  94                /* run-wake GPE has been enabled */
  95                if (!dev->wakeup.flags.run_wake)
  96                        acpi_enable_gpe(dev->wakeup.gpe_device, 
  97                                dev->wakeup.gpe_number, ACPI_ISR);
  98                dev->wakeup.state.active = 1;
  99                spin_lock(&acpi_device_lock);
 100        }
 101        spin_unlock(&acpi_device_lock);
 102}
 103
 104/**
 105 * acpi_disable_wakeup_device - disable devices' wakeup capability
 106 *      @sleep_state:   ACPI state
 107 * Disable all wakup devices's GPE and wakeup capability
 108 */
 109void
 110acpi_disable_wakeup_device (
 111        u8              sleep_state)
 112{
 113        struct list_head * node, * next;
 114
 115        ACPI_FUNCTION_TRACE("acpi_disable_wakeup_device");
 116
 117        spin_lock(&acpi_device_lock);
 118        list_for_each_safe(node, next, &acpi_wakeup_device_list) {
 119                struct acpi_device * dev = container_of(node, 
 120                        struct acpi_device, wakeup_list);
 121
 122                if (dev->wakeup.flags.run_wake && !dev->wakeup.state.enabled) {
 123                        spin_unlock(&acpi_device_lock);
 124                        acpi_set_gpe_type(dev->wakeup.gpe_device, 
 125                                dev->wakeup.gpe_number, ACPI_GPE_TYPE_WAKE_RUN);
 126                        /* Re-enable it, since set_gpe_type will disable it */
 127                        acpi_enable_gpe(dev->wakeup.gpe_device, 
 128                                dev->wakeup.gpe_number, ACPI_NOT_ISR);
 129                        spin_lock(&acpi_device_lock);
 130                        continue;
 131                }
 132
 133                if (!dev->wakeup.flags.valid || 
 134                        !dev->wakeup.state.active ||
 135                        (sleep_state > (u32) dev->wakeup.sleep_state))
 136                        continue;
 137
 138                spin_unlock(&acpi_device_lock);
 139                acpi_disable_wakeup_device_power(dev);
 140                /* Never disable run-wake GPE */
 141                if (!dev->wakeup.flags.run_wake) {
 142                        acpi_disable_gpe(dev->wakeup.gpe_device, 
 143                                dev->wakeup.gpe_number, ACPI_NOT_ISR);
 144                        acpi_clear_gpe(dev->wakeup.gpe_device, 
 145                                dev->wakeup.gpe_number, ACPI_NOT_ISR);
 146                }
 147                dev->wakeup.state.active = 0;
 148                spin_lock(&acpi_device_lock);
 149        }
 150        spin_unlock(&acpi_device_lock);
 151}
 152
 153static int __init acpi_wakeup_device_init(void)
 154{
 155        struct list_head * node, * next;
 156
 157        if (acpi_disabled)
 158                return 0;
 159        printk("ACPI wakeup devices: \n");
 160
 161        spin_lock(&acpi_device_lock);
 162        list_for_each_safe(node, next, &acpi_wakeup_device_list) {
 163                struct acpi_device * dev = container_of(node, 
 164                        struct acpi_device, wakeup_list);
 165                
 166                /* In case user doesn't load button driver */
 167                if (dev->wakeup.flags.run_wake && !dev->wakeup.state.enabled) {
 168                        spin_unlock(&acpi_device_lock);
 169                        acpi_set_gpe_type(dev->wakeup.gpe_device, 
 170                                dev->wakeup.gpe_number, ACPI_GPE_TYPE_WAKE_RUN);
 171                        acpi_enable_gpe(dev->wakeup.gpe_device, 
 172                                dev->wakeup.gpe_number, ACPI_NOT_ISR);
 173                        dev->wakeup.state.enabled = 1;
 174                        spin_lock(&acpi_device_lock);
 175                }
 176                printk("%4s ", dev->pnp.bus_id);
 177        }
 178        spin_unlock(&acpi_device_lock);
 179        printk("\n");
 180
 181        return 0;
 182}
 183
 184late_initcall(acpi_wakeup_device_init);
 185#endif
 186
 187/*
 188 * Disable all wakeup GPEs before power off.
 189 * 
 190 * Since acpi_enter_sleep_state() will disable all
 191 * RUNTIME GPEs, we simply mark all GPES that
 192 * are not enabled for wakeup from S5 as RUNTIME.
 193 */
 194void acpi_wakeup_gpe_poweroff_prepare(void)
 195{
 196        struct list_head * node, * next;
 197
 198        list_for_each_safe(node, next, &acpi_wakeup_device_list) {
 199                struct acpi_device * dev = container_of(node,
 200                        struct acpi_device, wakeup_list);
 201
 202                /* The GPE can wakeup system from S5, don't touch it */
 203                if ((u32)dev->wakeup.sleep_state == ACPI_STATE_S5)
 204                        continue;
 205                /* acpi_set_gpe_type will automatically disable GPE */
 206                acpi_set_gpe_type(dev->wakeup.gpe_device,
 207                        dev->wakeup.gpe_number, ACPI_GPE_TYPE_RUNTIME);
 208        }
 209}
 210
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.