1*d467fd9eSpatrick /* $OpenBSD: qcsmptp.c,v 1.2 2023/07/04 14:32:21 patrick Exp $ */
20b5b3cbdSpatrick /*
30b5b3cbdSpatrick * Copyright (c) 2023 Patrick Wildt <patrick@blueri.se>
40b5b3cbdSpatrick *
50b5b3cbdSpatrick * Permission to use, copy, modify, and distribute this software for any
60b5b3cbdSpatrick * purpose with or without fee is hereby granted, provided that the above
70b5b3cbdSpatrick * copyright notice and this permission notice appear in all copies.
80b5b3cbdSpatrick *
90b5b3cbdSpatrick * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
100b5b3cbdSpatrick * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
110b5b3cbdSpatrick * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
120b5b3cbdSpatrick * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
130b5b3cbdSpatrick * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
140b5b3cbdSpatrick * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
150b5b3cbdSpatrick * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
160b5b3cbdSpatrick */
170b5b3cbdSpatrick
180b5b3cbdSpatrick #include <sys/param.h>
190b5b3cbdSpatrick #include <sys/systm.h>
200b5b3cbdSpatrick #include <sys/device.h>
210b5b3cbdSpatrick #include <sys/malloc.h>
220b5b3cbdSpatrick #include <sys/atomic.h>
230b5b3cbdSpatrick
240b5b3cbdSpatrick #include <machine/bus.h>
250b5b3cbdSpatrick #include <machine/fdt.h>
260b5b3cbdSpatrick
270b5b3cbdSpatrick #include <dev/ofw/openfirm.h>
280b5b3cbdSpatrick #include <dev/ofw/ofw_misc.h>
290b5b3cbdSpatrick #include <dev/ofw/fdt.h>
300b5b3cbdSpatrick
310b5b3cbdSpatrick #define SMP2P_MAX_ENTRY 16
320b5b3cbdSpatrick #define SMP2P_MAX_ENTRY_NAME 16
330b5b3cbdSpatrick
340b5b3cbdSpatrick struct qcsmptp_smem_item {
350b5b3cbdSpatrick uint32_t magic;
360b5b3cbdSpatrick #define SMP2P_MAGIC 0x504d5324
370b5b3cbdSpatrick uint8_t version;
380b5b3cbdSpatrick #define SMP2P_VERSION 1
390b5b3cbdSpatrick unsigned features:24;
400b5b3cbdSpatrick #define SMP2P_FEATURE_SSR_ACK (1 << 0)
410b5b3cbdSpatrick uint16_t local_pid;
420b5b3cbdSpatrick uint16_t remote_pid;
430b5b3cbdSpatrick uint16_t total_entries;
440b5b3cbdSpatrick uint16_t valid_entries;
450b5b3cbdSpatrick uint32_t flags;
460b5b3cbdSpatrick #define SMP2P_FLAGS_RESTART_DONE (1 << 0)
470b5b3cbdSpatrick #define SMP2P_FLAGS_RESTART_ACK (1 << 1)
480b5b3cbdSpatrick
490b5b3cbdSpatrick struct {
500b5b3cbdSpatrick uint8_t name[SMP2P_MAX_ENTRY_NAME];
510b5b3cbdSpatrick uint32_t value;
520b5b3cbdSpatrick } entries[SMP2P_MAX_ENTRY];
530b5b3cbdSpatrick } __packed;
540b5b3cbdSpatrick
550b5b3cbdSpatrick struct qcsmptp_intrhand {
560b5b3cbdSpatrick TAILQ_ENTRY(qcsmptp_intrhand) ih_q;
570b5b3cbdSpatrick int (*ih_func)(void *);
580b5b3cbdSpatrick void *ih_arg;
590b5b3cbdSpatrick void *ih_ic;
600b5b3cbdSpatrick int ih_pin;
610b5b3cbdSpatrick int ih_enabled;
620b5b3cbdSpatrick };
630b5b3cbdSpatrick
640b5b3cbdSpatrick struct qcsmptp_interrupt_controller {
650b5b3cbdSpatrick TAILQ_HEAD(,qcsmptp_intrhand) ic_intrq;
660b5b3cbdSpatrick struct qcsmptp_softc *ic_sc;
670b5b3cbdSpatrick struct interrupt_controller ic_ic;
680b5b3cbdSpatrick };
690b5b3cbdSpatrick
700b5b3cbdSpatrick struct qcsmptp_entry {
710b5b3cbdSpatrick TAILQ_ENTRY(qcsmptp_entry) e_q;
720b5b3cbdSpatrick char *e_name;
730b5b3cbdSpatrick int e_namelen;
740b5b3cbdSpatrick uint32_t *e_value;
750b5b3cbdSpatrick uint32_t e_last_value;
760b5b3cbdSpatrick struct qcsmptp_interrupt_controller *e_ic;
770b5b3cbdSpatrick };
780b5b3cbdSpatrick
790b5b3cbdSpatrick struct qcsmptp_softc {
800b5b3cbdSpatrick struct device sc_dev;
810b5b3cbdSpatrick int sc_node;
820b5b3cbdSpatrick void *sc_ih;
830b5b3cbdSpatrick
840b5b3cbdSpatrick uint16_t sc_local_pid;
850b5b3cbdSpatrick uint16_t sc_remote_pid;
860b5b3cbdSpatrick uint32_t sc_smem_id[2];
870b5b3cbdSpatrick
880b5b3cbdSpatrick struct qcsmptp_smem_item *sc_in;
890b5b3cbdSpatrick struct qcsmptp_smem_item *sc_out;
900b5b3cbdSpatrick
910b5b3cbdSpatrick TAILQ_HEAD(,qcsmptp_entry) sc_inboundq;
920b5b3cbdSpatrick TAILQ_HEAD(,qcsmptp_entry) sc_outboundq;
930b5b3cbdSpatrick
940b5b3cbdSpatrick int sc_negotiated;
950b5b3cbdSpatrick int sc_ssr_ack_enabled;
960b5b3cbdSpatrick int sc_ssr_ack;
970b5b3cbdSpatrick
980b5b3cbdSpatrick uint16_t sc_valid_entries;
990b5b3cbdSpatrick
1000b5b3cbdSpatrick struct mbox_channel *sc_mc;
1010b5b3cbdSpatrick };
1020b5b3cbdSpatrick
1030b5b3cbdSpatrick int qcsmptp_match(struct device *, void *, void *);
1040b5b3cbdSpatrick void qcsmptp_attach(struct device *, struct device *, void *);
1050b5b3cbdSpatrick void qcsmptp_deferred(struct device *);
1060b5b3cbdSpatrick
1070b5b3cbdSpatrick const struct cfattach qcsmptp_ca = {
1080b5b3cbdSpatrick sizeof (struct qcsmptp_softc), qcsmptp_match, qcsmptp_attach
1090b5b3cbdSpatrick };
1100b5b3cbdSpatrick
1110b5b3cbdSpatrick struct cfdriver qcsmptp_cd = {
1120b5b3cbdSpatrick NULL, "qcsmptp", DV_DULL
1130b5b3cbdSpatrick };
1140b5b3cbdSpatrick
1150b5b3cbdSpatrick int qcsmptp_intr(void *);
1160b5b3cbdSpatrick void *qcsmptp_intr_establish(void *, int *, int, struct cpu_info *,
1170b5b3cbdSpatrick int (*)(void *), void *, char *);
1180b5b3cbdSpatrick void qcsmptp_intr_disestablish(void *);
1190b5b3cbdSpatrick void qcsmptp_intr_enable(void *);
1200b5b3cbdSpatrick void qcsmptp_intr_disable(void *);
1210b5b3cbdSpatrick void qcsmptp_intr_barrier(void *);
1220b5b3cbdSpatrick
1230b5b3cbdSpatrick extern int qcsmem_alloc(int, int, int);
1240b5b3cbdSpatrick extern void *qcsmem_get(int, int, int *);
1250b5b3cbdSpatrick
1260b5b3cbdSpatrick int
qcsmptp_match(struct device * parent,void * match,void * aux)1270b5b3cbdSpatrick qcsmptp_match(struct device *parent, void *match, void *aux)
1280b5b3cbdSpatrick {
1290b5b3cbdSpatrick struct fdt_attach_args *faa = aux;
1300b5b3cbdSpatrick
1310b5b3cbdSpatrick return OF_is_compatible(faa->fa_node, "qcom,smp2p");
1320b5b3cbdSpatrick }
1330b5b3cbdSpatrick
1340b5b3cbdSpatrick void
qcsmptp_attach(struct device * parent,struct device * self,void * aux)1350b5b3cbdSpatrick qcsmptp_attach(struct device *parent, struct device *self, void *aux)
1360b5b3cbdSpatrick {
1370b5b3cbdSpatrick struct qcsmptp_softc *sc = (struct qcsmptp_softc *)self;
1380b5b3cbdSpatrick struct fdt_attach_args *faa = aux;
1390b5b3cbdSpatrick
1400b5b3cbdSpatrick sc->sc_node = faa->fa_node;
1410b5b3cbdSpatrick
1420b5b3cbdSpatrick TAILQ_INIT(&sc->sc_inboundq);
1430b5b3cbdSpatrick TAILQ_INIT(&sc->sc_outboundq);
1440b5b3cbdSpatrick
1450b5b3cbdSpatrick sc->sc_ih = fdt_intr_establish(faa->fa_node, IPL_BIO,
1460b5b3cbdSpatrick qcsmptp_intr, sc, sc->sc_dev.dv_xname);
1470b5b3cbdSpatrick if (sc->sc_ih == NULL) {
1480b5b3cbdSpatrick printf(": can't establish interrupt\n");
1490b5b3cbdSpatrick return;
1500b5b3cbdSpatrick }
1510b5b3cbdSpatrick
1520b5b3cbdSpatrick sc->sc_local_pid = OF_getpropint(faa->fa_node,
1530b5b3cbdSpatrick "qcom,local-pid", 0xffff);
1540b5b3cbdSpatrick sc->sc_remote_pid = OF_getpropint(faa->fa_node,
1550b5b3cbdSpatrick "qcom,remote-pid", 0xffff);
1560b5b3cbdSpatrick if (sc->sc_local_pid == 0xffff || sc->sc_remote_pid == 0xffff) {
1570b5b3cbdSpatrick printf(": can't get pids\n");
1580b5b3cbdSpatrick return;
1590b5b3cbdSpatrick }
1600b5b3cbdSpatrick
1610b5b3cbdSpatrick if (OF_getpropintarray(faa->fa_node, "qcom,smem", sc->sc_smem_id,
1620b5b3cbdSpatrick sizeof(sc->sc_smem_id)) != sizeof(sc->sc_smem_id)) {
1630b5b3cbdSpatrick printf(": can't get smem property \n");
1640b5b3cbdSpatrick return;
1650b5b3cbdSpatrick }
1660b5b3cbdSpatrick
1670b5b3cbdSpatrick printf("\n");
1680b5b3cbdSpatrick
1690b5b3cbdSpatrick config_defer(self, qcsmptp_deferred);
1700b5b3cbdSpatrick }
1710b5b3cbdSpatrick
1720b5b3cbdSpatrick void
qcsmptp_deferred(struct device * self)1730b5b3cbdSpatrick qcsmptp_deferred(struct device *self)
1740b5b3cbdSpatrick {
1750b5b3cbdSpatrick struct qcsmptp_softc *sc = (struct qcsmptp_softc *)self;
1760b5b3cbdSpatrick struct qcsmptp_entry *e;
1770b5b3cbdSpatrick int node, size;
1780b5b3cbdSpatrick
1790b5b3cbdSpatrick sc->sc_mc = mbox_channel_idx(sc->sc_node, 0, NULL);
1800b5b3cbdSpatrick if (sc->sc_mc == NULL) {
1810b5b3cbdSpatrick printf(": can't get mailbox\n");
1820b5b3cbdSpatrick return;
1830b5b3cbdSpatrick }
1840b5b3cbdSpatrick
185*d467fd9eSpatrick if (qcsmem_alloc(sc->sc_remote_pid, sc->sc_smem_id[0],
186*d467fd9eSpatrick sizeof(*sc->sc_in)) != 0) {
187*d467fd9eSpatrick printf(": can't alloc smp2p item\n");
188*d467fd9eSpatrick return;
189*d467fd9eSpatrick }
190*d467fd9eSpatrick
191*d467fd9eSpatrick sc->sc_in = qcsmem_get(sc->sc_remote_pid, sc->sc_smem_id[0], NULL);
192*d467fd9eSpatrick if (sc->sc_in == NULL) {
193*d467fd9eSpatrick printf(": can't get smp2p item\n");
194*d467fd9eSpatrick return;
195*d467fd9eSpatrick }
196*d467fd9eSpatrick
1970b5b3cbdSpatrick if (qcsmem_alloc(sc->sc_remote_pid, sc->sc_smem_id[1],
1980b5b3cbdSpatrick sizeof(*sc->sc_out)) != 0) {
1990b5b3cbdSpatrick printf(": can't alloc smp2p item\n");
2000b5b3cbdSpatrick return;
2010b5b3cbdSpatrick }
2020b5b3cbdSpatrick
2030b5b3cbdSpatrick sc->sc_out = qcsmem_get(sc->sc_remote_pid, sc->sc_smem_id[1], NULL);
2040b5b3cbdSpatrick if (sc->sc_out == NULL) {
2050b5b3cbdSpatrick printf(": can't get smp2p item\n");
2060b5b3cbdSpatrick return;
2070b5b3cbdSpatrick }
2080b5b3cbdSpatrick
2090b5b3cbdSpatrick memset(sc->sc_out, 0, sizeof(*sc->sc_out));
2100b5b3cbdSpatrick sc->sc_out->magic = SMP2P_MAGIC;
2110b5b3cbdSpatrick sc->sc_out->local_pid = sc->sc_local_pid;
2120b5b3cbdSpatrick sc->sc_out->remote_pid = sc->sc_remote_pid;
2130b5b3cbdSpatrick sc->sc_out->total_entries = SMP2P_MAX_ENTRY;
2140b5b3cbdSpatrick sc->sc_out->features = SMP2P_FEATURE_SSR_ACK;
2150b5b3cbdSpatrick membar_sync();
2160b5b3cbdSpatrick sc->sc_out->version = SMP2P_VERSION;
2170b5b3cbdSpatrick mbox_send(sc->sc_mc, NULL, 0);
2180b5b3cbdSpatrick
2190b5b3cbdSpatrick for (node = OF_child(sc->sc_node); node; node = OF_peer(node)) {
2200b5b3cbdSpatrick size = OF_getproplen(node, "qcom,entry-name");
2210b5b3cbdSpatrick if (size <= 0)
2220b5b3cbdSpatrick continue;
2230b5b3cbdSpatrick e = malloc(sizeof(*e), M_DEVBUF, M_WAITOK | M_ZERO);
2240b5b3cbdSpatrick e->e_namelen = size;
2250b5b3cbdSpatrick e->e_name = malloc(e->e_namelen, M_DEVBUF, M_WAITOK);
2260b5b3cbdSpatrick OF_getprop(node, "qcom,entry-name", e->e_name,
2270b5b3cbdSpatrick e->e_namelen);
2280b5b3cbdSpatrick e->e_name[e->e_namelen - 1] = '\0';
2290b5b3cbdSpatrick
2300b5b3cbdSpatrick if (OF_getproplen(node, "interrupt-controller") == 0) {
2310b5b3cbdSpatrick struct qcsmptp_interrupt_controller *ic;
2320b5b3cbdSpatrick ic = malloc(sizeof(*ic), M_DEVBUF, M_WAITOK | M_ZERO);
2330b5b3cbdSpatrick TAILQ_INIT(&ic->ic_intrq);
2340b5b3cbdSpatrick ic->ic_sc = sc;
2350b5b3cbdSpatrick ic->ic_ic.ic_node = node;
2360b5b3cbdSpatrick ic->ic_ic.ic_cookie = ic;
2370b5b3cbdSpatrick ic->ic_ic.ic_establish = qcsmptp_intr_establish;
2380b5b3cbdSpatrick ic->ic_ic.ic_disestablish = qcsmptp_intr_disestablish;
2390b5b3cbdSpatrick ic->ic_ic.ic_enable = qcsmptp_intr_enable;
2400b5b3cbdSpatrick ic->ic_ic.ic_disable = qcsmptp_intr_disable;
2410b5b3cbdSpatrick ic->ic_ic.ic_barrier = qcsmptp_intr_barrier;
2420b5b3cbdSpatrick fdt_intr_register(&ic->ic_ic);
2430b5b3cbdSpatrick e->e_ic = ic;
2440b5b3cbdSpatrick TAILQ_INSERT_TAIL(&sc->sc_inboundq, e, e_q);
2450b5b3cbdSpatrick } else {
2460b5b3cbdSpatrick if (sc->sc_out->valid_entries >= SMP2P_MAX_ENTRY)
2470b5b3cbdSpatrick continue;
2480b5b3cbdSpatrick
2490b5b3cbdSpatrick strlcpy(sc->sc_out->entries[sc->sc_out->valid_entries].name,
2500b5b3cbdSpatrick e->e_name, SMP2P_MAX_ENTRY_NAME);
2510b5b3cbdSpatrick e->e_value = &sc->sc_out->entries[sc->sc_out->valid_entries].value;
2520b5b3cbdSpatrick sc->sc_out->valid_entries++;
2530b5b3cbdSpatrick TAILQ_INSERT_TAIL(&sc->sc_outboundq, e, e_q);
2540b5b3cbdSpatrick
2550b5b3cbdSpatrick /* TODO: provide as smem state */
2560b5b3cbdSpatrick }
2570b5b3cbdSpatrick }
2580b5b3cbdSpatrick }
2590b5b3cbdSpatrick
2600b5b3cbdSpatrick int
qcsmptp_intr(void * arg)2610b5b3cbdSpatrick qcsmptp_intr(void *arg)
2620b5b3cbdSpatrick {
2630b5b3cbdSpatrick struct qcsmptp_softc *sc = arg;
2640b5b3cbdSpatrick struct qcsmptp_entry *e;
2650b5b3cbdSpatrick struct qcsmptp_intrhand *ih;
2660b5b3cbdSpatrick uint32_t changed, val;
2670b5b3cbdSpatrick int do_ack = 0, i;
2680b5b3cbdSpatrick
2690b5b3cbdSpatrick /* Do initial feature negotiation if inbound is new. */
2700b5b3cbdSpatrick if (!sc->sc_negotiated) {
2710b5b3cbdSpatrick if (sc->sc_in->version != sc->sc_out->version)
2720b5b3cbdSpatrick return 1;
2730b5b3cbdSpatrick sc->sc_out->features &= sc->sc_in->features;
2740b5b3cbdSpatrick if (sc->sc_out->features & SMP2P_FEATURE_SSR_ACK)
2750b5b3cbdSpatrick sc->sc_ssr_ack_enabled = 1;
2760b5b3cbdSpatrick sc->sc_negotiated = 1;
2770b5b3cbdSpatrick }
2780b5b3cbdSpatrick if (!sc->sc_negotiated)
2790b5b3cbdSpatrick return 1;
2800b5b3cbdSpatrick
2810b5b3cbdSpatrick /* Use ACK mechanism if negotiated. */
2820b5b3cbdSpatrick if (sc->sc_ssr_ack_enabled &&
2830b5b3cbdSpatrick !!(sc->sc_in->flags & SMP2P_FLAGS_RESTART_DONE) != sc->sc_ssr_ack)
2840b5b3cbdSpatrick do_ack = 1;
2850b5b3cbdSpatrick
2860b5b3cbdSpatrick /* Catch up on new inbound entries that got added in the meantime. */
2870b5b3cbdSpatrick for (i = sc->sc_valid_entries; i < sc->sc_in->valid_entries; i++) {
2880b5b3cbdSpatrick TAILQ_FOREACH(e, &sc->sc_inboundq, e_q) {
2890b5b3cbdSpatrick if (strncmp(sc->sc_in->entries[i].name, e->e_name,
2900b5b3cbdSpatrick SMP2P_MAX_ENTRY_NAME) != 0)
2910b5b3cbdSpatrick continue;
2920b5b3cbdSpatrick e->e_value = &sc->sc_in->entries[i].value;
2930b5b3cbdSpatrick }
2940b5b3cbdSpatrick }
2950b5b3cbdSpatrick sc->sc_valid_entries = i;
2960b5b3cbdSpatrick
2970b5b3cbdSpatrick /* For each inbound "interrupt controller". */
2980b5b3cbdSpatrick TAILQ_FOREACH(e, &sc->sc_inboundq, e_q) {
2990b5b3cbdSpatrick if (e->e_value == NULL)
3000b5b3cbdSpatrick continue;
3010b5b3cbdSpatrick val = *e->e_value;
3020b5b3cbdSpatrick if (val == e->e_last_value)
3030b5b3cbdSpatrick continue;
3040b5b3cbdSpatrick changed = val ^ e->e_last_value;
3050b5b3cbdSpatrick e->e_last_value = val;
3060b5b3cbdSpatrick TAILQ_FOREACH(ih, &e->e_ic->ic_intrq, ih_q) {
3070b5b3cbdSpatrick if (!ih->ih_enabled)
3080b5b3cbdSpatrick continue;
3090b5b3cbdSpatrick if ((changed & (1 << ih->ih_pin)) == 0)
3100b5b3cbdSpatrick continue;
3110b5b3cbdSpatrick ih->ih_func(ih->ih_arg);
3120b5b3cbdSpatrick }
3130b5b3cbdSpatrick }
3140b5b3cbdSpatrick
3150b5b3cbdSpatrick if (do_ack) {
3160b5b3cbdSpatrick sc->sc_ssr_ack = !sc->sc_ssr_ack;
3170b5b3cbdSpatrick if (sc->sc_ssr_ack)
3180b5b3cbdSpatrick sc->sc_out->flags |= SMP2P_FLAGS_RESTART_ACK;
3190b5b3cbdSpatrick else
3200b5b3cbdSpatrick sc->sc_out->flags &= ~SMP2P_FLAGS_RESTART_ACK;
3210b5b3cbdSpatrick membar_sync();
3220b5b3cbdSpatrick mbox_send(sc->sc_mc, NULL, 0);
3230b5b3cbdSpatrick }
3240b5b3cbdSpatrick
3250b5b3cbdSpatrick return 1;
3260b5b3cbdSpatrick }
3270b5b3cbdSpatrick
3280b5b3cbdSpatrick void *
qcsmptp_intr_establish(void * cookie,int * cells,int ipl,struct cpu_info * ci,int (* func)(void *),void * arg,char * name)3290b5b3cbdSpatrick qcsmptp_intr_establish(void *cookie, int *cells, int ipl,
3300b5b3cbdSpatrick struct cpu_info *ci, int (*func)(void *), void *arg, char *name)
3310b5b3cbdSpatrick {
3320b5b3cbdSpatrick struct qcsmptp_interrupt_controller *ic = cookie;
3330b5b3cbdSpatrick struct qcsmptp_softc *sc = ic->ic_sc;
3340b5b3cbdSpatrick struct qcsmptp_intrhand *ih;
3350b5b3cbdSpatrick
3360b5b3cbdSpatrick ih = malloc(sizeof(*ih), M_DEVBUF, M_WAITOK | M_ZERO);
3370b5b3cbdSpatrick ih->ih_func = func;
3380b5b3cbdSpatrick ih->ih_arg = arg;
3390b5b3cbdSpatrick ih->ih_ic = ic;
3400b5b3cbdSpatrick ih->ih_pin = cells[0];
3410b5b3cbdSpatrick TAILQ_INSERT_TAIL(&ic->ic_intrq, ih, ih_q);
3420b5b3cbdSpatrick
3430b5b3cbdSpatrick qcsmptp_intr_enable(ih);
3440b5b3cbdSpatrick
3450b5b3cbdSpatrick if (ipl & IPL_WAKEUP)
3460b5b3cbdSpatrick intr_set_wakeup(sc->sc_ih);
3470b5b3cbdSpatrick
3480b5b3cbdSpatrick return ih;
3490b5b3cbdSpatrick }
3500b5b3cbdSpatrick
3510b5b3cbdSpatrick void
qcsmptp_intr_disestablish(void * cookie)3520b5b3cbdSpatrick qcsmptp_intr_disestablish(void *cookie)
3530b5b3cbdSpatrick {
3540b5b3cbdSpatrick struct qcsmptp_intrhand *ih = cookie;
3550b5b3cbdSpatrick struct qcsmptp_interrupt_controller *ic = ih->ih_ic;
3560b5b3cbdSpatrick
3570b5b3cbdSpatrick qcsmptp_intr_disable(ih);
3580b5b3cbdSpatrick
3590b5b3cbdSpatrick TAILQ_REMOVE(&ic->ic_intrq, ih, ih_q);
3600b5b3cbdSpatrick free(ih, M_DEVBUF, sizeof(*ih));
3610b5b3cbdSpatrick }
3620b5b3cbdSpatrick
3630b5b3cbdSpatrick void
qcsmptp_intr_enable(void * cookie)3640b5b3cbdSpatrick qcsmptp_intr_enable(void *cookie)
3650b5b3cbdSpatrick {
3660b5b3cbdSpatrick struct qcsmptp_intrhand *ih = cookie;
3670b5b3cbdSpatrick
3680b5b3cbdSpatrick ih->ih_enabled = 1;
3690b5b3cbdSpatrick }
3700b5b3cbdSpatrick
3710b5b3cbdSpatrick void
qcsmptp_intr_disable(void * cookie)3720b5b3cbdSpatrick qcsmptp_intr_disable(void *cookie)
3730b5b3cbdSpatrick {
3740b5b3cbdSpatrick struct qcsmptp_intrhand *ih = cookie;
3750b5b3cbdSpatrick
3760b5b3cbdSpatrick ih->ih_enabled = 0;
3770b5b3cbdSpatrick }
3780b5b3cbdSpatrick
3790b5b3cbdSpatrick void
qcsmptp_intr_barrier(void * cookie)3800b5b3cbdSpatrick qcsmptp_intr_barrier(void *cookie)
3810b5b3cbdSpatrick {
3820b5b3cbdSpatrick struct qcsmptp_intrhand *ih = cookie;
3830b5b3cbdSpatrick struct qcsmptp_interrupt_controller *ic = ih->ih_ic;
3840b5b3cbdSpatrick struct qcsmptp_softc *sc = ic->ic_sc;
3850b5b3cbdSpatrick
3860b5b3cbdSpatrick intr_barrier(sc->sc_ih);
3870b5b3cbdSpatrick }
388