Merge tag 'tegra-for-3.8-fixes-for-rc1' of git://git.kernel.org/pub/scm/linux/kernel...
[profile/ivi/kernel-adaptation-intel-automotive.git] / drivers / acpi / acpica / hwgpe.c
1 /******************************************************************************
2  *
3  * Module Name: hwgpe - Low level GPE enable/disable/clear functions
4  *
5  *****************************************************************************/
6
7 /*
8  * Copyright (C) 2000 - 2012, Intel Corp.
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions, and the following disclaimer,
16  *    without modification.
17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18  *    substantially similar to the "NO WARRANTY" disclaimer below
19  *    ("Disclaimer") and any redistribution must be conditioned upon
20  *    including a substantially similar Disclaimer requirement for further
21  *    binary redistribution.
22  * 3. Neither the names of the above-listed copyright holders nor the names
23  *    of any contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * Alternatively, this software may be distributed under the terms of the
27  * GNU General Public License ("GPL") version 2 as published by the Free
28  * Software Foundation.
29  *
30  * NO WARRANTY
31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41  * POSSIBILITY OF SUCH DAMAGES.
42  */
43
44 #include <acpi/acpi.h>
45 #include "accommon.h"
46 #include "acevents.h"
47
48 #define _COMPONENT          ACPI_HARDWARE
49 ACPI_MODULE_NAME("hwgpe")
50 #if (!ACPI_REDUCED_HARDWARE)    /* Entire module */
51 /* Local prototypes */
52 static acpi_status
53 acpi_hw_enable_wakeup_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
54                                 struct acpi_gpe_block_info *gpe_block,
55                                 void *context);
56
57 /******************************************************************************
58  *
59  * FUNCTION:    acpi_hw_get_gpe_register_bit
60  *
61  * PARAMETERS:  gpe_event_info      - Info block for the GPE
62  *
63  * RETURN:      Register mask with a one in the GPE bit position
64  *
65  * DESCRIPTION: Compute the register mask for this GPE. One bit is set in the
66  *              correct position for the input GPE.
67  *
68  ******************************************************************************/
69
70 u32 acpi_hw_get_gpe_register_bit(struct acpi_gpe_event_info *gpe_event_info)
71 {
72         return (u32)1 << (gpe_event_info->gpe_number -
73                  gpe_event_info->register_info->base_gpe_number);
74 }
75
76 /******************************************************************************
77  *
78  * FUNCTION:    acpi_hw_low_set_gpe
79  *
80  * PARAMETERS:  gpe_event_info      - Info block for the GPE to be disabled
81  *              action              - Enable or disable
82  *
83  * RETURN:      Status
84  *
85  * DESCRIPTION: Enable or disable a single GPE in the parent enable register.
86  *
87  ******************************************************************************/
88
89 acpi_status
90 acpi_hw_low_set_gpe(struct acpi_gpe_event_info *gpe_event_info, u32 action)
91 {
92         struct acpi_gpe_register_info *gpe_register_info;
93         acpi_status status;
94         u32 enable_mask;
95         u32 register_bit;
96
97         ACPI_FUNCTION_ENTRY();
98
99         /* Get the info block for the entire GPE register */
100
101         gpe_register_info = gpe_event_info->register_info;
102         if (!gpe_register_info) {
103                 return (AE_NOT_EXIST);
104         }
105
106         /* Get current value of the enable register that contains this GPE */
107
108         status = acpi_hw_read(&enable_mask, &gpe_register_info->enable_address);
109         if (ACPI_FAILURE(status)) {
110                 return (status);
111         }
112
113         /* Set or clear just the bit that corresponds to this GPE */
114
115         register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info);
116         switch (action) {
117         case ACPI_GPE_CONDITIONAL_ENABLE:
118
119                 /* Only enable if the enable_for_run bit is set */
120
121                 if (!(register_bit & gpe_register_info->enable_for_run)) {
122                         return (AE_BAD_PARAMETER);
123                 }
124
125                 /*lint -fallthrough */
126
127         case ACPI_GPE_ENABLE:
128                 ACPI_SET_BIT(enable_mask, register_bit);
129                 break;
130
131         case ACPI_GPE_DISABLE:
132                 ACPI_CLEAR_BIT(enable_mask, register_bit);
133                 break;
134
135         default:
136                 ACPI_ERROR((AE_INFO, "Invalid GPE Action, %u\n", action));
137                 return (AE_BAD_PARAMETER);
138         }
139
140         /* Write the updated enable mask */
141
142         status = acpi_hw_write(enable_mask, &gpe_register_info->enable_address);
143         return (status);
144 }
145
146 /******************************************************************************
147  *
148  * FUNCTION:    acpi_hw_clear_gpe
149  *
150  * PARAMETERS:  gpe_event_info      - Info block for the GPE to be cleared
151  *
152  * RETURN:      Status
153  *
154  * DESCRIPTION: Clear the status bit for a single GPE.
155  *
156  ******************************************************************************/
157
158 acpi_status acpi_hw_clear_gpe(struct acpi_gpe_event_info * gpe_event_info)
159 {
160         struct acpi_gpe_register_info *gpe_register_info;
161         acpi_status status;
162         u32 register_bit;
163
164         ACPI_FUNCTION_ENTRY();
165
166         /* Get the info block for the entire GPE register */
167
168         gpe_register_info = gpe_event_info->register_info;
169         if (!gpe_register_info) {
170                 return (AE_NOT_EXIST);
171         }
172
173         /*
174          * Write a one to the appropriate bit in the status register to
175          * clear this GPE.
176          */
177         register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info);
178
179         status = acpi_hw_write(register_bit,
180                                &gpe_register_info->status_address);
181
182         return (status);
183 }
184
185 /******************************************************************************
186  *
187  * FUNCTION:    acpi_hw_get_gpe_status
188  *
189  * PARAMETERS:  gpe_event_info      - Info block for the GPE to queried
190  *              event_status        - Where the GPE status is returned
191  *
192  * RETURN:      Status
193  *
194  * DESCRIPTION: Return the status of a single GPE.
195  *
196  ******************************************************************************/
197
198 acpi_status
199 acpi_hw_get_gpe_status(struct acpi_gpe_event_info * gpe_event_info,
200                        acpi_event_status * event_status)
201 {
202         u32 in_byte;
203         u32 register_bit;
204         struct acpi_gpe_register_info *gpe_register_info;
205         acpi_event_status local_event_status = 0;
206         acpi_status status;
207
208         ACPI_FUNCTION_ENTRY();
209
210         if (!event_status) {
211                 return (AE_BAD_PARAMETER);
212         }
213
214         /* Get the info block for the entire GPE register */
215
216         gpe_register_info = gpe_event_info->register_info;
217
218         /* Get the register bitmask for this GPE */
219
220         register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info);
221
222         /* GPE currently enabled? (enabled for runtime?) */
223
224         if (register_bit & gpe_register_info->enable_for_run) {
225                 local_event_status |= ACPI_EVENT_FLAG_ENABLED;
226         }
227
228         /* GPE enabled for wake? */
229
230         if (register_bit & gpe_register_info->enable_for_wake) {
231                 local_event_status |= ACPI_EVENT_FLAG_WAKE_ENABLED;
232         }
233
234         /* GPE currently active (status bit == 1)? */
235
236         status = acpi_hw_read(&in_byte, &gpe_register_info->status_address);
237         if (ACPI_FAILURE(status)) {
238                 return (status);
239         }
240
241         if (register_bit & in_byte) {
242                 local_event_status |= ACPI_EVENT_FLAG_SET;
243         }
244
245         /* Set return value */
246
247         (*event_status) = local_event_status;
248         return (AE_OK);
249 }
250
251 /******************************************************************************
252  *
253  * FUNCTION:    acpi_hw_disable_gpe_block
254  *
255  * PARAMETERS:  gpe_xrupt_info      - GPE Interrupt info
256  *              gpe_block           - Gpe Block info
257  *
258  * RETURN:      Status
259  *
260  * DESCRIPTION: Disable all GPEs within a single GPE block
261  *
262  ******************************************************************************/
263
264 acpi_status
265 acpi_hw_disable_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
266                           struct acpi_gpe_block_info *gpe_block, void *context)
267 {
268         u32 i;
269         acpi_status status;
270
271         /* Examine each GPE Register within the block */
272
273         for (i = 0; i < gpe_block->register_count; i++) {
274
275                 /* Disable all GPEs in this register */
276
277                 status =
278                     acpi_hw_write(0x00,
279                                   &gpe_block->register_info[i].enable_address);
280                 if (ACPI_FAILURE(status)) {
281                         return (status);
282                 }
283         }
284
285         return (AE_OK);
286 }
287
288 /******************************************************************************
289  *
290  * FUNCTION:    acpi_hw_clear_gpe_block
291  *
292  * PARAMETERS:  gpe_xrupt_info      - GPE Interrupt info
293  *              gpe_block           - Gpe Block info
294  *
295  * RETURN:      Status
296  *
297  * DESCRIPTION: Clear status bits for all GPEs within a single GPE block
298  *
299  ******************************************************************************/
300
301 acpi_status
302 acpi_hw_clear_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
303                         struct acpi_gpe_block_info *gpe_block, void *context)
304 {
305         u32 i;
306         acpi_status status;
307
308         /* Examine each GPE Register within the block */
309
310         for (i = 0; i < gpe_block->register_count; i++) {
311
312                 /* Clear status on all GPEs in this register */
313
314                 status =
315                     acpi_hw_write(0xFF,
316                                   &gpe_block->register_info[i].status_address);
317                 if (ACPI_FAILURE(status)) {
318                         return (status);
319                 }
320         }
321
322         return (AE_OK);
323 }
324
325 /******************************************************************************
326  *
327  * FUNCTION:    acpi_hw_enable_runtime_gpe_block
328  *
329  * PARAMETERS:  gpe_xrupt_info      - GPE Interrupt info
330  *              gpe_block           - Gpe Block info
331  *
332  * RETURN:      Status
333  *
334  * DESCRIPTION: Enable all "runtime" GPEs within a single GPE block. Includes
335  *              combination wake/run GPEs.
336  *
337  ******************************************************************************/
338
339 acpi_status
340 acpi_hw_enable_runtime_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
341                                  struct acpi_gpe_block_info * gpe_block,
342                                  void *context)
343 {
344         u32 i;
345         acpi_status status;
346
347         /* NOTE: assumes that all GPEs are currently disabled */
348
349         /* Examine each GPE Register within the block */
350
351         for (i = 0; i < gpe_block->register_count; i++) {
352                 if (!gpe_block->register_info[i].enable_for_run) {
353                         continue;
354                 }
355
356                 /* Enable all "runtime" GPEs in this register */
357
358                 status =
359                     acpi_hw_write(gpe_block->register_info[i].enable_for_run,
360                                   &gpe_block->register_info[i].enable_address);
361                 if (ACPI_FAILURE(status)) {
362                         return (status);
363                 }
364         }
365
366         return (AE_OK);
367 }
368
369 /******************************************************************************
370  *
371  * FUNCTION:    acpi_hw_enable_wakeup_gpe_block
372  *
373  * PARAMETERS:  gpe_xrupt_info      - GPE Interrupt info
374  *              gpe_block           - Gpe Block info
375  *
376  * RETURN:      Status
377  *
378  * DESCRIPTION: Enable all "wake" GPEs within a single GPE block. Includes
379  *              combination wake/run GPEs.
380  *
381  ******************************************************************************/
382
383 static acpi_status
384 acpi_hw_enable_wakeup_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
385                                 struct acpi_gpe_block_info *gpe_block,
386                                 void *context)
387 {
388         u32 i;
389         acpi_status status;
390
391         /* Examine each GPE Register within the block */
392
393         for (i = 0; i < gpe_block->register_count; i++) {
394                 if (!gpe_block->register_info[i].enable_for_wake) {
395                         continue;
396                 }
397
398                 /* Enable all "wake" GPEs in this register */
399
400                 status =
401                     acpi_hw_write(gpe_block->register_info[i].enable_for_wake,
402                                   &gpe_block->register_info[i].enable_address);
403                 if (ACPI_FAILURE(status)) {
404                         return (status);
405                 }
406         }
407
408         return (AE_OK);
409 }
410
411 /******************************************************************************
412  *
413  * FUNCTION:    acpi_hw_disable_all_gpes
414  *
415  * PARAMETERS:  None
416  *
417  * RETURN:      Status
418  *
419  * DESCRIPTION: Disable and clear all GPEs in all GPE blocks
420  *
421  ******************************************************************************/
422
423 acpi_status acpi_hw_disable_all_gpes(void)
424 {
425         acpi_status status;
426
427         ACPI_FUNCTION_TRACE(hw_disable_all_gpes);
428
429         status = acpi_ev_walk_gpe_list(acpi_hw_disable_gpe_block, NULL);
430         status = acpi_ev_walk_gpe_list(acpi_hw_clear_gpe_block, NULL);
431         return_ACPI_STATUS(status);
432 }
433
434 /******************************************************************************
435  *
436  * FUNCTION:    acpi_hw_enable_all_runtime_gpes
437  *
438  * PARAMETERS:  None
439  *
440  * RETURN:      Status
441  *
442  * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks
443  *
444  ******************************************************************************/
445
446 acpi_status acpi_hw_enable_all_runtime_gpes(void)
447 {
448         acpi_status status;
449
450         ACPI_FUNCTION_TRACE(hw_enable_all_runtime_gpes);
451
452         status = acpi_ev_walk_gpe_list(acpi_hw_enable_runtime_gpe_block, NULL);
453         return_ACPI_STATUS(status);
454 }
455
456 /******************************************************************************
457  *
458  * FUNCTION:    acpi_hw_enable_all_wakeup_gpes
459  *
460  * PARAMETERS:  None
461  *
462  * RETURN:      Status
463  *
464  * DESCRIPTION: Enable all "wakeup" GPEs, in all GPE blocks
465  *
466  ******************************************************************************/
467
468 acpi_status acpi_hw_enable_all_wakeup_gpes(void)
469 {
470         acpi_status status;
471
472         ACPI_FUNCTION_TRACE(hw_enable_all_wakeup_gpes);
473
474         status = acpi_ev_walk_gpe_list(acpi_hw_enable_wakeup_gpe_block, NULL);
475         return_ACPI_STATUS(status);
476 }
477
478 #endif                          /* !ACPI_REDUCED_HARDWARE */