--- zzzz-none-000/linux-4.9.279/drivers/acpi/acpica/evgpe.c 2021-08-08 06:38:54.000000000 +0000 +++ puma7-atom-6591-750/linux-4.9.279/drivers/acpi/acpica/evgpe.c 2023-02-08 11:43:42.000000000 +0000 @@ -47,6 +47,17 @@ #include "acnamesp.h" #define _COMPONENT ACPI_EVENTS +//PM1_CTRL register address +#define PM1_CTRL_ADDRESS 0x404 +//Base GPE number for the Punit SCI interrupt event +#define PUNIT_SCI_BASE_GPE_NUM 0x0 +//GPE number for the Punit SCI interrupt event +#define PUNIT_SCI_GPE_NUM 0x4 +//Punit SCI bit mask for GPE0a_EN register +#define PUNIT_SCI_BIT_MASK 0x10 +//SCI_EN bit in PM1_CNT register +#define SCI_EN_BIT_MASK 0x1 + ACPI_MODULE_NAME("evgpe") #if (!ACPI_REDUCED_HARDWARE) /* Entire module */ /* Local prototypes */ @@ -462,6 +473,10 @@ status = acpi_hw_read(&enable_reg, &gpe_register_info->enable_address); + //Workaround for the issue that PUNIT GPE event doesn't have enable bit. + if(gpe_register_info->base_gpe_number == PUNIT_SCI_BASE_GPE_NUM){ + enable_reg = enable_reg | PUNIT_SCI_BIT_MASK; + } if (ACPI_FAILURE(status)) { goto unlock_and_exit; } @@ -709,7 +724,9 @@ acpi_status acpi_ev_finish_gpe(struct acpi_gpe_event_info *gpe_event_info) { acpi_status status; - + u32 reg_value; + struct acpi_generic_address pm1_ctrl_address; + if ((gpe_event_info->flags & ACPI_GPE_XRUPT_TYPE_MASK) == ACPI_GPE_LEVEL_TRIGGERED) { /* @@ -722,13 +739,29 @@ } } - /* - * Enable this GPE, conditionally. This means that the GPE will - * only be physically enabled if the enable_mask bit is set - * in the event_info. - */ - (void)acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_CONDITIONAL_ENABLE); - gpe_event_info->disable_for_dispatch = FALSE; + /*Workaround for the issue that PUNIT GPE event doesn't have enable bit. + Instead of enabling the individual punit enable bit, we enable the master + SCI_EN.*/ + if(gpe_event_info->gpe_number == PUNIT_SCI_GPE_NUM){ + /*Since GPE0a_Status register and PM1_CNT register are under the same + register block, we can reuse all the setting.*/ + pm1_ctrl_address = gpe_event_info->register_info->status_address; + pm1_ctrl_address.address = PM1_CTRL_ADDRESS; + status = acpi_hw_read(®_value, &pm1_ctrl_address); + //Set SCI_EN bit in PM1_CTRL register. + reg_value = reg_value | SCI_EN_BIT_MASK; + status = acpi_hw_write(reg_value, &pm1_ctrl_address); + } + else{ + /* + * Enable this GPE, conditionally. This means that the GPE will + * only be physically enabled if the enable_mask bit is set + * in the event_info. + */ + (void)acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_CONDITIONAL_ENABLE); + gpe_event_info->disable_for_dispatch = FALSE; + } + return (AE_OK); } @@ -756,6 +789,8 @@ { acpi_status status; u32 return_value; + u32 reg_value; + struct acpi_generic_address pm1_ctrl_address; ACPI_FUNCTION_TRACE(ev_gpe_dispatch); @@ -792,7 +827,23 @@ } } - gpe_event_info->disable_for_dispatch = TRUE; + + /*Workaround for the issue that PUNIT GPE event doesn't have enable bit. + Instead of disabling the individual punit enable bit, we disable the master + SCI_EN.*/ + if(gpe_event_info->gpe_number == PUNIT_SCI_GPE_NUM){ + /*Since GPE0a_Status register and PM1_CNT register are under the same + register block, we can reuse all the setting.*/ + pm1_ctrl_address = gpe_event_info->register_info->status_address; + pm1_ctrl_address.address = PM1_CTRL_ADDRESS; + status = acpi_hw_read(®_value, &pm1_ctrl_address); + //Clear SCI_EN bit in PM1_CTRL register. + reg_value = reg_value & (~SCI_EN_BIT_MASK); + status = acpi_hw_write(reg_value, &pm1_ctrl_address); + } + else{ + gpe_event_info->disable_for_dispatch = TRUE; + } /* * Dispatch the GPE to either an installed handler or the control