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