aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/acpica/evgpe.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/acpica/evgpe.c')
-rw-r--r--drivers/acpi/acpica/evgpe.c142
1 files changed, 127 insertions, 15 deletions
diff --git a/drivers/acpi/acpica/evgpe.c b/drivers/acpi/acpica/evgpe.c
index 7c2c336006a..f226eac314d 100644
--- a/drivers/acpi/acpica/evgpe.c
+++ b/drivers/acpi/acpica/evgpe.c
@@ -54,51 +54,159 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context);
54 54
55/******************************************************************************* 55/*******************************************************************************
56 * 56 *
57 * FUNCTION: acpi_ev_update_gpe_enable_masks 57 * FUNCTION: acpi_ev_update_gpe_enable_mask
58 * 58 *
59 * PARAMETERS: gpe_event_info - GPE to update 59 * PARAMETERS: gpe_event_info - GPE to update
60 * 60 *
61 * RETURN: Status 61 * RETURN: Status
62 * 62 *
63 * DESCRIPTION: Updates GPE register enable masks based upon whether there are 63 * DESCRIPTION: Updates GPE register enable mask based upon whether there are
64 * references (either wake or run) to this GPE 64 * runtime references to this GPE
65 * 65 *
66 ******************************************************************************/ 66 ******************************************************************************/
67 67
68acpi_status 68acpi_status
69acpi_ev_update_gpe_enable_masks(struct acpi_gpe_event_info *gpe_event_info) 69acpi_ev_update_gpe_enable_mask(struct acpi_gpe_event_info *gpe_event_info)
70{ 70{
71 struct acpi_gpe_register_info *gpe_register_info; 71 struct acpi_gpe_register_info *gpe_register_info;
72 u32 register_bit; 72 u32 register_bit;
73 73
74 ACPI_FUNCTION_TRACE(ev_update_gpe_enable_masks); 74 ACPI_FUNCTION_TRACE(ev_update_gpe_enable_mask);
75 75
76 gpe_register_info = gpe_event_info->register_info; 76 gpe_register_info = gpe_event_info->register_info;
77 if (!gpe_register_info) { 77 if (!gpe_register_info) {
78 return_ACPI_STATUS(AE_NOT_EXIST); 78 return_ACPI_STATUS(AE_NOT_EXIST);
79 } 79 }
80 80
81 register_bit = acpi_hw_gpe_register_bit(gpe_event_info, 81 register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info,
82 gpe_register_info); 82 gpe_register_info);
83 83
84 /* Clear the wake/run bits up front */ 84 /* Clear the run bit up front */
85 85
86 ACPI_CLEAR_BIT(gpe_register_info->enable_for_wake, register_bit);
87 ACPI_CLEAR_BIT(gpe_register_info->enable_for_run, register_bit); 86 ACPI_CLEAR_BIT(gpe_register_info->enable_for_run, register_bit);
88 87
89 /* Set the mask bits only if there are references to this GPE */ 88 /* Set the mask bit only if there are references to this GPE */
90 89
91 if (gpe_event_info->runtime_count) { 90 if (gpe_event_info->runtime_count) {
92 ACPI_SET_BIT(gpe_register_info->enable_for_run, register_bit); 91 ACPI_SET_BIT(gpe_register_info->enable_for_run, (u8)register_bit);
93 } 92 }
94 93
95 if (gpe_event_info->wakeup_count) { 94 return_ACPI_STATUS(AE_OK);
96 ACPI_SET_BIT(gpe_register_info->enable_for_wake, register_bit); 95}
96
97/*******************************************************************************
98 *
99 * FUNCTION: acpi_ev_enable_gpe
100 *
101 * PARAMETERS: gpe_event_info - GPE to enable
102 *
103 * RETURN: Status
104 *
105 * DESCRIPTION: Clear the given GPE from stale events and enable it.
106 *
107 ******************************************************************************/
108acpi_status
109acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info)
110{
111 acpi_status status;
112
113 ACPI_FUNCTION_TRACE(ev_enable_gpe);
114
115 /*
116 * We will only allow a GPE to be enabled if it has either an
117 * associated method (_Lxx/_Exx) or a handler. Otherwise, the
118 * GPE will be immediately disabled by acpi_ev_gpe_dispatch the
119 * first time it fires.
120 */
121 if (!(gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK)) {
122 return_ACPI_STATUS(AE_NO_HANDLER);
97 } 123 }
98 124
99 return_ACPI_STATUS(AE_OK); 125 /* Clear the GPE (of stale events) */
126 status = acpi_hw_clear_gpe(gpe_event_info);
127 if (ACPI_FAILURE(status)) {
128 return_ACPI_STATUS(status);
129 }
130
131 /* Enable the requested GPE */
132 status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_ENABLE);
133
134 return_ACPI_STATUS(status);
135}
136
137
138/*******************************************************************************
139 *
140 * FUNCTION: acpi_raw_enable_gpe
141 *
142 * PARAMETERS: gpe_event_info - GPE to enable
143 *
144 * RETURN: Status
145 *
146 * DESCRIPTION: Add a reference to a GPE. On the first reference, the GPE is
147 * hardware-enabled.
148 *
149 ******************************************************************************/
150
151acpi_status acpi_raw_enable_gpe(struct acpi_gpe_event_info *gpe_event_info)
152{
153 acpi_status status = AE_OK;
154
155 if (gpe_event_info->runtime_count == ACPI_UINT8_MAX) {
156 return_ACPI_STATUS(AE_LIMIT);
157 }
158
159 gpe_event_info->runtime_count++;
160 if (gpe_event_info->runtime_count == 1) {
161 status = acpi_ev_update_gpe_enable_mask(gpe_event_info);
162 if (ACPI_SUCCESS(status)) {
163 status = acpi_ev_enable_gpe(gpe_event_info);
164 }
165
166 if (ACPI_FAILURE(status)) {
167 gpe_event_info->runtime_count--;
168 }
169 }
170
171 return_ACPI_STATUS(status);
100} 172}
101 173
174/*******************************************************************************
175 *
176 * FUNCTION: acpi_raw_disable_gpe
177 *
178 * PARAMETERS: gpe_event_info - GPE to disable
179 *
180 * RETURN: Status
181 *
182 * DESCRIPTION: Remove a reference to a GPE. When the last reference is
183 * removed, the GPE is hardware-disabled.
184 *
185 ******************************************************************************/
186
187acpi_status acpi_raw_disable_gpe(struct acpi_gpe_event_info *gpe_event_info)
188{
189 acpi_status status = AE_OK;
190
191 if (!gpe_event_info->runtime_count) {
192 return_ACPI_STATUS(AE_LIMIT);
193 }
194
195 gpe_event_info->runtime_count--;
196 if (!gpe_event_info->runtime_count) {
197 status = acpi_ev_update_gpe_enable_mask(gpe_event_info);
198 if (ACPI_SUCCESS(status)) {
199 status = acpi_hw_low_set_gpe(gpe_event_info,
200 ACPI_GPE_DISABLE);
201 }
202
203 if (ACPI_FAILURE(status)) {
204 gpe_event_info->runtime_count++;
205 }
206 }
207
208 return_ACPI_STATUS(status);
209}
102 210
103/******************************************************************************* 211/*******************************************************************************
104 * 212 *
@@ -417,8 +525,12 @@ static void acpi_ev_asynch_enable_gpe(void *context)
417 } 525 }
418 } 526 }
419 527
420 /* Enable this GPE */ 528 /*
421 (void)acpi_hw_write_gpe_enable_reg(gpe_event_info); 529 * Enable this GPE, conditionally. This means that the GPE will only be
530 * physically enabled if the enable_for_run bit is set in the event_info
531 */
532 (void)acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_COND_ENABLE);
533
422 return_VOID; 534 return_VOID;
423} 535}
424 536