From 0b6813b0c5547848ad4bfd1021622647a4059935 Mon Sep 17 00:00:00 2001 From: kettenis Date: Sun, 23 Jul 2023 11:49:17 +0000 Subject: [PATCH] Improve suspend/resume support. Power off the associated power domain during suspend and re-initialize the "dwc3" specific registers upon resume. ok patrick@ --- sys/dev/fdt/xhci_fdt.c | 59 ++++++++++++++++++++++++++++++++---------- 1 file changed, 46 insertions(+), 13 deletions(-) diff --git a/sys/dev/fdt/xhci_fdt.c b/sys/dev/fdt/xhci_fdt.c index 3c172bcfaf1..41ed4b660a1 100644 --- a/sys/dev/fdt/xhci_fdt.c +++ b/sys/dev/fdt/xhci_fdt.c @@ -1,4 +1,4 @@ -/* $OpenBSD: xhci_fdt.c,v 1.23 2023/04/03 01:55:00 dlg Exp $ */ +/* $OpenBSD: xhci_fdt.c,v 1.24 2023/07/23 11:49:17 kettenis Exp $ */ /* * Copyright (c) 2017 Mark Kettenis * @@ -56,13 +56,15 @@ struct xhci_fdt_softc { int xhci_fdt_match(struct device *, void *, void *); void xhci_fdt_attach(struct device *, struct device *, void *); +int xhci_fdt_activate(struct device *, int); const struct cfattach xhci_fdt_ca = { sizeof(struct xhci_fdt_softc), xhci_fdt_match, xhci_fdt_attach, NULL, - xhci_activate + xhci_fdt_activate }; -int xhci_cdns_init(struct xhci_fdt_softc *); +int xhci_cdns_attach(struct xhci_fdt_softc *); +int xhci_snps_attach(struct xhci_fdt_softc *); int xhci_snps_init(struct xhci_fdt_softc *); void xhci_init_phys(struct xhci_fdt_softc *); @@ -139,9 +141,9 @@ xhci_fdt_attach(struct device *parent, struct device *self, void *aux) * functionality. */ if (OF_is_compatible(sc->sc_node, "cdns,usb3")) - error = xhci_cdns_init(sc); + error = xhci_cdns_attach(sc); if (OF_is_compatible(sc->sc_node, "snps,dwc3")) - error = xhci_snps_init(sc); + error = xhci_snps_attach(sc); if (error) { printf(": can't initialize hardware\n"); goto disestablish_ret; @@ -170,6 +172,31 @@ unmap: bus_space_unmap(sc->sc.iot, sc->sc.ioh, sc->sc.sc_size); } +int +xhci_fdt_activate(struct device *self, int act) +{ + struct xhci_fdt_softc *sc = (struct xhci_fdt_softc *)self; + int rv = 0; + + switch (act) { + case DVACT_POWERDOWN: + rv = xhci_activate(self, act); + power_domain_disable(sc->sc_node); + break; + case DVACT_RESUME: + power_domain_enable(sc->sc_node); + if (OF_is_compatible(sc->sc_node, "snps,dwc3")) + xhci_snps_init(sc); + rv = xhci_activate(self, act); + break; + default: + rv = xhci_activate(self, act); + break; + } + + return rv; +} + /* * Cadence USB3 controller. */ @@ -183,7 +210,7 @@ unmap: #define OTG_STS_XHCI_READY (1 << 26) int -xhci_cdns_init(struct xhci_fdt_softc *sc) +xhci_cdns_attach(struct xhci_fdt_softc *sc) { uint32_t did, sts; int timo; @@ -252,27 +279,33 @@ xhci_snps_ep_get_cookie(void *cookie, struct endpoint *ep) } int -xhci_snps_init(struct xhci_fdt_softc *sc) +xhci_snps_attach(struct xhci_fdt_softc *sc) { - char phy_type[16] = { 0 }; - int node = sc->sc_node; - uint32_t reg; - /* * On Apple hardware we need to reset the controller when we * see a new connection. */ - if (OF_is_compatible(node, "apple,dwc3")) { + if (OF_is_compatible(sc->sc_node, "apple,dwc3")) { sc->sc_usb_controller_port.up_cookie = sc; sc->sc_usb_controller_port.up_connect = xhci_snps_connect; task_set(&sc->sc_snps_connect_task, xhci_snps_do_connect, sc); - sc->sc_ports.dp_node = node; + sc->sc_ports.dp_node = sc->sc_node; sc->sc_ports.dp_cookie = &sc->sc_usb_controller_port; sc->sc_ports.dp_ep_get_cookie = xhci_snps_ep_get_cookie; device_ports_register(&sc->sc_ports, EP_USB_CONTROLLER_PORT); } + return xhci_snps_init(sc); +} + +int +xhci_snps_init(struct xhci_fdt_softc *sc) +{ + char phy_type[16] = { 0 }; + int node = sc->sc_node; + uint32_t reg; + /* We don't support device mode, so always force host mode. */ reg = bus_space_read_4(sc->sc.iot, sc->sc.ioh, USB3_GCTL); reg &= ~USB3_GCTL_PRTCAPDIR_MASK; -- 2.20.1