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