Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
hwgpe.c
Go to the documentation of this file.
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 
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 
92 {
93  struct acpi_gpe_register_info *gpe_register_info;
95  u32 enable_mask;
96  u32 register_bit;
97 
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) {
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 
160 {
161  struct acpi_gpe_register_info *gpe_register_info;
163  u32 register_bit;
164 
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 
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;
208 
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 
267  struct acpi_gpe_block_info *gpe_block, void *context)
268 {
269  u32 i;
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 
304  struct acpi_gpe_block_info *gpe_block, void *context)
305 {
306  u32 i;
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 
342  struct acpi_gpe_block_info *gpe_block, void *context)
343 {
344  u32 i;
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;
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 
424 {
426 
427  ACPI_FUNCTION_TRACE(hw_disable_all_gpes);
428 
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 
447 {
449 
450  ACPI_FUNCTION_TRACE(hw_enable_all_runtime_gpes);
451 
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 
469 {
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 */