diff options
author | Mark Kettenis <kettenis@cvs.openbsd.org> | 2022-11-09 19:18:12 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@cvs.openbsd.org> | 2022-11-09 19:18:12 +0000 |
commit | 500070ba952da06307f0478e23f6516993226ea6 (patch) | |
tree | 53acb6ffc44b52199ad1f6d2033ad48b1de2a6dd /sys/arch/arm64/dev | |
parent | bd372d2f3fb22c5ffde4360f952e488b0d396c33 (diff) |
Implement wakeup interrupt support. For now this is only implemented for
aplintc(4); other arm64 interrupt controllers will follow.
ok patrick@
Diffstat (limited to 'sys/arch/arm64/dev')
-rw-r--r-- | sys/arch/arm64/dev/aplintc.c | 121 | ||||
-rw-r--r-- | sys/arch/arm64/dev/aplmbox.c | 5 | ||||
-rw-r--r-- | sys/arch/arm64/dev/aplns.c | 4 | ||||
-rw-r--r-- | sys/arch/arm64/dev/aplrtk.c | 4 | ||||
-rw-r--r-- | sys/arch/arm64/dev/aplsmc.c | 4 | ||||
-rw-r--r-- | sys/arch/arm64/dev/rtkit.c | 8 | ||||
-rw-r--r-- | sys/arch/arm64/dev/rtkit.h | 4 |
7 files changed, 101 insertions, 49 deletions
diff --git a/sys/arch/arm64/dev/aplintc.c b/sys/arch/arm64/dev/aplintc.c index 01970a97ce0..43f8254356d 100644 --- a/sys/arch/arm64/dev/aplintc.c +++ b/sys/arch/arm64/dev/aplintc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: aplintc.c,v 1.16 2022/11/08 14:01:13 kettenis Exp $ */ +/* $OpenBSD: aplintc.c,v 1.17 2022/11/09 19:18:11 kettenis Exp $ */ /* * Copyright (c) 2021 Mark Kettenis * @@ -123,13 +123,51 @@ struct aplintc_softc { struct evcount sc_ipi_count; }; +static inline void +aplintc_sw_clr(struct aplintc_softc *sc, int die, int irq) +{ + if (sc->sc_version == 1) + HWRITE4(sc, AIC_SW_CLR(irq), AIC_SW_BIT(irq)); + else + HWRITE4(sc, AIC2_SW_CLR(die, irq), AIC_SW_BIT(irq)); +} + +static inline void +aplintc_sw_set(struct aplintc_softc *sc, int die, int irq) +{ + if (sc->sc_version == 1) + HWRITE4(sc, AIC_SW_SET(irq), AIC_SW_BIT(irq)); + else + HWRITE4(sc, AIC2_SW_SET(die, irq), AIC_SW_BIT(irq)); +} + +static inline void +aplintc_mask_clr(struct aplintc_softc *sc, int die, int irq) +{ + if (sc->sc_version == 1) + HWRITE4(sc, AIC_MASK_CLR(irq), AIC_MASK_BIT(irq)); + else + HWRITE4(sc, AIC2_MASK_CLR(die, irq), AIC_MASK_BIT(irq)); +} + +static inline void +aplintc_mask_set(struct aplintc_softc *sc, int die, int irq) +{ + if (sc->sc_version == 1) + HWRITE4(sc, AIC_MASK_SET(irq), AIC_MASK_BIT(irq)); + else + HWRITE4(sc, AIC2_MASK_SET(die, irq), AIC_MASK_BIT(irq)); +} + struct aplintc_softc *aplintc_sc; int aplintc_match(struct device *, void *, void *); void aplintc_attach(struct device *, struct device *, void *); +int aplintc_activate(struct device *, int act); const struct cfattach aplintc_ca = { - sizeof (struct aplintc_softc), aplintc_match, aplintc_attach + sizeof (struct aplintc_softc), aplintc_match, aplintc_attach, + NULL, aplintc_activate }; struct cfdriver aplintc_cd = { @@ -148,6 +186,7 @@ void aplintc_setipl(int); void *aplintc_intr_establish(void *, int *, int, struct cpu_info *, int (*)(void *), void *, char *); void aplintc_intr_disestablish(void *); +void aplintc_intr_enable_wakeup(void *); void aplintc_send_ipi(struct cpu_info *, int); void aplintc_handle_ipi(struct aplintc_softc *); @@ -241,6 +280,7 @@ aplintc_attach(struct device *parent, struct device *self, void *aux) sc->sc_ic.ic_disestablish = aplintc_intr_disestablish; sc->sc_ic.ic_cpu_enable = aplintc_cpuinit; sc->sc_ic.ic_barrier = aplintc_intr_barrier; + sc->sc_ic.ic_enable_wakeup = aplintc_intr_enable_wakeup; arm_intr_register_fdt(&sc->sc_ic); #ifdef MULTIPROCESSOR @@ -251,6 +291,39 @@ aplintc_attach(struct device *parent, struct device *self, void *aux) HSET4(sc, AIC2_CONFIG, AIC2_CONFIG_ENABLE); } +int +aplintc_activate(struct device *self, int act) +{ + struct aplintc_softc *sc = (struct aplintc_softc *)self; + struct intrhand *ih; + int die, irq; + + switch (act) { + case DVACT_SUSPEND: + for (die = 0; die < sc->sc_ndie; die++) { + for (irq = 0; irq < sc->sc_nirq; irq++) { + ih = sc->sc_irq_handler[die][irq]; + if (ih == NULL || (ih->ih_flags & IPL_WAKEUP)) + continue; + aplintc_mask_set(sc, die, irq); + } + } + break; + case DVACT_RESUME: + for (die = 0; die < sc->sc_ndie; die++) { + for (irq = 0; irq < sc->sc_nirq; irq++) { + ih = sc->sc_irq_handler[die][irq]; + if (ih == NULL || (ih->ih_flags & IPL_WAKEUP)) + continue; + aplintc_mask_clr(sc, die, irq); + } + } + break; + } + + return 0; +} + void aplintc_cpuinit(void) { @@ -276,42 +349,6 @@ aplintc_cpuinit(void) } } -static inline void -aplintc_sw_clr(struct aplintc_softc *sc, int die, int irq) -{ - if (sc->sc_version == 1) - HWRITE4(sc, AIC_SW_CLR(irq), AIC_SW_BIT(irq)); - else - HWRITE4(sc, AIC2_SW_CLR(die, irq), AIC_SW_BIT(irq)); -} - -static inline void -aplintc_sw_set(struct aplintc_softc *sc, int die, int irq) -{ - if (sc->sc_version == 1) - HWRITE4(sc, AIC_SW_SET(irq), AIC_SW_BIT(irq)); - else - HWRITE4(sc, AIC2_SW_SET(die, irq), AIC_SW_BIT(irq)); -} - -static inline void -aplintc_mask_clr(struct aplintc_softc *sc, int die, int irq) -{ - if (sc->sc_version == 1) - HWRITE4(sc, AIC_MASK_CLR(irq), AIC_MASK_BIT(irq)); - else - HWRITE4(sc, AIC2_MASK_CLR(die, irq), AIC_MASK_BIT(irq)); -} - -static inline void -aplintc_mask_set(struct aplintc_softc *sc, int die, int irq) -{ - if (sc->sc_version == 1) - HWRITE4(sc, AIC_MASK_SET(irq), AIC_MASK_BIT(irq)); - else - HWRITE4(sc, AIC2_MASK_SET(die, irq), AIC_MASK_BIT(irq)); -} - void aplintc_run_handler(struct intrhand *ih, void *frame, int s) { @@ -600,6 +637,14 @@ aplintc_intr_disestablish(void *cookie) free(ih, M_DEVBUF, sizeof(*ih)); } +void +aplintc_intr_enable_wakeup(void *cookie) +{ + struct intrhand *ih = cookie; + + ih->ih_flags |= IPL_WAKEUP; +} + #ifdef MULTIPROCESSOR void diff --git a/sys/arch/arm64/dev/aplmbox.c b/sys/arch/arm64/dev/aplmbox.c index 090e6a07acb..9c313af857a 100644 --- a/sys/arch/arm64/dev/aplmbox.c +++ b/sys/arch/arm64/dev/aplmbox.c @@ -1,4 +1,4 @@ -/* $OpenBSD: aplmbox.c,v 1.2 2022/01/04 20:55:48 kettenis Exp $ */ +/* $OpenBSD: aplmbox.c,v 1.3 2022/11/09 19:18:11 kettenis Exp $ */ /* * Copyright (c) 2021 Mark Kettenis <kettenis@openbsd.org> * @@ -147,6 +147,9 @@ aplmbox_channel(void *cookie, uint32_t *cells, struct mbox_client *mc) if (mc) { sc->sc_rx_callback = mc->mc_rx_callback; sc->sc_rx_arg = mc->mc_rx_arg; + + if (mc->mc_flags & MC_WAKEUP) + intr_enable_wakeup(sc->sc_ih); } return sc; diff --git a/sys/arch/arm64/dev/aplns.c b/sys/arch/arm64/dev/aplns.c index f56c40ba077..38ce2246c79 100644 --- a/sys/arch/arm64/dev/aplns.c +++ b/sys/arch/arm64/dev/aplns.c @@ -1,4 +1,4 @@ -/* $OpenBSD: aplns.c,v 1.13 2022/11/09 18:17:00 kettenis Exp $ */ +/* $OpenBSD: aplns.c,v 1.14 2022/11/09 19:18:11 kettenis Exp $ */ /* * Copyright (c) 2014, 2021 David Gwynne <dlg@openbsd.org> * @@ -215,7 +215,7 @@ nvme_ans_attach(struct device *parent, struct device *self, void *aux) asc->asc_rtkit.rk_map = nvme_ans_sart_map; asc->asc_rtkit_state = - rtkit_init(faa->fa_node, NULL, &asc->asc_rtkit); + rtkit_init(faa->fa_node, NULL, 0, &asc->asc_rtkit); if (asc->asc_rtkit_state == NULL) { printf(": can't map mailbox channel\n"); goto disestablish; diff --git a/sys/arch/arm64/dev/aplrtk.c b/sys/arch/arm64/dev/aplrtk.c index 0833b3ffec9..97a95e82f76 100644 --- a/sys/arch/arm64/dev/aplrtk.c +++ b/sys/arch/arm64/dev/aplrtk.c @@ -1,4 +1,4 @@ -/* $OpenBSD: aplrtk.c,v 1.2 2022/09/03 19:05:52 kettenis Exp $ */ +/* $OpenBSD: aplrtk.c,v 1.3 2022/11/09 19:18:11 kettenis Exp $ */ /* * Copyright (c) 2022 Mark Kettenis <kettenis@openbsd.org> * @@ -105,7 +105,7 @@ aplrtk_do_start(struct aplrtk_softc *sc) sc->sc_rtkit.rk_cookie = sc; sc->sc_rtkit.rk_dmat = sc->sc_dmat; - sc->sc_state = rtkit_init(sc->sc_node, NULL, &sc->sc_rtkit); + sc->sc_state = rtkit_init(sc->sc_node, NULL, 0, &sc->sc_rtkit); if (sc->sc_state == NULL) return EIO; diff --git a/sys/arch/arm64/dev/aplsmc.c b/sys/arch/arm64/dev/aplsmc.c index b62448ec447..a210dcbe687 100644 --- a/sys/arch/arm64/dev/aplsmc.c +++ b/sys/arch/arm64/dev/aplsmc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: aplsmc.c,v 1.14 2022/10/12 13:39:50 kettenis Exp $ */ +/* $OpenBSD: aplsmc.c,v 1.15 2022/11/09 19:18:11 kettenis Exp $ */ /* * Copyright (c) 2021 Mark Kettenis <kettenis@openbsd.org> * @@ -212,7 +212,7 @@ aplsmc_attach(struct device *parent, struct device *self, void *aux) return; } - sc->sc_rs = rtkit_init(faa->fa_node, NULL, NULL); + sc->sc_rs = rtkit_init(faa->fa_node, NULL, RK_WAKEUP, NULL); if (sc->sc_rs == NULL) { printf(": can't map mailbox channel\n"); return; diff --git a/sys/arch/arm64/dev/rtkit.c b/sys/arch/arm64/dev/rtkit.c index c3442456e64..ac2d3ae2942 100644 --- a/sys/arch/arm64/dev/rtkit.c +++ b/sys/arch/arm64/dev/rtkit.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rtkit.c,v 1.7 2022/11/09 18:17:00 kettenis Exp $ */ +/* $OpenBSD: rtkit.c,v 1.8 2022/11/09 19:18:11 kettenis Exp $ */ /* * Copyright (c) 2021 Mark Kettenis <kettenis@openbsd.org> * @@ -433,7 +433,7 @@ rtkit_rx_callback(void *cookie) } struct rtkit_state * -rtkit_init(int node, const char *name, struct rtkit *rk) +rtkit_init(int node, const char *name, int flags, struct rtkit *rk) { struct rtkit_state *state; struct mbox_client client; @@ -441,6 +441,9 @@ rtkit_init(int node, const char *name, struct rtkit *rk) state = malloc(sizeof(*state), M_DEVBUF, M_WAITOK | M_ZERO); client.mc_rx_callback = rtkit_rx_callback; client.mc_rx_arg = state; + if (flags & RK_WAKEUP) + client.mc_flags |= MC_WAKEUP; + state->mc = mbox_channel(node, name, &client); if (state->mc == NULL) { free(state, M_DEVBUF, sizeof(*state)); @@ -472,7 +475,6 @@ rtkit_boot(struct rtkit_state *state) return 0; } - void rtkit_shutdown(struct rtkit_state *state) { diff --git a/sys/arch/arm64/dev/rtkit.h b/sys/arch/arm64/dev/rtkit.h index f91e1f9d931..eda7b266894 100644 --- a/sys/arch/arm64/dev/rtkit.h +++ b/sys/arch/arm64/dev/rtkit.h @@ -12,7 +12,9 @@ struct rtkit { int (*rk_map)(void *, bus_addr_t, bus_size_t); }; -struct rtkit_state *rtkit_init(int, const char *, struct rtkit *); +#define RK_WAKEUP 0x00000001 + +struct rtkit_state *rtkit_init(int, const char *, int, struct rtkit *); int rtkit_boot(struct rtkit_state *); void rtkit_shutdown(struct rtkit_state *); int rtkit_set_ap_pwrstate(struct rtkit_state *, uint16_t); |