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