Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

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