summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/dev/acpi/bytgpio.c17
-rw-r--r--sys/dev/acpi/dsdt.c71
2 files changed, 78 insertions, 10 deletions
diff --git a/sys/dev/acpi/bytgpio.c b/sys/dev/acpi/bytgpio.c
index 11654f545ed..ec38f909f07 100644
--- a/sys/dev/acpi/bytgpio.c
+++ b/sys/dev/acpi/bytgpio.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: bytgpio.c,v 1.8 2016/05/04 08:30:56 kettenis Exp $ */
+/* $OpenBSD: bytgpio.c,v 1.9 2016/05/07 18:08:27 kettenis Exp $ */
/*
* Copyright (c) 2016 Mark Kettenis
*
@@ -124,6 +124,8 @@ bytgpio_attach(struct device *parent, struct device *self, void *aux)
struct acpi_attach_args *aaa = aux;
struct bytgpio_softc *sc = (struct bytgpio_softc *)self;
struct aml_value res;
+ struct aml_value arg[2];
+ struct aml_node *node;
int64_t uid;
uint32_t reg;
int i;
@@ -211,8 +213,19 @@ bytgpio_attach(struct device *parent, struct device *self, void *aux)
reg &= ~BYTGPIO_CONF_GD_MASK;
bus_space_write_4(sc->sc_memt, sc->sc_memh, sc->sc_pins[i] * 16, reg);
}
-
+
printf(", %d pins\n", sc->sc_npins);
+
+ /* Register address space. */
+ memset(&arg, 0, sizeof(arg));
+ arg[0].type = AML_OBJTYPE_INTEGER;
+ arg[0].v_integer = ACPI_OPREG_GPIO;
+ arg[1].type = AML_OBJTYPE_INTEGER;
+ arg[1].v_integer = 1;
+ node = aml_searchname(sc->sc_node, "_REG");
+ if (node && aml_evalnode(sc->sc_acpi, node, 2, arg, NULL))
+ printf("%s: _REG failed\n", sc->sc_dev.dv_xname);
+
return;
fail:
diff --git a/sys/dev/acpi/dsdt.c b/sys/dev/acpi/dsdt.c
index f04eb8f946d..60e659e1383 100644
--- a/sys/dev/acpi/dsdt.c
+++ b/sys/dev/acpi/dsdt.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: dsdt.c,v 1.221 2016/03/14 06:37:31 guenther Exp $ */
+/* $OpenBSD: dsdt.c,v 1.222 2016/05/07 18:08:27 kettenis Exp $ */
/*
* Copyright (c) 2005 Jordan Hargrave <jordan@openbsd.org>
*
@@ -2206,6 +2206,7 @@ aml_evalhid(struct aml_node *node, struct aml_value *val)
}
void aml_rwgas(struct aml_value *, int, int, struct aml_value *, int, int);
+void aml_rwgpio(struct aml_value *, int, int, struct aml_value *, int, int);
void aml_rwindexfield(struct aml_value *, struct aml_value *val, int);
void aml_rwfield(struct aml_value *, int, int, struct aml_value *, int);
@@ -2332,6 +2333,37 @@ aml_rwgas(struct aml_value *rgn, int bpos, int blen, struct aml_value *val,
}
void
+aml_rwgpio(struct aml_value *conn, int bpos, int blen, struct aml_value *val,
+ int mode, int flag)
+{
+ union acpi_resource *crs = (union acpi_resource *)conn->v_buffer;
+ struct aml_node *node;
+ uint16_t pin;
+ int v = 0;
+
+ if (conn->type != AML_OBJTYPE_BUFFER || conn->length < 5 ||
+ AML_CRSTYPE(crs) != LR_GPIO || AML_CRSLEN(crs) > conn->length)
+ aml_die("Invalid GpioIo");
+ if (bpos != 0 || blen != 1)
+ aml_die("Invalid GpioIo access");
+
+ node = aml_searchname(conn->node,
+ (char *)&crs->pad[crs->lr_gpio.res_off]);
+ pin = *(uint16_t *)&crs->pad[crs->lr_gpio.pin_off];
+
+ if (node == NULL || node->gpio == NULL)
+ aml_die("Could not find GpioIo pin");
+
+ if (mode == ACPI_IOWRITE) {
+ printf("GpioIO write unimplemented\n");
+ return;
+ }
+
+ v = node->gpio->read_pin(node->gpio->cookie, pin);
+ _aml_setvalue(val, AML_OBJTYPE_INTEGER, v, NULL);
+}
+
+void
aml_rwindexfield(struct aml_value *fld, struct aml_value *val, int mode)
{
struct aml_value tmp, *ref1, *ref2;
@@ -2427,8 +2459,22 @@ aml_rwfield(struct aml_value *fld, int bpos, int blen, struct aml_value *val,
aml_rwgas(ref1, fld->v_field.bitpos, fld->v_field.bitlen,
val, mode, fld->v_field.flags);
} else if (fld->v_field.type == AMLOP_FIELD) {
- aml_rwgas(ref1, fld->v_field.bitpos + bpos, blen, val, mode,
- fld->v_field.flags);
+ switch (ref1->v_opregion.iospace) {
+ case ACPI_OPREG_GPIO:
+ aml_rwgpio(ref2, bpos, blen, val, mode,
+ fld->v_field.flags);
+ break;
+ case ACPI_OPREG_SYSMEM:
+ case ACPI_OPREG_SYSIO:
+ case ACPI_OPREG_PCICFG:
+ case ACPI_OPREG_EC:
+ aml_rwgas(ref1, fld->v_field.bitpos + bpos, blen,
+ val, mode, fld->v_field.flags);
+ break;
+ default:
+ aml_die("Unsupported RegionSpace");
+ break;
+ }
} else if (mode == ACPI_IOREAD) {
/* bufferfield:read */
_aml_setvalue(val, AML_OBJTYPE_INTEGER, 0, 0);
@@ -2498,6 +2544,7 @@ void
aml_parsefieldlist(struct aml_scope *mscope, int opcode, int flags,
struct aml_value *data, struct aml_value *index, int indexval)
{
+ struct aml_value *conn = NULL;
struct aml_value *rv;
int bpos, blen;
@@ -2506,20 +2553,28 @@ aml_parsefieldlist(struct aml_scope *mscope, int opcode, int flags,
bpos = 0;
while (mscope->pos < mscope->end) {
switch (*mscope->pos) {
- case 0x00: // reserved, length
+ case 0x00: /* reserved, length */
mscope->pos++;
blen = aml_parselength(mscope);
break;
- case 0x01: // flags
+ case 0x01: /* flags */
mscope->pos += 3;
blen = 0;
break;
- default: // 4-byte name, length
+ case 0x02: /* connection */
+ mscope->pos++;
+ blen = 0;
+ conn = aml_parse(mscope, 'o', "Connection");
+ if (conn == NULL)
+ aml_die("Could not parse connection");
+ conn->node = mscope->node;
+ break;
+ default: /* 4-byte name, length */
mscope->pos = aml_parsename(mscope->node, mscope->pos,
&rv, 1);
blen = aml_parselength(mscope);
- aml_createfield(rv, opcode, data, bpos, blen, index,
- indexval, flags);
+ aml_createfield(rv, opcode, data, bpos, blen,
+ conn ? conn : index, indexval, flags);
aml_delref(&rv, 0);
break;
}