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