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