2 /*******************************************************************************
4 * Module Name: hwregs - Read/write access functions for the various ACPI
5 * control and status registers.
7 ******************************************************************************/
10 * Copyright (C) 2000 - 2008, Intel Corp.
11 * All rights reserved.
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
16 * 1. Redistributions of source code must retain the above copyright
17 * notice, this list of conditions, and the following disclaimer,
18 * without modification.
19 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
20 * substantially similar to the "NO WARRANTY" disclaimer below
21 * ("Disclaimer") and any redistribution must be conditioned upon
22 * including a substantially similar Disclaimer requirement for further
23 * binary redistribution.
24 * 3. Neither the names of the above-listed copyright holders nor the names
25 * of any contributors may be used to endorse or promote products derived
26 * from this software without specific prior written permission.
28 * Alternatively, this software may be distributed under the terms of the
29 * GNU General Public License ("GPL") version 2 as published by the Free
30 * Software Foundation.
33 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
34 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
35 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
36 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
37 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
38 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
39 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
40 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
41 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
42 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
43 * POSSIBILITY OF SUCH DAMAGES.
46 #include <acpi/acpi.h>
47 #include <acpi/acnamesp.h>
48 #include <acpi/acevents.h>
50 #define _COMPONENT ACPI_HARDWARE
51 ACPI_MODULE_NAME("hwregs")
53 /*******************************************************************************
55 * FUNCTION: acpi_hw_clear_acpi_status
61 * DESCRIPTION: Clears all fixed and general purpose status bits
62 * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
64 ******************************************************************************/
65 acpi_status
acpi_hw_clear_acpi_status(void)
68 acpi_cpu_flags lock_flags
= 0;
70 ACPI_FUNCTION_TRACE(hw_clear_acpi_status
);
72 ACPI_DEBUG_PRINT((ACPI_DB_IO
, "About to write %04X to %04X\n",
73 ACPI_BITMASK_ALL_FIXED_STATUS
,
74 (u16
) acpi_gbl_FADT
.xpm1a_event_block
.address
));
76 lock_flags
= acpi_os_acquire_lock(acpi_gbl_hardware_lock
);
78 status
= acpi_hw_register_write(ACPI_REGISTER_PM1_STATUS
,
79 ACPI_BITMASK_ALL_FIXED_STATUS
);
80 if (ACPI_FAILURE(status
)) {
84 /* Clear the fixed events */
86 if (acpi_gbl_FADT
.xpm1b_event_block
.address
) {
87 status
= acpi_write(ACPI_BITMASK_ALL_FIXED_STATUS
,
88 &acpi_gbl_FADT
.xpm1b_event_block
);
89 if (ACPI_FAILURE(status
)) {
94 /* Clear the GPE Bits in all GPE registers in all GPE blocks */
96 status
= acpi_ev_walk_gpe_list(acpi_hw_clear_gpe_block
, NULL
);
99 acpi_os_release_lock(acpi_gbl_hardware_lock
, lock_flags
);
100 return_ACPI_STATUS(status
);
103 /*******************************************************************************
105 * FUNCTION: acpi_hw_get_register_bit_mask
107 * PARAMETERS: register_id - Index of ACPI Register to access
109 * RETURN: The bitmask to be used when accessing the register
111 * DESCRIPTION: Map register_id into a register bitmask.
113 ******************************************************************************/
115 struct acpi_bit_register_info
*acpi_hw_get_bit_register_info(u32 register_id
)
117 ACPI_FUNCTION_ENTRY();
119 if (register_id
> ACPI_BITREG_MAX
) {
120 ACPI_ERROR((AE_INFO
, "Invalid BitRegister ID: %X",
125 return (&acpi_gbl_bit_register_info
[register_id
]);
128 /******************************************************************************
130 * FUNCTION: acpi_hw_register_read
132 * PARAMETERS: register_id - ACPI Register ID
133 * return_value - Where the register value is returned
135 * RETURN: Status and the value read.
137 * DESCRIPTION: Read from the specified ACPI register
139 ******************************************************************************/
141 acpi_hw_register_read(u32 register_id
, u32
* return_value
)
147 ACPI_FUNCTION_TRACE(hw_register_read
);
149 switch (register_id
) {
150 case ACPI_REGISTER_PM1_STATUS
: /* 16-bit access */
152 status
= acpi_read(&value1
, &acpi_gbl_FADT
.xpm1a_event_block
);
153 if (ACPI_FAILURE(status
)) {
157 /* PM1B is optional */
159 status
= acpi_read(&value2
, &acpi_gbl_FADT
.xpm1b_event_block
);
163 case ACPI_REGISTER_PM1_ENABLE
: /* 16-bit access */
165 status
= acpi_read(&value1
, &acpi_gbl_xpm1a_enable
);
166 if (ACPI_FAILURE(status
)) {
170 /* PM1B is optional */
172 status
= acpi_read(&value2
, &acpi_gbl_xpm1b_enable
);
176 case ACPI_REGISTER_PM1_CONTROL
: /* 16-bit access */
178 status
= acpi_read(&value1
, &acpi_gbl_FADT
.xpm1a_control_block
);
179 if (ACPI_FAILURE(status
)) {
183 status
= acpi_read(&value2
, &acpi_gbl_FADT
.xpm1b_control_block
);
187 case ACPI_REGISTER_PM2_CONTROL
: /* 8-bit access */
189 status
= acpi_read(&value1
, &acpi_gbl_FADT
.xpm2_control_block
);
192 case ACPI_REGISTER_PM_TIMER
: /* 32-bit access */
194 status
= acpi_read(&value1
, &acpi_gbl_FADT
.xpm_timer_block
);
197 case ACPI_REGISTER_SMI_COMMAND_BLOCK
: /* 8-bit access */
200 acpi_os_read_port(acpi_gbl_FADT
.smi_command
, &value1
, 8);
204 ACPI_ERROR((AE_INFO
, "Unknown Register ID: %X", register_id
));
205 status
= AE_BAD_PARAMETER
;
211 if (ACPI_SUCCESS(status
)) {
212 *return_value
= value1
;
215 return_ACPI_STATUS(status
);
218 /******************************************************************************
220 * FUNCTION: acpi_hw_register_write
222 * PARAMETERS: register_id - ACPI Register ID
223 * Value - The value to write
227 * DESCRIPTION: Write to the specified ACPI register
229 * NOTE: In accordance with the ACPI specification, this function automatically
230 * preserves the value of the following bits, meaning that these bits cannot be
231 * changed via this interface:
233 * PM1_CONTROL[0] = SCI_EN
238 * 1) Hardware Ignored Bits: When software writes to a register with ignored
239 * bit fields, it preserves the ignored bit fields
240 * 2) SCI_EN: OSPM always preserves this bit position
242 ******************************************************************************/
244 acpi_status
acpi_hw_register_write(u32 register_id
, u32 value
)
249 ACPI_FUNCTION_TRACE(hw_register_write
);
251 switch (register_id
) {
252 case ACPI_REGISTER_PM1_STATUS
: /* 16-bit access */
254 /* Perform a read first to preserve certain bits (per ACPI spec) */
256 status
= acpi_hw_register_read(ACPI_REGISTER_PM1_STATUS
,
258 if (ACPI_FAILURE(status
)) {
262 /* Insert the bits to be preserved */
264 ACPI_INSERT_BITS(value
, ACPI_PM1_STATUS_PRESERVED_BITS
,
267 /* Now we can write the data */
269 status
= acpi_write(value
, &acpi_gbl_FADT
.xpm1a_event_block
);
270 if (ACPI_FAILURE(status
)) {
274 /* PM1B is optional */
276 status
= acpi_write(value
, &acpi_gbl_FADT
.xpm1b_event_block
);
279 case ACPI_REGISTER_PM1_ENABLE
: /* 16-bit access */
281 status
= acpi_write(value
, &acpi_gbl_xpm1a_enable
);
282 if (ACPI_FAILURE(status
)) {
286 /* PM1B is optional */
288 status
= acpi_write(value
, &acpi_gbl_xpm1b_enable
);
291 case ACPI_REGISTER_PM1_CONTROL
: /* 16-bit access */
294 * Perform a read first to preserve certain bits (per ACPI spec)
296 status
= acpi_hw_register_read(ACPI_REGISTER_PM1_CONTROL
,
298 if (ACPI_FAILURE(status
)) {
302 /* Insert the bits to be preserved */
304 ACPI_INSERT_BITS(value
, ACPI_PM1_CONTROL_PRESERVED_BITS
,
307 /* Now we can write the data */
309 status
= acpi_write(value
, &acpi_gbl_FADT
.xpm1a_control_block
);
310 if (ACPI_FAILURE(status
)) {
314 status
= acpi_write(value
, &acpi_gbl_FADT
.xpm1b_control_block
);
317 case ACPI_REGISTER_PM1A_CONTROL
: /* 16-bit access */
319 status
= acpi_write(value
, &acpi_gbl_FADT
.xpm1a_control_block
);
322 case ACPI_REGISTER_PM1B_CONTROL
: /* 16-bit access */
324 status
= acpi_write(value
, &acpi_gbl_FADT
.xpm1b_control_block
);
327 case ACPI_REGISTER_PM2_CONTROL
: /* 8-bit access */
329 status
= acpi_write(value
, &acpi_gbl_FADT
.xpm2_control_block
);
332 case ACPI_REGISTER_PM_TIMER
: /* 32-bit access */
334 status
= acpi_write(value
, &acpi_gbl_FADT
.xpm_timer_block
);
337 case ACPI_REGISTER_SMI_COMMAND_BLOCK
: /* 8-bit access */
339 /* SMI_CMD is currently always in IO space */
342 acpi_os_write_port(acpi_gbl_FADT
.smi_command
, value
, 8);
346 status
= AE_BAD_PARAMETER
;
351 return_ACPI_STATUS(status
);