summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2022-09-10 13:14:40 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2022-09-10 13:14:40 +0000
commit26b48406b1577bdb765633cb79ff9de4ef972e6b (patch)
tree31d9e64d177a9f43745060fb5bde7c90cb5de0ce /sys/dev
parent139db9828936b1eb0976f61423ec42ae78526597 (diff)
Generalize the code such that it works on SC7180 SoCs as well.
ok mglocker@, patrick@
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/acpi/qcgpio.c75
1 files changed, 58 insertions, 17 deletions
diff --git a/sys/dev/acpi/qcgpio.c b/sys/dev/acpi/qcgpio.c
index 3a606924884..532e89ab360 100644
--- a/sys/dev/acpi/qcgpio.c
+++ b/sys/dev/acpi/qcgpio.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: qcgpio.c,v 1.2 2022/09/08 06:32:32 kettenis Exp $ */
+/* $OpenBSD: qcgpio.c,v 1.3 2022/09/10 13:14:39 kettenis Exp $ */
/*
* Copyright (c) 2022 Mark Kettenis <kettenis@openbsd.org>
*
@@ -43,6 +43,11 @@
#define TLMM_GPIO_INTR_STATUS(pin) (0x000c + 0x1000 * (pin))
#define TLMM_GPIO_INTR_STATUS_INTR_STATUS (1 << 0)
+/* SC7180 has multiple tiles */
+#define QCGPIO_SC7180_WEST 0x00100000
+#define QCGPIO_SC7180_NORTH 0x00500000
+#define QCGPIO_SC7180_SOUTH 0x00900000
+
#define HREAD4(sc, reg) \
(bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg)))
#define HWRITE4(sc, reg, val) \
@@ -68,6 +73,7 @@ struct qcgpio_softc {
void *sc_ih;
uint32_t sc_npins;
+ int (*sc_pin_map)(int, bus_size_t *);
struct qcgpio_intrhand *sc_pin_ih;
struct acpi_gpio sc_gpio;
@@ -86,9 +92,13 @@ struct cfdriver qcgpio_cd = {
const char *qcgpio_hids[] = {
"QCOM060C",
+ "QCOM080D",
NULL
};
+int qcgpio_sc7180_pin_map(int, bus_size_t *);
+int qcgpio_sc8280xp_pin_map(int, bus_size_t *);
+
int qcgpio_read_pin(void *, int);
void qcgpio_write_pin(void *, int, int);
void qcgpio_intr_establish(void *, int, int, int (*)(void *), void *);
@@ -125,7 +135,15 @@ qcgpio_attach(struct device *parent, struct device *self, void *aux)
return;
}
- sc->sc_npins = 1024;
+ if (strcmp(aaa->aaa_dev, "QCOM080D") == 0) {
+ sc->sc_npins = 119;
+ sc->sc_pin_map = qcgpio_sc7180_pin_map;
+ } else if (strcmp(aaa->aaa_dev, "QCOM060C") == 0) {
+ sc->sc_npins = 228;
+ sc->sc_pin_map = qcgpio_sc8280xp_pin_map;
+ }
+ KASSERT(sc->sc_npins != 0);
+
sc->sc_pin_ih = mallocarray(sc->sc_npins, sizeof(*sc->sc_pin_ih),
M_DEVBUF, M_WAITOK | M_ZERO);
@@ -157,17 +175,31 @@ unmap:
bus_space_unmap(sc->sc_iot, sc->sc_ioh, aaa->aaa_size[0]);
}
+int
+qcgpio_sc7180_pin_map(int pin, bus_size_t *off)
+{
+ switch (pin) {
+ case 33:
+ case 0x180:
+ *off = QCGPIO_SC7180_NORTH;
+ return 33;
+ default:
+ return -1;
+ }
+}
int
-qcgpio_pin_map(int pin)
+qcgpio_sc8280xp_pin_map(int pin, bus_size_t *off)
{
switch (pin) {
case 107:
case 175:
return pin;
- case 832:
+ case 0x2c0:
+ return 107;
+ case 0x340:
return 104;
- case 896:
+ case 0x380:
return 182;
default:
return -1;
@@ -178,13 +210,14 @@ int
qcgpio_read_pin(void *cookie, int pin)
{
struct qcgpio_softc *sc = cookie;
+ bus_size_t off = 0;
uint32_t reg;
- pin = qcgpio_pin_map(pin);
+ pin = sc->sc_pin_map(pin, &off);
if (pin < 0 || pin >= sc->sc_npins)
return 0;
- reg = HREAD4(sc, TLMM_GPIO_IN_OUT(pin));
+ reg = HREAD4(sc, off + TLMM_GPIO_IN_OUT(pin));
return !!(reg & TLMM_GPIO_IN_OUT_GPIO_IN);
}
@@ -192,15 +225,19 @@ void
qcgpio_write_pin(void *cookie, int pin, int val)
{
struct qcgpio_softc *sc = cookie;
+ bus_size_t off = 0;
- pin = qcgpio_pin_map(pin);
+ pin = sc->sc_pin_map(pin, &off);
if (pin < 0 || pin >= sc->sc_npins)
return;
- if (val)
- HSET4(sc, TLMM_GPIO_IN_OUT(pin), TLMM_GPIO_IN_OUT_GPIO_OUT);
- else
- HCLR4(sc, TLMM_GPIO_IN_OUT(pin), TLMM_GPIO_IN_OUT_GPIO_OUT);
+ if (val) {
+ HSET4(sc, off + TLMM_GPIO_IN_OUT(pin),
+ TLMM_GPIO_IN_OUT_GPIO_OUT);
+ } else {
+ HCLR4(sc, off + TLMM_GPIO_IN_OUT(pin),
+ TLMM_GPIO_IN_OUT_GPIO_OUT);
+ }
}
void
@@ -208,16 +245,17 @@ qcgpio_intr_establish(void *cookie, int pin, int flags,
int (*func)(void *), void *arg)
{
struct qcgpio_softc *sc = cookie;
+ bus_size_t off = 0;
uint32_t reg;
- pin = qcgpio_pin_map(pin);
+ pin = sc->sc_pin_map(pin, &off);
if (pin < 0 || pin >= sc->sc_npins)
return;
sc->sc_pin_ih[pin].ih_func = func;
sc->sc_pin_ih[pin].ih_arg = arg;
- reg = HREAD4(sc, TLMM_GPIO_INTR_CFG(pin));
+ reg = HREAD4(sc, off + TLMM_GPIO_INTR_CFG(pin));
reg &= ~TLMM_GPIO_INTR_CFG_INTR_DECT_CTL_MASK;
reg &= ~TLMM_GPIO_INTR_CFG_INTR_POL_CTL;
switch (flags & (LR_GPIO_MODE | LR_GPIO_POLARITY)) {
@@ -248,7 +286,7 @@ qcgpio_intr_establish(void *cookie, int pin, int flags,
reg |= TLMM_GPIO_INTR_CFG_TARGET_PROC_RPM;
reg |= TLMM_GPIO_INTR_CFG_INTR_RAW_STATUS_EN;
reg |= TLMM_GPIO_INTR_CFG_INTR_ENABLE;
- HWRITE4(sc, TLMM_GPIO_INTR_CFG(pin), reg);
+ HWRITE4(sc, off + TLMM_GPIO_INTR_CFG(pin), reg);
}
int
@@ -256,18 +294,21 @@ qcgpio_intr(void *arg)
{
struct qcgpio_softc *sc = arg;
int pin, handled = 0;
+ bus_size_t off = 0;
uint32_t stat;
for (pin = 0; pin < sc->sc_npins; pin++) {
if (sc->sc_pin_ih[pin].ih_func == NULL)
continue;
- stat = HREAD4(sc, TLMM_GPIO_INTR_STATUS(pin));
+ sc->sc_pin_map(pin, &off);
+
+ stat = HREAD4(sc, off + TLMM_GPIO_INTR_STATUS(pin));
if (stat & TLMM_GPIO_INTR_STATUS_INTR_STATUS) {
sc->sc_pin_ih[pin].ih_func(sc->sc_pin_ih[pin].ih_arg);
handled = 1;
}
- HWRITE4(sc, TLMM_GPIO_INTR_STATUS(pin),
+ HWRITE4(sc, off + TLMM_GPIO_INTR_STATUS(pin),
stat & ~TLMM_GPIO_INTR_STATUS_INTR_STATUS);
}