]> rtime.felk.cvut.cz Git - lisovros/linux_canprio.git/blob - drivers/acpi/acpica/hwgpe.c
ACPI / ACPICA: Use helper function for computing GPE masks
[lisovros/linux_canprio.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_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:      Status
66  *
67  * DESCRIPTION: Compute GPE enable mask with one bit corresponding to the given
68  *              GPE set.
69  *
70  ******************************************************************************/
71
72 u32 acpi_hw_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_disable_gpe
82  *
83  * PARAMETERS:  gpe_event_info      - Info block for the GPE to be disabled
84  *
85  * RETURN:      Status
86  *
87  * DESCRIPTION: Disable a single GPE in the enable register.
88  *
89  ******************************************************************************/
90
91 acpi_status acpi_hw_low_disable_gpe(struct acpi_gpe_event_info *gpe_event_info)
92 {
93         struct acpi_gpe_register_info *gpe_register_info;
94         acpi_status status;
95         u32 enable_mask;
96         u32 register_bit;
97
98         /* Get the info block for the entire GPE register */
99
100         gpe_register_info = gpe_event_info->register_info;
101         if (!gpe_register_info) {
102                 return (AE_NOT_EXIST);
103         }
104
105         /* Get current value of the enable register that contains this GPE */
106
107         status = acpi_hw_read(&enable_mask, &gpe_register_info->enable_address);
108         if (ACPI_FAILURE(status)) {
109                 return (status);
110         }
111
112         /* Clear just the bit that corresponds to this GPE */
113
114         register_bit = acpi_hw_gpe_register_bit(gpe_event_info,
115                                                 gpe_register_info);
116         ACPI_CLEAR_BIT(enable_mask, register_bit);
117
118         /* Write the updated enable mask */
119
120         status = acpi_hw_write(enable_mask, &gpe_register_info->enable_address);
121         return (status);
122 }
123
124 /******************************************************************************
125  *
126  * FUNCTION:    acpi_hw_write_gpe_enable_reg
127  *
128  * PARAMETERS:  gpe_event_info      - Info block for the GPE to be enabled
129  *
130  * RETURN:      Status
131  *
132  * DESCRIPTION: Write a GPE enable register.  Note: The bit for this GPE must
133  *              already be cleared or set in the parent register
134  *              enable_for_run mask.
135  *
136  ******************************************************************************/
137
138 acpi_status
139 acpi_hw_write_gpe_enable_reg(struct acpi_gpe_event_info * gpe_event_info)
140 {
141         struct acpi_gpe_register_info *gpe_register_info;
142         acpi_status status;
143
144         ACPI_FUNCTION_ENTRY();
145
146         /* Get the info block for the entire GPE register */
147
148         gpe_register_info = gpe_event_info->register_info;
149         if (!gpe_register_info) {
150                 return (AE_NOT_EXIST);
151         }
152
153         /* Write the entire GPE (runtime) enable register */
154
155         status = acpi_hw_write(gpe_register_info->enable_for_run,
156                                &gpe_register_info->enable_address);
157
158         return (status);
159 }
160
161 /******************************************************************************
162  *
163  * FUNCTION:    acpi_hw_clear_gpe
164  *
165  * PARAMETERS:  gpe_event_info      - Info block for the GPE to be cleared
166  *
167  * RETURN:      Status
168  *
169  * DESCRIPTION: Clear the status bit for a single GPE.
170  *
171  ******************************************************************************/
172
173 acpi_status acpi_hw_clear_gpe(struct acpi_gpe_event_info * gpe_event_info)
174 {
175         struct acpi_gpe_register_info *gpe_register_info;
176         acpi_status status;
177         u32 register_bit;
178
179         ACPI_FUNCTION_ENTRY();
180
181         /* Get the info block for the entire GPE register */
182
183         gpe_register_info = gpe_event_info->register_info;
184         if (!gpe_register_info) {
185                 return (AE_NOT_EXIST);
186         }
187
188         register_bit = acpi_hw_gpe_register_bit(gpe_event_info,
189                                                 gpe_register_info);
190
191         /*
192          * Write a one to the appropriate bit in the status register to
193          * clear this GPE.
194          */
195         status = acpi_hw_write(register_bit,
196                                &gpe_register_info->status_address);
197
198         return (status);
199 }
200
201 /******************************************************************************
202  *
203  * FUNCTION:    acpi_hw_get_gpe_status
204  *
205  * PARAMETERS:  gpe_event_info      - Info block for the GPE to queried
206  *              event_status        - Where the GPE status is returned
207  *
208  * RETURN:      Status
209  *
210  * DESCRIPTION: Return the status of a single GPE.
211  *
212  ******************************************************************************/
213
214 acpi_status
215 acpi_hw_get_gpe_status(struct acpi_gpe_event_info * gpe_event_info,
216                        acpi_event_status * event_status)
217 {
218         u32 in_byte;
219         u32 register_bit;
220         struct acpi_gpe_register_info *gpe_register_info;
221         acpi_status status;
222         acpi_event_status local_event_status = 0;
223
224         ACPI_FUNCTION_ENTRY();
225
226         if (!event_status) {
227                 return (AE_BAD_PARAMETER);
228         }
229
230         /* Get the info block for the entire GPE register */
231
232         gpe_register_info = gpe_event_info->register_info;
233
234         /* Get the register bitmask for this GPE */
235
236         register_bit = acpi_hw_gpe_register_bit(gpe_event_info,
237                                                 gpe_register_info);
238
239         /* GPE currently enabled? (enabled for runtime?) */
240
241         if (register_bit & gpe_register_info->enable_for_run) {
242                 local_event_status |= ACPI_EVENT_FLAG_ENABLED;
243         }
244
245         /* GPE enabled for wake? */
246
247         if (register_bit & gpe_register_info->enable_for_wake) {
248                 local_event_status |= ACPI_EVENT_FLAG_WAKE_ENABLED;
249         }
250
251         /* GPE currently active (status bit == 1)? */
252
253         status = acpi_hw_read(&in_byte, &gpe_register_info->status_address);
254         if (ACPI_FAILURE(status)) {
255                 return (status);
256         }
257
258         if (register_bit & in_byte) {
259                 local_event_status |= ACPI_EVENT_FLAG_SET;
260         }
261
262         /* Set return value */
263
264         (*event_status) = local_event_status;
265         return (AE_OK);
266 }
267
268 /******************************************************************************
269  *
270  * FUNCTION:    acpi_hw_disable_gpe_block
271  *
272  * PARAMETERS:  gpe_xrupt_info      - GPE Interrupt info
273  *              gpe_block           - Gpe Block info
274  *
275  * RETURN:      Status
276  *
277  * DESCRIPTION: Disable all GPEs within a single GPE block
278  *
279  ******************************************************************************/
280
281 acpi_status
282 acpi_hw_disable_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
283                           struct acpi_gpe_block_info *gpe_block, void *context)
284 {
285         u32 i;
286         acpi_status status;
287
288         /* Examine each GPE Register within the block */
289
290         for (i = 0; i < gpe_block->register_count; i++) {
291
292                 /* Disable all GPEs in this register */
293
294                 status =
295                     acpi_hw_write(0x00,
296                                   &gpe_block->register_info[i].enable_address);
297                 if (ACPI_FAILURE(status)) {
298                         return (status);
299                 }
300         }
301
302         return (AE_OK);
303 }
304
305 /******************************************************************************
306  *
307  * FUNCTION:    acpi_hw_clear_gpe_block
308  *
309  * PARAMETERS:  gpe_xrupt_info      - GPE Interrupt info
310  *              gpe_block           - Gpe Block info
311  *
312  * RETURN:      Status
313  *
314  * DESCRIPTION: Clear status bits for all GPEs within a single GPE block
315  *
316  ******************************************************************************/
317
318 acpi_status
319 acpi_hw_clear_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
320                         struct acpi_gpe_block_info *gpe_block, void *context)
321 {
322         u32 i;
323         acpi_status status;
324
325         /* Examine each GPE Register within the block */
326
327         for (i = 0; i < gpe_block->register_count; i++) {
328
329                 /* Clear status on all GPEs in this register */
330
331                 status =
332                     acpi_hw_write(0xFF,
333                                   &gpe_block->register_info[i].status_address);
334                 if (ACPI_FAILURE(status)) {
335                         return (status);
336                 }
337         }
338
339         return (AE_OK);
340 }
341
342 /******************************************************************************
343  *
344  * FUNCTION:    acpi_hw_enable_runtime_gpe_block
345  *
346  * PARAMETERS:  gpe_xrupt_info      - GPE Interrupt info
347  *              gpe_block           - Gpe Block info
348  *
349  * RETURN:      Status
350  *
351  * DESCRIPTION: Enable all "runtime" GPEs within a single GPE block. Includes
352  *              combination wake/run GPEs.
353  *
354  ******************************************************************************/
355
356 acpi_status
357 acpi_hw_enable_runtime_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
358                                  struct acpi_gpe_block_info *gpe_block, void *context)
359 {
360         u32 i;
361         acpi_status status;
362
363         /* NOTE: assumes that all GPEs are currently disabled */
364
365         /* Examine each GPE Register within the block */
366
367         for (i = 0; i < gpe_block->register_count; i++) {
368                 if (!gpe_block->register_info[i].enable_for_run) {
369                         continue;
370                 }
371
372                 /* Enable all "runtime" GPEs in this register */
373
374                 status =
375                     acpi_hw_write(gpe_block->register_info[i].enable_for_run,
376                                   &gpe_block->register_info[i].enable_address);
377                 if (ACPI_FAILURE(status)) {
378                         return (status);
379                 }
380         }
381
382         return (AE_OK);
383 }
384
385 /******************************************************************************
386  *
387  * FUNCTION:    acpi_hw_enable_wakeup_gpe_block
388  *
389  * PARAMETERS:  gpe_xrupt_info      - GPE Interrupt info
390  *              gpe_block           - Gpe Block info
391  *
392  * RETURN:      Status
393  *
394  * DESCRIPTION: Enable all "wake" GPEs within a single GPE block. Includes
395  *              combination wake/run GPEs.
396  *
397  ******************************************************************************/
398
399 static acpi_status
400 acpi_hw_enable_wakeup_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
401                                 struct acpi_gpe_block_info *gpe_block,
402                                 void *context)
403 {
404         u32 i;
405         acpi_status status;
406
407         /* Examine each GPE Register within the block */
408
409         for (i = 0; i < gpe_block->register_count; i++) {
410                 if (!gpe_block->register_info[i].enable_for_wake) {
411                         continue;
412                 }
413
414                 /* Enable all "wake" GPEs in this register */
415
416                 status =
417                     acpi_hw_write(gpe_block->register_info[i].enable_for_wake,
418                                   &gpe_block->register_info[i].enable_address);
419                 if (ACPI_FAILURE(status)) {
420                         return (status);
421                 }
422         }
423
424         return (AE_OK);
425 }
426
427 /******************************************************************************
428  *
429  * FUNCTION:    acpi_hw_disable_all_gpes
430  *
431  * PARAMETERS:  None
432  *
433  * RETURN:      Status
434  *
435  * DESCRIPTION: Disable and clear all GPEs in all GPE blocks
436  *
437  ******************************************************************************/
438
439 acpi_status acpi_hw_disable_all_gpes(void)
440 {
441         acpi_status status;
442
443         ACPI_FUNCTION_TRACE(hw_disable_all_gpes);
444
445         status = acpi_ev_walk_gpe_list(acpi_hw_disable_gpe_block, NULL);
446         status = acpi_ev_walk_gpe_list(acpi_hw_clear_gpe_block, NULL);
447         return_ACPI_STATUS(status);
448 }
449
450 /******************************************************************************
451  *
452  * FUNCTION:    acpi_hw_enable_all_runtime_gpes
453  *
454  * PARAMETERS:  None
455  *
456  * RETURN:      Status
457  *
458  * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks
459  *
460  ******************************************************************************/
461
462 acpi_status acpi_hw_enable_all_runtime_gpes(void)
463 {
464         acpi_status status;
465
466         ACPI_FUNCTION_TRACE(hw_enable_all_runtime_gpes);
467
468         status = acpi_ev_walk_gpe_list(acpi_hw_enable_runtime_gpe_block, NULL);
469         return_ACPI_STATUS(status);
470 }
471
472 /******************************************************************************
473  *
474  * FUNCTION:    acpi_hw_enable_all_wakeup_gpes
475  *
476  * PARAMETERS:  None
477  *
478  * RETURN:      Status
479  *
480  * DESCRIPTION: Enable all "wakeup" GPEs, in all GPE blocks
481  *
482  ******************************************************************************/
483
484 acpi_status acpi_hw_enable_all_wakeup_gpes(void)
485 {
486         acpi_status status;
487
488         ACPI_FUNCTION_TRACE(hw_enable_all_wakeup_gpes);
489
490         status = acpi_ev_walk_gpe_list(acpi_hw_enable_wakeup_gpe_block, NULL);
491         return_ACPI_STATUS(status);
492 }