1 /* $OpenBSD: amdgpio.c,v 1.2 2020/01/26 00:11:42 jsg Exp $ */ 2 /* 3 * Copyright (c) 2016 Mark Kettenis 4 * Copyright (c) 2019 James Hastings 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include <sys/param.h> 20 #include <sys/malloc.h> 21 #include <sys/systm.h> 22 23 #include <dev/acpi/acpireg.h> 24 #include <dev/acpi/acpivar.h> 25 #include <dev/acpi/acpidev.h> 26 #include <dev/acpi/amltypes.h> 27 #include <dev/acpi/dsdt.h> 28 29 #define AMDGPIO_CONF_LEVEL 0x00000100 30 #define AMDGPIO_CONF_ACTLO 0x00000200 31 #define AMDGPIO_CONF_ACTBOTH 0x00000400 32 #define AMDGPIO_CONF_MASK 0x00000600 33 #define AMDGPIO_CONF_INT_EN 0x00000800 34 #define AMDGPIO_CONF_INT_MASK 0x00001000 35 #define AMDGPIO_CONF_RXSTATE 0x00010000 36 #define AMDGPIO_CONF_TXSTATE 0x00400000 37 #define AMDGPIO_CONF_TXSTATE_EN 0x00800000 38 #define AMDGPIO_CONF_INT_STS 0x10000000 39 #define AMDGPIO_IRQ_MASTER_EOI 0x20000000 40 #define AMDGPIO_IRQ_BITS 46 41 #define AMDGPIO_IRQ_PINS 4 42 43 #define AMDGPIO_IRQ_MASTER 0xfc 44 #define AMDGPIO_IRQ_STS 0x2f8 45 46 struct amdgpio_intrhand { 47 int (*ih_func)(void *); 48 void *ih_arg; 49 }; 50 51 struct amdgpio_softc { 52 struct device sc_dev; 53 struct acpi_softc *sc_acpi; 54 struct aml_node *sc_node; 55 56 bus_space_tag_t sc_memt; 57 bus_space_handle_t sc_memh; 58 bus_addr_t sc_addr; 59 bus_size_t sc_size; 60 61 int sc_irq; 62 int sc_irq_flags; 63 void *sc_ih; 64 65 int sc_npins; 66 struct amdgpio_intrhand *sc_pin_ih; 67 68 struct acpi_gpio sc_gpio; 69 }; 70 71 int amdgpio_match(struct device *, void *, void *); 72 void amdgpio_attach(struct device *, struct device *, void *); 73 74 struct cfattach amdgpio_ca = { 75 sizeof(struct amdgpio_softc), amdgpio_match, amdgpio_attach 76 }; 77 78 struct cfdriver amdgpio_cd = { 79 NULL, "amdgpio", DV_DULL 80 }; 81 82 const char *amdgpio_hids[] = { 83 "AMDI0030", 84 "AMD0030", 85 NULL 86 }; 87 88 int amdgpio_parse_resources(int, union acpi_resource *, void *); 89 int amdgpio_read_pin(void *, int); 90 void amdgpio_write_pin(void *, int, int); 91 void amdgpio_intr_establish(void *, int, int, int (*)(), void *); 92 int amdgpio_pin_intr(struct amdgpio_softc *, int); 93 int amdgpio_intr(void *); 94 95 int 96 amdgpio_match(struct device *parent, void *match, void *aux) 97 { 98 struct acpi_attach_args *aaa = aux; 99 struct cfdata *cf = match; 100 101 return acpi_matchhids(aaa, amdgpio_hids, cf->cf_driver->cd_name); 102 } 103 104 void 105 amdgpio_attach(struct device *parent, struct device *self, void *aux) 106 { 107 struct acpi_attach_args *aaa = aux; 108 struct amdgpio_softc *sc = (struct amdgpio_softc *)self; 109 struct aml_value res; 110 int64_t uid; 111 112 sc->sc_acpi = (struct acpi_softc *)parent; 113 sc->sc_node = aaa->aaa_node; 114 printf(": %s", sc->sc_node->name); 115 116 if (aml_evalinteger(sc->sc_acpi, sc->sc_node, "_UID", 0, NULL, &uid)) { 117 printf(", can't find uid\n"); 118 return; 119 } 120 121 printf(" uid %lld", uid); 122 123 switch (uid) { 124 case 0: 125 sc->sc_npins = 184; 126 break; 127 default: 128 printf("\n"); 129 return; 130 } 131 132 if (aml_evalname(sc->sc_acpi, sc->sc_node, "_CRS", 0, NULL, &res)) { 133 printf(", can't find registers\n"); 134 return; 135 } 136 137 aml_parse_resource(&res, amdgpio_parse_resources, sc); 138 aml_freevalue(&res); 139 printf(" addr 0x%lx/0x%lx", sc->sc_addr, sc->sc_size); 140 if (sc->sc_addr == 0 || sc->sc_size == 0) { 141 printf("\n"); 142 return; 143 } 144 145 sc->sc_pin_ih = mallocarray(sc->sc_npins, sizeof(*sc->sc_pin_ih), 146 M_DEVBUF, M_NOWAIT | M_ZERO); 147 if (sc->sc_pin_ih == NULL) { 148 printf("\n"); 149 return; 150 } 151 152 printf(" irq %d", sc->sc_irq); 153 154 sc->sc_memt = aaa->aaa_memt; 155 if (bus_space_map(sc->sc_memt, sc->sc_addr, sc->sc_size, 0, 156 &sc->sc_memh)) { 157 printf(", can't map registers\n"); 158 goto free; 159 } 160 161 sc->sc_ih = acpi_intr_establish(sc->sc_irq, sc->sc_irq_flags, IPL_BIO, 162 amdgpio_intr, sc, sc->sc_dev.dv_xname); 163 if (sc->sc_ih == NULL) { 164 printf(", can't establish interrupt\n"); 165 goto unmap; 166 } 167 168 sc->sc_gpio.cookie = sc; 169 sc->sc_gpio.read_pin = amdgpio_read_pin; 170 sc->sc_gpio.write_pin = amdgpio_write_pin; 171 sc->sc_gpio.intr_establish = amdgpio_intr_establish; 172 sc->sc_node->gpio = &sc->sc_gpio; 173 174 printf(", %d pins\n", sc->sc_npins); 175 176 acpi_register_gpio(sc->sc_acpi, sc->sc_node); 177 return; 178 179 unmap: 180 bus_space_unmap(sc->sc_memt, sc->sc_memh, sc->sc_size); 181 free: 182 free(sc->sc_pin_ih, M_DEVBUF, sc->sc_npins * sizeof(*sc->sc_pin_ih)); 183 } 184 185 int 186 amdgpio_parse_resources(int crsidx, union acpi_resource *crs, void *arg) 187 { 188 struct amdgpio_softc *sc = arg; 189 int type = AML_CRSTYPE(crs); 190 191 switch (type) { 192 case LR_MEM32FIXED: 193 sc->sc_addr = crs->lr_m32fixed._bas; 194 sc->sc_size = crs->lr_m32fixed._len; 195 break; 196 case LR_EXTIRQ: 197 sc->sc_irq = crs->lr_extirq.irq[0]; 198 sc->sc_irq_flags = crs->lr_extirq.flags; 199 break; 200 default: 201 printf(" type 0x%x\n", type); 202 break; 203 } 204 205 return 0; 206 } 207 208 int 209 amdgpio_read_pin(void *cookie, int pin) 210 { 211 struct amdgpio_softc *sc = cookie; 212 uint32_t reg; 213 214 reg = bus_space_read_4(sc->sc_memt, sc->sc_memh, pin * 4); 215 216 return !!(reg & AMDGPIO_CONF_RXSTATE); 217 } 218 219 void 220 amdgpio_write_pin(void *cookie, int pin, int value) 221 { 222 struct amdgpio_softc *sc = cookie; 223 uint32_t reg; 224 225 reg = bus_space_read_4(sc->sc_memt, sc->sc_memh, pin * 4); 226 reg |= AMDGPIO_CONF_TXSTATE_EN; 227 if (value) 228 reg |= AMDGPIO_CONF_TXSTATE; 229 else 230 reg &= ~AMDGPIO_CONF_TXSTATE; 231 bus_space_write_4(sc->sc_memt, sc->sc_memh, pin * 4, reg); 232 } 233 234 void 235 amdgpio_intr_establish(void *cookie, int pin, int flags, 236 int (*func)(void *), void *arg) 237 { 238 struct amdgpio_softc *sc = cookie; 239 uint32_t reg; 240 241 KASSERT(pin >= 0 && pin != 63 && pin < sc->sc_npins); 242 243 sc->sc_pin_ih[pin].ih_func = func; 244 sc->sc_pin_ih[pin].ih_arg = arg; 245 246 reg = bus_space_read_4(sc->sc_memt, sc->sc_memh, pin * 4); 247 reg &= ~(AMDGPIO_CONF_MASK | AMDGPIO_CONF_LEVEL | 248 AMDGPIO_CONF_TXSTATE_EN); 249 if ((flags & LR_GPIO_MODE) == 0) 250 reg |= AMDGPIO_CONF_LEVEL; 251 if ((flags & LR_GPIO_POLARITY) == LR_GPIO_ACTLO) 252 reg |= AMDGPIO_CONF_ACTLO; 253 if ((flags & LR_GPIO_POLARITY) == LR_GPIO_ACTBOTH) 254 reg |= AMDGPIO_CONF_ACTBOTH; 255 reg |= (AMDGPIO_CONF_INT_MASK | AMDGPIO_CONF_INT_EN); 256 bus_space_write_4(sc->sc_memt, sc->sc_memh, pin * 4, reg); 257 } 258 259 int 260 amdgpio_pin_intr(struct amdgpio_softc *sc, int pin) 261 { 262 uint32_t reg; 263 int rc = 0; 264 265 reg = bus_space_read_4(sc->sc_memt, sc->sc_memh, pin * 4); 266 if (reg & AMDGPIO_CONF_INT_STS) { 267 if (sc->sc_pin_ih[pin].ih_func) { 268 sc->sc_pin_ih[pin].ih_func(sc->sc_pin_ih[pin].ih_arg); 269 270 /* Clear interrupt */ 271 reg = bus_space_read_4(sc->sc_memt, sc->sc_memh, 272 pin * 4); 273 bus_space_write_4(sc->sc_memt, sc->sc_memh, 274 pin * 4, reg); 275 rc = 1; 276 } else { 277 /* Mask unhandled interrupt */ 278 reg &= ~(AMDGPIO_CONF_INT_MASK | AMDGPIO_CONF_INT_EN); 279 bus_space_write_4(sc->sc_memt, sc->sc_memh, 280 pin * 4, reg); 281 } 282 } 283 284 return rc; 285 } 286 287 int 288 amdgpio_intr(void *arg) 289 { 290 struct amdgpio_softc *sc = arg; 291 uint64_t status; 292 uint32_t reg; 293 int rc = 0, pin = 0; 294 int i, j; 295 296 status = bus_space_read_4(sc->sc_memt, sc->sc_memh, 297 AMDGPIO_IRQ_STS + 4); 298 status <<= 32; 299 status |= bus_space_read_4(sc->sc_memt, sc->sc_memh, 300 AMDGPIO_IRQ_STS); 301 302 /* One status bit for every four pins */ 303 for (i = 0; i < AMDGPIO_IRQ_BITS; i++, pin += 4) { 304 if (status & (1 << i)) { 305 for (j = 0; j < AMDGPIO_IRQ_PINS; j++) { 306 if (amdgpio_pin_intr(sc, pin + j)) 307 rc = 1; 308 } 309 } 310 } 311 312 /* Signal end of interrupt */ 313 reg = bus_space_read_4(sc->sc_memt, sc->sc_memh, 314 AMDGPIO_IRQ_MASTER); 315 reg |= AMDGPIO_IRQ_MASTER_EOI; 316 bus_space_write_4(sc->sc_memt, sc->sc_memh, 317 AMDGPIO_IRQ_MASTER, reg); 318 319 return rc; 320 } 321