exserial.c 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  1. // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
  2. /******************************************************************************
  3. *
  4. * Module Name: exserial - field_unit support for serial address spaces
  5. *
  6. * Copyright (C) 2000 - 2018, Intel Corp.
  7. *
  8. *****************************************************************************/
  9. #include <acpi/acpi.h>
  10. #include "accommon.h"
  11. #include "acdispat.h"
  12. #include "acinterp.h"
  13. #include "amlcode.h"
  14. #define _COMPONENT ACPI_EXECUTER
  15. ACPI_MODULE_NAME("exserial")
  16. /*******************************************************************************
  17. *
  18. * FUNCTION: acpi_ex_read_gpio
  19. *
  20. * PARAMETERS: obj_desc - The named field to read
  21. * buffer - Where the return data is returnd
  22. *
  23. * RETURN: Status
  24. *
  25. * DESCRIPTION: Read from a named field that references a Generic Serial Bus
  26. * field
  27. *
  28. ******************************************************************************/
  29. acpi_status acpi_ex_read_gpio(union acpi_operand_object *obj_desc, void *buffer)
  30. {
  31. acpi_status status;
  32. ACPI_FUNCTION_TRACE_PTR(ex_read_gpio, obj_desc);
  33. /*
  34. * For GPIO (general_purpose_io), the Address will be the bit offset
  35. * from the previous Connection() operator, making it effectively a
  36. * pin number index. The bit_length is the length of the field, which
  37. * is thus the number of pins.
  38. */
  39. ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
  40. "GPIO FieldRead [FROM]: Pin %u Bits %u\n",
  41. obj_desc->field.pin_number_index,
  42. obj_desc->field.bit_length));
  43. /* Lock entire transaction if requested */
  44. acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags);
  45. /* Perform the read */
  46. status = acpi_ex_access_region(obj_desc, 0, (u64 *)buffer, ACPI_READ);
  47. acpi_ex_release_global_lock(obj_desc->common_field.field_flags);
  48. return_ACPI_STATUS(status);
  49. }
  50. /*******************************************************************************
  51. *
  52. * FUNCTION: acpi_ex_write_gpio
  53. *
  54. * PARAMETERS: source_desc - Contains data to write. Expect to be
  55. * an Integer object.
  56. * obj_desc - The named field
  57. * result_desc - Where the return value is returned, if any
  58. *
  59. * RETURN: Status
  60. *
  61. * DESCRIPTION: Write to a named field that references a General Purpose I/O
  62. * field.
  63. *
  64. ******************************************************************************/
  65. acpi_status
  66. acpi_ex_write_gpio(union acpi_operand_object *source_desc,
  67. union acpi_operand_object *obj_desc,
  68. union acpi_operand_object **return_buffer)
  69. {
  70. acpi_status status;
  71. void *buffer;
  72. ACPI_FUNCTION_TRACE_PTR(ex_write_gpio, obj_desc);
  73. /*
  74. * For GPIO (general_purpose_io), we will bypass the entire field
  75. * mechanism and handoff the bit address and bit width directly to
  76. * the handler. The Address will be the bit offset
  77. * from the previous Connection() operator, making it effectively a
  78. * pin number index. The bit_length is the length of the field, which
  79. * is thus the number of pins.
  80. */
  81. if (source_desc->common.type != ACPI_TYPE_INTEGER) {
  82. return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
  83. }
  84. ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
  85. "GPIO FieldWrite [FROM]: (%s:%X), Value %.8X [TO]: Pin %u Bits %u\n",
  86. acpi_ut_get_type_name(source_desc->common.type),
  87. source_desc->common.type,
  88. (u32)source_desc->integer.value,
  89. obj_desc->field.pin_number_index,
  90. obj_desc->field.bit_length));
  91. buffer = &source_desc->integer.value;
  92. /* Lock entire transaction if requested */
  93. acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags);
  94. /* Perform the write */
  95. status = acpi_ex_access_region(obj_desc, 0, (u64 *)buffer, ACPI_WRITE);
  96. acpi_ex_release_global_lock(obj_desc->common_field.field_flags);
  97. return_ACPI_STATUS(status);
  98. }
  99. /*******************************************************************************
  100. *
  101. * FUNCTION: acpi_ex_read_serial_bus
  102. *
  103. * PARAMETERS: obj_desc - The named field to read
  104. * return_buffer - Where the return value is returned, if any
  105. *
  106. * RETURN: Status
  107. *
  108. * DESCRIPTION: Read from a named field that references a serial bus
  109. * (SMBus, IPMI, or GSBus).
  110. *
  111. ******************************************************************************/
  112. acpi_status
  113. acpi_ex_read_serial_bus(union acpi_operand_object *obj_desc,
  114. union acpi_operand_object **return_buffer)
  115. {
  116. acpi_status status;
  117. u32 buffer_length;
  118. union acpi_operand_object *buffer_desc;
  119. u32 function;
  120. u16 accessor_type;
  121. ACPI_FUNCTION_TRACE_PTR(ex_read_serial_bus, obj_desc);
  122. /*
  123. * This is an SMBus, GSBus or IPMI read. We must create a buffer to
  124. * hold the data and then directly access the region handler.
  125. *
  126. * Note: SMBus and GSBus protocol value is passed in upper 16-bits
  127. * of Function
  128. *
  129. * Common buffer format:
  130. * Status; (Byte 0 of the data buffer)
  131. * Length; (Byte 1 of the data buffer)
  132. * Data[x-1]: (Bytes 2-x of the arbitrary length data buffer)
  133. */
  134. switch (obj_desc->field.region_obj->region.space_id) {
  135. case ACPI_ADR_SPACE_SMBUS:
  136. buffer_length = ACPI_SMBUS_BUFFER_SIZE;
  137. function = ACPI_READ | (obj_desc->field.attribute << 16);
  138. break;
  139. case ACPI_ADR_SPACE_IPMI:
  140. buffer_length = ACPI_IPMI_BUFFER_SIZE;
  141. function = ACPI_READ;
  142. break;
  143. case ACPI_ADR_SPACE_GSBUS:
  144. accessor_type = obj_desc->field.attribute;
  145. if (accessor_type == AML_FIELD_ATTRIB_RAW_PROCESS_BYTES) {
  146. ACPI_ERROR((AE_INFO,
  147. "Invalid direct read using bidirectional write-then-read protocol"));
  148. return_ACPI_STATUS(AE_AML_PROTOCOL);
  149. }
  150. status =
  151. acpi_ex_get_protocol_buffer_length(accessor_type,
  152. &buffer_length);
  153. if (ACPI_FAILURE(status)) {
  154. ACPI_ERROR((AE_INFO,
  155. "Invalid protocol ID for GSBus: 0x%4.4X",
  156. accessor_type));
  157. return_ACPI_STATUS(status);
  158. }
  159. /* Add header length to get the full size of the buffer */
  160. buffer_length += ACPI_SERIAL_HEADER_SIZE;
  161. function = ACPI_READ | (accessor_type << 16);
  162. break;
  163. default:
  164. return_ACPI_STATUS(AE_AML_INVALID_SPACE_ID);
  165. }
  166. /* Create the local transfer buffer that is returned to the caller */
  167. buffer_desc = acpi_ut_create_buffer_object(buffer_length);
  168. if (!buffer_desc) {
  169. return_ACPI_STATUS(AE_NO_MEMORY);
  170. }
  171. /* Lock entire transaction if requested */
  172. acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags);
  173. /* Call the region handler for the write-then-read */
  174. status = acpi_ex_access_region(obj_desc, 0,
  175. ACPI_CAST_PTR(u64,
  176. buffer_desc->buffer.
  177. pointer), function);
  178. acpi_ex_release_global_lock(obj_desc->common_field.field_flags);
  179. *return_buffer = buffer_desc;
  180. return_ACPI_STATUS(status);
  181. }
  182. /*******************************************************************************
  183. *
  184. * FUNCTION: acpi_ex_write_serial_bus
  185. *
  186. * PARAMETERS: source_desc - Contains data to write
  187. * obj_desc - The named field
  188. * return_buffer - Where the return value is returned, if any
  189. *
  190. * RETURN: Status
  191. *
  192. * DESCRIPTION: Write to a named field that references a serial bus
  193. * (SMBus, IPMI, GSBus).
  194. *
  195. ******************************************************************************/
  196. acpi_status
  197. acpi_ex_write_serial_bus(union acpi_operand_object *source_desc,
  198. union acpi_operand_object *obj_desc,
  199. union acpi_operand_object **return_buffer)
  200. {
  201. acpi_status status;
  202. u32 buffer_length;
  203. void *buffer;
  204. union acpi_operand_object *buffer_desc;
  205. u32 function;
  206. u16 accessor_type;
  207. ACPI_FUNCTION_TRACE_PTR(ex_write_serial_bus, obj_desc);
  208. /*
  209. * This is an SMBus, GSBus or IPMI write. We will bypass the entire
  210. * field mechanism and handoff the buffer directly to the handler.
  211. * For these address spaces, the buffer is bidirectional; on a
  212. * write, return data is returned in the same buffer.
  213. *
  214. * Source must be a buffer of sufficient size, these are fixed size:
  215. * ACPI_SMBUS_BUFFER_SIZE, or ACPI_IPMI_BUFFER_SIZE.
  216. *
  217. * Note: SMBus and GSBus protocol type is passed in upper 16-bits
  218. * of Function
  219. *
  220. * Common buffer format:
  221. * Status; (Byte 0 of the data buffer)
  222. * Length; (Byte 1 of the data buffer)
  223. * Data[x-1]: (Bytes 2-x of the arbitrary length data buffer)
  224. */
  225. if (source_desc->common.type != ACPI_TYPE_BUFFER) {
  226. ACPI_ERROR((AE_INFO,
  227. "SMBus/IPMI/GenericSerialBus write requires "
  228. "Buffer, found type %s",
  229. acpi_ut_get_object_type_name(source_desc)));
  230. return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
  231. }
  232. switch (obj_desc->field.region_obj->region.space_id) {
  233. case ACPI_ADR_SPACE_SMBUS:
  234. buffer_length = ACPI_SMBUS_BUFFER_SIZE;
  235. function = ACPI_WRITE | (obj_desc->field.attribute << 16);
  236. break;
  237. case ACPI_ADR_SPACE_IPMI:
  238. buffer_length = ACPI_IPMI_BUFFER_SIZE;
  239. function = ACPI_WRITE;
  240. break;
  241. case ACPI_ADR_SPACE_GSBUS:
  242. accessor_type = obj_desc->field.attribute;
  243. status =
  244. acpi_ex_get_protocol_buffer_length(accessor_type,
  245. &buffer_length);
  246. if (ACPI_FAILURE(status)) {
  247. ACPI_ERROR((AE_INFO,
  248. "Invalid protocol ID for GSBus: 0x%4.4X",
  249. accessor_type));
  250. return_ACPI_STATUS(status);
  251. }
  252. /* Add header length to get the full size of the buffer */
  253. buffer_length += ACPI_SERIAL_HEADER_SIZE;
  254. function = ACPI_WRITE | (accessor_type << 16);
  255. break;
  256. default:
  257. return_ACPI_STATUS(AE_AML_INVALID_SPACE_ID);
  258. }
  259. /* Create the transfer/bidirectional/return buffer */
  260. buffer_desc = acpi_ut_create_buffer_object(buffer_length);
  261. if (!buffer_desc) {
  262. return_ACPI_STATUS(AE_NO_MEMORY);
  263. }
  264. /* Copy the input buffer data to the transfer buffer */
  265. buffer = buffer_desc->buffer.pointer;
  266. memcpy(buffer, source_desc->buffer.pointer,
  267. min(buffer_length, source_desc->buffer.length));
  268. /* Lock entire transaction if requested */
  269. acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags);
  270. /*
  271. * Perform the write (returns status and perhaps data in the
  272. * same buffer)
  273. */
  274. status = acpi_ex_access_region(obj_desc, 0, (u64 *)buffer, function);
  275. acpi_ex_release_global_lock(obj_desc->common_field.field_flags);
  276. *return_buffer = buffer_desc;
  277. return_ACPI_STATUS(status);
  278. }