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) { 119 case ACPI_GPE_CONDITIONAL_ENABLE: 120 121 /* Only enable if the enable_for_run bit is set */ 122 123 if (!(register_bit & gpe_register_info->enable_for_run)) { 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 return (status); 149 } 150 151 /****************************************************************************** 152 * 153 * FUNCTION: acpi_hw_clear_gpe 154 * 155 * PARAMETERS: gpe_event_info - Info block for the GPE to be cleared 156 * 157 * RETURN: Status 158 * 159 * DESCRIPTION: Clear the status bit for a single GPE. 160 * 161 ******************************************************************************/ 162 163 acpi_status acpi_hw_clear_gpe(struct acpi_gpe_event_info * gpe_event_info) 164 { 165 struct acpi_gpe_register_info *gpe_register_info; 166 acpi_status status; 167 u32 register_bit; 168 169 ACPI_FUNCTION_ENTRY(); 170 171 /* Get the info block for the entire GPE register */ 172 173 gpe_register_info = gpe_event_info->register_info; 174 if (!gpe_register_info) { 175 return (AE_NOT_EXIST); 176 } 177 178 /* 179 * Write a one to the appropriate bit in the status register to 180 * clear this GPE. 181 */ 182 register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info); 183 184 status = acpi_hw_write(register_bit, 185 &gpe_register_info->status_address); 186 187 return (status); 188 } 189 190 /****************************************************************************** 191 * 192 * FUNCTION: acpi_hw_get_gpe_status 193 * 194 * PARAMETERS: gpe_event_info - Info block for the GPE to queried 195 * event_status - Where the GPE status is returned 196 * 197 * RETURN: Status 198 * 199 * DESCRIPTION: Return the status of a single GPE. 200 * 201 ******************************************************************************/ 202 203 acpi_status 204 acpi_hw_get_gpe_status(struct acpi_gpe_event_info * gpe_event_info, 205 acpi_event_status * event_status) 206 { 207 u32 in_byte; 208 u32 register_bit; 209 struct acpi_gpe_register_info *gpe_register_info; 210 acpi_event_status local_event_status = 0; 211 acpi_status status; 212 213 ACPI_FUNCTION_ENTRY(); 214 215 if (!event_status) { 216 return (AE_BAD_PARAMETER); 217 } 218 219 /* Get the info block for the entire GPE register */ 220 221 gpe_register_info = gpe_event_info->register_info; 222 223 /* Get the register bitmask for this GPE */ 224 225 register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info); 226 227 /* GPE currently enabled? (enabled for runtime?) */ 228 229 if (register_bit & gpe_register_info->enable_for_run) { 230 local_event_status |= ACPI_EVENT_FLAG_ENABLED; 231 } 232 233 /* GPE enabled for wake? */ 234 235 if (register_bit & gpe_register_info->enable_for_wake) { 236 local_event_status |= ACPI_EVENT_FLAG_WAKE_ENABLED; 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_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_disable_gpe_block 259 * 260 * PARAMETERS: gpe_xrupt_info - GPE Interrupt info 261 * gpe_block - Gpe Block info 262 * 263 * RETURN: Status 264 * 265 * DESCRIPTION: Disable all GPEs within a single GPE block 266 * 267 ******************************************************************************/ 268 269 acpi_status 270 acpi_hw_disable_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info, 271 struct acpi_gpe_block_info *gpe_block, void *context) 272 { 273 u32 i; 274 acpi_status status; 275 276 /* Examine each GPE Register within the block */ 277 278 for (i = 0; i < gpe_block->register_count; i++) { 279 280 /* Disable all GPEs in this register */ 281 282 status = 283 acpi_hw_write(0x00, 284 &gpe_block->register_info[i].enable_address); 285 if (ACPI_FAILURE(status)) { 286 return (status); 287 } 288 } 289 290 return (AE_OK); 291 } 292 293 /****************************************************************************** 294 * 295 * FUNCTION: acpi_hw_clear_gpe_block 296 * 297 * PARAMETERS: gpe_xrupt_info - GPE Interrupt info 298 * gpe_block - Gpe Block info 299 * 300 * RETURN: Status 301 * 302 * DESCRIPTION: Clear status bits for all GPEs within a single GPE block 303 * 304 ******************************************************************************/ 305 306 acpi_status 307 acpi_hw_clear_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info, 308 struct acpi_gpe_block_info *gpe_block, void *context) 309 { 310 u32 i; 311 acpi_status status; 312 313 /* Examine each GPE Register within the block */ 314 315 for (i = 0; i < gpe_block->register_count; i++) { 316 317 /* Clear status on all GPEs in this register */ 318 319 status = 320 acpi_hw_write(0xFF, 321 &gpe_block->register_info[i].status_address); 322 if (ACPI_FAILURE(status)) { 323 return (status); 324 } 325 } 326 327 return (AE_OK); 328 } 329 330 /****************************************************************************** 331 * 332 * FUNCTION: acpi_hw_enable_runtime_gpe_block 333 * 334 * PARAMETERS: gpe_xrupt_info - GPE Interrupt info 335 * gpe_block - Gpe Block info 336 * 337 * RETURN: Status 338 * 339 * DESCRIPTION: Enable all "runtime" GPEs within a single GPE block. Includes 340 * combination wake/run GPEs. 341 * 342 ******************************************************************************/ 343 344 acpi_status 345 acpi_hw_enable_runtime_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info, 346 struct acpi_gpe_block_info * gpe_block, 347 void *context) 348 { 349 u32 i; 350 acpi_status status; 351 352 /* NOTE: assumes that all GPEs are currently disabled */ 353 354 /* Examine each GPE Register within the block */ 355 356 for (i = 0; i < gpe_block->register_count; i++) { 357 if (!gpe_block->register_info[i].enable_for_run) { 358 continue; 359 } 360 361 /* Enable all "runtime" GPEs in this register */ 362 363 status = 364 acpi_hw_write(gpe_block->register_info[i].enable_for_run, 365 &gpe_block->register_info[i].enable_address); 366 if (ACPI_FAILURE(status)) { 367 return (status); 368 } 369 } 370 371 return (AE_OK); 372 } 373 374 /****************************************************************************** 375 * 376 * FUNCTION: acpi_hw_enable_wakeup_gpe_block 377 * 378 * PARAMETERS: gpe_xrupt_info - GPE Interrupt info 379 * gpe_block - Gpe Block info 380 * 381 * RETURN: Status 382 * 383 * DESCRIPTION: Enable all "wake" GPEs within a single GPE block. Includes 384 * combination wake/run GPEs. 385 * 386 ******************************************************************************/ 387 388 static acpi_status 389 acpi_hw_enable_wakeup_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info, 390 struct acpi_gpe_block_info *gpe_block, 391 void *context) 392 { 393 u32 i; 394 acpi_status status; 395 396 /* Examine each GPE Register within the block */ 397 398 for (i = 0; i < gpe_block->register_count; i++) { 399 if (!gpe_block->register_info[i].enable_for_wake) { 400 continue; 401 } 402 403 /* Enable all "wake" GPEs in this register */ 404 405 status = 406 acpi_hw_write(gpe_block->register_info[i].enable_for_wake, 407 &gpe_block->register_info[i].enable_address); 408 if (ACPI_FAILURE(status)) { 409 return (status); 410 } 411 } 412 413 return (AE_OK); 414 } 415 416 /****************************************************************************** 417 * 418 * FUNCTION: acpi_hw_disable_all_gpes 419 * 420 * PARAMETERS: None 421 * 422 * RETURN: Status 423 * 424 * DESCRIPTION: Disable and clear all GPEs in all GPE blocks 425 * 426 ******************************************************************************/ 427 428 acpi_status acpi_hw_disable_all_gpes(void) 429 { 430 acpi_status status; 431 432 ACPI_FUNCTION_TRACE(hw_disable_all_gpes); 433 434 status = acpi_ev_walk_gpe_list(acpi_hw_disable_gpe_block, NULL); 435 status = acpi_ev_walk_gpe_list(acpi_hw_clear_gpe_block, NULL); 436 return_ACPI_STATUS(status); 437 } 438 439 /****************************************************************************** 440 * 441 * FUNCTION: acpi_hw_enable_all_runtime_gpes 442 * 443 * PARAMETERS: None 444 * 445 * RETURN: Status 446 * 447 * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks 448 * 449 ******************************************************************************/ 450 451 acpi_status acpi_hw_enable_all_runtime_gpes(void) 452 { 453 acpi_status status; 454 455 ACPI_FUNCTION_TRACE(hw_enable_all_runtime_gpes); 456 457 status = acpi_ev_walk_gpe_list(acpi_hw_enable_runtime_gpe_block, NULL); 458 return_ACPI_STATUS(status); 459 } 460 461 /****************************************************************************** 462 * 463 * FUNCTION: acpi_hw_enable_all_wakeup_gpes 464 * 465 * PARAMETERS: None 466 * 467 * RETURN: Status 468 * 469 * DESCRIPTION: Enable all "wakeup" GPEs, in all GPE blocks 470 * 471 ******************************************************************************/ 472 473 acpi_status acpi_hw_enable_all_wakeup_gpes(void) 474 { 475 acpi_status status; 476 477 ACPI_FUNCTION_TRACE(hw_enable_all_wakeup_gpes); 478 479 status = acpi_ev_walk_gpe_list(acpi_hw_enable_wakeup_gpe_block, NULL); 480 return_ACPI_STATUS(status); 481 } 482 483 #endif /* !ACPI_REDUCED_HARDWARE */ 484