Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
0002 /******************************************************************************
0003  *
0004  * Module Name: hwgpe - Low level GPE enable/disable/clear functions
0005  *
0006  * Copyright (C) 2000 - 2022, Intel Corp.
0007  *
0008  *****************************************************************************/
0009 
0010 #include <acpi/acpi.h>
0011 #include "accommon.h"
0012 #include "acevents.h"
0013 
0014 #define _COMPONENT          ACPI_HARDWARE
0015 ACPI_MODULE_NAME("hwgpe")
0016 #if (!ACPI_REDUCED_HARDWARE)    /* Entire module */
0017 /* Local prototypes */
0018 static acpi_status
0019 acpi_hw_enable_wakeup_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
0020                 struct acpi_gpe_block_info *gpe_block,
0021                 void *context);
0022 
0023 static acpi_status
0024 acpi_hw_gpe_enable_write(u8 enable_mask,
0025              struct acpi_gpe_register_info *gpe_register_info);
0026 
0027 /******************************************************************************
0028  *
0029  * FUNCTION:    acpi_hw_gpe_read
0030  *
0031  * PARAMETERS:  value               - Where the value is returned
0032  *              reg                 - GPE register structure
0033  *
0034  * RETURN:      Status
0035  *
0036  * DESCRIPTION: Read from a GPE register in either memory or IO space.
0037  *
0038  * LIMITATIONS: <These limitations also apply to acpi_hw_gpe_write>
0039  *      space_ID must be system_memory or system_IO.
0040  *
0041  ******************************************************************************/
0042 
0043 acpi_status acpi_hw_gpe_read(u64 *value, struct acpi_gpe_address *reg)
0044 {
0045     acpi_status status;
0046     u32 value32;
0047 
0048     if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
0049 #ifdef ACPI_GPE_USE_LOGICAL_ADDRESSES
0050         *value = (u64)ACPI_GET8((unsigned long)reg->address);
0051         return_ACPI_STATUS(AE_OK);
0052 #else
0053         return acpi_os_read_memory((acpi_physical_address)reg->address,
0054                         value, ACPI_GPE_REGISTER_WIDTH);
0055 #endif
0056     }
0057 
0058     status = acpi_os_read_port((acpi_io_address)reg->address,
0059                    &value32, ACPI_GPE_REGISTER_WIDTH);
0060     if (ACPI_FAILURE(status))
0061         return_ACPI_STATUS(status);
0062 
0063     *value = (u64)value32;
0064 
0065     return_ACPI_STATUS(AE_OK);
0066 }
0067 
0068 /******************************************************************************
0069  *
0070  * FUNCTION:    acpi_hw_gpe_write
0071  *
0072  * PARAMETERS:  value               - Value to be written
0073  *              reg                 - GPE register structure
0074  *
0075  * RETURN:      Status
0076  *
0077  * DESCRIPTION: Write to a GPE register in either memory or IO space.
0078  *
0079  ******************************************************************************/
0080 
0081 acpi_status acpi_hw_gpe_write(u64 value, struct acpi_gpe_address *reg)
0082 {
0083     if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
0084 #ifdef ACPI_GPE_USE_LOGICAL_ADDRESSES
0085         ACPI_SET8((unsigned long)reg->address, value);
0086         return_ACPI_STATUS(AE_OK);
0087 #else
0088         return acpi_os_write_memory((acpi_physical_address)reg->address,
0089                         value, ACPI_GPE_REGISTER_WIDTH);
0090 #endif
0091     }
0092 
0093     return acpi_os_write_port((acpi_io_address)reg->address, (u32)value,
0094                   ACPI_GPE_REGISTER_WIDTH);
0095 }
0096 
0097 /******************************************************************************
0098  *
0099  * FUNCTION:    acpi_hw_get_gpe_register_bit
0100  *
0101  * PARAMETERS:  gpe_event_info      - Info block for the GPE
0102  *
0103  * RETURN:  Register mask with a one in the GPE bit position
0104  *
0105  * DESCRIPTION: Compute the register mask for this GPE. One bit is set in the
0106  *              correct position for the input GPE.
0107  *
0108  ******************************************************************************/
0109 
0110 u32 acpi_hw_get_gpe_register_bit(struct acpi_gpe_event_info *gpe_event_info)
0111 {
0112 
0113     return ((u32)1 <<
0114         (gpe_event_info->gpe_number -
0115          gpe_event_info->register_info->base_gpe_number));
0116 }
0117 
0118 /******************************************************************************
0119  *
0120  * FUNCTION:    acpi_hw_low_set_gpe
0121  *
0122  * PARAMETERS:  gpe_event_info      - Info block for the GPE to be disabled
0123  *      action          - Enable or disable
0124  *
0125  * RETURN:  Status
0126  *
0127  * DESCRIPTION: Enable or disable a single GPE in the parent enable register.
0128  *              The enable_mask field of the involved GPE register must be
0129  *              updated by the caller if necessary.
0130  *
0131  ******************************************************************************/
0132 
0133 acpi_status
0134 acpi_hw_low_set_gpe(struct acpi_gpe_event_info *gpe_event_info, u32 action)
0135 {
0136     struct acpi_gpe_register_info *gpe_register_info;
0137     acpi_status status = AE_OK;
0138     u64 enable_mask;
0139     u32 register_bit;
0140 
0141     ACPI_FUNCTION_ENTRY();
0142 
0143     /* Get the info block for the entire GPE register */
0144 
0145     gpe_register_info = gpe_event_info->register_info;
0146     if (!gpe_register_info) {
0147         return (AE_NOT_EXIST);
0148     }
0149 
0150     /* Get current value of the enable register that contains this GPE */
0151 
0152     status = acpi_hw_gpe_read(&enable_mask,
0153                   &gpe_register_info->enable_address);
0154     if (ACPI_FAILURE(status)) {
0155         return (status);
0156     }
0157 
0158     /* Set or clear just the bit that corresponds to this GPE */
0159 
0160     register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info);
0161     switch (action) {
0162     case ACPI_GPE_CONDITIONAL_ENABLE:
0163 
0164         /* Only enable if the corresponding enable_mask bit is set */
0165 
0166         if (!(register_bit & gpe_register_info->enable_mask)) {
0167             return (AE_BAD_PARAMETER);
0168         }
0169 
0170         ACPI_FALLTHROUGH;
0171 
0172     case ACPI_GPE_ENABLE:
0173 
0174         ACPI_SET_BIT(enable_mask, register_bit);
0175         break;
0176 
0177     case ACPI_GPE_DISABLE:
0178 
0179         ACPI_CLEAR_BIT(enable_mask, register_bit);
0180         break;
0181 
0182     default:
0183 
0184         ACPI_ERROR((AE_INFO, "Invalid GPE Action, %u", action));
0185         return (AE_BAD_PARAMETER);
0186     }
0187 
0188     if (!(register_bit & gpe_register_info->mask_for_run)) {
0189 
0190         /* Write the updated enable mask */
0191 
0192         status = acpi_hw_gpe_write(enable_mask,
0193                        &gpe_register_info->enable_address);
0194     }
0195     return (status);
0196 }
0197 
0198 /******************************************************************************
0199  *
0200  * FUNCTION:    acpi_hw_clear_gpe
0201  *
0202  * PARAMETERS:  gpe_event_info      - Info block for the GPE to be cleared
0203  *
0204  * RETURN:      Status
0205  *
0206  * DESCRIPTION: Clear the status bit for a single GPE.
0207  *
0208  ******************************************************************************/
0209 
0210 acpi_status acpi_hw_clear_gpe(struct acpi_gpe_event_info *gpe_event_info)
0211 {
0212     struct acpi_gpe_register_info *gpe_register_info;
0213     acpi_status status;
0214     u32 register_bit;
0215 
0216     ACPI_FUNCTION_ENTRY();
0217 
0218     /* Get the info block for the entire GPE register */
0219 
0220     gpe_register_info = gpe_event_info->register_info;
0221     if (!gpe_register_info) {
0222         return (AE_NOT_EXIST);
0223     }
0224 
0225     /*
0226      * Write a one to the appropriate bit in the status register to
0227      * clear this GPE.
0228      */
0229     register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info);
0230 
0231     status = acpi_hw_gpe_write(register_bit,
0232                    &gpe_register_info->status_address);
0233     return (status);
0234 }
0235 
0236 /******************************************************************************
0237  *
0238  * FUNCTION:    acpi_hw_get_gpe_status
0239  *
0240  * PARAMETERS:  gpe_event_info      - Info block for the GPE to queried
0241  *              event_status        - Where the GPE status is returned
0242  *
0243  * RETURN:      Status
0244  *
0245  * DESCRIPTION: Return the status of a single GPE.
0246  *
0247  ******************************************************************************/
0248 
0249 acpi_status
0250 acpi_hw_get_gpe_status(struct acpi_gpe_event_info *gpe_event_info,
0251                acpi_event_status *event_status)
0252 {
0253     u64 in_byte;
0254     u32 register_bit;
0255     struct acpi_gpe_register_info *gpe_register_info;
0256     acpi_event_status local_event_status = 0;
0257     acpi_status status;
0258 
0259     ACPI_FUNCTION_ENTRY();
0260 
0261     if (!event_status) {
0262         return (AE_BAD_PARAMETER);
0263     }
0264 
0265     /* GPE currently handled? */
0266 
0267     if (ACPI_GPE_DISPATCH_TYPE(gpe_event_info->flags) !=
0268         ACPI_GPE_DISPATCH_NONE) {
0269         local_event_status |= ACPI_EVENT_FLAG_HAS_HANDLER;
0270     }
0271 
0272     /* Get the info block for the entire GPE register */
0273 
0274     gpe_register_info = gpe_event_info->register_info;
0275 
0276     /* Get the register bitmask for this GPE */
0277 
0278     register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info);
0279 
0280     /* GPE currently enabled? (enabled for runtime?) */
0281 
0282     if (register_bit & gpe_register_info->enable_for_run) {
0283         local_event_status |= ACPI_EVENT_FLAG_ENABLED;
0284     }
0285 
0286     /* GPE currently masked? (masked for runtime?) */
0287 
0288     if (register_bit & gpe_register_info->mask_for_run) {
0289         local_event_status |= ACPI_EVENT_FLAG_MASKED;
0290     }
0291 
0292     /* GPE enabled for wake? */
0293 
0294     if (register_bit & gpe_register_info->enable_for_wake) {
0295         local_event_status |= ACPI_EVENT_FLAG_WAKE_ENABLED;
0296     }
0297 
0298     /* GPE currently enabled (enable bit == 1)? */
0299 
0300     status = acpi_hw_gpe_read(&in_byte, &gpe_register_info->enable_address);
0301     if (ACPI_FAILURE(status)) {
0302         return (status);
0303     }
0304 
0305     if (register_bit & in_byte) {
0306         local_event_status |= ACPI_EVENT_FLAG_ENABLE_SET;
0307     }
0308 
0309     /* GPE currently active (status bit == 1)? */
0310 
0311     status = acpi_hw_gpe_read(&in_byte, &gpe_register_info->status_address);
0312     if (ACPI_FAILURE(status)) {
0313         return (status);
0314     }
0315 
0316     if (register_bit & in_byte) {
0317         local_event_status |= ACPI_EVENT_FLAG_STATUS_SET;
0318     }
0319 
0320     /* Set return value */
0321 
0322     (*event_status) = local_event_status;
0323     return (AE_OK);
0324 }
0325 
0326 /******************************************************************************
0327  *
0328  * FUNCTION:    acpi_hw_gpe_enable_write
0329  *
0330  * PARAMETERS:  enable_mask         - Bit mask to write to the GPE register
0331  *              gpe_register_info   - Gpe Register info
0332  *
0333  * RETURN:      Status
0334  *
0335  * DESCRIPTION: Write the enable mask byte to the given GPE register.
0336  *
0337  ******************************************************************************/
0338 
0339 static acpi_status
0340 acpi_hw_gpe_enable_write(u8 enable_mask,
0341              struct acpi_gpe_register_info *gpe_register_info)
0342 {
0343     acpi_status status;
0344 
0345     gpe_register_info->enable_mask = enable_mask;
0346 
0347     status = acpi_hw_gpe_write(enable_mask,
0348                    &gpe_register_info->enable_address);
0349     return (status);
0350 }
0351 
0352 /******************************************************************************
0353  *
0354  * FUNCTION:    acpi_hw_disable_gpe_block
0355  *
0356  * PARAMETERS:  gpe_xrupt_info      - GPE Interrupt info
0357  *              gpe_block           - Gpe Block info
0358  *
0359  * RETURN:      Status
0360  *
0361  * DESCRIPTION: Disable all GPEs within a single GPE block
0362  *
0363  ******************************************************************************/
0364 
0365 acpi_status
0366 acpi_hw_disable_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
0367               struct acpi_gpe_block_info *gpe_block, void *context)
0368 {
0369     u32 i;
0370     acpi_status status;
0371 
0372     /* Examine each GPE Register within the block */
0373 
0374     for (i = 0; i < gpe_block->register_count; i++) {
0375 
0376         /* Disable all GPEs in this register */
0377 
0378         status =
0379             acpi_hw_gpe_enable_write(0x00,
0380                          &gpe_block->register_info[i]);
0381         if (ACPI_FAILURE(status)) {
0382             return (status);
0383         }
0384     }
0385 
0386     return (AE_OK);
0387 }
0388 
0389 /******************************************************************************
0390  *
0391  * FUNCTION:    acpi_hw_clear_gpe_block
0392  *
0393  * PARAMETERS:  gpe_xrupt_info      - GPE Interrupt info
0394  *              gpe_block           - Gpe Block info
0395  *
0396  * RETURN:      Status
0397  *
0398  * DESCRIPTION: Clear status bits for all GPEs within a single GPE block
0399  *
0400  ******************************************************************************/
0401 
0402 acpi_status
0403 acpi_hw_clear_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
0404             struct acpi_gpe_block_info *gpe_block, void *context)
0405 {
0406     u32 i;
0407     acpi_status status;
0408 
0409     /* Examine each GPE Register within the block */
0410 
0411     for (i = 0; i < gpe_block->register_count; i++) {
0412 
0413         /* Clear status on all GPEs in this register */
0414 
0415         status = acpi_hw_gpe_write(0xFF,
0416                        &gpe_block->register_info[i].status_address);
0417         if (ACPI_FAILURE(status)) {
0418             return (status);
0419         }
0420     }
0421 
0422     return (AE_OK);
0423 }
0424 
0425 /******************************************************************************
0426  *
0427  * FUNCTION:    acpi_hw_enable_runtime_gpe_block
0428  *
0429  * PARAMETERS:  gpe_xrupt_info      - GPE Interrupt info
0430  *              gpe_block           - Gpe Block info
0431  *
0432  * RETURN:      Status
0433  *
0434  * DESCRIPTION: Enable all "runtime" GPEs within a single GPE block. Includes
0435  *              combination wake/run GPEs.
0436  *
0437  ******************************************************************************/
0438 
0439 acpi_status
0440 acpi_hw_enable_runtime_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
0441                  struct acpi_gpe_block_info *gpe_block,
0442                  void *context)
0443 {
0444     u32 i;
0445     acpi_status status;
0446     struct acpi_gpe_register_info *gpe_register_info;
0447     u8 enable_mask;
0448 
0449     /* NOTE: assumes that all GPEs are currently disabled */
0450 
0451     /* Examine each GPE Register within the block */
0452 
0453     for (i = 0; i < gpe_block->register_count; i++) {
0454         gpe_register_info = &gpe_block->register_info[i];
0455         if (!gpe_register_info->enable_for_run) {
0456             continue;
0457         }
0458 
0459         /* Enable all "runtime" GPEs in this register */
0460 
0461         enable_mask = gpe_register_info->enable_for_run &
0462             ~gpe_register_info->mask_for_run;
0463         status =
0464             acpi_hw_gpe_enable_write(enable_mask, gpe_register_info);
0465         if (ACPI_FAILURE(status)) {
0466             return (status);
0467         }
0468     }
0469 
0470     return (AE_OK);
0471 }
0472 
0473 /******************************************************************************
0474  *
0475  * FUNCTION:    acpi_hw_enable_wakeup_gpe_block
0476  *
0477  * PARAMETERS:  gpe_xrupt_info      - GPE Interrupt info
0478  *              gpe_block           - Gpe Block info
0479  *
0480  * RETURN:      Status
0481  *
0482  * DESCRIPTION: Enable all "wake" GPEs within a single GPE block. Includes
0483  *              combination wake/run GPEs.
0484  *
0485  ******************************************************************************/
0486 
0487 static acpi_status
0488 acpi_hw_enable_wakeup_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
0489                 struct acpi_gpe_block_info *gpe_block,
0490                 void *context)
0491 {
0492     u32 i;
0493     acpi_status status;
0494     struct acpi_gpe_register_info *gpe_register_info;
0495 
0496     /* Examine each GPE Register within the block */
0497 
0498     for (i = 0; i < gpe_block->register_count; i++) {
0499         gpe_register_info = &gpe_block->register_info[i];
0500 
0501         /*
0502          * Enable all "wake" GPEs in this register and disable the
0503          * remaining ones.
0504          */
0505 
0506         status =
0507             acpi_hw_gpe_enable_write(gpe_register_info->enable_for_wake,
0508                          gpe_register_info);
0509         if (ACPI_FAILURE(status)) {
0510             return (status);
0511         }
0512     }
0513 
0514     return (AE_OK);
0515 }
0516 
0517 struct acpi_gpe_block_status_context {
0518     struct acpi_gpe_register_info *gpe_skip_register_info;
0519     u8 gpe_skip_mask;
0520     u8 retval;
0521 };
0522 
0523 /******************************************************************************
0524  *
0525  * FUNCTION:    acpi_hw_get_gpe_block_status
0526  *
0527  * PARAMETERS:  gpe_xrupt_info      - GPE Interrupt info
0528  *              gpe_block           - Gpe Block info
0529  *              context             - GPE list walk context data
0530  *
0531  * RETURN:      Success
0532  *
0533  * DESCRIPTION: Produce a combined GPE status bits mask for the given block.
0534  *
0535  ******************************************************************************/
0536 
0537 static acpi_status
0538 acpi_hw_get_gpe_block_status(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
0539                  struct acpi_gpe_block_info *gpe_block,
0540                  void *context)
0541 {
0542     struct acpi_gpe_block_status_context *c = context;
0543     struct acpi_gpe_register_info *gpe_register_info;
0544     u64 in_enable, in_status;
0545     acpi_status status;
0546     u8 ret_mask;
0547     u32 i;
0548 
0549     /* Examine each GPE Register within the block */
0550 
0551     for (i = 0; i < gpe_block->register_count; i++) {
0552         gpe_register_info = &gpe_block->register_info[i];
0553 
0554         status = acpi_hw_gpe_read(&in_enable,
0555                       &gpe_register_info->enable_address);
0556         if (ACPI_FAILURE(status)) {
0557             continue;
0558         }
0559 
0560         status = acpi_hw_gpe_read(&in_status,
0561                       &gpe_register_info->status_address);
0562         if (ACPI_FAILURE(status)) {
0563             continue;
0564         }
0565 
0566         ret_mask = in_enable & in_status;
0567         if (ret_mask && c->gpe_skip_register_info == gpe_register_info) {
0568             ret_mask &= ~c->gpe_skip_mask;
0569         }
0570         c->retval |= ret_mask;
0571     }
0572 
0573     return (AE_OK);
0574 }
0575 
0576 /******************************************************************************
0577  *
0578  * FUNCTION:    acpi_hw_disable_all_gpes
0579  *
0580  * PARAMETERS:  None
0581  *
0582  * RETURN:      Status
0583  *
0584  * DESCRIPTION: Disable and clear all GPEs in all GPE blocks
0585  *
0586  ******************************************************************************/
0587 
0588 acpi_status acpi_hw_disable_all_gpes(void)
0589 {
0590     acpi_status status;
0591 
0592     ACPI_FUNCTION_TRACE(hw_disable_all_gpes);
0593 
0594     status = acpi_ev_walk_gpe_list(acpi_hw_disable_gpe_block, NULL);
0595     return_ACPI_STATUS(status);
0596 }
0597 
0598 /******************************************************************************
0599  *
0600  * FUNCTION:    acpi_hw_enable_all_runtime_gpes
0601  *
0602  * PARAMETERS:  None
0603  *
0604  * RETURN:      Status
0605  *
0606  * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks
0607  *
0608  ******************************************************************************/
0609 
0610 acpi_status acpi_hw_enable_all_runtime_gpes(void)
0611 {
0612     acpi_status status;
0613 
0614     ACPI_FUNCTION_TRACE(hw_enable_all_runtime_gpes);
0615 
0616     status = acpi_ev_walk_gpe_list(acpi_hw_enable_runtime_gpe_block, NULL);
0617     return_ACPI_STATUS(status);
0618 }
0619 
0620 /******************************************************************************
0621  *
0622  * FUNCTION:    acpi_hw_enable_all_wakeup_gpes
0623  *
0624  * PARAMETERS:  None
0625  *
0626  * RETURN:      Status
0627  *
0628  * DESCRIPTION: Enable all "wakeup" GPEs, in all GPE blocks
0629  *
0630  ******************************************************************************/
0631 
0632 acpi_status acpi_hw_enable_all_wakeup_gpes(void)
0633 {
0634     acpi_status status;
0635 
0636     ACPI_FUNCTION_TRACE(hw_enable_all_wakeup_gpes);
0637 
0638     status = acpi_ev_walk_gpe_list(acpi_hw_enable_wakeup_gpe_block, NULL);
0639     return_ACPI_STATUS(status);
0640 }
0641 
0642 /******************************************************************************
0643  *
0644  * FUNCTION:    acpi_hw_check_all_gpes
0645  *
0646  * PARAMETERS:  gpe_skip_device      - GPE devoce of the GPE to skip
0647  *              gpe_skip_number      - Number of the GPE to skip
0648  *
0649  * RETURN:      Combined status of all GPEs
0650  *
0651  * DESCRIPTION: Check all enabled GPEs in all GPE blocks, except for the one
0652  *              represented by the "skip" arguments, and return TRUE if the
0653  *              status bit is set for at least one of them of FALSE otherwise.
0654  *
0655  ******************************************************************************/
0656 
0657 u8 acpi_hw_check_all_gpes(acpi_handle gpe_skip_device, u32 gpe_skip_number)
0658 {
0659     struct acpi_gpe_block_status_context context = {
0660         .gpe_skip_register_info = NULL,
0661         .retval = 0,
0662     };
0663     struct acpi_gpe_event_info *gpe_event_info;
0664     acpi_cpu_flags flags;
0665 
0666     ACPI_FUNCTION_TRACE(acpi_hw_check_all_gpes);
0667 
0668     flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
0669 
0670     gpe_event_info = acpi_ev_get_gpe_event_info(gpe_skip_device,
0671                             gpe_skip_number);
0672     if (gpe_event_info) {
0673         context.gpe_skip_register_info = gpe_event_info->register_info;
0674         context.gpe_skip_mask = acpi_hw_get_gpe_register_bit(gpe_event_info);
0675     }
0676 
0677     acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
0678 
0679     (void)acpi_ev_walk_gpe_list(acpi_hw_get_gpe_block_status, &context);
0680     return (context.retval != 0);
0681 }
0682 
0683 #endif              /* !ACPI_REDUCED_HARDWARE */