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