• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/drivers/acpi/acpica/
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
50ACPI_MODULE_NAME("hwgpe")
51
52/* Local prototypes */
53static acpi_status
54acpi_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_get_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
72u32 acpi_hw_get_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_set_gpe
82 *
83 * PARAMETERS:	gpe_event_info	    - Info block for the GPE to be disabled
84 *		action		    - Enable or disable
85 *
86 * RETURN:	Status
87 *
88 * DESCRIPTION: Enable or disable a single GPE in its enable register.
89 *
90 ******************************************************************************/
91
92acpi_status
93acpi_hw_low_set_gpe(struct acpi_gpe_event_info *gpe_event_info, u8 action)
94{
95	struct acpi_gpe_register_info *gpe_register_info;
96	acpi_status status;
97	u32 enable_mask;
98	u32 register_bit;
99
100	ACPI_FUNCTION_ENTRY();
101
102	/* Get the info block for the entire GPE register */
103
104	gpe_register_info = gpe_event_info->register_info;
105	if (!gpe_register_info) {
106		return (AE_NOT_EXIST);
107	}
108
109	/* Get current value of the enable register that contains this GPE */
110
111	status = acpi_hw_read(&enable_mask, &gpe_register_info->enable_address);
112	if (ACPI_FAILURE(status)) {
113		return (status);
114	}
115
116	/* Set ot clear just the bit that corresponds to this GPE */
117
118	register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info,
119						gpe_register_info);
120	switch (action) {
121	case ACPI_GPE_COND_ENABLE:
122		if (!(register_bit & gpe_register_info->enable_for_run))
123			return (AE_BAD_PARAMETER);
124
125	case ACPI_GPE_ENABLE:
126		ACPI_SET_BIT(enable_mask, register_bit);
127		break;
128
129	case ACPI_GPE_DISABLE:
130		ACPI_CLEAR_BIT(enable_mask, register_bit);
131		break;
132
133	default:
134		ACPI_ERROR((AE_INFO, "Invalid action\n"));
135		return (AE_BAD_PARAMETER);
136	}
137
138	/* Write the updated enable mask */
139
140	status = acpi_hw_write(enable_mask, &gpe_register_info->enable_address);
141	return (status);
142}
143
144/******************************************************************************
145 *
146 * FUNCTION:    acpi_hw_clear_gpe
147 *
148 * PARAMETERS:  gpe_event_info      - Info block for the GPE to be cleared
149 *
150 * RETURN:      Status
151 *
152 * DESCRIPTION: Clear the status bit for a single GPE.
153 *
154 ******************************************************************************/
155
156acpi_status acpi_hw_clear_gpe(struct acpi_gpe_event_info * gpe_event_info)
157{
158	struct acpi_gpe_register_info *gpe_register_info;
159	acpi_status status;
160	u32 register_bit;
161
162	ACPI_FUNCTION_ENTRY();
163
164	/* Get the info block for the entire GPE register */
165
166	gpe_register_info = gpe_event_info->register_info;
167	if (!gpe_register_info) {
168		return (AE_NOT_EXIST);
169	}
170
171	register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info,
172						gpe_register_info);
173
174	/*
175	 * Write a one to the appropriate bit in the status register to
176	 * clear this GPE.
177	 */
178	status = acpi_hw_write(register_bit,
179			       &gpe_register_info->status_address);
180
181	return (status);
182}
183
184/******************************************************************************
185 *
186 * FUNCTION:    acpi_hw_get_gpe_status
187 *
188 * PARAMETERS:  gpe_event_info      - Info block for the GPE to queried
189 *              event_status        - Where the GPE status is returned
190 *
191 * RETURN:      Status
192 *
193 * DESCRIPTION: Return the status of a single GPE.
194 *
195 ******************************************************************************/
196
197acpi_status
198acpi_hw_get_gpe_status(struct acpi_gpe_event_info * gpe_event_info,
199		       acpi_event_status * event_status)
200{
201	u32 in_byte;
202	u32 register_bit;
203	struct acpi_gpe_register_info *gpe_register_info;
204	acpi_status status;
205	acpi_event_status local_event_status = 0;
206
207	ACPI_FUNCTION_ENTRY();
208
209	if (!event_status) {
210		return (AE_BAD_PARAMETER);
211	}
212
213	/* Get the info block for the entire GPE register */
214
215	gpe_register_info = gpe_event_info->register_info;
216
217	/* Get the register bitmask for this GPE */
218
219	register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info,
220						gpe_register_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
264acpi_status
265acpi_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
301acpi_status
302acpi_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
339acpi_status
340acpi_hw_enable_runtime_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
341				 struct acpi_gpe_block_info *gpe_block, void *context)
342{
343	u32 i;
344	acpi_status status;
345
346	/* NOTE: assumes that all GPEs are currently disabled */
347
348	/* Examine each GPE Register within the block */
349
350	for (i = 0; i < gpe_block->register_count; i++) {
351		if (!gpe_block->register_info[i].enable_for_run) {
352			continue;
353		}
354
355		/* Enable all "runtime" GPEs in this register */
356
357		status =
358		    acpi_hw_write(gpe_block->register_info[i].enable_for_run,
359				  &gpe_block->register_info[i].enable_address);
360		if (ACPI_FAILURE(status)) {
361			return (status);
362		}
363	}
364
365	return (AE_OK);
366}
367
368/******************************************************************************
369 *
370 * FUNCTION:    acpi_hw_enable_wakeup_gpe_block
371 *
372 * PARAMETERS:  gpe_xrupt_info      - GPE Interrupt info
373 *              gpe_block           - Gpe Block info
374 *
375 * RETURN:      Status
376 *
377 * DESCRIPTION: Enable all "wake" GPEs within a single GPE block. Includes
378 *              combination wake/run GPEs.
379 *
380 ******************************************************************************/
381
382static acpi_status
383acpi_hw_enable_wakeup_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
384				struct acpi_gpe_block_info *gpe_block,
385				void *context)
386{
387	u32 i;
388	acpi_status status;
389
390	/* Examine each GPE Register within the block */
391
392	for (i = 0; i < gpe_block->register_count; i++) {
393		if (!gpe_block->register_info[i].enable_for_wake) {
394			continue;
395		}
396
397		/* Enable all "wake" GPEs in this register */
398
399		status =
400		    acpi_hw_write(gpe_block->register_info[i].enable_for_wake,
401				  &gpe_block->register_info[i].enable_address);
402		if (ACPI_FAILURE(status)) {
403			return (status);
404		}
405	}
406
407	return (AE_OK);
408}
409
410/******************************************************************************
411 *
412 * FUNCTION:    acpi_hw_disable_all_gpes
413 *
414 * PARAMETERS:  None
415 *
416 * RETURN:      Status
417 *
418 * DESCRIPTION: Disable and clear all GPEs in all GPE blocks
419 *
420 ******************************************************************************/
421
422acpi_status acpi_hw_disable_all_gpes(void)
423{
424	acpi_status status;
425
426	ACPI_FUNCTION_TRACE(hw_disable_all_gpes);
427
428	status = acpi_ev_walk_gpe_list(acpi_hw_disable_gpe_block, NULL);
429	status = acpi_ev_walk_gpe_list(acpi_hw_clear_gpe_block, NULL);
430	return_ACPI_STATUS(status);
431}
432
433/******************************************************************************
434 *
435 * FUNCTION:    acpi_hw_enable_all_runtime_gpes
436 *
437 * PARAMETERS:  None
438 *
439 * RETURN:      Status
440 *
441 * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks
442 *
443 ******************************************************************************/
444
445acpi_status acpi_hw_enable_all_runtime_gpes(void)
446{
447	acpi_status status;
448
449	ACPI_FUNCTION_TRACE(hw_enable_all_runtime_gpes);
450
451	status = acpi_ev_walk_gpe_list(acpi_hw_enable_runtime_gpe_block, NULL);
452	return_ACPI_STATUS(status);
453}
454
455/******************************************************************************
456 *
457 * FUNCTION:    acpi_hw_enable_all_wakeup_gpes
458 *
459 * PARAMETERS:  None
460 *
461 * RETURN:      Status
462 *
463 * DESCRIPTION: Enable all "wakeup" GPEs, in all GPE blocks
464 *
465 ******************************************************************************/
466
467acpi_status acpi_hw_enable_all_wakeup_gpes(void)
468{
469	acpi_status status;
470
471	ACPI_FUNCTION_TRACE(hw_enable_all_wakeup_gpes);
472
473	status = acpi_ev_walk_gpe_list(acpi_hw_enable_wakeup_gpe_block, NULL);
474	return_ACPI_STATUS(status);
475}
476