1*3bf60960Sjsg /* $OpenBSD: intr.h,v 1.8 2024/10/16 02:32:27 jsg Exp $ */ 2380aa7b9Sjsg 3baed8f06Sdrahn /* 4baed8f06Sdrahn * Copyright (c) 2001-2004 Opsycon AB (www.opsycon.se / www.opsycon.com) 5baed8f06Sdrahn * 6baed8f06Sdrahn * Redistribution and use in source and binary forms, with or without 7baed8f06Sdrahn * modification, are permitted provided that the following conditions 8baed8f06Sdrahn * are met: 9baed8f06Sdrahn * 1. Redistributions of source code must retain the above copyright 10baed8f06Sdrahn * notice, this list of conditions and the following disclaimer. 11baed8f06Sdrahn * 2. Redistributions in binary form must reproduce the above copyright 12baed8f06Sdrahn * notice, this list of conditions and the following disclaimer in the 13baed8f06Sdrahn * documentation and/or other materials provided with the distribution. 14baed8f06Sdrahn * 15baed8f06Sdrahn * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 16baed8f06Sdrahn * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17baed8f06Sdrahn * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18baed8f06Sdrahn * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 19baed8f06Sdrahn * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20baed8f06Sdrahn * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21baed8f06Sdrahn * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22baed8f06Sdrahn * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23baed8f06Sdrahn * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24baed8f06Sdrahn * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25baed8f06Sdrahn * SUCH DAMAGE. 26baed8f06Sdrahn * 27baed8f06Sdrahn */ 28baed8f06Sdrahn 29baed8f06Sdrahn #ifndef _MACHINE_INTR_H_ 30baed8f06Sdrahn #define _MACHINE_INTR_H_ 31baed8f06Sdrahn 32baed8f06Sdrahn /* 33baed8f06Sdrahn * The interrupt level ipl is a logical level; per-platform interrupt 34baed8f06Sdrahn * code will turn it into the appropriate hardware interrupt masks 35baed8f06Sdrahn * values. 36baed8f06Sdrahn * 37baed8f06Sdrahn * Interrupt sources on the CPU are kept enabled regardless of the 38baed8f06Sdrahn * current ipl value; individual hardware sources interrupting while 39baed8f06Sdrahn * logically masked are masked on the fly, remembered as pending, and 40baed8f06Sdrahn * unmasked at the first splx() opportunity. 41baed8f06Sdrahn */ 42baed8f06Sdrahn #ifdef _KERNEL 43baed8f06Sdrahn 44baed8f06Sdrahn /* Interrupt priority `levels'; not mutually exclusive. */ 45baed8f06Sdrahn #define IPL_NONE 0 /* nothing */ 46baed8f06Sdrahn #define IPL_SOFT 1 /* soft interrupts */ 47baed8f06Sdrahn #define IPL_SOFTCLOCK 2 /* soft clock interrupts */ 48baed8f06Sdrahn #define IPL_SOFTNET 3 /* soft network interrupts */ 49baed8f06Sdrahn #define IPL_SOFTTTY 4 /* soft terminal interrupts */ 50baed8f06Sdrahn #define IPL_BIO 5 /* block I/O */ 51baed8f06Sdrahn #define IPL_NET 6 /* network */ 52baed8f06Sdrahn #define IPL_TTY 7 /* terminal */ 53baed8f06Sdrahn #define IPL_VM 8 /* memory allocation */ 54baed8f06Sdrahn #define IPL_AUDIO 9 /* audio */ 55baed8f06Sdrahn #define IPL_CLOCK 10 /* clock */ 56baed8f06Sdrahn #define IPL_SCHED IPL_CLOCK 57baed8f06Sdrahn #define IPL_STATCLOCK IPL_CLOCK 58baed8f06Sdrahn #define IPL_HIGH 11 /* everything */ 59baed8f06Sdrahn #define IPL_IPI 12 /* interprocessor interrupt */ 60baed8f06Sdrahn #define NIPL 13 /* number of levels */ 61baed8f06Sdrahn 62baed8f06Sdrahn #define IPL_MPFLOOR IPL_TTY 63baed8f06Sdrahn /* Interrupt priority 'flags'. */ 64baed8f06Sdrahn #define IPL_IRQMASK 0xf /* priority only */ 65baed8f06Sdrahn #define IPL_FLAGMASK 0xf00 /* flags only*/ 66baed8f06Sdrahn #define IPL_MPSAFE 0x100 /* 'mpsafe' interrupt, no kernel lock */ 67baed8f06Sdrahn 68baed8f06Sdrahn /* Interrupt sharing types. */ 69baed8f06Sdrahn #define IST_NONE 0 /* none */ 70baed8f06Sdrahn #define IST_PULSE 1 /* pulsed */ 71baed8f06Sdrahn #define IST_EDGE 2 /* edge-triggered */ 72baed8f06Sdrahn #define IST_LEVEL 3 /* level-triggered */ 73baed8f06Sdrahn 74baed8f06Sdrahn #define IST_LEVEL_LOW IST_LEVEL 75baed8f06Sdrahn #define IST_LEVEL_HIGH 4 76baed8f06Sdrahn #define IST_EDGE_FALLING IST_EDGE 77baed8f06Sdrahn #define IST_EDGE_RISING 5 78baed8f06Sdrahn #define IST_EDGE_BOTH 6 79baed8f06Sdrahn 80baed8f06Sdrahn /* RISCV interrupt mcause, from freebsd */ 81baed8f06Sdrahn #define RISCV_NIRQ 1024 82baed8f06Sdrahn 83baed8f06Sdrahn #ifndef NIRQ 84baed8f06Sdrahn #define NIRQ RISCV_NIRQ 85baed8f06Sdrahn #endif 86baed8f06Sdrahn 87baed8f06Sdrahn enum { 88baed8f06Sdrahn IRQ_SOFTWARE_USER, 89baed8f06Sdrahn IRQ_SOFTWARE_SUPERVISOR, 90baed8f06Sdrahn IRQ_SOFTWARE_HYPERVISOR, 91baed8f06Sdrahn IRQ_SOFTWARE_MACHINE, 92baed8f06Sdrahn IRQ_TIMER_USER, 93baed8f06Sdrahn IRQ_TIMER_SUPERVISOR, 94baed8f06Sdrahn IRQ_TIMER_HYPERVISOR, 95baed8f06Sdrahn IRQ_TIMER_MACHINE, 96baed8f06Sdrahn IRQ_EXTERNAL_USER, 97baed8f06Sdrahn IRQ_EXTERNAL_SUPERVISOR, 98baed8f06Sdrahn IRQ_EXTERNAL_HYPERVISOR, 99baed8f06Sdrahn IRQ_EXTERNAL_MACHINE, 100baed8f06Sdrahn INTC_NIRQS 101baed8f06Sdrahn }; 102baed8f06Sdrahn 103baed8f06Sdrahn #ifndef _LOCORE 104baed8f06Sdrahn #include <sys/queue.h> 105baed8f06Sdrahn 106baed8f06Sdrahn int splraise(int); 107baed8f06Sdrahn int spllower(int); 108baed8f06Sdrahn void splx(int); 109baed8f06Sdrahn 110baed8f06Sdrahn void riscv_cpu_intr(void *); 111baed8f06Sdrahn void riscv_do_pending_intr(int); 112baed8f06Sdrahn void riscv_set_intr_func(int (*raise)(int), int (*lower)(int), 113baed8f06Sdrahn void (*x)(int), void (*setipl)(int)); 114baed8f06Sdrahn void riscv_set_intr_handler(void (*intr_handle)(void *)); 115baed8f06Sdrahn 1161378d87cSkettenis struct machine_intr_handle { 1171378d87cSkettenis struct interrupt_controller *ih_ic; 1181378d87cSkettenis void *ih_ih; 1191378d87cSkettenis }; 1201378d87cSkettenis 121baed8f06Sdrahn struct riscv_intr_func { 122baed8f06Sdrahn int (*raise)(int); 123baed8f06Sdrahn int (*lower)(int); 124baed8f06Sdrahn void (*x)(int); 125baed8f06Sdrahn void (*setipl)(int); 126baed8f06Sdrahn }; 127baed8f06Sdrahn 128baed8f06Sdrahn extern struct riscv_intr_func riscv_intr_func; 129baed8f06Sdrahn 130baed8f06Sdrahn #define splraise(cpl) (riscv_intr_func.raise(cpl)) 131baed8f06Sdrahn #define _splraise(cpl) (riscv_intr_func.raise(cpl)) 132baed8f06Sdrahn #define spllower(cpl) (riscv_intr_func.lower(cpl)) 133baed8f06Sdrahn #define splx(cpl) (riscv_intr_func.x(cpl)) 134baed8f06Sdrahn 135baed8f06Sdrahn #define splsoft() splraise(IPL_SOFT) 136baed8f06Sdrahn #define splsoftclock() splraise(IPL_SOFTCLOCK) 137baed8f06Sdrahn #define splsoftnet() splraise(IPL_SOFTNET) 138baed8f06Sdrahn #define splsofttty() splraise(IPL_SOFTTTY) 139baed8f06Sdrahn #define splbio() splraise(IPL_BIO) 140baed8f06Sdrahn #define splnet() splraise(IPL_NET) 141baed8f06Sdrahn #define spltty() splraise(IPL_TTY) 142baed8f06Sdrahn #define splvm() splraise(IPL_VM) 143baed8f06Sdrahn #define splaudio() splraise(IPL_AUDIO) 144baed8f06Sdrahn #define splclock() splraise(IPL_CLOCK) 145baed8f06Sdrahn #define splsched() splraise(IPL_SCHED) 146baed8f06Sdrahn #define splstatclock() splraise(IPL_STATCLOCK) 147baed8f06Sdrahn #define splhigh() splraise(IPL_HIGH) 148baed8f06Sdrahn 149baed8f06Sdrahn #define spl0() spllower(IPL_NONE) 150baed8f06Sdrahn 151baed8f06Sdrahn void intr_barrier(void *); 152baed8f06Sdrahn 153baed8f06Sdrahn void riscv_init_smask(void); /* XXX */ 154baed8f06Sdrahn extern uint32_t riscv_smask[NIPL]; 155baed8f06Sdrahn 156baed8f06Sdrahn #include <machine/softintr.h> 157baed8f06Sdrahn 158baed8f06Sdrahn void riscv_clock_register(void (*)(void), void (*)(u_int), void (*)(int), 159baed8f06Sdrahn void (*)(void)); 160baed8f06Sdrahn 161baed8f06Sdrahn /* 162baed8f06Sdrahn **** interrupt controller structure and routines **** 163baed8f06Sdrahn */ 164baed8f06Sdrahn struct cpu_info; 165baed8f06Sdrahn struct interrupt_controller { 166baed8f06Sdrahn int ic_node; 167baed8f06Sdrahn void *ic_cookie; 1681378d87cSkettenis void *(*ic_establish)(void *, int *, int, struct cpu_info *, 1691378d87cSkettenis int (*)(void *), void *, char *); 1701378d87cSkettenis void *(*ic_establish_msi)(void *, uint64_t *, uint64_t *, int, 1711378d87cSkettenis struct cpu_info *, int (*)(void *), void *, char *); 172baed8f06Sdrahn void (*ic_disestablish)(void *); 173baed8f06Sdrahn void (*ic_enable)(void *); 174baed8f06Sdrahn void (*ic_disable)(void *); 175baed8f06Sdrahn void (*ic_route)(void *, int, struct cpu_info *); 176baed8f06Sdrahn void (*ic_cpu_enable)(void); 1771378d87cSkettenis void (*ic_barrier)(void *); 178baed8f06Sdrahn 179baed8f06Sdrahn LIST_ENTRY(interrupt_controller) ic_list; 180baed8f06Sdrahn uint32_t ic_phandle; 181baed8f06Sdrahn uint32_t ic_cells; 182baed8f06Sdrahn }; 183baed8f06Sdrahn 184baed8f06Sdrahn void riscv_intr_init_fdt(void); 185baed8f06Sdrahn void riscv_intr_register_fdt(struct interrupt_controller *); 186baed8f06Sdrahn void *riscv_intr_establish_fdt(int, int, int (*)(void *), 187baed8f06Sdrahn void *, char *); 188baed8f06Sdrahn void *riscv_intr_establish_fdt_idx(int, int, int, int (*)(void *), 189baed8f06Sdrahn void *, char *); 1901378d87cSkettenis void *riscv_intr_establish_fdt_idx_cpu(int, int, int, struct cpu_info *, 1911378d87cSkettenis int (*)(void *), void *, char *); 1921378d87cSkettenis void *riscv_intr_establish_fdt_imap_cpu(int, int *, int, int, 1931378d87cSkettenis struct cpu_info *, int (*)(void *), void *, char *); 1941378d87cSkettenis void *riscv_intr_establish_fdt_msi(int, uint64_t *, uint64_t *, int, 1951378d87cSkettenis int (*)(void *), void *, char *); 1961378d87cSkettenis void *riscv_intr_establish_fdt_msi_cpu(int, uint64_t *, uint64_t *, int, 1971378d87cSkettenis struct cpu_info *, int (*)(void *), void *, char *); 198baed8f06Sdrahn void riscv_intr_disestablish_fdt(void *); 199baed8f06Sdrahn void riscv_intr_enable(void *); 200baed8f06Sdrahn void riscv_intr_disable(void *); 201baed8f06Sdrahn void riscv_intr_route(void *, int, struct cpu_info *); 202baed8f06Sdrahn void riscv_intr_cpu_enable(void); 203baed8f06Sdrahn 20411548269Skettenis #define IPI_NOP 0 20511548269Skettenis #define IPI_DDB (1 << 0) 206baed8f06Sdrahn 20711548269Skettenis void intr_send_ipi(struct cpu_info *, int); 208baed8f06Sdrahn 209baed8f06Sdrahn #ifdef DIAGNOSTIC 210baed8f06Sdrahn /* 211baed8f06Sdrahn * Although this function is implemented in MI code, it must be in this MD 212baed8f06Sdrahn * header because we don't want this header to include MI includes. 213baed8f06Sdrahn */ 214baed8f06Sdrahn void splassert_fail(int, int, const char *); 215baed8f06Sdrahn extern int splassert_ctl; 216baed8f06Sdrahn void riscv_splassert_check(int, const char *); 217baed8f06Sdrahn #define splassert(__wantipl) do { \ 218baed8f06Sdrahn if (splassert_ctl > 0) { \ 219baed8f06Sdrahn riscv_splassert_check(__wantipl, __func__); \ 220baed8f06Sdrahn } \ 221baed8f06Sdrahn } while (0) 222baed8f06Sdrahn #define splsoftassert(wantipl) splassert(wantipl) 223baed8f06Sdrahn #else 224baed8f06Sdrahn #define splassert(wantipl) do { /* nothing */ } while (0) 225baed8f06Sdrahn #define splsoftassert(wantipl) do { /* nothing */ } while (0) 226baed8f06Sdrahn #endif 227baed8f06Sdrahn 228baed8f06Sdrahn #endif /* ! _LOCORE */ 229baed8f06Sdrahn 230baed8f06Sdrahn #endif /* _KERNEL */ 231baed8f06Sdrahn 232baed8f06Sdrahn #endif /* _MACHINE_INTR_H_ */ 233baed8f06Sdrahn 234