-/* $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>
*
#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) \
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;
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 *);
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);
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;
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);
}
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
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)) {
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
{
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);
}