root/drivers/acpi/acpica/hwgpe.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ACPI_MODULE_NAME
  2. acpi_hw_low_set_gpe
  3. acpi_hw_clear_gpe
  4. acpi_hw_get_gpe_status
  5. acpi_hw_gpe_enable_write
  6. acpi_hw_disable_gpe_block
  7. acpi_hw_clear_gpe_block
  8. acpi_hw_enable_runtime_gpe_block
  9. acpi_hw_enable_wakeup_gpe_block
  10. acpi_hw_get_gpe_block_status
  11. acpi_hw_disable_all_gpes
  12. acpi_hw_enable_all_runtime_gpes
  13. acpi_hw_enable_all_wakeup_gpes
  14. acpi_hw_check_all_gpes

   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 - 2019, Intel Corp.
   7  *
   8  *****************************************************************************/
   9 
  10 #include <acpi/acpi.h>
  11 #include "accommon.h"
  12 #include "acevents.h"
  13 
  14 #define _COMPONENT          ACPI_HARDWARE
  15 ACPI_MODULE_NAME("hwgpe")
  16 #if (!ACPI_REDUCED_HARDWARE)    /* Entire module */
  17 /* Local prototypes */
  18 static acpi_status
  19 acpi_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 
  23 static acpi_status
  24 acpi_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 
  40 u32 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 
  63 acpi_status
  64 acpi_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 
 140 acpi_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 
 179 acpi_status
 180 acpi_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 
 269 static acpi_status
 270 acpi_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 
 294 acpi_status
 295 acpi_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 
 331 acpi_status
 332 acpi_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 
 369 acpi_status
 370 acpi_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 
 417 static acpi_status
 418 acpi_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 struct acpi_gpe_block_status_context {
 448         struct acpi_gpe_register_info *gpe_skip_register_info;
 449         u8 gpe_skip_mask;
 450         u8 retval;
 451 };
 452 
 453 /******************************************************************************
 454  *
 455  * FUNCTION:    acpi_hw_get_gpe_block_status
 456  *
 457  * PARAMETERS:  gpe_xrupt_info      - GPE Interrupt info
 458  *              gpe_block           - Gpe Block info
 459  *              context             - GPE list walk context data
 460  *
 461  * RETURN:      Success
 462  *
 463  * DESCRIPTION: Produce a combined GPE status bits mask for the given block.
 464  *
 465  ******************************************************************************/
 466 
 467 static acpi_status
 468 acpi_hw_get_gpe_block_status(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
 469                              struct acpi_gpe_block_info *gpe_block,
 470                              void *context)
 471 {
 472         struct acpi_gpe_block_status_context *c = context;
 473         struct acpi_gpe_register_info *gpe_register_info;
 474         u64 in_enable, in_status;
 475         acpi_status status;
 476         u8 ret_mask;
 477         u32 i;
 478 
 479         /* Examine each GPE Register within the block */
 480 
 481         for (i = 0; i < gpe_block->register_count; i++) {
 482                 gpe_register_info = &gpe_block->register_info[i];
 483 
 484                 status = acpi_hw_read(&in_enable,
 485                                       &gpe_register_info->enable_address);
 486                 if (ACPI_FAILURE(status)) {
 487                         continue;
 488                 }
 489 
 490                 status = acpi_hw_read(&in_status,
 491                                       &gpe_register_info->status_address);
 492                 if (ACPI_FAILURE(status)) {
 493                         continue;
 494                 }
 495 
 496                 ret_mask = in_enable & in_status;
 497                 if (ret_mask && c->gpe_skip_register_info == gpe_register_info) {
 498                         ret_mask &= ~c->gpe_skip_mask;
 499                 }
 500                 c->retval |= ret_mask;
 501         }
 502 
 503         return (AE_OK);
 504 }
 505 
 506 /******************************************************************************
 507  *
 508  * FUNCTION:    acpi_hw_disable_all_gpes
 509  *
 510  * PARAMETERS:  None
 511  *
 512  * RETURN:      Status
 513  *
 514  * DESCRIPTION: Disable and clear all GPEs in all GPE blocks
 515  *
 516  ******************************************************************************/
 517 
 518 acpi_status acpi_hw_disable_all_gpes(void)
 519 {
 520         acpi_status status;
 521 
 522         ACPI_FUNCTION_TRACE(hw_disable_all_gpes);
 523 
 524         status = acpi_ev_walk_gpe_list(acpi_hw_disable_gpe_block, NULL);
 525         return_ACPI_STATUS(status);
 526 }
 527 
 528 /******************************************************************************
 529  *
 530  * FUNCTION:    acpi_hw_enable_all_runtime_gpes
 531  *
 532  * PARAMETERS:  None
 533  *
 534  * RETURN:      Status
 535  *
 536  * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks
 537  *
 538  ******************************************************************************/
 539 
 540 acpi_status acpi_hw_enable_all_runtime_gpes(void)
 541 {
 542         acpi_status status;
 543 
 544         ACPI_FUNCTION_TRACE(hw_enable_all_runtime_gpes);
 545 
 546         status = acpi_ev_walk_gpe_list(acpi_hw_enable_runtime_gpe_block, NULL);
 547         return_ACPI_STATUS(status);
 548 }
 549 
 550 /******************************************************************************
 551  *
 552  * FUNCTION:    acpi_hw_enable_all_wakeup_gpes
 553  *
 554  * PARAMETERS:  None
 555  *
 556  * RETURN:      Status
 557  *
 558  * DESCRIPTION: Enable all "wakeup" GPEs, in all GPE blocks
 559  *
 560  ******************************************************************************/
 561 
 562 acpi_status acpi_hw_enable_all_wakeup_gpes(void)
 563 {
 564         acpi_status status;
 565 
 566         ACPI_FUNCTION_TRACE(hw_enable_all_wakeup_gpes);
 567 
 568         status = acpi_ev_walk_gpe_list(acpi_hw_enable_wakeup_gpe_block, NULL);
 569         return_ACPI_STATUS(status);
 570 }
 571 
 572 /******************************************************************************
 573  *
 574  * FUNCTION:    acpi_hw_check_all_gpes
 575  *
 576  * PARAMETERS:  gpe_skip_device      - GPE devoce of the GPE to skip
 577  *              gpe_skip_number      - Number of the GPE to skip
 578  *
 579  * RETURN:      Combined status of all GPEs
 580  *
 581  * DESCRIPTION: Check all enabled GPEs in all GPE blocks, except for the one
 582  *              represented by the "skip" arguments, and return TRUE if the
 583  *              status bit is set for at least one of them of FALSE otherwise.
 584  *
 585  ******************************************************************************/
 586 
 587 u8 acpi_hw_check_all_gpes(acpi_handle gpe_skip_device, u32 gpe_skip_number)
 588 {
 589         struct acpi_gpe_block_status_context context = {
 590                 .gpe_skip_register_info = NULL,
 591                 .retval = 0,
 592         };
 593         struct acpi_gpe_event_info *gpe_event_info;
 594         acpi_cpu_flags flags;
 595 
 596         ACPI_FUNCTION_TRACE(acpi_hw_check_all_gpes);
 597 
 598         flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
 599 
 600         gpe_event_info = acpi_ev_get_gpe_event_info(gpe_skip_device,
 601                                                     gpe_skip_number);
 602         if (gpe_event_info) {
 603                 context.gpe_skip_register_info = gpe_event_info->register_info;
 604                 context.gpe_skip_mask = acpi_hw_get_gpe_register_bit(gpe_event_info);
 605         }
 606 
 607         acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
 608 
 609         (void)acpi_ev_walk_gpe_list(acpi_hw_get_gpe_block_status, &context);
 610         return (context.retval != 0);
 611 }
 612 
 613 #endif                          /* !ACPI_REDUCED_HARDWARE */

/* [<][>][^][v][top][bottom][index][help] */