forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-10-22 8ac6c7a54ed1b98d142dce24b11c6de6a1e239a5
kernel/drivers/acpi/acpica/exfield.c
....@@ -1,9 +1,9 @@
11 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
22 /******************************************************************************
33 *
4
- * Module Name: exfield - ACPI AML (p-code) execution - field manipulation
4
+ * Module Name: exfield - AML execution - field_unit read/write
55 *
6
- * Copyright (C) 2000 - 2018, Intel Corp.
6
+ * Copyright (C) 2000 - 2020, Intel Corp.
77 *
88 *****************************************************************************/
99
....@@ -16,64 +16,73 @@
1616 #define _COMPONENT ACPI_EXECUTER
1717 ACPI_MODULE_NAME("exfield")
1818
19
-/* Local prototypes */
20
-static u32
21
-acpi_ex_get_serial_access_length(u32 accessor_type, u32 access_length);
19
+/*
20
+ * This table maps the various Attrib protocols to the byte transfer
21
+ * length. Used for the generic serial bus.
22
+ */
23
+#define ACPI_INVALID_PROTOCOL_ID 0x80
24
+#define ACPI_MAX_PROTOCOL_ID 0x0F
25
+static const u8 acpi_protocol_lengths[] = {
26
+ ACPI_INVALID_PROTOCOL_ID, /* 0 - reserved */
27
+ ACPI_INVALID_PROTOCOL_ID, /* 1 - reserved */
28
+ 0x00, /* 2 - ATTRIB_QUICK */
29
+ ACPI_INVALID_PROTOCOL_ID, /* 3 - reserved */
30
+ 0x01, /* 4 - ATTRIB_SEND_RECEIVE */
31
+ ACPI_INVALID_PROTOCOL_ID, /* 5 - reserved */
32
+ 0x01, /* 6 - ATTRIB_BYTE */
33
+ ACPI_INVALID_PROTOCOL_ID, /* 7 - reserved */
34
+ 0x02, /* 8 - ATTRIB_WORD */
35
+ ACPI_INVALID_PROTOCOL_ID, /* 9 - reserved */
36
+ 0xFF, /* A - ATTRIB_BLOCK */
37
+ 0xFF, /* B - ATTRIB_BYTES */
38
+ 0x02, /* C - ATTRIB_PROCESS_CALL */
39
+ 0xFF, /* D - ATTRIB_BLOCK_PROCESS_CALL */
40
+ 0xFF, /* E - ATTRIB_RAW_BYTES */
41
+ 0xFF /* F - ATTRIB_RAW_PROCESS_BYTES */
42
+};
43
+
44
+#define PCC_MASTER_SUBSPACE 3
45
+
46
+/*
47
+ * The following macros determine a given offset is a COMD field.
48
+ * According to the specification, generic subspaces (types 0-2) contains a
49
+ * 2-byte COMD field at offset 4 and master subspaces (type 3) contains a 4-byte
50
+ * COMD field starting at offset 12.
51
+ */
52
+#define GENERIC_SUBSPACE_COMMAND(a) (4 == a || a == 5)
53
+#define MASTER_SUBSPACE_COMMAND(a) (12 <= a && a <= 15)
2254
2355 /*******************************************************************************
2456 *
25
- * FUNCTION: acpi_ex_get_serial_access_length
57
+ * FUNCTION: acpi_ex_get_protocol_buffer_length
2658 *
27
- * PARAMETERS: accessor_type - The type of the protocol indicated by region
59
+ * PARAMETERS: protocol_id - The type of the protocol indicated by region
2860 * field access attributes
29
- * access_length - The access length of the region field
61
+ * return_length - Where the protocol byte transfer length is
62
+ * returned
3063 *
31
- * RETURN: Decoded access length
64
+ * RETURN: Status and decoded byte transfer length
3265 *
3366 * DESCRIPTION: This routine returns the length of the generic_serial_bus
3467 * protocol bytes
3568 *
3669 ******************************************************************************/
3770
38
-static u32
39
-acpi_ex_get_serial_access_length(u32 accessor_type, u32 access_length)
71
+acpi_status
72
+acpi_ex_get_protocol_buffer_length(u32 protocol_id, u32 *return_length)
4073 {
41
- u32 length;
4274
43
- switch (accessor_type) {
44
- case AML_FIELD_ATTRIB_QUICK:
75
+ if ((protocol_id > ACPI_MAX_PROTOCOL_ID) ||
76
+ (acpi_protocol_lengths[protocol_id] == ACPI_INVALID_PROTOCOL_ID)) {
77
+ ACPI_ERROR((AE_INFO,
78
+ "Invalid Field/AccessAs protocol ID: 0x%4.4X",
79
+ protocol_id));
4580
46
- length = 0;
47
- break;
48
-
49
- case AML_FIELD_ATTRIB_SEND_RCV:
50
- case AML_FIELD_ATTRIB_BYTE:
51
-
52
- length = 1;
53
- break;
54
-
55
- case AML_FIELD_ATTRIB_WORD:
56
- case AML_FIELD_ATTRIB_WORD_CALL:
57
-
58
- length = 2;
59
- break;
60
-
61
- case AML_FIELD_ATTRIB_MULTIBYTE:
62
- case AML_FIELD_ATTRIB_RAW_BYTES:
63
- case AML_FIELD_ATTRIB_RAW_PROCESS:
64
-
65
- length = access_length;
66
- break;
67
-
68
- case AML_FIELD_ATTRIB_BLOCK:
69
- case AML_FIELD_ATTRIB_BLOCK_CALL:
70
- default:
71
-
72
- length = ACPI_GSBUS_BUFFER_SIZE - 2;
73
- break;
81
+ return (AE_AML_PROTOCOL);
7482 }
7583
76
- return (length);
84
+ *return_length = acpi_protocol_lengths[protocol_id];
85
+ return (AE_OK);
7786 }
7887
7988 /*******************************************************************************
....@@ -87,7 +96,8 @@
8796 * RETURN: Status
8897 *
8998 * DESCRIPTION: Read from a named field. Returns either an Integer or a
90
- * Buffer, depending on the size of the field.
99
+ * Buffer, depending on the size of the field and whether if a
100
+ * field is created by the create_field() operator.
91101 *
92102 ******************************************************************************/
93103
....@@ -98,10 +108,8 @@
98108 {
99109 acpi_status status;
100110 union acpi_operand_object *buffer_desc;
101
- acpi_size length;
102111 void *buffer;
103
- u32 function;
104
- u16 accessor_type;
112
+ u32 buffer_length;
105113
106114 ACPI_FUNCTION_TRACE_PTR(ex_read_data_from_field, obj_desc);
107115
....@@ -132,60 +140,11 @@
132140 ACPI_ADR_SPACE_GSBUS
133141 || obj_desc->field.region_obj->region.space_id ==
134142 ACPI_ADR_SPACE_IPMI)) {
135
- /*
136
- * This is an SMBus, GSBus or IPMI read. We must create a buffer to
137
- * hold the data and then directly access the region handler.
138
- *
139
- * Note: SMBus and GSBus protocol value is passed in upper 16-bits
140
- * of Function
141
- */
142
- if (obj_desc->field.region_obj->region.space_id ==
143
- ACPI_ADR_SPACE_SMBUS) {
144
- length = ACPI_SMBUS_BUFFER_SIZE;
145
- function =
146
- ACPI_READ | (obj_desc->field.attribute << 16);
147
- } else if (obj_desc->field.region_obj->region.space_id ==
148
- ACPI_ADR_SPACE_GSBUS) {
149
- accessor_type = obj_desc->field.attribute;
150
- length =
151
- acpi_ex_get_serial_access_length(accessor_type,
152
- obj_desc->field.
153
- access_length);
154143
155
- /*
156
- * Add additional 2 bytes for the generic_serial_bus data buffer:
157
- *
158
- * Status; (Byte 0 of the data buffer)
159
- * Length; (Byte 1 of the data buffer)
160
- * Data[x-1]: (Bytes 2-x of the arbitrary length data buffer)
161
- */
162
- length += 2;
163
- function = ACPI_READ | (accessor_type << 16);
164
- } else { /* IPMI */
144
+ /* SMBus, GSBus, IPMI serial */
165145
166
- length = ACPI_IPMI_BUFFER_SIZE;
167
- function = ACPI_READ;
168
- }
169
-
170
- buffer_desc = acpi_ut_create_buffer_object(length);
171
- if (!buffer_desc) {
172
- return_ACPI_STATUS(AE_NO_MEMORY);
173
- }
174
-
175
- /* Lock entire transaction if requested */
176
-
177
- acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags);
178
-
179
- /* Call the region handler for the read */
180
-
181
- status = acpi_ex_access_region(obj_desc, 0,
182
- ACPI_CAST_PTR(u64,
183
- buffer_desc->
184
- buffer.pointer),
185
- function);
186
-
187
- acpi_ex_release_global_lock(obj_desc->common_field.field_flags);
188
- goto exit;
146
+ status = acpi_ex_read_serial_bus(obj_desc, ret_buffer_desc);
147
+ return_ACPI_STATUS(status);
189148 }
190149
191150 /*
....@@ -196,16 +155,21 @@
196155 * the use of arithmetic operators on the returned value if the
197156 * field size is equal or smaller than an Integer.
198157 *
158
+ * However, all buffer fields created by create_field operator needs to
159
+ * remain as a buffer to match other AML interpreter implementations.
160
+ *
199161 * Note: Field.length is in bits.
200162 */
201
- length =
163
+ buffer_length =
202164 (acpi_size)ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->field.bit_length);
203165
204
- if (length > acpi_gbl_integer_byte_width) {
166
+ if (buffer_length > acpi_gbl_integer_byte_width ||
167
+ (obj_desc->common.type == ACPI_TYPE_BUFFER_FIELD &&
168
+ obj_desc->buffer_field.is_create_field)) {
205169
206170 /* Field is too large for an Integer, create a Buffer instead */
207171
208
- buffer_desc = acpi_ut_create_buffer_object(length);
172
+ buffer_desc = acpi_ut_create_buffer_object(buffer_length);
209173 if (!buffer_desc) {
210174 return_ACPI_STATUS(AE_NO_MEMORY);
211175 }
....@@ -218,47 +182,43 @@
218182 return_ACPI_STATUS(AE_NO_MEMORY);
219183 }
220184
221
- length = acpi_gbl_integer_byte_width;
185
+ buffer_length = acpi_gbl_integer_byte_width;
222186 buffer = &buffer_desc->integer.value;
223187 }
224188
225189 if ((obj_desc->common.type == ACPI_TYPE_LOCAL_REGION_FIELD) &&
226190 (obj_desc->field.region_obj->region.space_id ==
227191 ACPI_ADR_SPACE_GPIO)) {
192
+
193
+ /* General Purpose I/O */
194
+
195
+ status = acpi_ex_read_gpio(obj_desc, buffer);
196
+ goto exit;
197
+ } else if ((obj_desc->common.type == ACPI_TYPE_LOCAL_REGION_FIELD) &&
198
+ (obj_desc->field.region_obj->region.space_id ==
199
+ ACPI_ADR_SPACE_PLATFORM_COMM)) {
228200 /*
229
- * For GPIO (general_purpose_io), the Address will be the bit offset
230
- * from the previous Connection() operator, making it effectively a
231
- * pin number index. The bit_length is the length of the field, which
232
- * is thus the number of pins.
201
+ * Reading from a PCC field unit does not require the handler because
202
+ * it only requires reading from the internal_pcc_buffer.
233203 */
234204 ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
235
- "GPIO FieldRead [FROM]: Pin %u Bits %u\n",
236
- obj_desc->field.pin_number_index,
205
+ "PCC FieldRead bits %u\n",
237206 obj_desc->field.bit_length));
238207
239
- /* Lock entire transaction if requested */
208
+ memcpy(buffer,
209
+ obj_desc->field.region_obj->field.internal_pcc_buffer +
210
+ obj_desc->field.base_byte_offset,
211
+ (acpi_size)ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->field.
212
+ bit_length));
240213
241
- acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags);
242
-
243
- /* Perform the write */
244
-
245
- status =
246
- acpi_ex_access_region(obj_desc, 0, (u64 *)buffer,
247
- ACPI_READ);
248
-
249
- acpi_ex_release_global_lock(obj_desc->common_field.field_flags);
250
- if (ACPI_FAILURE(status)) {
251
- acpi_ut_remove_reference(buffer_desc);
252
- } else {
253
- *ret_buffer_desc = buffer_desc;
254
- }
255
- return_ACPI_STATUS(status);
214
+ *ret_buffer_desc = buffer_desc;
215
+ return AE_OK;
256216 }
257217
258218 ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
259219 "FieldRead [TO]: Obj %p, Type %X, Buf %p, ByteLen %X\n",
260220 obj_desc, obj_desc->common.type, buffer,
261
- (u32) length));
221
+ buffer_length));
262222 ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
263223 "FieldRead [FROM]: BitLen %X, BitOff %X, ByteOff %X\n",
264224 obj_desc->common_field.bit_length,
....@@ -271,7 +231,7 @@
271231
272232 /* Read from the field */
273233
274
- status = acpi_ex_extract_from_field(obj_desc, buffer, (u32) length);
234
+ status = acpi_ex_extract_from_field(obj_desc, buffer, buffer_length);
275235 acpi_ex_release_global_lock(obj_desc->common_field.field_flags);
276236
277237 exit:
....@@ -304,11 +264,9 @@
304264 union acpi_operand_object **result_desc)
305265 {
306266 acpi_status status;
307
- u32 length;
267
+ u32 buffer_length;
268
+ u32 data_length;
308269 void *buffer;
309
- union acpi_operand_object *buffer_desc;
310
- u32 function;
311
- u16 accessor_type;
312270
313271 ACPI_FUNCTION_TRACE_PTR(ex_write_data_to_field, obj_desc);
314272
....@@ -331,131 +289,59 @@
331289 }
332290 } else if ((obj_desc->common.type == ACPI_TYPE_LOCAL_REGION_FIELD) &&
333291 (obj_desc->field.region_obj->region.space_id ==
292
+ ACPI_ADR_SPACE_GPIO)) {
293
+
294
+ /* General Purpose I/O */
295
+
296
+ status = acpi_ex_write_gpio(source_desc, obj_desc, result_desc);
297
+ return_ACPI_STATUS(status);
298
+ } else if ((obj_desc->common.type == ACPI_TYPE_LOCAL_REGION_FIELD) &&
299
+ (obj_desc->field.region_obj->region.space_id ==
334300 ACPI_ADR_SPACE_SMBUS
335301 || obj_desc->field.region_obj->region.space_id ==
336302 ACPI_ADR_SPACE_GSBUS
337303 || obj_desc->field.region_obj->region.space_id ==
338304 ACPI_ADR_SPACE_IPMI)) {
339
- /*
340
- * This is an SMBus, GSBus or IPMI write. We will bypass the entire
341
- * field mechanism and handoff the buffer directly to the handler.
342
- * For these address spaces, the buffer is bi-directional; on a
343
- * write, return data is returned in the same buffer.
344
- *
345
- * Source must be a buffer of sufficient size:
346
- * ACPI_SMBUS_BUFFER_SIZE, ACPI_GSBUS_BUFFER_SIZE, or
347
- * ACPI_IPMI_BUFFER_SIZE.
348
- *
349
- * Note: SMBus and GSBus protocol type is passed in upper 16-bits
350
- * of Function
351
- */
352
- if (source_desc->common.type != ACPI_TYPE_BUFFER) {
353
- ACPI_ERROR((AE_INFO,
354
- "SMBus/IPMI/GenericSerialBus write requires "
355
- "Buffer, found type %s",
356
- acpi_ut_get_object_type_name(source_desc)));
357305
358
- return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
359
- }
306
+ /* SMBus, GSBus, IPMI serial */
360307
361
- if (obj_desc->field.region_obj->region.space_id ==
362
- ACPI_ADR_SPACE_SMBUS) {
363
- length = ACPI_SMBUS_BUFFER_SIZE;
364
- function =
365
- ACPI_WRITE | (obj_desc->field.attribute << 16);
366
- } else if (obj_desc->field.region_obj->region.space_id ==
367
- ACPI_ADR_SPACE_GSBUS) {
368
- accessor_type = obj_desc->field.attribute;
369
- length =
370
- acpi_ex_get_serial_access_length(accessor_type,
371
- obj_desc->field.
372
- access_length);
373
-
374
- /*
375
- * Add additional 2 bytes for the generic_serial_bus data buffer:
376
- *
377
- * Status; (Byte 0 of the data buffer)
378
- * Length; (Byte 1 of the data buffer)
379
- * Data[x-1]: (Bytes 2-x of the arbitrary length data buffer)
380
- */
381
- length += 2;
382
- function = ACPI_WRITE | (accessor_type << 16);
383
- } else { /* IPMI */
384
-
385
- length = ACPI_IPMI_BUFFER_SIZE;
386
- function = ACPI_WRITE;
387
- }
388
-
389
- if (source_desc->buffer.length < length) {
390
- ACPI_ERROR((AE_INFO,
391
- "SMBus/IPMI/GenericSerialBus write requires "
392
- "Buffer of length %u, found length %u",
393
- length, source_desc->buffer.length));
394
-
395
- return_ACPI_STATUS(AE_AML_BUFFER_LIMIT);
396
- }
397
-
398
- /* Create the bi-directional buffer */
399
-
400
- buffer_desc = acpi_ut_create_buffer_object(length);
401
- if (!buffer_desc) {
402
- return_ACPI_STATUS(AE_NO_MEMORY);
403
- }
404
-
405
- buffer = buffer_desc->buffer.pointer;
406
- memcpy(buffer, source_desc->buffer.pointer, length);
407
-
408
- /* Lock entire transaction if requested */
409
-
410
- acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags);
411
-
412
- /*
413
- * Perform the write (returns status and perhaps data in the
414
- * same buffer)
415
- */
416308 status =
417
- acpi_ex_access_region(obj_desc, 0, (u64 *)buffer, function);
418
- acpi_ex_release_global_lock(obj_desc->common_field.field_flags);
419
-
420
- *result_desc = buffer_desc;
309
+ acpi_ex_write_serial_bus(source_desc, obj_desc,
310
+ result_desc);
421311 return_ACPI_STATUS(status);
422312 } else if ((obj_desc->common.type == ACPI_TYPE_LOCAL_REGION_FIELD) &&
423313 (obj_desc->field.region_obj->region.space_id ==
424
- ACPI_ADR_SPACE_GPIO)) {
314
+ ACPI_ADR_SPACE_PLATFORM_COMM)) {
425315 /*
426
- * For GPIO (general_purpose_io), we will bypass the entire field
427
- * mechanism and handoff the bit address and bit width directly to
428
- * the handler. The Address will be the bit offset
429
- * from the previous Connection() operator, making it effectively a
430
- * pin number index. The bit_length is the length of the field, which
431
- * is thus the number of pins.
316
+ * According to the spec a write to the COMD field will invoke the
317
+ * region handler. Otherwise, write to the pcc_internal buffer. This
318
+ * implementation will use the offsets specified rather than the name
319
+ * of the field. This is considered safer because some firmware tools
320
+ * are known to obfiscate named objects.
432321 */
433
- if (source_desc->common.type != ACPI_TYPE_INTEGER) {
434
- return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
322
+ data_length =
323
+ (acpi_size)ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->field.
324
+ bit_length);
325
+ memcpy(obj_desc->field.region_obj->field.internal_pcc_buffer +
326
+ obj_desc->field.base_byte_offset,
327
+ source_desc->buffer.pointer, data_length);
328
+
329
+ if (MASTER_SUBSPACE_COMMAND(obj_desc->field.base_byte_offset)) {
330
+
331
+ /* Perform the write */
332
+
333
+ ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
334
+ "PCC COMD field has been written. Invoking PCC handler now.\n"));
335
+
336
+ status =
337
+ acpi_ex_access_region(obj_desc, 0,
338
+ (u64 *)obj_desc->field.
339
+ region_obj->field.
340
+ internal_pcc_buffer,
341
+ ACPI_WRITE);
342
+ return_ACPI_STATUS(status);
435343 }
436
-
437
- ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
438
- "GPIO FieldWrite [FROM]: (%s:%X), Val %.8X [TO]: Pin %u Bits %u\n",
439
- acpi_ut_get_type_name(source_desc->common.
440
- type),
441
- source_desc->common.type,
442
- (u32)source_desc->integer.value,
443
- obj_desc->field.pin_number_index,
444
- obj_desc->field.bit_length));
445
-
446
- buffer = &source_desc->integer.value;
447
-
448
- /* Lock entire transaction if requested */
449
-
450
- acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags);
451
-
452
- /* Perform the write */
453
-
454
- status =
455
- acpi_ex_access_region(obj_desc, 0, (u64 *)buffer,
456
- ACPI_WRITE);
457
- acpi_ex_release_global_lock(obj_desc->common_field.field_flags);
458
- return_ACPI_STATUS(status);
344
+ return (AE_OK);
459345 }
460346
461347 /* Get a pointer to the data to be written */
....@@ -464,23 +350,22 @@
464350 case ACPI_TYPE_INTEGER:
465351
466352 buffer = &source_desc->integer.value;
467
- length = sizeof(source_desc->integer.value);
353
+ buffer_length = sizeof(source_desc->integer.value);
468354 break;
469355
470356 case ACPI_TYPE_BUFFER:
471357
472358 buffer = source_desc->buffer.pointer;
473
- length = source_desc->buffer.length;
359
+ buffer_length = source_desc->buffer.length;
474360 break;
475361
476362 case ACPI_TYPE_STRING:
477363
478364 buffer = source_desc->string.pointer;
479
- length = source_desc->string.length;
365
+ buffer_length = source_desc->string.length;
480366 break;
481367
482368 default:
483
-
484369 return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
485370 }
486371
....@@ -488,7 +373,7 @@
488373 "FieldWrite [FROM]: Obj %p (%s:%X), Buf %p, ByteLen %X\n",
489374 source_desc,
490375 acpi_ut_get_type_name(source_desc->common.type),
491
- source_desc->common.type, buffer, length));
376
+ source_desc->common.type, buffer, buffer_length));
492377
493378 ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
494379 "FieldWrite [TO]: Obj %p (%s:%X), BitLen %X, BitOff %X, ByteOff %X\n",
....@@ -505,8 +390,7 @@
505390
506391 /* Write to the field */
507392
508
- status = acpi_ex_insert_into_field(obj_desc, buffer, length);
393
+ status = acpi_ex_insert_into_field(obj_desc, buffer, buffer_length);
509394 acpi_ex_release_global_lock(obj_desc->common_field.field_flags);
510
-
511395 return_ACPI_STATUS(status);
512396 }