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