ACPICA: Events: Add support to return both enable/status register values for GPE...
[firefly-linux-kernel-4.4.55.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 - 2015, 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 static acpi_status
58 acpi_hw_gpe_enable_write(u8 enable_mask,
59                          struct acpi_gpe_register_info *gpe_register_info);
60
61 /******************************************************************************
62  *
63  * FUNCTION:    acpi_hw_get_gpe_register_bit
64  *
65  * PARAMETERS:  gpe_event_info      - Info block for the GPE
66  *
67  * RETURN:      Register mask with a one in the GPE bit position
68  *
69  * DESCRIPTION: Compute the register mask for this GPE. One bit is set in the
70  *              correct position for the input GPE.
71  *
72  ******************************************************************************/
73
74 u32 acpi_hw_get_gpe_register_bit(struct acpi_gpe_event_info *gpe_event_info)
75 {
76
77         return ((u32)1 <<
78                 (gpe_event_info->gpe_number -
79                  gpe_event_info->register_info->base_gpe_number));
80 }
81
82 /******************************************************************************
83  *
84  * FUNCTION:    acpi_hw_low_set_gpe
85  *
86  * PARAMETERS:  gpe_event_info      - Info block for the GPE to be disabled
87  *              action              - Enable or disable
88  *
89  * RETURN:      Status
90  *
91  * DESCRIPTION: Enable or disable a single GPE in the parent enable register.
92  *
93  ******************************************************************************/
94
95 acpi_status
96 acpi_hw_low_set_gpe(struct acpi_gpe_event_info *gpe_event_info, u32 action)
97 {
98         struct acpi_gpe_register_info *gpe_register_info;
99         acpi_status status;
100         u32 enable_mask;
101         u32 register_bit;
102
103         ACPI_FUNCTION_ENTRY();
104
105         /* Get the info block for the entire GPE register */
106
107         gpe_register_info = gpe_event_info->register_info;
108         if (!gpe_register_info) {
109                 return (AE_NOT_EXIST);
110         }
111
112         /* Get current value of the enable register that contains this GPE */
113
114         status = acpi_hw_read(&enable_mask, &gpe_register_info->enable_address);
115         if (ACPI_FAILURE(status)) {
116                 return (status);
117         }
118
119         /* Set or clear just the bit that corresponds to this GPE */
120
121         register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info);
122         switch (action & ~ACPI_GPE_SAVE_MASK) {
123         case ACPI_GPE_CONDITIONAL_ENABLE:
124
125                 /* Only enable if the corresponding enable_mask bit is set */
126
127                 if (!(register_bit & gpe_register_info->enable_mask)) {
128                         return (AE_BAD_PARAMETER);
129                 }
130
131                 /*lint -fallthrough */
132
133         case ACPI_GPE_ENABLE:
134
135                 ACPI_SET_BIT(enable_mask, register_bit);
136                 break;
137
138         case ACPI_GPE_DISABLE:
139
140                 ACPI_CLEAR_BIT(enable_mask, register_bit);
141                 break;
142
143         default:
144
145                 ACPI_ERROR((AE_INFO, "Invalid GPE Action, %u", action));
146                 return (AE_BAD_PARAMETER);
147         }
148
149         /* Write the updated enable mask */
150
151         status = acpi_hw_write(enable_mask, &gpe_register_info->enable_address);
152         if (ACPI_SUCCESS(status) && (action & ACPI_GPE_SAVE_MASK)) {
153                 gpe_register_info->enable_mask = (u8)enable_mask;
154         }
155         return (status);
156 }
157
158 /******************************************************************************
159  *
160  * FUNCTION:    acpi_hw_clear_gpe
161  *
162  * PARAMETERS:  gpe_event_info      - Info block for the GPE to be cleared
163  *
164  * RETURN:      Status
165  *
166  * DESCRIPTION: Clear the status bit for a single GPE.
167  *
168  ******************************************************************************/
169
170 acpi_status acpi_hw_clear_gpe(struct acpi_gpe_event_info * gpe_event_info)
171 {
172         struct acpi_gpe_register_info *gpe_register_info;
173         acpi_status status;
174         u32 register_bit;
175
176         ACPI_FUNCTION_ENTRY();
177
178         /* Get the info block for the entire GPE register */
179
180         gpe_register_info = gpe_event_info->register_info;
181         if (!gpe_register_info) {
182                 return (AE_NOT_EXIST);
183         }
184
185         /*
186          * Write a one to the appropriate bit in the status register to
187          * clear this GPE.
188          */
189         register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info);
190
191         status = acpi_hw_write(register_bit,
192                                &gpe_register_info->status_address);
193
194         return (status);
195 }
196
197 /******************************************************************************
198  *
199  * FUNCTION:    acpi_hw_get_gpe_status
200  *
201  * PARAMETERS:  gpe_event_info      - Info block for the GPE to queried
202  *              event_status        - Where the GPE status is returned
203  *
204  * RETURN:      Status
205  *
206  * DESCRIPTION: Return the status of a single GPE.
207  *
208  ******************************************************************************/
209
210 acpi_status
211 acpi_hw_get_gpe_status(struct acpi_gpe_event_info * gpe_event_info,
212                        acpi_event_status *event_status)
213 {
214         u32 in_byte;
215         u32 register_bit;
216         struct acpi_gpe_register_info *gpe_register_info;
217         acpi_event_status local_event_status = 0;
218         acpi_status status;
219
220         ACPI_FUNCTION_ENTRY();
221
222         if (!event_status) {
223                 return (AE_BAD_PARAMETER);
224         }
225
226         /* GPE currently handled? */
227
228         if (ACPI_GPE_DISPATCH_TYPE(gpe_event_info->flags) !=
229             ACPI_GPE_DISPATCH_NONE) {
230                 local_event_status |= ACPI_EVENT_FLAG_HAS_HANDLER;
231         }
232
233         /* Get the info block for the entire GPE register */
234
235         gpe_register_info = gpe_event_info->register_info;
236
237         /* Get the register bitmask for this GPE */
238
239         register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info);
240
241         /* GPE currently enabled? (enabled for runtime?) */
242
243         if (register_bit & gpe_register_info->enable_for_run) {
244                 local_event_status |= ACPI_EVENT_FLAG_ENABLED;
245         }
246
247         /* GPE enabled for wake? */
248
249         if (register_bit & gpe_register_info->enable_for_wake) {
250                 local_event_status |= ACPI_EVENT_FLAG_WAKE_ENABLED;
251         }
252
253         /* GPE currently enabled (enable bit == 1)? */
254
255         status = acpi_hw_read(&in_byte, &gpe_register_info->enable_address);
256         if (ACPI_FAILURE(status)) {
257                 return (status);
258         }
259
260         if (register_bit & in_byte) {
261                 local_event_status |= ACPI_EVENT_FLAG_ENABLE_SET;
262         }
263
264         /* GPE currently active (status bit == 1)? */
265
266         status = acpi_hw_read(&in_byte, &gpe_register_info->status_address);
267         if (ACPI_FAILURE(status)) {
268                 return (status);
269         }
270
271         if (register_bit & in_byte) {
272                 local_event_status |= ACPI_EVENT_FLAG_STATUS_SET;
273         }
274
275         /* Set return value */
276
277         (*event_status) = local_event_status;
278         return (AE_OK);
279 }
280
281 /******************************************************************************
282  *
283  * FUNCTION:    acpi_hw_gpe_enable_write
284  *
285  * PARAMETERS:  enable_mask         - Bit mask to write to the GPE register
286  *              gpe_register_info   - Gpe Register info
287  *
288  * RETURN:      Status
289  *
290  * DESCRIPTION: Write the enable mask byte to the given GPE register.
291  *
292  ******************************************************************************/
293
294 static acpi_status
295 acpi_hw_gpe_enable_write(u8 enable_mask,
296                          struct acpi_gpe_register_info *gpe_register_info)
297 {
298         acpi_status status;
299
300         status = acpi_hw_write(enable_mask, &gpe_register_info->enable_address);
301         if (ACPI_SUCCESS(status)) {
302                 gpe_register_info->enable_mask = enable_mask;
303         }
304         return (status);
305 }
306
307 /******************************************************************************
308  *
309  * FUNCTION:    acpi_hw_disable_gpe_block
310  *
311  * PARAMETERS:  gpe_xrupt_info      - GPE Interrupt info
312  *              gpe_block           - Gpe Block info
313  *
314  * RETURN:      Status
315  *
316  * DESCRIPTION: Disable all GPEs within a single GPE block
317  *
318  ******************************************************************************/
319
320 acpi_status
321 acpi_hw_disable_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
322                           struct acpi_gpe_block_info *gpe_block, void *context)
323 {
324         u32 i;
325         acpi_status status;
326
327         /* Examine each GPE Register within the block */
328
329         for (i = 0; i < gpe_block->register_count; i++) {
330
331                 /* Disable all GPEs in this register */
332
333                 status =
334                     acpi_hw_gpe_enable_write(0x00,
335                                              &gpe_block->register_info[i]);
336                 if (ACPI_FAILURE(status)) {
337                         return (status);
338                 }
339         }
340
341         return (AE_OK);
342 }
343
344 /******************************************************************************
345  *
346  * FUNCTION:    acpi_hw_clear_gpe_block
347  *
348  * PARAMETERS:  gpe_xrupt_info      - GPE Interrupt info
349  *              gpe_block           - Gpe Block info
350  *
351  * RETURN:      Status
352  *
353  * DESCRIPTION: Clear status bits for all GPEs within a single GPE block
354  *
355  ******************************************************************************/
356
357 acpi_status
358 acpi_hw_clear_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
359                         struct acpi_gpe_block_info *gpe_block, void *context)
360 {
361         u32 i;
362         acpi_status status;
363
364         /* Examine each GPE Register within the block */
365
366         for (i = 0; i < gpe_block->register_count; i++) {
367
368                 /* Clear status on all GPEs in this register */
369
370                 status =
371                     acpi_hw_write(0xFF,
372                                   &gpe_block->register_info[i].status_address);
373                 if (ACPI_FAILURE(status)) {
374                         return (status);
375                 }
376         }
377
378         return (AE_OK);
379 }
380
381 /******************************************************************************
382  *
383  * FUNCTION:    acpi_hw_enable_runtime_gpe_block
384  *
385  * PARAMETERS:  gpe_xrupt_info      - GPE Interrupt info
386  *              gpe_block           - Gpe Block info
387  *
388  * RETURN:      Status
389  *
390  * DESCRIPTION: Enable all "runtime" GPEs within a single GPE block. Includes
391  *              combination wake/run GPEs.
392  *
393  ******************************************************************************/
394
395 acpi_status
396 acpi_hw_enable_runtime_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
397                                  struct acpi_gpe_block_info * gpe_block,
398                                  void *context)
399 {
400         u32 i;
401         acpi_status status;
402         struct acpi_gpe_register_info *gpe_register_info;
403
404         /* NOTE: assumes that all GPEs are currently disabled */
405
406         /* Examine each GPE Register within the block */
407
408         for (i = 0; i < gpe_block->register_count; i++) {
409                 gpe_register_info = &gpe_block->register_info[i];
410                 if (!gpe_register_info->enable_for_run) {
411                         continue;
412                 }
413
414                 /* Enable all "runtime" GPEs in this register */
415
416                 status =
417                     acpi_hw_gpe_enable_write(gpe_register_info->enable_for_run,
418                                              gpe_register_info);
419                 if (ACPI_FAILURE(status)) {
420                         return (status);
421                 }
422         }
423
424         return (AE_OK);
425 }
426
427 /******************************************************************************
428  *
429  * FUNCTION:    acpi_hw_enable_wakeup_gpe_block
430  *
431  * PARAMETERS:  gpe_xrupt_info      - GPE Interrupt info
432  *              gpe_block           - Gpe Block info
433  *
434  * RETURN:      Status
435  *
436  * DESCRIPTION: Enable all "wake" GPEs within a single GPE block. Includes
437  *              combination wake/run GPEs.
438  *
439  ******************************************************************************/
440
441 static acpi_status
442 acpi_hw_enable_wakeup_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
443                                 struct acpi_gpe_block_info *gpe_block,
444                                 void *context)
445 {
446         u32 i;
447         acpi_status status;
448         struct acpi_gpe_register_info *gpe_register_info;
449
450         /* Examine each GPE Register within the block */
451
452         for (i = 0; i < gpe_block->register_count; i++) {
453                 gpe_register_info = &gpe_block->register_info[i];
454
455                 /*
456                  * Enable all "wake" GPEs in this register and disable the
457                  * remaining ones.
458                  */
459
460                 status =
461                     acpi_hw_gpe_enable_write(gpe_register_info->enable_for_wake,
462                                              gpe_register_info);
463                 if (ACPI_FAILURE(status)) {
464                         return (status);
465                 }
466         }
467
468         return (AE_OK);
469 }
470
471 /******************************************************************************
472  *
473  * FUNCTION:    acpi_hw_disable_all_gpes
474  *
475  * PARAMETERS:  None
476  *
477  * RETURN:      Status
478  *
479  * DESCRIPTION: Disable and clear all GPEs in all GPE blocks
480  *
481  ******************************************************************************/
482
483 acpi_status acpi_hw_disable_all_gpes(void)
484 {
485         acpi_status status;
486
487         ACPI_FUNCTION_TRACE(hw_disable_all_gpes);
488
489         status = acpi_ev_walk_gpe_list(acpi_hw_disable_gpe_block, NULL);
490         status = acpi_ev_walk_gpe_list(acpi_hw_clear_gpe_block, NULL);
491         return_ACPI_STATUS(status);
492 }
493
494 /******************************************************************************
495  *
496  * FUNCTION:    acpi_hw_enable_all_runtime_gpes
497  *
498  * PARAMETERS:  None
499  *
500  * RETURN:      Status
501  *
502  * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks
503  *
504  ******************************************************************************/
505
506 acpi_status acpi_hw_enable_all_runtime_gpes(void)
507 {
508         acpi_status status;
509
510         ACPI_FUNCTION_TRACE(hw_enable_all_runtime_gpes);
511
512         status = acpi_ev_walk_gpe_list(acpi_hw_enable_runtime_gpe_block, NULL);
513         return_ACPI_STATUS(status);
514 }
515
516 /******************************************************************************
517  *
518  * FUNCTION:    acpi_hw_enable_all_wakeup_gpes
519  *
520  * PARAMETERS:  None
521  *
522  * RETURN:      Status
523  *
524  * DESCRIPTION: Enable all "wakeup" GPEs, in all GPE blocks
525  *
526  ******************************************************************************/
527
528 acpi_status acpi_hw_enable_all_wakeup_gpes(void)
529 {
530         acpi_status status;
531
532         ACPI_FUNCTION_TRACE(hw_enable_all_wakeup_gpes);
533
534         status = acpi_ev_walk_gpe_list(acpi_hw_enable_wakeup_gpe_block, NULL);
535         return_ACPI_STATUS(status);
536 }
537
538 #endif                          /* !ACPI_REDUCED_HARDWARE */