Branch data Line data Source code
1 : : // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 : : /******************************************************************************
3 : : *
4 : : * Module Name: hwxface - Public ACPICA hardware interfaces
5 : : *
6 : : * Copyright (C) 2000 - 2020, Intel Corp.
7 : : *
8 : : *****************************************************************************/
9 : :
10 : : #define EXPORT_ACPI_INTERFACES
11 : :
12 : : #include <acpi/acpi.h>
13 : : #include "accommon.h"
14 : : #include "acnamesp.h"
15 : :
16 : : #define _COMPONENT ACPI_HARDWARE
17 : : ACPI_MODULE_NAME("hwxface")
18 : :
19 : : /******************************************************************************
20 : : *
21 : : * FUNCTION: acpi_reset
22 : : *
23 : : * PARAMETERS: None
24 : : *
25 : : * RETURN: Status
26 : : *
27 : : * DESCRIPTION: Set reset register in memory or IO space. Note: Does not
28 : : * support reset register in PCI config space, this must be
29 : : * handled separately.
30 : : *
31 : : ******************************************************************************/
32 : 0 : acpi_status acpi_reset(void)
33 : : {
34 : 0 : struct acpi_generic_address *reset_reg;
35 : 0 : acpi_status status;
36 : :
37 : 0 : ACPI_FUNCTION_TRACE(acpi_reset);
38 : :
39 : 0 : reset_reg = &acpi_gbl_FADT.reset_register;
40 : :
41 : : /* Check if the reset register is supported */
42 : :
43 [ # # ]: 0 : if (!(acpi_gbl_FADT.flags & ACPI_FADT_RESET_REGISTER) ||
44 [ # # ]: 0 : !reset_reg->address) {
45 : : return_ACPI_STATUS(AE_NOT_EXIST);
46 : : }
47 : :
48 [ # # ]: 0 : if (reset_reg->space_id == ACPI_ADR_SPACE_SYSTEM_IO) {
49 : : /*
50 : : * For I/O space, write directly to the OSL. This bypasses the port
51 : : * validation mechanism, which may block a valid write to the reset
52 : : * register.
53 : : *
54 : : * NOTE:
55 : : * The ACPI spec requires the reset register width to be 8, so we
56 : : * hardcode it here and ignore the FADT value. This maintains
57 : : * compatibility with other ACPI implementations that have allowed
58 : : * BIOS code with bad register width values to go unnoticed.
59 : : */
60 : 0 : status = acpi_os_write_port((acpi_io_address)reset_reg->address,
61 : 0 : acpi_gbl_FADT.reset_value,
62 : : ACPI_RESET_REGISTER_WIDTH);
63 : : } else {
64 : : /* Write the reset value to the reset register */
65 : :
66 : 0 : status = acpi_hw_write(acpi_gbl_FADT.reset_value, reset_reg);
67 : : }
68 : :
69 : : return_ACPI_STATUS(status);
70 : : }
71 : :
72 : : ACPI_EXPORT_SYMBOL(acpi_reset)
73 : :
74 : : /******************************************************************************
75 : : *
76 : : * FUNCTION: acpi_read
77 : : *
78 : : * PARAMETERS: value - Where the value is returned
79 : : * reg - GAS register structure
80 : : *
81 : : * RETURN: Status
82 : : *
83 : : * DESCRIPTION: Read from either memory or IO space.
84 : : *
85 : : * LIMITATIONS: <These limitations also apply to acpi_write>
86 : : * bit_width must be exactly 8, 16, 32, or 64.
87 : : * space_ID must be system_memory or system_IO.
88 : : * bit_offset and access_width are currently ignored, as there has
89 : : * not been a need to implement these.
90 : : *
91 : : ******************************************************************************/
92 : 0 : acpi_status acpi_read(u64 *return_value, struct acpi_generic_address *reg)
93 : : {
94 : 0 : acpi_status status;
95 : :
96 : 0 : ACPI_FUNCTION_NAME(acpi_read);
97 : :
98 : 0 : status = acpi_hw_read(return_value, reg);
99 : 0 : return (status);
100 : : }
101 : :
102 : : ACPI_EXPORT_SYMBOL(acpi_read)
103 : :
104 : : /******************************************************************************
105 : : *
106 : : * FUNCTION: acpi_write
107 : : *
108 : : * PARAMETERS: value - Value to be written
109 : : * reg - GAS register structure
110 : : *
111 : : * RETURN: Status
112 : : *
113 : : * DESCRIPTION: Write to either memory or IO space.
114 : : *
115 : : ******************************************************************************/
116 : 0 : acpi_status acpi_write(u64 value, struct acpi_generic_address *reg)
117 : : {
118 : 0 : acpi_status status;
119 : :
120 : 0 : ACPI_FUNCTION_NAME(acpi_write);
121 : :
122 : 0 : status = acpi_hw_write(value, reg);
123 : 0 : return (status);
124 : : }
125 : :
126 : : ACPI_EXPORT_SYMBOL(acpi_write)
127 : :
128 : : #if (!ACPI_REDUCED_HARDWARE)
129 : : /*******************************************************************************
130 : : *
131 : : * FUNCTION: acpi_read_bit_register
132 : : *
133 : : * PARAMETERS: register_id - ID of ACPI Bit Register to access
134 : : * return_value - Value that was read from the register,
135 : : * normalized to bit position zero.
136 : : *
137 : : * RETURN: Status and the value read from the specified Register. Value
138 : : * returned is normalized to bit0 (is shifted all the way right)
139 : : *
140 : : * DESCRIPTION: ACPI bit_register read function. Does not acquire the HW lock.
141 : : *
142 : : * SUPPORTS: Bit fields in PM1 Status, PM1 Enable, PM1 Control, and
143 : : * PM2 Control.
144 : : *
145 : : * Note: The hardware lock is not required when reading the ACPI bit registers
146 : : * since almost all of them are single bit and it does not matter that
147 : : * the parent hardware register can be split across two physical
148 : : * registers. The only multi-bit field is SLP_TYP in the PM1 control
149 : : * register, but this field does not cross an 8-bit boundary (nor does
150 : : * it make much sense to actually read this field.)
151 : : *
152 : : ******************************************************************************/
153 : 196 : acpi_status acpi_read_bit_register(u32 register_id, u32 *return_value)
154 : : {
155 : 196 : struct acpi_bit_register_info *bit_reg_info;
156 : 196 : u32 register_value;
157 : 196 : u32 value;
158 : 196 : acpi_status status;
159 : :
160 : 196 : ACPI_FUNCTION_TRACE_U32(acpi_read_bit_register, register_id);
161 : :
162 : : /* Get the info structure corresponding to the requested ACPI Register */
163 : :
164 : 196 : bit_reg_info = acpi_hw_get_bit_register_info(register_id);
165 [ + - ]: 196 : if (!bit_reg_info) {
166 : : return_ACPI_STATUS(AE_BAD_PARAMETER);
167 : : }
168 : :
169 : : /* Read the entire parent register */
170 : :
171 : 196 : status = acpi_hw_register_read(bit_reg_info->parent_register,
172 : : ®ister_value);
173 [ + - ]: 196 : if (ACPI_FAILURE(status)) {
174 : : return_ACPI_STATUS(status);
175 : : }
176 : :
177 : : /* Normalize the value that was read, mask off other bits */
178 : :
179 : 196 : value = ((register_value & bit_reg_info->access_bit_mask)
180 : 196 : >> bit_reg_info->bit_position);
181 : :
182 : : ACPI_DEBUG_PRINT((ACPI_DB_IO,
183 : : "BitReg %X, ParentReg %X, Actual %8.8X, ReturnValue %8.8X\n",
184 : : register_id, bit_reg_info->parent_register,
185 : 196 : register_value, value));
186 : :
187 : 196 : *return_value = value;
188 : 196 : return_ACPI_STATUS(AE_OK);
189 : : }
190 : :
191 : : ACPI_EXPORT_SYMBOL(acpi_read_bit_register)
192 : :
193 : : /*******************************************************************************
194 : : *
195 : : * FUNCTION: acpi_write_bit_register
196 : : *
197 : : * PARAMETERS: register_id - ID of ACPI Bit Register to access
198 : : * value - Value to write to the register, in bit
199 : : * position zero. The bit is automatically
200 : : * shifted to the correct position.
201 : : *
202 : : * RETURN: Status
203 : : *
204 : : * DESCRIPTION: ACPI Bit Register write function. Acquires the hardware lock
205 : : * since most operations require a read/modify/write sequence.
206 : : *
207 : : * SUPPORTS: Bit fields in PM1 Status, PM1 Enable, PM1 Control, and
208 : : * PM2 Control.
209 : : *
210 : : * Note that at this level, the fact that there may be actually two
211 : : * hardware registers (A and B - and B may not exist) is abstracted.
212 : : *
213 : : ******************************************************************************/
214 : 364 : acpi_status acpi_write_bit_register(u32 register_id, u32 value)
215 : : {
216 : 364 : struct acpi_bit_register_info *bit_reg_info;
217 : 364 : acpi_cpu_flags lock_flags;
218 : 364 : u32 register_value;
219 : 364 : acpi_status status = AE_OK;
220 : :
221 : 364 : ACPI_FUNCTION_TRACE_U32(acpi_write_bit_register, register_id);
222 : :
223 : : /* Get the info structure corresponding to the requested ACPI Register */
224 : :
225 : 364 : bit_reg_info = acpi_hw_get_bit_register_info(register_id);
226 [ + - ]: 364 : if (!bit_reg_info) {
227 : : return_ACPI_STATUS(AE_BAD_PARAMETER);
228 : : }
229 : :
230 : 364 : lock_flags = acpi_os_acquire_raw_lock(acpi_gbl_hardware_lock);
231 : :
232 : : /*
233 : : * At this point, we know that the parent register is one of the
234 : : * following: PM1 Status, PM1 Enable, PM1 Control, or PM2 Control
235 : : */
236 [ + + ]: 364 : if (bit_reg_info->parent_register != ACPI_REGISTER_PM1_STATUS) {
237 : : /*
238 : : * 1) Case for PM1 Enable, PM1 Control, and PM2 Control
239 : : *
240 : : * Perform a register read to preserve the bits that we are not
241 : : * interested in
242 : : */
243 : 252 : status = acpi_hw_register_read(bit_reg_info->parent_register,
244 : : ®ister_value);
245 [ - + ]: 252 : if (ACPI_FAILURE(status)) {
246 : 0 : goto unlock_and_exit;
247 : : }
248 : :
249 : : /*
250 : : * Insert the input bit into the value that was just read
251 : : * and write the register
252 : : */
253 : 252 : ACPI_REGISTER_INSERT_VALUE(register_value,
254 : : bit_reg_info->bit_position,
255 : : bit_reg_info->access_bit_mask,
256 : : value);
257 : :
258 : 252 : status = acpi_hw_register_write(bit_reg_info->parent_register,
259 : : register_value);
260 : : } else {
261 : : /*
262 : : * 2) Case for PM1 Status
263 : : *
264 : : * The Status register is different from the rest. Clear an event
265 : : * by writing 1, writing 0 has no effect. So, the only relevant
266 : : * information is the single bit we're interested in, all others
267 : : * should be written as 0 so they will be left unchanged.
268 : : */
269 : 112 : register_value = ACPI_REGISTER_PREPARE_BITS(value,
270 : : bit_reg_info->
271 : : bit_position,
272 : : bit_reg_info->
273 : : access_bit_mask);
274 : :
275 : : /* No need to write the register if value is all zeros */
276 : :
277 [ - + ]: 112 : if (register_value) {
278 : 112 : status =
279 : 112 : acpi_hw_register_write(ACPI_REGISTER_PM1_STATUS,
280 : : register_value);
281 : : }
282 : : }
283 : :
284 : : ACPI_DEBUG_PRINT((ACPI_DB_IO,
285 : : "BitReg %X, ParentReg %X, Value %8.8X, Actual %8.8X\n",
286 : : register_id, bit_reg_info->parent_register, value,
287 : 364 : register_value));
288 : :
289 : 0 : unlock_and_exit:
290 : :
291 : 364 : acpi_os_release_raw_lock(acpi_gbl_hardware_lock, lock_flags);
292 : 364 : return_ACPI_STATUS(status);
293 : : }
294 : :
295 : : ACPI_EXPORT_SYMBOL(acpi_write_bit_register)
296 : : #endif /* !ACPI_REDUCED_HARDWARE */
297 : : /*******************************************************************************
298 : : *
299 : : * FUNCTION: acpi_get_sleep_type_data
300 : : *
301 : : * PARAMETERS: sleep_state - Numeric sleep state
302 : : * *sleep_type_a - Where SLP_TYPa is returned
303 : : * *sleep_type_b - Where SLP_TYPb is returned
304 : : *
305 : : * RETURN: Status
306 : : *
307 : : * DESCRIPTION: Obtain the SLP_TYPa and SLP_TYPb values for the requested
308 : : * sleep state via the appropriate \_Sx object.
309 : : *
310 : : * The sleep state package returned from the corresponding \_Sx_ object
311 : : * must contain at least one integer.
312 : : *
313 : : * March 2005:
314 : : * Added support for a package that contains two integers. This
315 : : * goes against the ACPI specification which defines this object as a
316 : : * package with one encoded DWORD integer. However, existing practice
317 : : * by many BIOS vendors is to return a package with 2 or more integer
318 : : * elements, at least one per sleep type (A/B).
319 : : *
320 : : * January 2013:
321 : : * Therefore, we must be prepared to accept a package with either a
322 : : * single integer or multiple integers.
323 : : *
324 : : * The single integer DWORD format is as follows:
325 : : * BYTE 0 - Value for the PM1A SLP_TYP register
326 : : * BYTE 1 - Value for the PM1B SLP_TYP register
327 : : * BYTE 2-3 - Reserved
328 : : *
329 : : * The dual integer format is as follows:
330 : : * Integer 0 - Value for the PM1A SLP_TYP register
331 : : * Integer 1 - Value for the PM1A SLP_TYP register
332 : : *
333 : : ******************************************************************************/
334 : : acpi_status
335 : 140 : acpi_get_sleep_type_data(u8 sleep_state, u8 *sleep_type_a, u8 *sleep_type_b)
336 : : {
337 : 140 : acpi_status status;
338 : 140 : struct acpi_evaluate_info *info;
339 : 140 : union acpi_operand_object **elements;
340 : :
341 : 140 : ACPI_FUNCTION_TRACE(acpi_get_sleep_type_data);
342 : :
343 : : /* Validate parameters */
344 : :
345 [ + - + - ]: 140 : if ((sleep_state > ACPI_S_STATES_MAX) || !sleep_type_a || !sleep_type_b) {
346 : : return_ACPI_STATUS(AE_BAD_PARAMETER);
347 : : }
348 : :
349 : : /* Allocate the evaluation information block */
350 : :
351 : 140 : info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info));
352 [ + - ]: 140 : if (!info) {
353 : : return_ACPI_STATUS(AE_NO_MEMORY);
354 : : }
355 : :
356 : : /*
357 : : * Evaluate the \_Sx namespace object containing the register values
358 : : * for this state
359 : : */
360 : 140 : info->relative_pathname = acpi_gbl_sleep_state_names[sleep_state];
361 : :
362 : 140 : status = acpi_ns_evaluate(info);
363 [ + + ]: 140 : if (ACPI_FAILURE(status)) {
364 [ + - ]: 56 : if (status == AE_NOT_FOUND) {
365 : :
366 : : /* The _Sx states are optional, ignore NOT_FOUND */
367 : :
368 : 56 : goto final_cleanup;
369 : : }
370 : :
371 : 0 : goto warning_cleanup;
372 : : }
373 : :
374 : : /* Must have a return object */
375 : :
376 [ - + ]: 84 : if (!info->return_object) {
377 : 0 : ACPI_ERROR((AE_INFO, "No Sleep State object returned from [%s]",
378 : : info->relative_pathname));
379 : 0 : status = AE_AML_NO_RETURN_VALUE;
380 : 0 : goto warning_cleanup;
381 : : }
382 : :
383 : : /* Return object must be of type Package */
384 : :
385 [ - + ]: 84 : if (info->return_object->common.type != ACPI_TYPE_PACKAGE) {
386 : 0 : ACPI_ERROR((AE_INFO,
387 : : "Sleep State return object is not a Package"));
388 : 0 : status = AE_AML_OPERAND_TYPE;
389 : 0 : goto return_value_cleanup;
390 : : }
391 : :
392 : : /*
393 : : * Any warnings about the package length or the object types have
394 : : * already been issued by the predefined name module -- there is no
395 : : * need to repeat them here.
396 : : */
397 : 84 : elements = info->return_object->package.elements;
398 [ - + - ]: 84 : switch (info->return_object->package.count) {
399 : : case 0:
400 : :
401 : : status = AE_AML_PACKAGE_LIMIT;
402 : : break;
403 : :
404 : 0 : case 1:
405 : :
406 [ # # ]: 0 : if (elements[0]->common.type != ACPI_TYPE_INTEGER) {
407 : : status = AE_AML_OPERAND_TYPE;
408 : : break;
409 : : }
410 : :
411 : : /* A valid _Sx_ package with one integer */
412 : :
413 : 0 : *sleep_type_a = (u8)elements[0]->integer.value;
414 : 0 : *sleep_type_b = (u8)(elements[0]->integer.value >> 8);
415 : 0 : break;
416 : :
417 : 84 : case 2:
418 : : default:
419 : :
420 [ + - ]: 84 : if ((elements[0]->common.type != ACPI_TYPE_INTEGER) ||
421 [ + - ]: 84 : (elements[1]->common.type != ACPI_TYPE_INTEGER)) {
422 : : status = AE_AML_OPERAND_TYPE;
423 : : break;
424 : : }
425 : :
426 : : /* A valid _Sx_ package with two integers */
427 : :
428 : 84 : *sleep_type_a = (u8)elements[0]->integer.value;
429 : 84 : *sleep_type_b = (u8)elements[1]->integer.value;
430 : 84 : break;
431 : : }
432 : :
433 : 84 : return_value_cleanup:
434 : 84 : acpi_ut_remove_reference(info->return_object);
435 : :
436 : 84 : warning_cleanup:
437 [ + - ]: 84 : if (ACPI_FAILURE(status)) {
438 : 0 : ACPI_EXCEPTION((AE_INFO, status,
439 : : "While evaluating Sleep State [%s]",
440 : : info->relative_pathname));
441 : : }
442 : :
443 : 84 : final_cleanup:
444 : 140 : ACPI_FREE(info);
445 : 140 : return_ACPI_STATUS(status);
446 : : }
447 : :
448 : : ACPI_EXPORT_SYMBOL(acpi_get_sleep_type_data)
|