xref: /openbmc/linux/drivers/acpi/acpica/hwregs.c (revision b8bb76713ec50df2f11efee386e16f93d51e1076)
1 
2 /*******************************************************************************
3  *
4  * Module Name: hwregs - Read/write access functions for the various ACPI
5  *                       control and status registers.
6  *
7  ******************************************************************************/
8 
9 /*
10  * Copyright (C) 2000 - 2008, Intel Corp.
11  * All rights reserved.
12  *
13  * Redistribution and use in source and binary forms, with or without
14  * modification, are permitted provided that the following conditions
15  * are met:
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.
27  *
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.
31  *
32  * NO WARRANTY
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.
44  */
45 
46 #include <acpi/acpi.h>
47 #include "accommon.h"
48 #include "acnamesp.h"
49 #include "acevents.h"
50 
51 #define _COMPONENT          ACPI_HARDWARE
52 ACPI_MODULE_NAME("hwregs")
53 
54 /*******************************************************************************
55  *
56  * FUNCTION:    acpi_hw_clear_acpi_status
57  *
58  * PARAMETERS:  None
59  *
60  * RETURN:      Status
61  *
62  * DESCRIPTION: Clears all fixed and general purpose status bits
63  *              THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
64  *
65  ******************************************************************************/
66 acpi_status acpi_hw_clear_acpi_status(void)
67 {
68 	acpi_status status;
69 	acpi_cpu_flags lock_flags = 0;
70 
71 	ACPI_FUNCTION_TRACE(hw_clear_acpi_status);
72 
73 	ACPI_DEBUG_PRINT((ACPI_DB_IO, "About to write %04X to %04X\n",
74 			  ACPI_BITMASK_ALL_FIXED_STATUS,
75 			  (u16) acpi_gbl_FADT.xpm1a_event_block.address));
76 
77 	lock_flags = acpi_os_acquire_lock(acpi_gbl_hardware_lock);
78 
79 	status = acpi_hw_register_write(ACPI_REGISTER_PM1_STATUS,
80 					ACPI_BITMASK_ALL_FIXED_STATUS);
81 	if (ACPI_FAILURE(status)) {
82 		goto unlock_and_exit;
83 	}
84 
85 	/* Clear the fixed events */
86 
87 	if (acpi_gbl_FADT.xpm1b_event_block.address) {
88 		status = acpi_write(ACPI_BITMASK_ALL_FIXED_STATUS,
89 				    &acpi_gbl_FADT.xpm1b_event_block);
90 		if (ACPI_FAILURE(status)) {
91 			goto unlock_and_exit;
92 		}
93 	}
94 
95 	/* Clear the GPE Bits in all GPE registers in all GPE blocks */
96 
97 	status = acpi_ev_walk_gpe_list(acpi_hw_clear_gpe_block, NULL);
98 
99       unlock_and_exit:
100 	acpi_os_release_lock(acpi_gbl_hardware_lock, lock_flags);
101 	return_ACPI_STATUS(status);
102 }
103 
104 /*******************************************************************************
105  *
106  * FUNCTION:    acpi_hw_get_register_bit_mask
107  *
108  * PARAMETERS:  register_id         - Index of ACPI Register to access
109  *
110  * RETURN:      The bitmask to be used when accessing the register
111  *
112  * DESCRIPTION: Map register_id into a register bitmask.
113  *
114  ******************************************************************************/
115 
116 struct acpi_bit_register_info *acpi_hw_get_bit_register_info(u32 register_id)
117 {
118 	ACPI_FUNCTION_ENTRY();
119 
120 	if (register_id > ACPI_BITREG_MAX) {
121 		ACPI_ERROR((AE_INFO, "Invalid BitRegister ID: %X",
122 			    register_id));
123 		return (NULL);
124 	}
125 
126 	return (&acpi_gbl_bit_register_info[register_id]);
127 }
128 
129 /******************************************************************************
130  *
131  * FUNCTION:    acpi_hw_register_read
132  *
133  * PARAMETERS:  register_id         - ACPI Register ID
134  *              return_value        - Where the register value is returned
135  *
136  * RETURN:      Status and the value read.
137  *
138  * DESCRIPTION: Read from the specified ACPI register
139  *
140  ******************************************************************************/
141 acpi_status
142 acpi_hw_register_read(u32 register_id, u32 * return_value)
143 {
144 	u32 value1 = 0;
145 	u32 value2 = 0;
146 	acpi_status status;
147 
148 	ACPI_FUNCTION_TRACE(hw_register_read);
149 
150 	switch (register_id) {
151 	case ACPI_REGISTER_PM1_STATUS:	/* 16-bit access */
152 
153 		status = acpi_read(&value1, &acpi_gbl_FADT.xpm1a_event_block);
154 		if (ACPI_FAILURE(status)) {
155 			goto exit;
156 		}
157 
158 		/* PM1B is optional */
159 
160 		status = acpi_read(&value2, &acpi_gbl_FADT.xpm1b_event_block);
161 		value1 |= value2;
162 		break;
163 
164 	case ACPI_REGISTER_PM1_ENABLE:	/* 16-bit access */
165 
166 		status = acpi_read(&value1, &acpi_gbl_xpm1a_enable);
167 		if (ACPI_FAILURE(status)) {
168 			goto exit;
169 		}
170 
171 		/* PM1B is optional */
172 
173 		status = acpi_read(&value2, &acpi_gbl_xpm1b_enable);
174 		value1 |= value2;
175 		break;
176 
177 	case ACPI_REGISTER_PM1_CONTROL:	/* 16-bit access */
178 
179 		status = acpi_read(&value1, &acpi_gbl_FADT.xpm1a_control_block);
180 		if (ACPI_FAILURE(status)) {
181 			goto exit;
182 		}
183 
184 		status = acpi_read(&value2, &acpi_gbl_FADT.xpm1b_control_block);
185 		value1 |= value2;
186 		break;
187 
188 	case ACPI_REGISTER_PM2_CONTROL:	/* 8-bit access */
189 
190 		status = acpi_read(&value1, &acpi_gbl_FADT.xpm2_control_block);
191 		break;
192 
193 	case ACPI_REGISTER_PM_TIMER:	/* 32-bit access */
194 
195 		status = acpi_read(&value1, &acpi_gbl_FADT.xpm_timer_block);
196 		break;
197 
198 	case ACPI_REGISTER_SMI_COMMAND_BLOCK:	/* 8-bit access */
199 
200 		status =
201 		    acpi_os_read_port(acpi_gbl_FADT.smi_command, &value1, 8);
202 		break;
203 
204 	default:
205 		ACPI_ERROR((AE_INFO, "Unknown Register ID: %X", register_id));
206 		status = AE_BAD_PARAMETER;
207 		break;
208 	}
209 
210       exit:
211 
212 	if (ACPI_SUCCESS(status)) {
213 		*return_value = value1;
214 	}
215 
216 	return_ACPI_STATUS(status);
217 }
218 
219 /******************************************************************************
220  *
221  * FUNCTION:    acpi_hw_register_write
222  *
223  * PARAMETERS:  register_id         - ACPI Register ID
224  *              Value               - The value to write
225  *
226  * RETURN:      Status
227  *
228  * DESCRIPTION: Write to the specified ACPI register
229  *
230  * NOTE: In accordance with the ACPI specification, this function automatically
231  * preserves the value of the following bits, meaning that these bits cannot be
232  * changed via this interface:
233  *
234  * PM1_CONTROL[0] = SCI_EN
235  * PM1_CONTROL[9]
236  * PM1_STATUS[11]
237  *
238  * ACPI References:
239  * 1) Hardware Ignored Bits: When software writes to a register with ignored
240  *      bit fields, it preserves the ignored bit fields
241  * 2) SCI_EN: OSPM always preserves this bit position
242  *
243  ******************************************************************************/
244 
245 acpi_status acpi_hw_register_write(u32 register_id, u32 value)
246 {
247 	acpi_status status;
248 	u32 read_value;
249 
250 	ACPI_FUNCTION_TRACE(hw_register_write);
251 
252 	switch (register_id) {
253 	case ACPI_REGISTER_PM1_STATUS:	/* 16-bit access */
254 
255 		/* Perform a read first to preserve certain bits (per ACPI spec) */
256 
257 		status = acpi_hw_register_read(ACPI_REGISTER_PM1_STATUS,
258 					       &read_value);
259 		if (ACPI_FAILURE(status)) {
260 			goto exit;
261 		}
262 
263 		/* Insert the bits to be preserved */
264 
265 		ACPI_INSERT_BITS(value, ACPI_PM1_STATUS_PRESERVED_BITS,
266 				 read_value);
267 
268 		/* Now we can write the data */
269 
270 		status = acpi_write(value, &acpi_gbl_FADT.xpm1a_event_block);
271 		if (ACPI_FAILURE(status)) {
272 			goto exit;
273 		}
274 
275 		/* PM1B is optional */
276 
277 		status = acpi_write(value, &acpi_gbl_FADT.xpm1b_event_block);
278 		break;
279 
280 	case ACPI_REGISTER_PM1_ENABLE:	/* 16-bit access */
281 
282 		status = acpi_write(value, &acpi_gbl_xpm1a_enable);
283 		if (ACPI_FAILURE(status)) {
284 			goto exit;
285 		}
286 
287 		/* PM1B is optional */
288 
289 		status = acpi_write(value, &acpi_gbl_xpm1b_enable);
290 		break;
291 
292 	case ACPI_REGISTER_PM1_CONTROL:	/* 16-bit access */
293 
294 		/*
295 		 * Perform a read first to preserve certain bits (per ACPI spec)
296 		 */
297 		status = acpi_hw_register_read(ACPI_REGISTER_PM1_CONTROL,
298 					       &read_value);
299 		if (ACPI_FAILURE(status)) {
300 			goto exit;
301 		}
302 
303 		/* Insert the bits to be preserved */
304 
305 		ACPI_INSERT_BITS(value, ACPI_PM1_CONTROL_PRESERVED_BITS,
306 				 read_value);
307 
308 		/* Now we can write the data */
309 
310 		status = acpi_write(value, &acpi_gbl_FADT.xpm1a_control_block);
311 		if (ACPI_FAILURE(status)) {
312 			goto exit;
313 		}
314 
315 		status = acpi_write(value, &acpi_gbl_FADT.xpm1b_control_block);
316 		break;
317 
318 	case ACPI_REGISTER_PM1A_CONTROL:	/* 16-bit access */
319 
320 		status = acpi_write(value, &acpi_gbl_FADT.xpm1a_control_block);
321 		break;
322 
323 	case ACPI_REGISTER_PM1B_CONTROL:	/* 16-bit access */
324 
325 		status = acpi_write(value, &acpi_gbl_FADT.xpm1b_control_block);
326 		break;
327 
328 	case ACPI_REGISTER_PM2_CONTROL:	/* 8-bit access */
329 
330 		status = acpi_write(value, &acpi_gbl_FADT.xpm2_control_block);
331 		break;
332 
333 	case ACPI_REGISTER_PM_TIMER:	/* 32-bit access */
334 
335 		status = acpi_write(value, &acpi_gbl_FADT.xpm_timer_block);
336 		break;
337 
338 	case ACPI_REGISTER_SMI_COMMAND_BLOCK:	/* 8-bit access */
339 
340 		/* SMI_CMD is currently always in IO space */
341 
342 		status =
343 		    acpi_os_write_port(acpi_gbl_FADT.smi_command, value, 8);
344 		break;
345 
346 	default:
347 		status = AE_BAD_PARAMETER;
348 		break;
349 	}
350 
351       exit:
352 	return_ACPI_STATUS(status);
353 }
354