From 9a869755d8128d0239bea33e5d836805bb935e81 Mon Sep 17 00:00:00 2001 From: kettenis Date: Thu, 9 Dec 2021 11:38:26 +0000 Subject: [PATCH] Add aplpmgr(4), a driver for the power management controller found on various Apple SoCs. ok patrick@ --- sys/arch/arm64/conf/GENERIC | 3 +- sys/arch/arm64/conf/RAMDISK | 3 +- sys/arch/arm64/conf/files.arm64 | 6 +- sys/arch/arm64/dev/aplns.c | 5 +- sys/arch/arm64/dev/aplpcie.c | 4 +- sys/arch/arm64/dev/aplpmgr.c | 160 ++++++++++++++++++++++++++++++++ 6 files changed, 176 insertions(+), 5 deletions(-) create mode 100644 sys/arch/arm64/dev/aplpmgr.c diff --git a/sys/arch/arm64/conf/GENERIC b/sys/arch/arm64/conf/GENERIC index 81c61fb9737..f231c2bb2e3 100644 --- a/sys/arch/arm64/conf/GENERIC +++ b/sys/arch/arm64/conf/GENERIC @@ -1,4 +1,4 @@ -# $OpenBSD: GENERIC,v 1.215 2021/12/03 19:16:29 uaa Exp $ +# $OpenBSD: GENERIC,v 1.216 2021/12/09 11:38:26 kettenis Exp $ # # GENERIC machine description file # @@ -145,6 +145,7 @@ aplintc* at fdt? early 1 aplpcie* at fdt? pci* at aplpcie? aplpinctrl* at fdt? early 1 +aplpmgr* at fdt? early 1 aplspi* at fdt? aplhidev* at spi? aplkbd* at aplhidev? diff --git a/sys/arch/arm64/conf/RAMDISK b/sys/arch/arm64/conf/RAMDISK index d63ade906b6..46ec65e080e 100644 --- a/sys/arch/arm64/conf/RAMDISK +++ b/sys/arch/arm64/conf/RAMDISK @@ -1,4 +1,4 @@ -# $OpenBSD: RAMDISK,v 1.161 2021/11/22 20:25:50 kettenis Exp $ +# $OpenBSD: RAMDISK,v 1.162 2021/12/09 11:38:26 kettenis Exp $ machine arm64 maxusers 4 @@ -109,6 +109,7 @@ aplintc* at fdt? early 1 aplpcie* at fdt? pci* at aplpcie? aplpinctrl* at fdt? early 1 +aplpmgr* at fdt? early 1 aplspi* at fdt? aplhidev* at spi? aplkbd* at aplhidev? diff --git a/sys/arch/arm64/conf/files.arm64 b/sys/arch/arm64/conf/files.arm64 index 139df931cca..be12fd6edd9 100644 --- a/sys/arch/arm64/conf/files.arm64 +++ b/sys/arch/arm64/conf/files.arm64 @@ -1,4 +1,4 @@ -# $OpenBSD: files.arm64,v 1.46 2021/11/01 09:02:46 kettenis Exp $ +# $OpenBSD: files.arm64,v 1.47 2021/12/09 11:38:26 kettenis Exp $ maxpartitions 16 maxusers 2 8 128 @@ -168,6 +168,10 @@ device aplpinctrl attach aplpinctrl at fdt file arch/arm64/dev/aplpinctrl.c aplpinctrl +device aplpmgr +attach aplpmgr at fdt +file arch/arm64/dev/aplpmgr.c aplpmgr + # Apple NVME Storage device aplns {} attach aplns at fdt diff --git a/sys/arch/arm64/dev/aplns.c b/sys/arch/arm64/dev/aplns.c index 52cb2a63f45..11c16805e36 100644 --- a/sys/arch/arm64/dev/aplns.c +++ b/sys/arch/arm64/dev/aplns.c @@ -1,4 +1,4 @@ -/* $OpenBSD: aplns.c,v 1.5 2021/08/29 11:23:29 kettenis Exp $ */ +/* $OpenBSD: aplns.c,v 1.6 2021/12/09 11:38:27 kettenis Exp $ */ /* * Copyright (c) 2014, 2021 David Gwynne * @@ -31,6 +31,7 @@ #include #include +#include #include #include @@ -165,6 +166,8 @@ nvme_ans_attach(struct device *parent, struct device *self, void *aux) return; } + power_domain_enable(faa->fa_node); + sc->sc_ih = fdt_intr_establish(faa->fa_node, IPL_BIO, nvme_intr, sc, sc->sc_dev.dv_xname); if (sc->sc_ih == NULL) { diff --git a/sys/arch/arm64/dev/aplpcie.c b/sys/arch/arm64/dev/aplpcie.c index 69d43d0f259..7480307646b 100644 --- a/sys/arch/arm64/dev/aplpcie.c +++ b/sys/arch/arm64/dev/aplpcie.c @@ -1,4 +1,4 @@ -/* $OpenBSD: aplpcie.c,v 1.8 2021/11/01 20:22:12 kettenis Exp $ */ +/* $OpenBSD: aplpcie.c,v 1.9 2021/12/09 11:38:27 kettenis Exp $ */ /* * Copyright (c) 2021 Mark Kettenis * @@ -32,6 +32,7 @@ #include #include #include +#include #include /* @@ -174,6 +175,7 @@ aplpcie_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); pinctrl_byname(sc->sc_node, "default"); sc->sc_msi_doorbell = diff --git a/sys/arch/arm64/dev/aplpmgr.c b/sys/arch/arm64/dev/aplpmgr.c new file mode 100644 index 00000000000..b858b028d5b --- /dev/null +++ b/sys/arch/arm64/dev/aplpmgr.c @@ -0,0 +1,160 @@ +/* $OpenBSD: aplpmgr.c,v 1.1 2021/12/09 11:38:27 kettenis Exp $ */ +/* + * Copyright (c) 2021 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 + +#define PMGR_PS_TARGET_MASK 0x0000000f +#define PMGR_PS_TARGET_SHIFT 0 +#define PMGR_PS_ACTUAL_MASK 0x000000f0 +#define PMGR_PS_ACTUAL_SHIFT 4 +#define PMGR_PS_ACTIVE 0xf +#define PMGR_PS_PWRGATE 0x0 + +#define HREAD4(sc, reg) \ + (bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg))) +#define HWRITE4(sc, reg, val) \ + bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (val)) + +struct aplpmgr_softc; + +struct aplpmgr_pwrstate { + struct aplpmgr_softc *ps_sc; + struct power_domain_device ps_pd; + bus_size_t ps_offset; +}; + +struct aplpmgr_softc { + struct device sc_dev; + bus_space_tag_t sc_iot; + bus_space_handle_t sc_ioh; + + struct aplpmgr_pwrstate *sc_pwrstate; + int sc_npwrstate; +}; + +int aplpmgr_match(struct device *, void *, void *); +void aplpmgr_attach(struct device *, struct device *, void *); + +const struct cfattach aplpmgr_ca = { + sizeof (struct aplpmgr_softc), aplpmgr_match, aplpmgr_attach +}; + +struct cfdriver aplpmgr_cd = { + NULL, "aplpmgr", DV_DULL +}; + +void aplpmgr_enable(void *, uint32_t *, int); + +int +aplpmgr_match(struct device *parent, void *match, void *aux) +{ + struct fdt_attach_args *faa = aux; + + if (OF_is_compatible(faa->fa_node, "apple,pmgr")) + return 10; /* Must beat syscon(4). */ + + return 0; +} + +void +aplpmgr_attach(struct device *parent, struct device *self, void *aux) +{ + struct aplpmgr_softc *sc = (struct aplpmgr_softc *)self; + struct fdt_attach_args *faa = aux; + struct aplpmgr_pwrstate *ps; + uint32_t reg[2]; + int node; + + if (faa->fa_nreg < 1) { + printf(": no registers\n"); + return; + } + + sc->sc_iot = faa->fa_iot; + if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr, + faa->fa_reg[0].size, 0, &sc->sc_ioh)) { + printf(": can't map registers\n"); + return; + } + + printf("\n"); + + for (node = OF_child(faa->fa_node); node; node = OF_peer(node)) { + if (OF_is_compatible(node, "apple,pmgr-pwrstate")) + sc->sc_npwrstate++; + } + + sc->sc_pwrstate = mallocarray(sc->sc_npwrstate, + sizeof(*sc->sc_pwrstate), M_DEVBUF, M_WAITOK | M_ZERO); + + ps = sc->sc_pwrstate; + for (node = OF_child(faa->fa_node); node; node = OF_peer(node)) { + if (!OF_is_compatible(node, "apple,pmgr-pwrstate")) + continue; + + if (OF_getpropintarray(node, "reg", reg, + sizeof(reg)) != sizeof(reg)) { + printf("%s: invalid reg property\n", + sc->sc_dev.dv_xname); + continue; + } + + ps->ps_sc = sc; + ps->ps_offset = reg[0]; + ps->ps_pd.pd_node = node; + ps->ps_pd.pd_cookie = ps; + ps->ps_pd.pd_enable = aplpmgr_enable; + power_domain_register(&ps->ps_pd); + ps++; + } +} + +void +aplpmgr_enable(void *cookie, uint32_t *cells, int on) +{ + struct aplpmgr_pwrstate *ps = cookie; + struct aplpmgr_softc *sc = ps->ps_sc; + uint32_t pstate = on ? PMGR_PS_ACTIVE : PMGR_PS_PWRGATE; + uint32_t val; + int timo; + + power_domain_enable_all(ps->ps_pd.pd_node); + + val = HREAD4(sc, ps->ps_offset); + val &= ~PMGR_PS_TARGET_MASK; + val |= (pstate << PMGR_PS_TARGET_SHIFT); + HWRITE4(sc, ps->ps_offset, val); + + for (timo = 0; timo < 100; timo++) { + val = HREAD4(sc, ps->ps_offset); + val &= PMGR_PS_ACTUAL_MASK; + if ((val >> PMGR_PS_ACTUAL_SHIFT) == pstate) + break; + delay(1); + } +} -- 2.20.1