Merge branch 'devel-stable' of master.kernel.org:/home/rmk/linux-2.6-arm
[pandora-kernel.git] / drivers / acpi / acpica / hwgpe.c
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:      Register mask with a one in the GPE bit position
66  *
67  * DESCRIPTION: Compute the register mask for this GPE. One bit is set in the
68  *              correct position for the input GPE.
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 the parent enable register.
89  *
90  ******************************************************************************/
91
92 acpi_status
93 acpi_hw_low_set_gpe(struct acpi_gpe_event_info *gpe_event_info, u32 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 or 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
123                 /* Only enable if the enable_for_run bit is set */
124
125                 if (!(register_bit & gpe_register_info->enable_for_run)) {
126                         return (AE_BAD_PARAMETER);
127                 }
128
129                 /*lint -fallthrough */
130
131         case ACPI_GPE_ENABLE:
132                 ACPI_SET_BIT(enable_mask, register_bit);
133                 break;
134
135         case ACPI_GPE_DISABLE:
136                 ACPI_CLEAR_BIT(enable_mask, register_bit);
137                 break;
138
139         default:
140                 ACPI_ERROR((AE_INFO, "Invalid GPE Action, %u\n", action));
141                 return (AE_BAD_PARAMETER);
142         }
143
144         /* Write the updated enable mask */
145
146         status = acpi_hw_write(enable_mask, &gpe_register_info->enable_address);
147         return (status);
148 }
149
150 /******************************************************************************
151  *
152  * FUNCTION:    acpi_hw_clear_gpe
153  *
154  * PARAMETERS:  gpe_event_info      - Info block for the GPE to be cleared
155  *
156  * RETURN:      Status
157  *
158  * DESCRIPTION: Clear the status bit for a single GPE.
159  *
160  ******************************************************************************/
161
162 acpi_status acpi_hw_clear_gpe(struct acpi_gpe_event_info * gpe_event_info)
163 {
164         struct acpi_gpe_register_info *gpe_register_info;
165         acpi_status status;
166         u32 register_bit;
167
168         ACPI_FUNCTION_ENTRY();
169
170         /* Get the info block for the entire GPE register */
171
172         gpe_register_info = gpe_event_info->register_info;
173         if (!gpe_register_info) {
174                 return (AE_NOT_EXIST);
175         }
176
177         /*
178          * Write a one to the appropriate bit in the status register to
179          * clear this GPE.
180          */
181         register_bit =
182             acpi_hw_get_gpe_register_bit(gpe_event_info, gpe_register_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                                                 gpe_register_info);
227
228         /* GPE currently enabled? (enabled for runtime?) */
229
230         if (register_bit & gpe_register_info->enable_for_run) {
231                 local_event_status |= ACPI_EVENT_FLAG_ENABLED;
232         }
233
234         /* GPE enabled for wake? */
235
236         if (register_bit & gpe_register_info->enable_for_wake) {
237                 local_event_status |= ACPI_EVENT_FLAG_WAKE_ENABLED;
238         }
239
240         /* GPE currently active (status bit == 1)? */
241
242         status = acpi_hw_read(&in_byte, &gpe_register_info->status_address);
243         if (ACPI_FAILURE(status)) {
244                 return (status);
245         }
246
247         if (register_bit & in_byte) {
248                 local_event_status |= ACPI_EVENT_FLAG_SET;
249         }
250
251         /* Set return value */
252
253         (*event_status) = local_event_status;
254         return (AE_OK);
255 }
256
257 /******************************************************************************
258  *
259  * FUNCTION:    acpi_hw_disable_gpe_block
260  *
261  * PARAMETERS:  gpe_xrupt_info      - GPE Interrupt info
262  *              gpe_block           - Gpe Block info
263  *
264  * RETURN:      Status
265  *
266  * DESCRIPTION: Disable all GPEs within a single GPE block
267  *
268  ******************************************************************************/
269
270 acpi_status
271 acpi_hw_disable_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
272                           struct acpi_gpe_block_info *gpe_block, void *context)
273 {
274         u32 i;
275         acpi_status status;
276
277         /* Examine each GPE Register within the block */
278
279         for (i = 0; i < gpe_block->register_count; i++) {
280
281                 /* Disable all GPEs in this register */
282
283                 status =
284                     acpi_hw_write(0x00,
285                                   &gpe_block->register_info[i].enable_address);
286                 if (ACPI_FAILURE(status)) {
287                         return (status);
288                 }
289         }
290
291         return (AE_OK);
292 }
293
294 /******************************************************************************
295  *
296  * FUNCTION:    acpi_hw_clear_gpe_block
297  *
298  * PARAMETERS:  gpe_xrupt_info      - GPE Interrupt info
299  *              gpe_block           - Gpe Block info
300  *
301  * RETURN:      Status
302  *
303  * DESCRIPTION: Clear status bits for all GPEs within a single GPE block
304  *
305  ******************************************************************************/
306
307 acpi_status
308 acpi_hw_clear_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
309                         struct acpi_gpe_block_info *gpe_block, void *context)
310 {
311         u32 i;
312         acpi_status status;
313
314         /* Examine each GPE Register within the block */
315
316         for (i = 0; i < gpe_block->register_count; i++) {
317
318                 /* Clear status on all GPEs in this register */
319
320                 status =
321                     acpi_hw_write(0xFF,
322                                   &gpe_block->register_info[i].status_address);
323                 if (ACPI_FAILURE(status)) {
324                         return (status);
325                 }
326         }
327
328         return (AE_OK);
329 }
330
331 /******************************************************************************
332  *
333  * FUNCTION:    acpi_hw_enable_runtime_gpe_block
334  *
335  * PARAMETERS:  gpe_xrupt_info      - GPE Interrupt info
336  *              gpe_block           - Gpe Block info
337  *
338  * RETURN:      Status
339  *
340  * DESCRIPTION: Enable all "runtime" GPEs within a single GPE block. Includes
341  *              combination wake/run GPEs.
342  *
343  ******************************************************************************/
344
345 acpi_status
346 acpi_hw_enable_runtime_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
347                                  struct acpi_gpe_block_info *gpe_block, 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 }