summaryrefslogtreecommitdiff
path: root/sys/arch/arm64/dev
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2022-11-09 19:18:12 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2022-11-09 19:18:12 +0000
commit500070ba952da06307f0478e23f6516993226ea6 (patch)
tree53acb6ffc44b52199ad1f6d2033ad48b1de2a6dd /sys/arch/arm64/dev
parentbd372d2f3fb22c5ffde4360f952e488b0d396c33 (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.c121
-rw-r--r--sys/arch/arm64/dev/aplmbox.c5
-rw-r--r--sys/arch/arm64/dev/aplns.c4
-rw-r--r--sys/arch/arm64/dev/aplrtk.c4
-rw-r--r--sys/arch/arm64/dev/aplsmc.c4
-rw-r--r--sys/arch/arm64/dev/rtkit.c8
-rw-r--r--sys/arch/arm64/dev/rtkit.h4
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);