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 - 2017, 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
  57static acpi_status
  58acpi_hw_gpe_enable_write(u8 enable_mask,
  59                         struct acpi_gpe_register_info *gpe_register_info);
  60
  61/******************************************************************************
  62 *
  63 * FUNCTION:    acpi_hw_get_gpe_register_bit
  64 *
  65 * PARAMETERS:  gpe_event_info      - Info block for the GPE
  66 *
  67 * RETURN:      Register mask with a one in the GPE bit position
  68 *
  69 * DESCRIPTION: Compute the register mask for this GPE. One bit is set in the
  70 *              correct position for the input GPE.
  71 *
  72 ******************************************************************************/
  73
  74u32 acpi_hw_get_gpe_register_bit(struct acpi_gpe_event_info *gpe_event_info)
  75{
  76
  77        return ((u32)1 <<
  78                (gpe_event_info->gpe_number -
  79                 gpe_event_info->register_info->base_gpe_number));
  80}
  81
  82/******************************************************************************
  83 *
  84 * FUNCTION:    acpi_hw_low_set_gpe
  85 *
  86 * PARAMETERS:  gpe_event_info      - Info block for the GPE to be disabled
  87 *              action              - Enable or disable
  88 *
  89 * RETURN:      Status
  90 *
  91 * DESCRIPTION: Enable or disable a single GPE in the parent enable register.
  92 *              The enable_mask field of the involved GPE register must be
  93 *              updated by the caller if necessary.
  94 *
  95 ******************************************************************************/
  96
  97acpi_status
  98acpi_hw_low_set_gpe(struct acpi_gpe_event_info *gpe_event_info, u32 action)
  99{
 100        struct acpi_gpe_register_info *gpe_register_info;
 101        acpi_status status = AE_OK;
 102        u32 enable_mask;
 103        u32 register_bit;
 104
 105        ACPI_FUNCTION_ENTRY();
 106
 107        /* Get the info block for the entire GPE register */
 108
 109        gpe_register_info = gpe_event_info->register_info;
 110        if (!gpe_register_info) {
 111                return (AE_NOT_EXIST);
 112        }
 113
 114        /* Get current value of the enable register that contains this GPE */
 115
 116        status = acpi_hw_read(&enable_mask, &gpe_register_info->enable_address);
 117        if (ACPI_FAILURE(status)) {
 118                return (status);
 119        }
 120
 121        /* Set or clear just the bit that corresponds to this GPE */
 122
 123        register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info);
 124        switch (action) {
 125        case ACPI_GPE_CONDITIONAL_ENABLE:
 126
 127                /* Only enable if the corresponding enable_mask bit is set */
 128
 129                if (!(register_bit & gpe_register_info->enable_mask)) {
 130                        return (AE_BAD_PARAMETER);
 131                }
 132
 133                /*lint -fallthrough */
 134
 135        case ACPI_GPE_ENABLE:
 136
 137                ACPI_SET_BIT(enable_mask, register_bit);
 138                break;
 139
 140        case ACPI_GPE_DISABLE:
 141
 142                ACPI_CLEAR_BIT(enable_mask, register_bit);
 143                break;
 144
 145        default:
 146
 147                ACPI_ERROR((AE_INFO, "Invalid GPE Action, %u", action));
 148                return (AE_BAD_PARAMETER);
 149        }
 150
 151        if (!(register_bit & gpe_register_info->mask_for_run)) {
 152
 153                /* Write the updated enable mask */
 154
 155                status =
 156                    acpi_hw_write(enable_mask,
 157                                  &gpe_register_info->enable_address);
 158        }
 159        return (status);
 160}
 161
 162/******************************************************************************
 163 *
 164 * FUNCTION:    acpi_hw_clear_gpe
 165 *
 166 * PARAMETERS:  gpe_event_info      - Info block for the GPE to be cleared
 167 *
 168 * RETURN:      Status
 169 *
 170 * DESCRIPTION: Clear the status bit for a single GPE.
 171 *
 172 ******************************************************************************/
 173
 174acpi_status acpi_hw_clear_gpe(struct acpi_gpe_event_info *gpe_event_info)
 175{
 176        struct acpi_gpe_register_info *gpe_register_info;
 177        acpi_status status;
 178        u32 register_bit;
 179
 180        ACPI_FUNCTION_ENTRY();
 181
 182        /* Get the info block for the entire GPE register */
 183
 184        gpe_register_info = gpe_event_info->register_info;
 185        if (!gpe_register_info) {
 186                return (AE_NOT_EXIST);
 187        }
 188
 189        /*
 190         * Write a one to the appropriate bit in the status register to
 191         * clear this GPE.
 192         */
 193        register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info);
 194
 195        status =
 196            acpi_hw_write(register_bit, &gpe_register_info->status_address);
 197        return (status);
 198}
 199
 200/******************************************************************************
 201 *
 202 * FUNCTION:    acpi_hw_get_gpe_status
 203 *
 204 * PARAMETERS:  gpe_event_info      - Info block for the GPE to queried
 205 *              event_status        - Where the GPE status is returned
 206 *
 207 * RETURN:      Status
 208 *
 209 * DESCRIPTION: Return the status of a single GPE.
 210 *
 211 ******************************************************************************/
 212
 213acpi_status
 214acpi_hw_get_gpe_status(struct acpi_gpe_event_info *gpe_event_info,
 215                       acpi_event_status *event_status)
 216{
 217        u32 in_byte;
 218        u32 register_bit;
 219        struct acpi_gpe_register_info *gpe_register_info;
 220        acpi_event_status local_event_status = 0;
 221        acpi_status status;
 222
 223        ACPI_FUNCTION_ENTRY();
 224
 225        if (!event_status) {
 226                return (AE_BAD_PARAMETER);
 227        }
 228
 229        /* GPE currently handled? */
 230
 231        if (ACPI_GPE_DISPATCH_TYPE(gpe_event_info->flags) !=
 232            ACPI_GPE_DISPATCH_NONE) {
 233                local_event_status |= ACPI_EVENT_FLAG_HAS_HANDLER;
 234        }
 235
 236        /* Get the info block for the entire GPE register */
 237
 238        gpe_register_info = gpe_event_info->register_info;
 239
 240        /* Get the register bitmask for this GPE */
 241
 242        register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info);
 243
 244        /* GPE currently enabled? (enabled for runtime?) */
 245
 246        if (register_bit & gpe_register_info->enable_for_run) {
 247                local_event_status |= ACPI_EVENT_FLAG_ENABLED;
 248        }
 249
 250        /* GPE currently masked? (masked for runtime?) */
 251
 252        if (register_bit & gpe_register_info->mask_for_run) {
 253                local_event_status |= ACPI_EVENT_FLAG_MASKED;
 254        }
 255
 256        /* GPE enabled for wake? */
 257
 258        if (register_bit & gpe_register_info->enable_for_wake) {
 259                local_event_status |= ACPI_EVENT_FLAG_WAKE_ENABLED;
 260        }
 261
 262        /* GPE currently enabled (enable bit == 1)? */
 263
 264        status = acpi_hw_read(&in_byte, &gpe_register_info->enable_address);
 265        if (ACPI_FAILURE(status)) {
 266                return (status);
 267        }
 268
 269        if (register_bit & in_byte) {
 270                local_event_status |= ACPI_EVENT_FLAG_ENABLE_SET;
 271        }
 272
 273        /* GPE currently active (status bit == 1)? */
 274
 275        status = acpi_hw_read(&in_byte, &gpe_register_info->status_address);
 276        if (ACPI_FAILURE(status)) {
 277                return (status);
 278        }
 279
 280        if (register_bit & in_byte) {
 281                local_event_status |= ACPI_EVENT_FLAG_STATUS_SET;
 282        }
 283
 284        /* Set return value */
 285
 286        (*event_status) = local_event_status;
 287        return (AE_OK);
 288}
 289
 290/******************************************************************************
 291 *
 292 * FUNCTION:    acpi_hw_gpe_enable_write
 293 *
 294 * PARAMETERS:  enable_mask         - Bit mask to write to the GPE register
 295 *              gpe_register_info   - Gpe Register info
 296 *
 297 * RETURN:      Status
 298 *
 299 * DESCRIPTION: Write the enable mask byte to the given GPE register.
 300 *
 301 ******************************************************************************/
 302
 303static acpi_status
 304acpi_hw_gpe_enable_write(u8 enable_mask,
 305                         struct acpi_gpe_register_info *gpe_register_info)
 306{
 307        acpi_status status;
 308
 309        gpe_register_info->enable_mask = enable_mask;
 310
 311        status = acpi_hw_write(enable_mask, &gpe_register_info->enable_address);
 312        return (status);
 313}
 314
 315/******************************************************************************
 316 *
 317 * FUNCTION:    acpi_hw_disable_gpe_block
 318 *
 319 * PARAMETERS:  gpe_xrupt_info      - GPE Interrupt info
 320 *              gpe_block           - Gpe Block info
 321 *
 322 * RETURN:      Status
 323 *
 324 * DESCRIPTION: Disable all GPEs within a single GPE block
 325 *
 326 ******************************************************************************/
 327
 328acpi_status
 329acpi_hw_disable_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
 330                          struct acpi_gpe_block_info *gpe_block, void *context)
 331{
 332        u32 i;
 333        acpi_status status;
 334
 335        /* Examine each GPE Register within the block */
 336
 337        for (i = 0; i < gpe_block->register_count; i++) {
 338
 339                /* Disable all GPEs in this register */
 340
 341                status =
 342                    acpi_hw_gpe_enable_write(0x00,
 343                                             &gpe_block->register_info[i]);
 344                if (ACPI_FAILURE(status)) {
 345                        return (status);
 346                }
 347        }
 348
 349        return (AE_OK);
 350}
 351
 352/******************************************************************************
 353 *
 354 * FUNCTION:    acpi_hw_clear_gpe_block
 355 *
 356 * PARAMETERS:  gpe_xrupt_info      - GPE Interrupt info
 357 *              gpe_block           - Gpe Block info
 358 *
 359 * RETURN:      Status
 360 *
 361 * DESCRIPTION: Clear status bits for all GPEs within a single GPE block
 362 *
 363 ******************************************************************************/
 364
 365acpi_status
 366acpi_hw_clear_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
 367                        struct acpi_gpe_block_info *gpe_block, void *context)
 368{
 369        u32 i;
 370        acpi_status status;
 371
 372        /* Examine each GPE Register within the block */
 373
 374        for (i = 0; i < gpe_block->register_count; i++) {
 375
 376                /* Clear status on all GPEs in this register */
 377
 378                status =
 379                    acpi_hw_write(0xFF,
 380                                  &gpe_block->register_info[i].status_address);
 381                if (ACPI_FAILURE(status)) {
 382                        return (status);
 383                }
 384        }
 385
 386        return (AE_OK);
 387}
 388
 389/******************************************************************************
 390 *
 391 * FUNCTION:    acpi_hw_enable_runtime_gpe_block
 392 *
 393 * PARAMETERS:  gpe_xrupt_info      - GPE Interrupt info
 394 *              gpe_block           - Gpe Block info
 395 *
 396 * RETURN:      Status
 397 *
 398 * DESCRIPTION: Enable all "runtime" GPEs within a single GPE block. Includes
 399 *              combination wake/run GPEs.
 400 *
 401 ******************************************************************************/
 402
 403acpi_status
 404acpi_hw_enable_runtime_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
 405                                 struct acpi_gpe_block_info *gpe_block,
 406                                 void *context)
 407{
 408        u32 i;
 409        acpi_status status;
 410        struct acpi_gpe_register_info *gpe_register_info;
 411        u8 enable_mask;
 412
 413        /* NOTE: assumes that all GPEs are currently disabled */
 414
 415        /* Examine each GPE Register within the block */
 416
 417        for (i = 0; i < gpe_block->register_count; i++) {
 418                gpe_register_info = &gpe_block->register_info[i];
 419                if (!gpe_register_info->enable_for_run) {
 420                        continue;
 421                }
 422
 423                /* Enable all "runtime" GPEs in this register */
 424
 425                enable_mask = gpe_register_info->enable_for_run &
 426                    ~gpe_register_info->mask_for_run;
 427                status =
 428                    acpi_hw_gpe_enable_write(enable_mask, gpe_register_info);
 429                if (ACPI_FAILURE(status)) {
 430                        return (status);
 431                }
 432        }
 433
 434        return (AE_OK);
 435}
 436
 437/******************************************************************************
 438 *
 439 * FUNCTION:    acpi_hw_enable_wakeup_gpe_block
 440 *
 441 * PARAMETERS:  gpe_xrupt_info      - GPE Interrupt info
 442 *              gpe_block           - Gpe Block info
 443 *
 444 * RETURN:      Status
 445 *
 446 * DESCRIPTION: Enable all "wake" GPEs within a single GPE block. Includes
 447 *              combination wake/run GPEs.
 448 *
 449 ******************************************************************************/
 450
 451static acpi_status
 452acpi_hw_enable_wakeup_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
 453                                struct acpi_gpe_block_info *gpe_block,
 454                                void *context)
 455{
 456        u32 i;
 457        acpi_status status;
 458        struct acpi_gpe_register_info *gpe_register_info;
 459
 460        /* Examine each GPE Register within the block */
 461
 462        for (i = 0; i < gpe_block->register_count; i++) {
 463                gpe_register_info = &gpe_block->register_info[i];
 464
 465                /*
 466                 * Enable all "wake" GPEs in this register and disable the
 467                 * remaining ones.
 468                 */
 469
 470                status =
 471                    acpi_hw_gpe_enable_write(gpe_register_info->enable_for_wake,
 472                                             gpe_register_info);
 473                if (ACPI_FAILURE(status)) {
 474                        return (status);
 475                }
 476        }
 477
 478        return (AE_OK);
 479}
 480
 481/******************************************************************************
 482 *
 483 * FUNCTION:    acpi_hw_disable_all_gpes
 484 *
 485 * PARAMETERS:  None
 486 *
 487 * RETURN:      Status
 488 *
 489 * DESCRIPTION: Disable and clear all GPEs in all GPE blocks
 490 *
 491 ******************************************************************************/
 492
 493acpi_status acpi_hw_disable_all_gpes(void)
 494{
 495        acpi_status status;
 496
 497        ACPI_FUNCTION_TRACE(hw_disable_all_gpes);
 498
 499        status = acpi_ev_walk_gpe_list(acpi_hw_disable_gpe_block, NULL);
 500        status = acpi_ev_walk_gpe_list(acpi_hw_clear_gpe_block, NULL);
 501        return_ACPI_STATUS(status);
 502}
 503
 504/******************************************************************************
 505 *
 506 * FUNCTION:    acpi_hw_enable_all_runtime_gpes
 507 *
 508 * PARAMETERS:  None
 509 *
 510 * RETURN:      Status
 511 *
 512 * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks
 513 *
 514 ******************************************************************************/
 515
 516acpi_status acpi_hw_enable_all_runtime_gpes(void)
 517{
 518        acpi_status status;
 519
 520        ACPI_FUNCTION_TRACE(hw_enable_all_runtime_gpes);
 521
 522        status = acpi_ev_walk_gpe_list(acpi_hw_enable_runtime_gpe_block, NULL);
 523        return_ACPI_STATUS(status);
 524}
 525
 526/******************************************************************************
 527 *
 528 * FUNCTION:    acpi_hw_enable_all_wakeup_gpes
 529 *
 530 * PARAMETERS:  None
 531 *
 532 * RETURN:      Status
 533 *
 534 * DESCRIPTION: Enable all "wakeup" GPEs, in all GPE blocks
 535 *
 536 ******************************************************************************/
 537
 538acpi_status acpi_hw_enable_all_wakeup_gpes(void)
 539{
 540        acpi_status status;
 541
 542        ACPI_FUNCTION_TRACE(hw_enable_all_wakeup_gpes);
 543
 544        status = acpi_ev_walk_gpe_list(acpi_hw_enable_wakeup_gpe_block, NULL);
 545        return_ACPI_STATUS(status);
 546}
 547
 548#endif                          /* !ACPI_REDUCED_HARDWARE */
 549