From: kettenis Date: Sun, 23 Jul 2023 11:47:20 +0000 (+0000) Subject: Implement suspend/resume support. This will turn off the power domain X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=f2e6717f7e3d6aae453e927d2de873a410e322a0;p=openbsd Implement suspend/resume support. This will turn off the power domain associated with a DART when we suspend and turn it back on upon resume. The DART is reconfigured with the same translation table that was present when we suspended. This is only done for DARTs that are under our control; locked DARTs and DARTs that were enabled at boot time are skipped. ok patrick@ --- diff --git a/sys/arch/arm64/dev/apldart.c b/sys/arch/arm64/dev/apldart.c index b22ca3d3edd..cc8c4b83e3a 100644 --- a/sys/arch/arm64/dev/apldart.c +++ b/sys/arch/arm64/dev/apldart.c @@ -1,4 +1,4 @@ -/* $OpenBSD: apldart.c,v 1.16 2022/07/21 18:24:24 kettenis Exp $ */ +/* $OpenBSD: apldart.c,v 1.17 2023/07/23 11:47:20 kettenis Exp $ */ /* * Copyright (c) 2021 Mark Kettenis * @@ -28,6 +28,7 @@ #include #include +#include #include /* @@ -161,6 +162,8 @@ struct apldart_softc { struct machine_bus_dma_tag sc_bus_dmat; struct iommu_device sc_id; + + int sc_do_suspend; }; struct apldart_map_state { @@ -187,9 +190,11 @@ void apldart_dmamem_free(bus_dma_tag_t, struct apldart_dmamem *); int apldart_match(struct device *, void *, void *); void apldart_attach(struct device *, struct device *, void *); +int apldart_activate(struct device *, int); const struct cfattach apldart_ca = { - sizeof (struct apldart_softc), apldart_match, apldart_attach + sizeof (struct apldart_softc), apldart_match, apldart_attach, NULL, + apldart_activate }; struct cfdriver apldart_cd = { @@ -255,8 +260,10 @@ apldart_attach(struct device *parent, struct device *self, void *aux) } sc->sc_dmat = faa->fa_dmat; - sc->sc_node = faa->fa_node; + + power_domain_enable(sc->sc_node); + if (OF_is_compatible(sc->sc_node, "apple,t8110-dart")) { params4 = HREAD4(sc, DART_T8110_PARAMS4); sc->sc_nsid = params4 & DART_T8110_PARAMS4_NSID_MASK; @@ -321,6 +328,11 @@ apldart_attach(struct device *parent, struct device *self, void *aux) } } + /* + * We have full control over this DART, so do suspend it. + */ + sc->sc_do_suspend = 1; + /* * Use bypass mode if supported. This avoids an issue with * the USB3 controllers which need mappings entered into two @@ -433,6 +445,83 @@ apldart_attach(struct device *parent, struct device *self, void *aux) iommu_device_register(&sc->sc_id); } +void +apldart_suspend(struct apldart_softc *sc) +{ + if (!sc->sc_do_suspend) + return; + + power_domain_disable(sc->sc_node); +} + +void +apldart_resume(struct apldart_softc *sc) +{ + paddr_t pa; + int ntte, nl1, nl2; + uint32_t params2; + int sid, idx; + + if (!sc->sc_do_suspend) + return; + + power_domain_enable(sc->sc_node); + + params2 = HREAD4(sc, DART_PARAMS2); + if (params2 & DART_PARAMS2_BYPASS_SUPPORT) { + for (sid = 0; sid < sc->sc_nsid; sid++) + HWRITE4(sc, DART_TCR(sc, sid), sc->sc_tcr_bypass); + return; + } + + ntte = howmany(sc->sc_dvaend, DART_PAGE_SIZE); + nl2 = howmany(ntte, DART_PAGE_SIZE / sizeof(uint64_t)); + nl1 = howmany(nl2, DART_PAGE_SIZE / sizeof(uint64_t)); + + /* Install page tables. */ + for (sid = 0; sid < sc->sc_nsid; sid++) { + pa = APLDART_DMA_DVA(sc->sc_l1); + for (idx = 0; idx < nl1; idx++) { + HWRITE4(sc, DART_TTBR(sc, sid, idx), + (pa >> DART_TTBR_SHIFT) | sc->sc_ttbr_valid); + pa += DART_PAGE_SIZE; + } + } + sc->sc_flush_tlb(sc); + + /* Enable all streams. */ + for (idx = 0; idx < howmany(sc->sc_nsid, 32); idx++) + HWRITE4(sc, DART_SID_ENABLE(sc, idx), ~0); + + /* Enable translations. */ + for (sid = 0; sid < sc->sc_nsid; sid++) + HWRITE4(sc, DART_TCR(sc, sid), sc->sc_tcr_translate_enable); + + if (OF_is_compatible(sc->sc_node, "apple,t8110-dart")) { + HWRITE4(sc, DART_T8110_ERROR, HREAD4(sc, DART_T8110_ERROR)); + HWRITE4(sc, DART_T8110_ERROR_MASK, 0); + } else { + HWRITE4(sc, DART_T8020_ERROR, HREAD4(sc, DART_T8020_ERROR)); + } +} + +int +apldart_activate(struct device *self, int act) +{ + struct apldart_softc *sc = (struct apldart_softc *)self; + + switch (act) { + case DVACT_SUSPEND: + apldart_suspend(sc); + break; + case DVACT_RESUME: + apldart_resume(sc); + break; + } + + return 0; +} + bus_dma_tag_t apldart_map(void *cookie, uint32_t *cells, bus_dma_tag_t dmat) {