linux/drivers/acpi/acpica/hwgpe.c
<<
>>
Prefs
   1
   2/******************************************************************************
   3 *
   4 * Module Name: hwgpe - Low level GPE enable/disable/clear functions
   5 *
   6 *****************************************************************************/
   7
   8/*
   9 * Copyright (C) 2000 - 2011, Intel Corp.
  10 * All rights reserved.
  11 *
  12 * Redistribution and use in source and binary forms, with or without
  13 * modification, are permitted provided that the following conditions
  14 * are met:
  15 * 1. Redistributions of source code must retain the above copyright
  16 *    notice, this list of conditions, and the following disclaimer,
  17 *    without modification.
  18 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
  19 *    substantially similar to the "NO WARRANTY" disclaimer below
  20 *    ("Disclaimer") and any redistribution must be conditioned upon
  21 *    including a substantially similar Disclaimer requirement for further
  22 *    binary redistribution.
  23 * 3. Neither the names of the above-listed copyright holders nor the names
  24 *    of any contributors may be used to endorse or promote products derived
  25 *    from this software without specific prior written permission.
  26 *
  27 * Alternatively, this software may be distributed under the terms of the
  28 * GNU General Public License ("GPL") version 2 as published by the Free
  29 * Software Foundation.
  30 *
  31 * NO WARRANTY
  32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  33 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  34 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
  35 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  36 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  41 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  42 * POSSIBILITY OF SUCH DAMAGES.
  43 */
  44
  45#include <acpi/acpi.h>
  46#include "accommon.h"
  47#include "acevents.h"
  48
  49#define _COMPONENT          ACPI_HARDWARE
  50ACPI_MODULE_NAME("hwgpe")
  51
  52/* Local prototypes */
  53static acpi_status
  54acpi_hw_enable_wakeup_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
  55                                struct acpi_gpe_block_info *gpe_block,
  56                                void *context);
  57
  58/******************************************************************************
  59 *
  60 * FUNCTION:    acpi_hw_get_gpe_register_bit
  61 *
  62 * PARAMETERS:  gpe_event_info      - Info block for the GPE
  63 *              gpe_register_info   - Info block for the GPE register
  64 *
  65 * RETURN:      Register mask with a one in the GPE bit position
  66 *
  67 * DESCRIPTION: Compute the register mask for this GPE. One bit is set in the
  68 *              correct position for the input GPE.
  69 *
  70 ******************************************************************************/
  71
  72u32 acpi_hw_get_gpe_register_bit(struct acpi_gpe_event_info *gpe_event_info,
  73                             struct acpi_gpe_register_info *gpe_register_info)
  74{
  75        return (u32)1 << (gpe_event_info->gpe_number -
  76                                gpe_register_info->base_gpe_number);
  77}
  78
  79/******************************************************************************
  80 *
  81 * FUNCTION:    acpi_hw_low_set_gpe
  82 *
  83 * PARAMETERS:  gpe_event_info      - Info block for the GPE to be disabled
  84 *              action              - Enable or disable
  85 *
  86 * RETURN:      Status
  87 *
  88 * DESCRIPTION: Enable or disable a single GPE in the parent enable register.
  89 *
  90 ******************************************************************************/
  91
  92acpi_status
  93acpi_hw_low_set_gpe(struct acpi_gpe_event_info *gpe_event_info, u32 action)
  94{
  95        struct acpi_gpe_register_info *gpe_register_info;
  96        acpi_status status;
  97        u32 enable_mask;
  98        u32 register_bit;
  99
 100        ACPI_FUNCTION_ENTRY();
 101
 102        /* Get the info block for the entire GPE register */
 103
 104        gpe_register_info = gpe_event_info->register_info;
 105        if (!gpe_register_info) {
 106                return (AE_NOT_EXIST);
 107        }
 108
 109        /* Get current value of the enable register that contains this GPE */
 110
 111        status = acpi_hw_read(&enable_mask, &gpe_register_info->enable_address);
 112        if (ACPI_FAILURE(status)) {
 113                return (status);
 114        }
 115
 116        /* Set or clear just the bit that corresponds to this GPE */
 117
 118        register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info,
 119                                                gpe_register_info);
 120        switch (action) {
 121        case ACPI_GPE_CONDITIONAL_ENABLE:
 122
 123                /* Only enable if the enable_for_run bit is set */
 124
 125                if (!(register_bit & gpe_register_info->enable_for_run)) {
 126                        return (AE_BAD_PARAMETER);
 127                }
 128
 129                /*lint -fallthrough */
 130
 131        case ACPI_GPE_ENABLE:
 132                ACPI_SET_BIT(enable_mask, register_bit);
 133                break;
 134
 135        case ACPI_GPE_DISABLE:
 136                ACPI_CLEAR_BIT(enable_mask, register_bit);
 137                break;
 138
 139        default:
 140                ACPI_ERROR((AE_INFO, "Invalid GPE Action, %u\n", action));
 141                return (AE_BAD_PARAMETER);
 142        }
 143
 144        /* Write the updated enable mask */
 145
 146        status = acpi_hw_write(enable_mask, &gpe_register_info->enable_address);
 147        return (status);
 148}
 149
 150/******************************************************************************
 151 *
 152 * FUNCTION:    acpi_hw_clear_gpe
 153 *
 154 * PARAMETERS:  gpe_event_info      - Info block for the GPE to be cleared
 155 *
 156 * RETURN:      Status
 157 *
 158 * DESCRIPTION: Clear the status bit for a single GPE.
 159 *
 160 ******************************************************************************/
 161
 162acpi_status acpi_hw_clear_gpe(struct acpi_gpe_event_info * gpe_event_info)
 163{
 164        struct acpi_gpe_register_info *gpe_register_info;
 165        acpi_status status;
 166        u32 register_bit;
 167
 168        ACPI_FUNCTION_ENTRY();
 169
 170        /* Get the info block for the entire GPE register */
 171
 172        gpe_register_info = gpe_event_info->register_info;
 173        if (!gpe_register_info) {
 174                return (AE_NOT_EXIST);
 175        }
 176
 177        /*
 178         * Write a one to the appropriate bit in the status register to
 179         * clear this GPE.
 180         */
 181        register_bit =
 182            acpi_hw_get_gpe_register_bit(gpe_event_info, gpe_register_info);
 183
 184        status = acpi_hw_write(register_bit,
 185                               &gpe_register_info->status_address);
 186
 187        return (status);
 188}
 189
 190/******************************************************************************
 191 *
 192 * FUNCTION:    acpi_hw_get_gpe_status
 193 *
 194 * PARAMETERS:  gpe_event_info      - Info block for the GPE to queried
 195 *              event_status        - Where the GPE status is returned
 196 *
 197 * RETURN:      Status
 198 *
 199 * DESCRIPTION: Return the status of a single GPE.
 200 *
 201 ******************************************************************************/
 202
 203acpi_status
 204acpi_hw_get_gpe_status(struct acpi_gpe_event_info * gpe_event_info,
 205                       acpi_event_status * event_status)
 206{
 207        u32 in_byte;
 208        u32 register_bit;
 209        struct acpi_gpe_register_info *gpe_register_info;
 210        acpi_event_status local_event_status = 0;
 211        acpi_status status;
 212
 213        ACPI_FUNCTION_ENTRY();
 214
 215        if (!event_status) {
 216                return (AE_BAD_PARAMETER);
 217        }
 218
 219        /* Get the info block for the entire GPE register */
 220
 221        gpe_register_info = gpe_event_info->register_info;
 222
 223        /* Get the register bitmask for this GPE */
 224
 225        register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info,
 226                                                gpe_register_info);
 227
 228        /* GPE currently enabled? (enabled for runtime?) */
 229
 230        if (register_bit & gpe_register_info->enable_for_run) {
 231                local_event_status |= ACPI_EVENT_FLAG_ENABLED;
 232        }
 233
 234        /* GPE enabled for wake? */
 235
 236        if (register_bit & gpe_register_info->enable_for_wake) {
 237                local_event_status |= ACPI_EVENT_FLAG_WAKE_ENABLED;
 238        }
 239
 240        /* GPE currently active (status bit == 1)? */
 241
 242        status = acpi_hw_read(&in_byte, &gpe_register_info->status_address);
 243        if (ACPI_FAILURE(status)) {
 244                return (status);
 245        }
 246
 247        if (register_bit & in_byte) {
 248                local_event_status |= ACPI_EVENT_FLAG_SET;
 249        }
 250
 251        /* Set return value */
 252
 253        (*event_status) = local_event_status;
 254        return (AE_OK);
 255}
 256
 257/******************************************************************************
 258 *
 259 * FUNCTION:    acpi_hw_disable_gpe_block
 260 *
 261 * PARAMETERS:  gpe_xrupt_info      - GPE Interrupt info
 262 *              gpe_block           - Gpe Block info
 263 *
 264 * RETURN:      Status
 265 *
 266 * DESCRIPTION: Disable all GPEs within a single GPE block
 267 *
 268 ******************************************************************************/
 269
 270acpi_status
 271acpi_hw_disable_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
 272                          struct acpi_gpe_block_info *gpe_block, void *context)
 273{
 274        u32 i;
 275        acpi_status status;
 276
 277        /* Examine each GPE Register within the block */
 278
 279        for (i = 0; i < gpe_block->register_count; i++) {
 280
 281                /* Disable all GPEs in this register */
 282
 283                status =
 284                    acpi_hw_write(0x00,
 285                                  &gpe_block->register_info[i].enable_address);
 286                if (ACPI_FAILURE(status)) {
 287                        return (status);
 288                }
 289        }
 290
 291        return (AE_OK);
 292}
 293
 294/******************************************************************************
 295 *
 296 * FUNCTION:    acpi_hw_clear_gpe_block
 297 *
 298 * PARAMETERS:  gpe_xrupt_info      - GPE Interrupt info
 299 *              gpe_block           - Gpe Block info
 300 *
 301 * RETURN:      Status
 302 *
 303 * DESCRIPTION: Clear status bits for all GPEs within a single GPE block
 304 *
 305 ******************************************************************************/
 306
 307acpi_status
 308acpi_hw_clear_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
 309                        struct acpi_gpe_block_info *gpe_block, void *context)
 310{
 311        u32 i;
 312        acpi_status status;
 313
 314        /* Examine each GPE Register within the block */
 315
 316        for (i = 0; i < gpe_block->register_count; i++) {
 317
 318                /* Clear status on all GPEs in this register */
 319
 320                status =
 321                    acpi_hw_write(0xFF,
 322                                  &gpe_block->register_info[i].status_address);
 323                if (ACPI_FAILURE(status)) {
 324                        return (status);
 325                }
 326        }
 327
 328        return (AE_OK);
 329}
 330
 331/******************************************************************************
 332 *
 333 * FUNCTION:    acpi_hw_enable_runtime_gpe_block
 334 *
 335 * PARAMETERS:  gpe_xrupt_info      - GPE Interrupt info
 336 *              gpe_block           - Gpe Block info
 337 *
 338 * RETURN:      Status
 339 *
 340 * DESCRIPTION: Enable all "runtime" GPEs within a single GPE block. Includes
 341 *              combination wake/run GPEs.
 342 *
 343 ******************************************************************************/
 344
 345acpi_status
 346acpi_hw_enable_runtime_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
 347                                 struct acpi_gpe_block_info *gpe_block, void *context)
 348{
 349        u32 i;
 350        acpi_status status;
 351
 352        /* NOTE: assumes that all GPEs are currently disabled */
 353
 354        /* Examine each GPE Register within the block */
 355
 356        for (i = 0; i < gpe_block->register_count; i++) {
 357                if (!gpe_block->register_info[i].enable_for_run) {
 358                        continue;
 359                }
 360
 361                /* Enable all "runtime" GPEs in this register */
 362
 363                status =
 364                    acpi_hw_write(gpe_block->register_info[i].enable_for_run,
 365                                  &gpe_block->register_info[i].enable_address);
 366                if (ACPI_FAILURE(status)) {
 367                        return (status);
 368                }
 369        }
 370
 371        return (AE_OK);
 372}
 373
 374/******************************************************************************
 375 *
 376 * FUNCTION:    acpi_hw_enable_wakeup_gpe_block
 377 *
 378 * PARAMETERS:  gpe_xrupt_info      - GPE Interrupt info
 379 *              gpe_block           - Gpe Block info
 380 *
 381 * RETURN:      Status
 382 *
 383 * DESCRIPTION: Enable all "wake" GPEs within a single GPE block. Includes
 384 *              combination wake/run GPEs.
 385 *
 386 ******************************************************************************/
 387
 388static acpi_status
 389acpi_hw_enable_wakeup_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
 390                                struct acpi_gpe_block_info *gpe_block,
 391                                void *context)
 392{
 393        u32 i;
 394        acpi_status status;
 395
 396        /* Examine each GPE Register within the block */
 397
 398        for (i = 0; i < gpe_block->register_count; i++) {
 399                if (!gpe_block->register_info[i].enable_for_wake) {
 400                        continue;
 401                }
 402
 403                /* Enable all "wake" GPEs in this register */
 404
 405                status =
 406                    acpi_hw_write(gpe_block->register_info[i].enable_for_wake,
 407                                  &gpe_block->register_info[i].enable_address);
 408                if (ACPI_FAILURE(status)) {
 409                        return (status);
 410                }
 411        }
 412
 413        return (AE_OK);
 414}
 415
 416/******************************************************************************
 417 *
 418 * FUNCTION:    acpi_hw_disable_all_gpes
 419 *
 420 * PARAMETERS:  None
 421 *
 422 * RETURN:      Status
 423 *
 424 * DESCRIPTION: Disable and clear all GPEs in all GPE blocks
 425 *
 426 ******************************************************************************/
 427
 428acpi_status acpi_hw_disable_all_gpes(void)
 429{
 430        acpi_status status;
 431
 432        ACPI_FUNCTION_TRACE(hw_disable_all_gpes);
 433
 434        status = acpi_ev_walk_gpe_list(acpi_hw_disable_gpe_block, NULL);
 435        status = acpi_ev_walk_gpe_list(acpi_hw_clear_gpe_block, NULL);
 436        return_ACPI_STATUS(status);
 437}
 438
 439/******************************************************************************
 440 *
 441 * FUNCTION:    acpi_hw_enable_all_runtime_gpes
 442 *
 443 * PARAMETERS:  None
 444 *
 445 * RETURN:      Status
 446 *
 447 * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks
 448 *
 449 ******************************************************************************/
 450
 451acpi_status acpi_hw_enable_all_runtime_gpes(void)
 452{
 453        acpi_status status;
 454
 455        ACPI_FUNCTION_TRACE(hw_enable_all_runtime_gpes);
 456
 457        status = acpi_ev_walk_gpe_list(acpi_hw_enable_runtime_gpe_block, NULL);
 458        return_ACPI_STATUS(status);
 459}
 460
 461/******************************************************************************
 462 *
 463 * FUNCTION:    acpi_hw_enable_all_wakeup_gpes
 464 *
 465 * PARAMETERS:  None
 466 *
 467 * RETURN:      Status
 468 *
 469 * DESCRIPTION: Enable all "wakeup" GPEs, in all GPE blocks
 470 *
 471 ******************************************************************************/
 472
 473acpi_status acpi_hw_enable_all_wakeup_gpes(void)
 474{
 475        acpi_status status;
 476
 477        ACPI_FUNCTION_TRACE(hw_enable_all_wakeup_gpes);
 478
 479        status = acpi_ev_walk_gpe_list(acpi_hw_enable_wakeup_gpe_block, NULL);
 480        return_ACPI_STATUS(status);
 481}
 482