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