summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/dev/acpi/ccpmic.c50
1 files changed, 46 insertions, 4 deletions
diff --git a/sys/dev/acpi/ccpmic.c b/sys/dev/acpi/ccpmic.c
index efcc749ffa7..9f6f3475161 100644
--- a/sys/dev/acpi/ccpmic.c
+++ b/sys/dev/acpi/ccpmic.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ccpmic.c,v 1.1 2018/05/21 13:37:31 kettenis Exp $ */
+/* $OpenBSD: ccpmic.c,v 1.2 2018/05/21 15:00:25 kettenis Exp $ */
/*
* Copyright (c) 2018 Mark Kettenis <kettenis@openbsd.org>
*
@@ -29,6 +29,21 @@
#include <dev/i2c/i2cvar.h>
+#define CCPMIC_GPIO0P0CTLO 0x2b
+#define CCPMIC_GPIO0P0CTLI 0x33
+#define CCPMIC_GPIO1P0CTLO 0x3b
+#define CCPMIC_GPIO1P0CTLI 0x43
+#define CCPMIC_GPIOPANELCTL 0x52
+#define CCPMIC_GPIOCTLO_RVAL_2KUP (1 << 1)
+#define CCPMIC_GPIOCTLO_DRV_REN (1 << 3)
+#define CCPMIC_GPIOCTLO_DIR_OUT (1 << 5)
+#define CCPMIC_GPIOCTLI_VALUE (1 << 0)
+
+#define CCPMIC_GPIOCTLO_INPUT \
+ (CCPMIC_GPIOCTLO_DRV_REN | CCPMIC_GPIOCTLO_RVAL_2KUP)
+#define CCPMIC_GPIOCTLO_OUTPUT \
+ (CCPMIC_GPIOCTLO_INPUT | CCPMIC_GPIOCTLO_DIR_OUT)
+
#define CCPMIC_V1P8SX 0x5d
#define CCPMIC_V1P2SX 0x61
#define CCPMIC_V2P85SX 0x66
@@ -40,6 +55,8 @@
#define CCPMIC_REGIONSPACE_THERMAL 0x8c
#define CCPMIC_REGIONSPACE_POWER 0x8d
+#define CCPMIC_NPINS 16
+
struct acpi_lpat {
int32_t temp;
int32_t raw;
@@ -295,17 +312,42 @@ ccpmic_power_opreg_handler(void *cookie, int iodir, uint64_t address,
}
/*
- * Allegdly the GPIOs are virtual and only there to deal with a
- * limitation of Microsoft Windows.
+ * We have 16 real GPIOs and a bunch of virtual ones. The virtual
+ * ones are mostly there to deal with a limitation of Microsoft
+ * Windows. We only implement the "panel" control GPIO, which
+ * actually maps onto a real GPIO.
*/
int
ccpmic_read_pin(void *cookie, int pin)
{
- return 0;
+ struct ccpmic_softc *sc = cookie;
+ uint8_t reg;
+
+ if (pin >= CCPMIC_NPINS)
+ return 0;
+
+ reg = ((pin < 8) ? CCPMIC_GPIO0P0CTLO : CCPMIC_GPIO1P0CTLO) + pin % 8;
+ ccpmic_write_1(sc, reg, CCPMIC_GPIOCTLO_INPUT, 0);
+ reg = ((pin < 8) ? CCPMIC_GPIO0P0CTLI : CCPMIC_GPIO1P0CTLI) + pin % 8;
+ return ccpmic_read_1(sc, reg, 0) & CCPMIC_GPIOCTLI_VALUE;
}
void
ccpmic_write_pin(void *cookie, int pin, int value)
{
+ struct ccpmic_softc *sc = cookie;
+ uint8_t reg;
+
+ if (pin == 0x5e) {
+ reg = CCPMIC_GPIOPANELCTL;
+ ccpmic_write_1(sc, reg, CCPMIC_GPIOCTLO_OUTPUT | !!value, 0);
+ return;
+ }
+
+ if (pin >= CCPMIC_NPINS)
+ return;
+
+ reg = ((pin < 8) ? CCPMIC_GPIO0P0CTLO : CCPMIC_GPIO1P0CTLO) + pin % 8;
+ ccpmic_write_1(sc, reg, CCPMIC_GPIOCTLO_OUTPUT | !!value, 0);
}