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 /****************************************************************************** 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 459 acpi_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 481 acpi_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 503 acpi_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