vserver 1.9.3
[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 - 2004, 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
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
198
199 /******************************************************************************
200  *
201  * FUNCTION:    acpi_hw_disable_gpe_block
202  *
203  * PARAMETERS:  gpe_xrupt_info      - GPE Interrupt info
204  *              gpe_block           - Gpe Block info
205  *
206  * RETURN:      Status
207  *
208  * DESCRIPTION: Disable all GPEs within a GPE block
209  *
210  ******************************************************************************/
211
212 acpi_status
213 acpi_hw_disable_gpe_block (
214         struct acpi_gpe_xrupt_info      *gpe_xrupt_info,
215         struct acpi_gpe_block_info      *gpe_block)
216 {
217         u32                             i;
218         acpi_status                     status;
219
220
221         /* Examine each GPE Register within the block */
222
223         for (i = 0; i < gpe_block->register_count; i++) {
224                 /* Disable all GPEs in this register */
225
226                 status = acpi_hw_low_level_write (8, 0x00,
227                                  &gpe_block->register_info[i].enable_address);
228                 if (ACPI_FAILURE (status)) {
229                         return (status);
230                 }
231         }
232
233         return (AE_OK);
234 }
235
236
237 /******************************************************************************
238  *
239  * FUNCTION:    acpi_hw_clear_gpe_block
240  *
241  * PARAMETERS:  gpe_xrupt_info      - GPE Interrupt info
242  *              gpe_block           - Gpe Block info
243  *
244  * RETURN:      Status
245  *
246  * DESCRIPTION: Clear status bits for all GPEs within a GPE block
247  *
248  ******************************************************************************/
249
250 acpi_status
251 acpi_hw_clear_gpe_block (
252         struct acpi_gpe_xrupt_info      *gpe_xrupt_info,
253         struct acpi_gpe_block_info      *gpe_block)
254 {
255         u32                             i;
256         acpi_status                     status;
257
258
259         /* Examine each GPE Register within the block */
260
261         for (i = 0; i < gpe_block->register_count; i++) {
262                 /* Clear status on all GPEs in this register */
263
264                 status = acpi_hw_low_level_write (8, 0xFF,
265                                  &gpe_block->register_info[i].status_address);
266                 if (ACPI_FAILURE (status)) {
267                         return (status);
268                 }
269         }
270
271         return (AE_OK);
272 }
273
274
275 /******************************************************************************
276  *
277  * FUNCTION:    acpi_hw_enable_runtime_gpe_block
278  *
279  * PARAMETERS:  gpe_xrupt_info      - GPE Interrupt info
280  *              gpe_block           - Gpe Block info
281  *
282  * RETURN:      Status
283  *
284  * DESCRIPTION: Enable all "runtime" GPEs within a GPE block. (Includes
285  *              combination wake/run GPEs.)
286  *
287  ******************************************************************************/
288
289 acpi_status
290 acpi_hw_enable_runtime_gpe_block (
291         struct acpi_gpe_xrupt_info      *gpe_xrupt_info,
292         struct acpi_gpe_block_info      *gpe_block)
293 {
294         u32                             i;
295         acpi_status                     status;
296
297
298         /* NOTE: assumes that all GPEs are currently disabled */
299
300         /* Examine each GPE Register within the block */
301
302         for (i = 0; i < gpe_block->register_count; i++) {
303                 if (!gpe_block->register_info[i].enable_for_run) {
304                         continue;
305                 }
306
307                 /* Enable all "runtime" GPEs in this register */
308
309                 status = acpi_hw_low_level_write (8, gpe_block->register_info[i].enable_for_run,
310                                  &gpe_block->register_info[i].enable_address);
311                 if (ACPI_FAILURE (status)) {
312                         return (status);
313                 }
314         }
315
316         return (AE_OK);
317 }
318
319
320 /******************************************************************************
321  *
322  * FUNCTION:    acpi_hw_enable_wakeup_gpe_block
323  *
324  * PARAMETERS:  gpe_xrupt_info      - GPE Interrupt info
325  *              gpe_block           - Gpe Block info
326  *
327  * RETURN:      Status
328  *
329  * DESCRIPTION: Enable all "wake" GPEs within a GPE block.  (Includes
330  *              combination wake/run GPEs.)
331  *
332  ******************************************************************************/
333
334 acpi_status
335 acpi_hw_enable_wakeup_gpe_block (
336         struct acpi_gpe_xrupt_info      *gpe_xrupt_info,
337         struct acpi_gpe_block_info      *gpe_block)
338 {
339         u32                             i;
340         acpi_status                     status;
341
342
343         /* Examine each GPE Register within the block */
344
345         for (i = 0; i < gpe_block->register_count; i++) {
346                 if (!gpe_block->register_info[i].enable_for_wake) {
347                         continue;
348                 }
349
350                 /* Enable all "wake" GPEs in this register */
351
352                 status = acpi_hw_low_level_write (8, gpe_block->register_info[i].enable_for_wake,
353                                  &gpe_block->register_info[i].enable_address);
354                 if (ACPI_FAILURE (status)) {
355                         return (status);
356                 }
357         }
358
359         return (AE_OK);
360 }
361
362
363 /******************************************************************************
364  *
365  * FUNCTION:    acpi_hw_disable_all_gpes
366  *
367  * PARAMETERS:  Flags           - ACPI_NOT_ISR or ACPI_ISR
368  *
369  * RETURN:      Status
370  *
371  * DESCRIPTION: Disable and clear all GPEs
372  *
373  ******************************************************************************/
374
375 acpi_status
376 acpi_hw_disable_all_gpes (
377         u32                             flags)
378 {
379         acpi_status                     status;
380
381
382         ACPI_FUNCTION_TRACE ("hw_disable_all_gpes");
383
384
385         status = acpi_ev_walk_gpe_list (acpi_hw_disable_gpe_block, flags);
386         status = acpi_ev_walk_gpe_list (acpi_hw_clear_gpe_block, flags);
387         return_ACPI_STATUS (status);
388 }
389
390
391 /******************************************************************************
392  *
393  * FUNCTION:    acpi_hw_enable_all_runtime_gpes
394  *
395  * PARAMETERS:  Flags           - ACPI_NOT_ISR or ACPI_ISR
396  *
397  * RETURN:      Status
398  *
399  * DESCRIPTION: Enable all GPEs of the given type
400  *
401  ******************************************************************************/
402
403 acpi_status
404 acpi_hw_enable_all_runtime_gpes (
405         u32                             flags)
406 {
407         acpi_status                     status;
408
409
410         ACPI_FUNCTION_TRACE ("hw_enable_all_runtime_gpes");
411
412
413         status = acpi_ev_walk_gpe_list (acpi_hw_enable_runtime_gpe_block, flags);
414         return_ACPI_STATUS (status);
415 }
416
417
418 /******************************************************************************
419  *
420  * FUNCTION:    acpi_hw_enable_all_wakeup_gpes
421  *
422  * PARAMETERS:  Flags           - ACPI_NOT_ISR or ACPI_ISR
423  *
424  * RETURN:      Status
425  *
426  * DESCRIPTION: Enable all GPEs of the given type
427  *
428  ******************************************************************************/
429
430 acpi_status
431 acpi_hw_enable_all_wakeup_gpes (
432         u32                             flags)
433 {
434         acpi_status                     status;
435
436
437         ACPI_FUNCTION_TRACE ("hw_enable_all_wakeup_gpes");
438
439
440         status = acpi_ev_walk_gpe_list (acpi_hw_enable_wakeup_gpe_block, flags);
441         return_ACPI_STATUS (status);
442 }
443