From 0aed1edf78f945804e3d48f9704f8c70b0ad6913 Mon Sep 17 00:00:00 2001 From: patrick Date: Wed, 29 Dec 2021 18:40:19 +0000 Subject: [PATCH] Allow ohci(4) and ehci(4) to attach to acpi(4). ok kettenis@ --- sys/dev/acpi/ehci_acpi.c | 124 +++++++++++++++++++++++++++++++ sys/dev/acpi/files.acpi | 10 ++- sys/dev/acpi/ohci_acpi.c | 154 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 287 insertions(+), 1 deletion(-) create mode 100644 sys/dev/acpi/ehci_acpi.c create mode 100644 sys/dev/acpi/ohci_acpi.c diff --git a/sys/dev/acpi/ehci_acpi.c b/sys/dev/acpi/ehci_acpi.c new file mode 100644 index 00000000000..83f2fef25bf --- /dev/null +++ b/sys/dev/acpi/ehci_acpi.c @@ -0,0 +1,124 @@ +/* $OpenBSD: ehci_acpi.c,v 1.1 2021/12/29 18:40:19 patrick Exp $ */ +/* + * Copyright (c) 2018 Mark Kettenis + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +struct ehci_acpi_softc { + struct ehci_softc sc; + struct acpi_softc *sc_acpi; + struct aml_node *sc_node; + void *sc_ih; +}; + +int ehci_acpi_match(struct device *, void *, void *); +void ehci_acpi_attach(struct device *, struct device *, void *); + +struct cfattach ehci_acpi_ca = { + sizeof(struct ehci_acpi_softc), ehci_acpi_match, ehci_acpi_attach +}; + +const char *ehci_hids[] = { + "PNP0D20", + NULL +}; + +int +ehci_acpi_match(struct device *parent, void *match, void *aux) +{ + struct acpi_attach_args *aaa = aux; + struct cfdata *cf = match; + + if (aaa->aaa_naddr < 1 || aaa->aaa_nirq < 1) + return 0; + return acpi_matchhids(aaa, ehci_hids, cf->cf_driver->cd_name); +} + +void +ehci_acpi_attach(struct device *parent, struct device *self, void *aux) +{ + struct ehci_acpi_softc *sc = (struct ehci_acpi_softc *)self; + struct acpi_attach_args *aaa = aux; + int error; + + sc->sc_acpi = (struct acpi_softc *)parent; + sc->sc_node = aaa->aaa_node; + printf(" %s", sc->sc_node->name); + + printf(" addr 0x%llx/0x%llx", aaa->aaa_addr[0], aaa->aaa_size[0]); + printf(" irq %d", aaa->aaa_irq[0]); + + sc->sc.iot = aaa->aaa_bst[0]; + sc->sc.sc_size = aaa->aaa_size[0]; + sc->sc.sc_bus.dmatag = aaa->aaa_dmat; + + if (bus_space_map(sc->sc.iot, aaa->aaa_addr[0], aaa->aaa_size[0], + 0, &sc->sc.ioh)) { + printf(": can't map registers\n"); + return; + } + + /* Disable interrupts, so we don't get any spurious ones. */ + sc->sc.sc_offs = EREAD1(&sc->sc, EHCI_CAPLENGTH); + EOWRITE2(&sc->sc, EHCI_USBINTR, 0); + + sc->sc_ih = acpi_intr_establish(aaa->aaa_irq[0], aaa->aaa_irq_flags[0], + IPL_USB, ehci_intr, sc, sc->sc.sc_bus.bdev.dv_xname); + if (sc->sc_ih == NULL) { + printf(": can't establish interrupt\n"); + goto unmap; + } + + printf("\n"); + + strlcpy(sc->sc.sc_vendor, "Generic", sizeof(sc->sc.sc_vendor)); + error = ehci_init(&sc->sc); + if (error) { + printf("%s: init failed, error=%d\n", + sc->sc.sc_bus.bdev.dv_xname, error); + goto disestablish_ret; + } + + /* Attach usb device. */ + config_found(self, &sc->sc.sc_bus, usbctlprint); + + return; + +disestablish_ret: + acpi_intr_disestablish(sc->sc_ih); +unmap: + bus_space_unmap(sc->sc.iot, sc->sc.ioh, sc->sc.sc_size); + return; +} diff --git a/sys/dev/acpi/files.acpi b/sys/dev/acpi/files.acpi index 95df4ffe448..f97eb6d4e3e 100644 --- a/sys/dev/acpi/files.acpi +++ b/sys/dev/acpi/files.acpi @@ -1,4 +1,4 @@ -# $OpenBSD: files.acpi,v 1.63 2021/12/26 13:55:36 kettenis Exp $ +# $OpenBSD: files.acpi,v 1.64 2021/12/29 18:40:19 patrick Exp $ # # Config file and device description for machine-independent ACPI code. # Included by ports that need it. @@ -187,6 +187,14 @@ file dev/acpi/pluart_acpi.c pluart_acpi attach sdhc at acpi with sdhc_acpi file dev/acpi/sdhc_acpi.c sdhc_acpi +# OHCI +attach ohci at acpi with ohci_acpi +file dev/acpi/ohci_acpi.c ohci_acpi + +# EHCI +attach ehci at acpi with ehci_acpi +file dev/acpi/ehci_acpi.c ehci_acpi + # XHCI attach xhci at acpi with xhci_acpi file dev/acpi/xhci_acpi.c xhci_acpi diff --git a/sys/dev/acpi/ohci_acpi.c b/sys/dev/acpi/ohci_acpi.c new file mode 100644 index 00000000000..64946eeecea --- /dev/null +++ b/sys/dev/acpi/ohci_acpi.c @@ -0,0 +1,154 @@ +/* $OpenBSD: ohci_acpi.c,v 1.1 2021/12/29 18:40:19 patrick Exp $ */ +/* + * Copyright (c) 2018 Mark Kettenis + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +struct ohci_acpi_softc { + struct ohci_softc sc; + struct acpi_softc *sc_acpi; + struct aml_node *sc_node; + void *sc_ih; +}; + +int ohci_acpi_match(struct device *, void *, void *); +void ohci_acpi_attach(struct device *, struct device *, void *); + +struct cfattach ohci_acpi_ca = { + sizeof(struct ohci_acpi_softc), ohci_acpi_match, ohci_acpi_attach +}; + +void ohci_acpi_attach_deferred(struct device *); + +int +ohci_acpi_match(struct device *parent, void *match, void *aux) +{ + struct acpi_attach_args *aaa = aux; + + return acpi_matchcls(aaa, PCI_CLASS_SERIALBUS, + PCI_SUBCLASS_SERIALBUS_USB, PCI_INTERFACE_OHCI); +} + +void +ohci_acpi_attach(struct device *parent, struct device *self, void *aux) +{ + struct ohci_acpi_softc *sc = (struct ohci_acpi_softc *)self; + struct acpi_attach_args *aaa = aux; + + sc->sc_acpi = (struct acpi_softc *)parent; + sc->sc_node = aaa->aaa_node; + printf(" %s", sc->sc_node->name); + + printf(" addr 0x%llx/0x%llx", aaa->aaa_addr[0], aaa->aaa_size[0]); + printf(" irq %d", aaa->aaa_irq[0]); + + sc->sc.iot = aaa->aaa_bst[0]; + sc->sc.sc_size = aaa->aaa_size[0]; + sc->sc.sc_bus.dmatag = aaa->aaa_dmat; + + if (bus_space_map(sc->sc.iot, aaa->aaa_addr[0], aaa->aaa_size[0], + 0, &sc->sc.ioh)) { + printf(": can't map registers\n"); + return; + } + + /* Record what interrupts were enabled by SMM/BIOS. */ + sc->sc.sc_intre = bus_space_read_4(sc->sc.iot, sc->sc.ioh, + OHCI_INTERRUPT_ENABLE); + + /* Disable interrupts, so we don't get any spurious ones. */ + bus_space_write_4(sc->sc.iot, sc->sc.ioh, OHCI_INTERRUPT_DISABLE, + OHCI_MIE); + + bus_space_barrier(sc->sc.iot, sc->sc.ioh, 0, sc->sc.sc_size, + BUS_SPACE_BARRIER_READ|BUS_SPACE_BARRIER_WRITE); + bus_space_write_4(sc->sc.iot, sc->sc.ioh, + OHCI_INTERRUPT_DISABLE, OHCI_MIE); + + /* Map and establish the interrupt. */ + sc->sc_ih = acpi_intr_establish(aaa->aaa_irq[0], aaa->aaa_irq_flags[0], + IPL_USB, ohci_intr, sc, sc->sc.sc_bus.bdev.dv_xname); + if (sc->sc_ih == NULL) { + printf(": can't establish interrupt\n"); + goto unmap; + } + + printf(": "); + + strlcpy(sc->sc.sc_vendor, "Generic", sizeof(sc->sc.sc_vendor)); + + /* Display revision and perform legacy emulation handover. */ + if (ohci_checkrev(&sc->sc) != USBD_NORMAL_COMPLETION || + ohci_handover(&sc->sc) != USBD_NORMAL_COMPLETION) + goto disestablish_ret; + + /* Ignore interrupts for now */ + sc->sc.sc_bus.dying = 1; + + config_defer(self, ohci_acpi_attach_deferred); + return; + +disestablish_ret: + acpi_intr_disestablish(sc->sc_ih); +unmap: + bus_space_unmap(sc->sc.iot, sc->sc.ioh, sc->sc.sc_size); + return; +} + +void +ohci_acpi_attach_deferred(struct device *self) +{ + struct ohci_acpi_softc *sc = (struct ohci_acpi_softc *)self; + usbd_status r; + int s; + + s = splusb(); + sc->sc.sc_bus.dying = 0; + r = ohci_init(&sc->sc); + splx(s); + + if (r != USBD_NORMAL_COMPLETION) { + printf("%s: init failed, error=%d\n", + sc->sc.sc_bus.bdev.dv_xname, r); + acpi_intr_disestablish(sc->sc_ih); + sc->sc_ih = NULL; + bus_space_unmap(sc->sc.iot, sc->sc.ioh, sc->sc.sc_size); + sc->sc.sc_size = 0; + return; + } + + /* Attach usb device. */ + config_found(self, &sc->sc.sc_bus, usbctlprint); +} -- 2.20.1