| 1 | /*- |
| 2 | * SPDX-License-Identifier: BSD-2-Clause |
| 3 | * |
| 4 | * Copyright (c) 2015-2016 Svatopluk Kraus |
| 5 | * Copyright (c) 2015-2016 Michal Meloun |
| 6 | * All rights reserved. |
| 7 | * |
| 8 | * Redistribution and use in source and binary forms, with or without |
| 9 | * modification, are permitted provided that the following conditions |
| 10 | * are met: |
| 11 | * 1. Redistributions of source code must retain the above copyright |
| 12 | * notice, this list of conditions and the following disclaimer. |
| 13 | * 2. Redistributions in binary form must reproduce the above copyright |
| 14 | * notice, this list of conditions and the following disclaimer in the |
| 15 | * documentation and/or other materials provided with the distribution. |
| 16 | * |
| 17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND |
| 18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
| 21 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| 22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
| 23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
| 24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
| 25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
| 26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| 27 | * SUCH DAMAGE. |
| 28 | */ |
| 29 | |
| 30 | #ifndef _SYS_INTR_H_ |
| 31 | #define _SYS_INTR_H_ |
| 32 | #ifndef INTRNG |
| 33 | #error Need INTRNG for this file |
| 34 | #endif |
| 35 | |
| 36 | #include <machine/intr.h> |
| 37 | |
| 38 | #define	INTR_IRQ_INVALID	0xFFFFFFFF |
| 39 | |
| 40 | #ifndef LOCORE |
| 41 | |
| 42 | enum intr_map_data_type { |
| 43 | 	INTR_MAP_DATA_ACPI = 0, |
| 44 | 	INTR_MAP_DATA_FDT, |
| 45 | 	INTR_MAP_DATA_GPIO, |
| 46 | 	INTR_MAP_DATA_MSI, |
| 47 | |
| 48 | 	/* Placeholders for platform specific types */ |
| 49 | 	INTR_MAP_DATA_PLAT_1 = 1000, |
| 50 | 	INTR_MAP_DATA_PLAT_2, |
| 51 | 	INTR_MAP_DATA_PLAT_3, |
| 52 | 	INTR_MAP_DATA_PLAT_4, |
| 53 | 	INTR_MAP_DATA_PLAT_5, |
| 54 | }; |
| 55 | |
| 56 | struct intr_map_data { |
| 57 | 	size_t			len; |
| 58 | 	enum intr_map_data_type	type; |
| 59 | }; |
| 60 | |
| 61 | struct intr_map_data_msi { |
| 62 | 	struct intr_map_data	hdr; |
| 63 | 	struct intr_irqsrc 	*isrc; |
| 64 | }; |
| 65 | |
| 66 | #ifdef notyet |
| 67 | #define	INTR_SOLO	INTR_MD1 |
| 68 | typedef int intr_irq_filter_t(void *arg, struct trapframe *tf); |
| 69 | #else |
| 70 | typedef int intr_irq_filter_t(void *arg); |
| 71 | #endif |
| 72 | typedef int intr_child_irq_filter_t(void *arg, uintptr_t irq); |
| 73 | |
| 74 | #define INTR_ISRC_NAMELEN	(MAXCOMLEN + 1) |
| 75 | |
| 76 | #define INTR_ISRCF_IPI		0x01	/* IPI interrupt */ |
| 77 | #define INTR_ISRCF_PPI		0x02	/* PPI interrupt */ |
| 78 | #define INTR_ISRCF_BOUND	0x04	/* bound to a CPU */ |
| 79 | |
| 80 | struct intr_pic; |
| 81 | |
| 82 | /* Interrupt source definition. */ |
| 83 | struct intr_irqsrc { |
| 84 | 	device_t		isrc_dev;	/* where isrc is mapped */ |
| 85 | 	u_int			isrc_irq;	/* unique identificator */ |
| 86 | 	u_int			isrc_flags; |
| 87 | 	char			isrc_name[INTR_ISRC_NAMELEN]; |
| 88 | 	cpuset_t		isrc_cpu;	/* on which CPUs is enabled */ |
| 89 | 	u_int			isrc_index; |
| 90 | 	u_long *		isrc_count; |
| 91 | 	u_int			isrc_handlers; |
| 92 | 	struct intr_event *	isrc_event; |
| 93 | #ifdef INTR_SOLO |
| 94 | 	intr_irq_filter_t *	isrc_filter; |
| 95 | 	void *			isrc_arg; |
| 96 | #endif |
| 97 | 	/* Used by MSI interrupts to store the iommu details */ |
| 98 | 	void *			isrc_iommu; |
| 99 | }; |
| 100 | |
| 101 | /* Intr interface for PIC. */ |
| 102 | int intr_isrc_deregister(struct intr_irqsrc *); |
| 103 | int intr_isrc_register(struct intr_irqsrc *, device_t, u_int, const char *, ...) |
| 104 | __printflike(4, 5); |
| 105 | |
| 106 | #ifdef SMP |
| 107 | bool intr_isrc_init_on_cpu(struct intr_irqsrc *isrc, u_int cpu); |
| 108 | #endif |
| 109 | |
| 110 | int intr_isrc_dispatch(struct intr_irqsrc *, struct trapframe *); |
| 111 | u_int intr_irq_next_cpu(u_int current_cpu, cpuset_t *cpumask); |
| 112 | |
| 113 | struct intr_pic *intr_pic_register(device_t, intptr_t); |
| 114 | int intr_pic_deregister(device_t, intptr_t); |
| 115 | int intr_pic_claim_root(device_t, intptr_t, intr_irq_filter_t *, void *, |
| 116 | uint32_t); |
| 117 | int intr_pic_add_handler(device_t, struct intr_pic *, |
| 118 | intr_child_irq_filter_t *, void *, uintptr_t, uintptr_t); |
| 119 | bool intr_is_per_cpu(struct resource *); |
| 120 | |
| 121 | device_t intr_irq_root_device(uint32_t); |
| 122 | |
| 123 | /* Intr interface for BUS. */ |
| 124 | |
| 125 | int intr_activate_irq(device_t, struct resource *); |
| 126 | int intr_deactivate_irq(device_t, struct resource *); |
| 127 | |
| 128 | int intr_setup_irq(device_t, struct resource *, driver_filter_t, driver_intr_t, |
| 129 | void *, int, void **); |
| 130 | int intr_teardown_irq(device_t, struct resource *, void *); |
| 131 | |
| 132 | int intr_describe_irq(device_t, struct resource *, void *, const char *); |
| 133 | int intr_child_irq_handler(struct intr_pic *, uintptr_t); |
| 134 | |
| 135 | /* Intr resources mapping. */ |
| 136 | struct intr_map_data *intr_alloc_map_data(enum intr_map_data_type, size_t, int); |
| 137 | void intr_free_intr_map_data(struct intr_map_data *); |
| 138 | u_int intr_map_irq(device_t, intptr_t, struct intr_map_data *); |
| 139 | void intr_unmap_irq(u_int ); |
| 140 | u_int intr_map_clone_irq(u_int ); |
| 141 | |
| 142 | /* MSI/MSI-X handling */ |
| 143 | int intr_msi_register(device_t, intptr_t); |
| 144 | int intr_alloc_msi(device_t, device_t, intptr_t, int, int, int *); |
| 145 | int intr_release_msi(device_t, device_t, intptr_t, int, int *); |
| 146 | int intr_map_msi(device_t, device_t, intptr_t, int, uint64_t *, uint32_t *); |
| 147 | int intr_alloc_msix(device_t, device_t, intptr_t, int *); |
| 148 | int intr_release_msix(device_t, device_t, intptr_t, int); |
| 149 | |
| 150 | #ifdef SMP |
| 151 | int intr_bind_irq(device_t, struct resource *, int); |
| 152 | |
| 153 | void intr_pic_init_secondary(void); |
| 154 | #endif |
| 155 | |
| 156 | extern u_int	intr_nirq;	/* number of IRQs on intrng platforms */ |
| 157 | |
| 158 | /* Intr interface for IPIs. */ |
| 159 | #ifdef SMP |
| 160 | typedef void intr_ipi_handler_t(void *); |
| 161 | |
| 162 | int intr_ipi_pic_register(device_t dev, u_int priority); |
| 163 | void intr_ipi_setup(u_int ipi, const char *name, intr_ipi_handler_t *hand, |
| 164 | void *arg); |
| 165 | void intr_ipi_send(cpuset_t cpus, u_int ipi); |
| 166 | void intr_ipi_dispatch(u_int ipi); |
| 167 | #endif |
| 168 | |
| 169 | /* Main interrupt handler called from asm on most archs except riscv. */ |
| 170 | void intr_irq_handler(struct trapframe *tf, uint32_t rootnum); |
| 171 | |
| 172 | #endif /* !LOCORE */ |
| 173 | |
| 174 | #endif	/* _SYS_INTR_H */ |