Hi folks, I'm trying to port amdgpio.c from OpenBSD (/sys/dev/acpi) to NetBSD then I can use my trackpad hopefully. I made some progress. The code is building but not crashing when the system boots (as expected). But now I can see new devices as 'not configured' message they did not exist before. MEM (PNP0C01) at acpi0 not configured VPC0 (VPC2004) at acpi0 not configured ITSD (IDEA2004) at acpi0 not configured HKDV (LKH2019) at acpi0 not configured acpiwmibus at acpiwmi1 not configured and then the crash happens in my bus_space_unmap(). Please, do you have any idea what could be the problem or how i can investigate it? Picture attached and code below: #include <sys/param.h> #include <sys/systm.h> #include <sys/malloc.h> #include <sys/device.h> #include <sys/device_impl.h> #include <sys/gpio.h> #include <sys/kmem.h> #include <dev/acpi/acpireg.h> #include <dev/acpi/acpivar.h> #include <dev/acpi/acpi_intr.h> #include <dev/acpi/acpi_event.h> #include <dev/gpio/gpiovar.h> #define LR_GPIO_POLARITY (3L << 1) #define LR_GPIO_ACTHI (0L << 1) #define LR_GPIO_ACTLO (1L << 1) #define LR_GPIO_ACTBOTH (2L << 1) #define LR_GPIO_MODE (1L << 0) #define LR_GPIO_LEVEL (0L << 0) #define AMDGPIO_CONF_LEVEL 0x00000100 #define AMDGPIO_CONF_ACTLO 0x00000200 #define AMDGPIO_CONF_ACTBOTH 0x00000400 #define AMDGPIO_CONF_MASK 0x00000600 #define AMDGPIO_CONF_INT_EN 0x00000800 #define AMDGPIO_CONF_INT_MASK 0x00001000 #define AMDGPIO_CONF_RXSTATE 0x00010000 #define AMDGPIO_CONF_TXSTATE 0x00400000 #define AMDGPIO_CONF_TXSTATE_EN 0x00800000 #define AMDGPIO_CONF_INT_STS 0x10000000 #define AMDGPIO_IRQ_MASTER_EOI 0x20000000 #define AMDGPIO_IRQ_BITS 46 #define AMDGPIO_IRQ_PINS 4 #define AMDGPIO_IRQ_MASTER 0xfc #define AMDGPIO_IRQ_STS 0x2f8 struct amdgpio_intrhand { int (*ih_func)(void *); void *ih_arg; }; struct amdgpio_pincfg { /* Modeled after pchgpio but we only have one value to save/restore */ uint32_t pin_cfg; }; struct amdgpio_softc { device_t sc_dev; struct acpi_softc *sc_acpi; ACPI_HANDLE sc_handle; bus_space_tag_t sc_memt; bus_space_handle_t sc_memh; bus_size_t sc_size; void *sc_ih; int sc_npins; int sc_pmf; struct amdgpio_pincfg *sc_pin_cfg; struct amdgpio_intrhand *sc_pin_ih; struct gpio_chipset_tag sc_gpio; }; int amdgpio_match(device_t, cfdata_t, void *); void amdgpio_attach(device_t, device_t, void *); int amdgpio_activate(device_t, int); CFATTACH_DECL_NEW(amdgpio_acpi, sizeof(struct amdgpio_softc), amdgpio_match, amdgpio_attach, NULL, NULL); static const struct device_compatible_entry compat_data[] = { { .compat = "AMDI0030" }, { .compat = "AMD0030" }, DEVICE_COMPAT_EOL }; int amdgpio_read_pin(void *, int); void amdgpio_write_pin(void *, int, int); void * amdgpio_intr_establish(void *, int, int, int, int (*)(void *), void *); void amdgpio_intr_enable(void *, int); void amdgpio_intr_disable(void *, void *); int amdgpio_pin_intr(struct amdgpio_softc *, int); int amdgpio_intr(void *); void amdgpio_save_pin(struct amdgpio_softc *, int pin); bool amdgpio_save(device_t self, const pmf_qual_t *qual); void amdgpio_restore_pin(struct amdgpio_softc *, int pin); bool amdgpio_restore(device_t self, const pmf_qual_t *qual); int amdgpio_match(device_t parent, cfdata_t cf, void *aux) { struct acpi_attach_args *aa = aux; return acpi_compatible_match(aa, compat_data); } void amdgpio_attach(device_t parent, device_t self, void *aux) { struct acpi_attach_args *aa = aux; struct amdgpio_softc *sc = device_private(self); struct gpiobus_attach_args gba; struct acpi_resources res; struct acpi_mem *mem; struct acpi_irq *irq; ACPI_STATUS rv; int64_t uid; sc->sc_dev = self; sc->sc_acpi = (struct acpi_softc *)parent; //sc->sc_node = aa->aa_node; if (acpi_eval_integer(aa->aa_node->ad_handle, "_UID", &uid)) { printf(": can't find uid\n"); return; } printf(" uid %ld", uid); switch (uid) { case 0: sc->sc_npins = 184; break; default: printf("\n"); return; } //sc->sc_memt = aa->aaa_bst[0]; rv = acpi_resource_parse(self, aa->aa_node->ad_handle, "_CRS", &res, &acpi_resource_parse_ops_default); if (ACPI_FAILURE(rv)) return; mem = acpi_res_mem(&res, 0); if (bus_space_map(aa->aa_memt, mem->ar_base, mem->ar_length, 0, &sc->sc_memh)) { aprint_error_dev(self, ": can't map registers\n"); return; } sc->sc_size = mem->ar_length; irq = acpi_res_irq(&res, 0); if (irq == NULL) { aprint_error_dev(self, "couldn't find irq resource\n"); goto done; } sc->sc_pin_cfg = kmem_zalloc(sc->sc_npins * sizeof(sc->sc_pin_cfg[0]), KM_SLEEP); sc->sc_pin_ih = kmem_zalloc(sc->sc_npins * sizeof(sc->sc_pin_ih[0]), KM_SLEEP); sc->sc_ih = acpi_intr_establish(self, (uint64_t)(uintptr_t)aa->aa_node->ad_handle, IPL_BIO, false, amdgpio_intr, sc, sc->sc_dev->dv_xname); if (sc->sc_ih == NULL) { printf(": can't establish interrupt\n"); goto unmap; } sc->sc_gpio.gp_cookie = sc; sc->sc_gpio.gp_pin_read = amdgpio_read_pin; sc->sc_gpio.gp_pin_write = amdgpio_write_pin; sc->sc_gpio.gp_intr_establish = amdgpio_intr_establish; //sc->sc_gpio.gp_intr_enable = amdgpio_intr_enable; sc->sc_gpio.gp_intr_disestablish = amdgpio_intr_disable; //sc->sc_node->gpio = &sc->sc_gpio; memset(&gba, 0, sizeof(gba)); gba.gba_npins = sc->sc_npins; printf(", %d pins\n", sc->sc_npins); #if NGPIO > 0 config_found(sc->sc_dev, &gba, gpiobus_print, CFARGS_NONE); #endif unmap: kmem_free(sc->sc_pin_ih, sc->sc_npins * sizeof(*sc->sc_pin_ih)); bus_space_unmap(sc->sc_memt, sc->sc_memh, sc->sc_size); sc->sc_size = 0; printf(" DOIS"); done: acpi_resource_cleanup(&res); (void)pmf_device_register(self, amdgpio_save, amdgpio_restore); sc->sc_pmf = 1; printf(" TRES"); kmem_free(sc->sc_pin_cfg, sc->sc_npins * sizeof(sc->sc_pin_cfg[0])); kmem_free(sc->sc_pin_ih, sc->sc_npins * sizeof(sc->sc_pin_ih[0])); printf(" QUATRO"); } void amdgpio_save_pin(struct amdgpio_softc *sc, int pin) { sc->sc_pin_cfg[pin].pin_cfg = bus_space_read_4(sc->sc_memt, sc->sc_memh, pin * 4); } bool amdgpio_save(device_t self, const pmf_qual_t *qual) { struct amdgpio_softc *sc = device_private(self); int pin; for (pin = 0; pin < sc->sc_npins; pin++) amdgpio_save_pin(sc, pin); return true; } void amdgpio_restore_pin(struct amdgpio_softc *sc, int pin) { if (!sc->sc_pin_ih[pin].ih_func) return; bus_space_write_4(sc->sc_memt, sc->sc_memh, pin * 4, sc->sc_pin_cfg[pin].pin_cfg); } bool amdgpio_restore(device_t self, const pmf_qual_t *qual) { int pin; struct amdgpio_softc *sc = device_private(self); for (pin = 0; pin < sc->sc_npins; pin++) amdgpio_restore_pin(sc, pin); return true; } int amdgpio_read_pin(void *cookie, int pin) { struct amdgpio_softc *sc = cookie; uint32_t reg; reg = bus_space_read_4(sc->sc_memt, sc->sc_memh, pin * 4); return !!(reg & AMDGPIO_CONF_RXSTATE); } void amdgpio_write_pin(void *cookie, int pin, int value) { struct amdgpio_softc *sc = cookie; uint32_t reg; reg = bus_space_read_4(sc->sc_memt, sc->sc_memh, pin * 4); reg |= AMDGPIO_CONF_TXSTATE_EN; if (value) reg |= AMDGPIO_CONF_TXSTATE; else reg &= ~AMDGPIO_CONF_TXSTATE; bus_space_write_4(sc->sc_memt, sc->sc_memh, pin * 4, reg); } void * amdgpio_intr_establish(void *cookie, int pin, int flags, int irqmode, int (*func)(void *), void *arg) { struct amdgpio_softc *sc = cookie; uint32_t reg; KASSERT(pin >= 0 && pin != 63 && pin < sc->sc_npins); sc->sc_pin_ih[pin].ih_func = func; sc->sc_pin_ih[pin].ih_arg = arg; reg = bus_space_read_4(sc->sc_memt, sc->sc_memh, pin * 4); reg &= ~(AMDGPIO_CONF_MASK | AMDGPIO_CONF_LEVEL | AMDGPIO_CONF_TXSTATE_EN); if ((flags & LR_GPIO_MODE) == 0) reg |= AMDGPIO_CONF_LEVEL; if ((flags & LR_GPIO_POLARITY) == LR_GPIO_ACTLO) reg |= AMDGPIO_CONF_ACTLO; if ((flags & LR_GPIO_POLARITY) == LR_GPIO_ACTBOTH) reg |= AMDGPIO_CONF_ACTBOTH; reg |= (AMDGPIO_CONF_INT_MASK | AMDGPIO_CONF_INT_EN); bus_space_write_4(sc->sc_memt, sc->sc_memh, pin * 4, reg); return NULL; } void amdgpio_intr_disable(void *cookie, void *pin) { struct amdgpio_softc *sc = cookie; uint32_t reg; int *pin_aux = pin; KASSERT(*pin_aux >= 0 && *pin_aux != 63 && *pin_aux < sc->sc_npins); reg = bus_space_read_4(sc->sc_memt, sc->sc_memh, *pin_aux * 4); reg &= ~(AMDGPIO_CONF_INT_MASK | AMDGPIO_CONF_INT_EN); bus_space_write_4(sc->sc_memt, sc->sc_memh, (int) *pin_aux * 4, reg); } int amdgpio_pin_intr(struct amdgpio_softc *sc, int pin) { uint32_t reg; int rc = 0; reg = bus_space_read_4(sc->sc_memt, sc->sc_memh, pin * 4); if (reg & AMDGPIO_CONF_INT_STS) { if (sc->sc_pin_ih[pin].ih_func) { sc->sc_pin_ih[pin].ih_func(sc->sc_pin_ih[pin].ih_arg); /* Clear interrupt */ reg = bus_space_read_4(sc->sc_memt, sc->sc_memh, pin * 4); bus_space_write_4(sc->sc_memt, sc->sc_memh, pin * 4, reg); rc = 1; } else { /* Mask unhandled interrupt */ reg &= ~(AMDGPIO_CONF_INT_MASK | AMDGPIO_CONF_INT_EN); bus_space_write_4(sc->sc_memt, sc->sc_memh, pin * 4, reg); } } return rc; } int amdgpio_intr(void *arg) { struct amdgpio_softc *sc = arg; uint64_t status; uint32_t reg; int rc = 0, pin = 0; int i, j; status = bus_space_read_4(sc->sc_memt, sc->sc_memh, AMDGPIO_IRQ_STS + 4); status <<= 32; status |= bus_space_read_4(sc->sc_memt, sc->sc_memh, AMDGPIO_IRQ_STS); /* One status bit for every four pins */ for (i = 0; i < AMDGPIO_IRQ_BITS; i++, pin += 4) { if (status & (1ULL << i)) { for (j = 0; j < AMDGPIO_IRQ_PINS; j++) { if (amdgpio_pin_intr(sc, pin + j)) rc = 1; } } } /* Signal end of interrupt */ reg = bus_space_read_4(sc->sc_memt, sc->sc_memh, AMDGPIO_IRQ_MASTER); reg |= AMDGPIO_IRQ_MASTER_EOI; bus_space_write_4(sc->sc_memt, sc->sc_memh, AMDGPIO_IRQ_MASTER, reg); return rc; } Sent from ProtonMail, Swiss-based encrypted email.
Attachment:
photo_2022-11-28_23-07-49.jpg
Description: JPEG image