root/drivers/acpi/acpica/exserial.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ACPI_MODULE_NAME
  2. acpi_ex_write_gpio
  3. acpi_ex_read_serial_bus
  4. acpi_ex_write_serial_bus

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

/* [<][>][^][v][top][bottom][index][help] */