summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Moore <Robert.Moore@intel.com>2014-09-04 14:20:20 -0700
committerRobert Moore <Robert.Moore@intel.com>2014-09-04 14:20:20 -0700
commitaca0478526af23718edaea15a24b229caeb2d7c5 (patch)
tree119ba899231ab72d720a0a7ea2fa97e23de15a86
parent4e7cb23515961ac4e01d0fda4f74f20c9e4c8e19 (diff)
downloadacpica-aca0478526af23718edaea15a24b229caeb2d7c5.tar.gz
Update to GPIO region handler interface.
Changes to correct several GPIO issues: 1) The UpdateRule in a GPIO field definition is now ignored; a read-modify-write operation is never performed for GPIO fields. (Internally, this means that the field assembly/disassembly code is completely bypassed for GPIO.) 2) The Address parameter passed to a GPIO region handler is now the bit offset of the field from a previous Connection() operator. Thus, it becomes a "Pin Number Index" into the Connection() resource descriptor. 3) The BitWidth parameter passed to a GPIO region handler is now the exact bit width of the GPIO field. Thus, it can be interpreted as "number of pins". Overall, we can now say that the region handler interface to GPIO handlers is a raw "bit/pin" addressed interface, not a byte-addressed interface like the SystemMemory handler interface. For Linux, this patch will need to be applied simultaneously with the Linux GPIO handler patch that supports it.
-rw-r--r--source/components/dispatcher/dsfield.c2
-rw-r--r--source/components/events/evregion.c46
-rw-r--r--source/components/executer/exfield.c68
-rw-r--r--source/components/executer/exprep.c2
-rw-r--r--source/include/aclocal.h1
-rw-r--r--source/include/acobject.h1
-rw-r--r--source/tools/acpiexec/aeregion.c16
7 files changed, 122 insertions, 14 deletions
diff --git a/source/components/dispatcher/dsfield.c b/source/components/dispatcher/dsfield.c
index 2219952b6..ccf786f70 100644
--- a/source/components/dispatcher/dsfield.c
+++ b/source/components/dispatcher/dsfield.c
@@ -463,6 +463,7 @@ AcpiDsGetFieldNames (
*/
Info->ResourceBuffer = NULL;
Info->ConnectionNode = NULL;
+ Info->PinNumberIndex = 0;
/*
* A Connection() is either an actual resource descriptor (buffer)
@@ -538,6 +539,7 @@ AcpiDsGetFieldNames (
}
Info->FieldBitPosition += Info->FieldBitLength;
+ Info->PinNumberIndex++; /* Index relative to previous Connection() */
break;
default:
diff --git a/source/components/events/evregion.c b/source/components/events/evregion.c
index 886f7aef1..029a45555 100644
--- a/source/components/events/evregion.c
+++ b/source/components/events/evregion.c
@@ -230,6 +230,7 @@ AcpiEvAddressSpaceDispatch (
ACPI_OPERAND_OBJECT *RegionObj2;
void *RegionContext = NULL;
ACPI_CONNECTION_INFO *Context;
+ ACPI_PHYSICAL_ADDRESS Address;
ACPI_FUNCTION_TRACE (EvAddressSpaceDispatch);
@@ -319,23 +320,33 @@ AcpiEvAddressSpaceDispatch (
/* We have everything we need, we can invoke the address space handler */
Handler = HandlerDesc->AddressSpace.Handler;
-
- ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
- "Handler %p (@%p) Address %8.8X%8.8X [%s]\n",
- &RegionObj->Region.Handler->AddressSpace, Handler,
- ACPI_FORMAT_NATIVE_UINT (RegionObj->Region.Address + RegionOffset),
- AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
+ Address = (RegionObj->Region.Address + RegionOffset);
/*
* Special handling for GenericSerialBus and GeneralPurposeIo:
* There are three extra parameters that must be passed to the
* handler via the context:
- * 1) Connection buffer, a resource template from Connection() op.
- * 2) Length of the above buffer.
- * 3) Actual access length from the AccessAs() op.
+ * 1) Connection buffer, a resource template from Connection() op
+ * 2) Length of the above buffer
+ * 3) Actual access length from the AccessAs() op
+ *
+ * In addition, for GeneralPurposeIo, the Address and BitWidth fields
+ * are defined as follows:
+ * 1) Address is the pin number index of the field (bit offset from
+ * the previous Connection)
+ * 2) BitWidth is the actual bit length of the field (number of pins)
*/
- if (((RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GSBUS) ||
- (RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GPIO)) &&
+ if ((RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GSBUS) &&
+ Context &&
+ FieldObj)
+ {
+ /* Get the Connection (ResourceTemplate) buffer */
+
+ Context->Connection = FieldObj->Field.ResourceBuffer;
+ Context->Length = FieldObj->Field.ResourceLength;
+ Context->AccessLength = FieldObj->Field.AccessLength;
+ }
+ if ((RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GPIO) &&
Context &&
FieldObj)
{
@@ -344,8 +355,16 @@ AcpiEvAddressSpaceDispatch (
Context->Connection = FieldObj->Field.ResourceBuffer;
Context->Length = FieldObj->Field.ResourceLength;
Context->AccessLength = FieldObj->Field.AccessLength;
+ Address = FieldObj->Field.PinNumberIndex;
+ BitWidth = FieldObj->Field.BitLength;
}
+ ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
+ "Handler %p (@%p) Address %8.8X%8.8X [%s]\n",
+ &RegionObj->Region.Handler->AddressSpace, Handler,
+ ACPI_FORMAT_NATIVE_UINT (Address),
+ AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
+
if (!(HandlerDesc->AddressSpace.HandlerFlags &
ACPI_ADDR_HANDLER_DEFAULT_INSTALLED))
{
@@ -359,9 +378,8 @@ AcpiEvAddressSpaceDispatch (
/* Call the handler */
- Status = Handler (Function,
- (RegionObj->Region.Address + RegionOffset), BitWidth, Value,
- Context, RegionObj2->Extra.RegionContext);
+ Status = Handler (Function, Address, BitWidth, Value, Context,
+ RegionObj2->Extra.RegionContext);
if (ACPI_FAILURE (Status))
{
diff --git a/source/components/executer/exfield.c b/source/components/executer/exfield.c
index 1263ed7af..f0bfb1117 100644
--- a/source/components/executer/exfield.c
+++ b/source/components/executer/exfield.c
@@ -345,6 +345,39 @@ AcpiExReadDataFromField (
Buffer = &BufferDesc->Integer.Value;
}
+ if ((ObjDesc->Common.Type == ACPI_TYPE_LOCAL_REGION_FIELD) &&
+ (ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GPIO))
+ {
+ /*
+ * For GPIO (GeneralPurposeIo), the Address will be the bit offset
+ * from the previous Connection() operator, making it effectively a
+ * pin number index. The BitLength is the length of the field, which
+ * is thus the number of pins.
+ */
+ ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
+ "GPIO FieldRead [FROM]: Pin %u Bits %u\n",
+ ObjDesc->Field.PinNumberIndex, ObjDesc->Field.BitLength));
+
+ /* Lock entire transaction if requested */
+
+ AcpiExAcquireGlobalLock (ObjDesc->CommonField.FieldFlags);
+
+ /* Perform the write */
+
+ Status = AcpiExAccessRegion (ObjDesc, 0,
+ (UINT64 *) Buffer, ACPI_READ);
+ AcpiExReleaseGlobalLock (ObjDesc->CommonField.FieldFlags);
+ if (ACPI_FAILURE (Status))
+ {
+ AcpiUtRemoveReference (BufferDesc);
+ }
+ else
+ {
+ *RetBufferDesc = BufferDesc;
+ }
+ return_ACPI_STATUS (Status);
+ }
+
ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
"FieldRead [TO]: Obj %p, Type %X, Buf %p, ByteLen %X\n",
ObjDesc, ObjDesc->Common.Type, Buffer, (UINT32) Length));
@@ -518,6 +551,41 @@ AcpiExWriteDataToField (
*ResultDesc = BufferDesc;
return_ACPI_STATUS (Status);
}
+ else if ((ObjDesc->Common.Type == ACPI_TYPE_LOCAL_REGION_FIELD) &&
+ (ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GPIO))
+ {
+ /*
+ * For GPIO (GeneralPurposeIo), we will bypass the entire field
+ * mechanism and handoff the bit address and bit width directly to
+ * the handler. The Address will be the bit offset
+ * from the previous Connection() operator, making it effectively a
+ * pin number index. The BitLength is the length of the field, which
+ * is thus the number of pins.
+ */
+ if (SourceDesc->Common.Type != ACPI_TYPE_INTEGER)
+ {
+ return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
+ }
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
+ "GPIO FieldWrite [FROM]: (%s:%X), Val %.8X [TO]: Pin %u Bits %u\n",
+ AcpiUtGetTypeName (SourceDesc->Common.Type),
+ SourceDesc->Common.Type, (UINT32) SourceDesc->Integer.Value,
+ ObjDesc->Field.PinNumberIndex, ObjDesc->Field.BitLength));
+
+ Buffer = &SourceDesc->Integer.Value;
+
+ /* Lock entire transaction if requested */
+
+ AcpiExAcquireGlobalLock (ObjDesc->CommonField.FieldFlags);
+
+ /* Perform the write */
+
+ Status = AcpiExAccessRegion (ObjDesc, 0,
+ (UINT64 *) Buffer, ACPI_WRITE);
+ AcpiExReleaseGlobalLock (ObjDesc->CommonField.FieldFlags);
+ return_ACPI_STATUS (Status);
+ }
/* Get a pointer to the data to be written */
diff --git a/source/components/executer/exprep.c b/source/components/executer/exprep.c
index f1707360f..276a77abd 100644
--- a/source/components/executer/exprep.c
+++ b/source/components/executer/exprep.c
@@ -587,6 +587,8 @@ AcpiExPrepFieldValue (
ObjDesc->Field.ResourceLength = Info->ResourceLength;
}
+ ObjDesc->Field.PinNumberIndex = Info->PinNumberIndex;
+
/* Allow full data read from EC address space */
if ((ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_EC) &&
diff --git a/source/include/aclocal.h b/source/include/aclocal.h
index 1ea772eee..2680834aa 100644
--- a/source/include/aclocal.h
+++ b/source/include/aclocal.h
@@ -363,6 +363,7 @@ typedef struct acpi_create_field_info
UINT32 FieldBitPosition;
UINT32 FieldBitLength;
UINT16 ResourceLength;
+ UINT16 PinNumberIndex;
UINT8 FieldFlags;
UINT8 Attribute;
UINT8 FieldType;
diff --git a/source/include/acobject.h b/source/include/acobject.h
index e90af0b52..6e3d0de9c 100644
--- a/source/include/acobject.h
+++ b/source/include/acobject.h
@@ -410,6 +410,7 @@ typedef struct acpi_object_region_field
UINT16 ResourceLength;
union acpi_operand_object *RegionObj; /* Containing OpRegion object */
UINT8 *ResourceBuffer; /* ResourceTemplate for serial regions/fields */
+ UINT16 PinNumberIndex; /* Index relative to previous Connection/Template */
} ACPI_OBJECT_REGION_FIELD;
diff --git a/source/tools/acpiexec/aeregion.c b/source/tools/acpiexec/aeregion.c
index aa746fec3..084925b51 100644
--- a/source/tools/acpiexec/aeregion.c
+++ b/source/tools/acpiexec/aeregion.c
@@ -685,6 +685,22 @@ AeRegionHandler (
}
return (AE_OK);
+ /*
+ * GPIO has some special semantics:
+ * 1) Address is the pin number index into the Connection() pin list
+ * 2) BitWidth is the actual number of bits (pins) defined by the field
+ */
+ case ACPI_ADR_SPACE_GPIO: /* ACPI 5.0 */
+
+ if (AcpiGbl_DisplayRegionAccess)
+ {
+ AcpiOsPrintf ("AcpiExec: GPIO "
+ "%s: Addr %.4X Width %X Conn %p\n",
+ (Function & ACPI_IO_MASK) ? "Write" : "Read ",
+ (UINT32) Address, BitWidth, MyContext->Connection);
+ }
+ return (AE_OK);
+
default:
break;
}