xref: /NextBSD/sys/arm64/arm64/gic_v3_var.h (revision 4557fabb34e865d7f40be64b39c9e34fa41dbb60)
1 /*-
2  * Copyright (c) 2015 The FreeBSD Foundation
3  * All rights reserved.
4  *
5  * This software was developed by Semihalf under
6  * the sponsorship of the FreeBSD Foundation.
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  * $FreeBSD$
30  */
31 
32 #ifndef _GIC_V3_VAR_H_
33 #define _GIC_V3_VAR_H_
34 
35 #define	GIC_V3_DEVSTR	"ARM Generic Interrupt Controller v3.0"
36 
37 DECLARE_CLASS(gic_v3_driver);
38 
39 #define	LPI_FLAGS_CONF_FLUSH	(1UL << 0)
40 #define	LPI_CONFTAB_SIZE	PAGE_SIZE_64K
41 /* 1 bit per LPI + 1 KB more for the obligatory PPI, SGI, SPI stuff */
42 #define	LPI_PENDTAB_SIZE	((LPI_CONFTAB_SIZE / 8) + 0x400)
43 
44 struct redist_lpis {
45 	vm_offset_t		conf_base;
46 	vm_offset_t		pend_base[MAXCPU];
47 	uint64_t		flags;
48 };
49 
50 struct gic_redists {
51 	/*
52 	 * Re-Distributor region description.
53 	 * We will have few of those depending
54 	 * on the #redistributor-regions property in FDT.
55 	 */
56 	struct resource **	regions;
57 	/* Number of Re-Distributor regions */
58 	u_int			nregions;
59 	/* Per-CPU Re-Distributor handler */
60 	struct resource *	pcpu[MAXCPU];
61 	/* LPIs data */
62 	struct redist_lpis	lpis;
63 };
64 
65 struct gic_v3_softc {
66 	device_t		dev;
67 	struct resource **	gic_res;
68 	struct mtx		gic_mtx;
69 	/* Distributor */
70 	struct resource *	gic_dist;
71 	/* Re-Distributors */
72 	struct gic_redists	gic_redists;
73 
74 	u_int			gic_nirqs;
75 	u_int			gic_idbits;
76 
77 	boolean_t		gic_registered;
78 };
79 
80 MALLOC_DECLARE(M_GIC_V3);
81 
82 /* Device methods */
83 int gic_v3_attach(device_t dev);
84 int gic_v3_detach(device_t dev);
85 
86 /*
87  * ITS
88  */
89 #define	GIC_V3_ITS_DEVSTR	"ARM GIC Interrupt Translation Service"
90 #define	GIC_V3_ITS_COMPSTR	"arm,gic-v3-its"
91 
92 DECLARE_CLASS(gic_v3_its_driver);
93 
94 /* LPI chunk owned by ITS device */
95 struct lpi_chunk {
96 	u_int	lpi_base;
97 	u_int	lpi_num;
98 	u_int	lpi_free;	/* First free LPI in set */
99 };
100 
101 /* ITS device */
102 struct its_dev {
103 	TAILQ_ENTRY(its_dev)	entry;
104 	/* PCI device */
105 	device_t		pci_dev;
106 	/* Device ID (i.e. PCI device ID) */
107 	uint32_t		devid;
108 	/* List of assigned LPIs */
109 	struct lpi_chunk	lpis;
110 	/* Virtual address of ITT */
111 	vm_offset_t		itt;
112 	/* Interrupt collection */
113 	struct its_col *	col;
114 };
115 TAILQ_HEAD(its_dev_list, its_dev);
116 
117 /* ITS private table description */
118 struct its_ptab {
119 	vm_offset_t	ptab_vaddr;	/* Virtual Address of table */
120 	size_t		ptab_pgsz;	/* Page size */
121 	size_t		ptab_npages;	/* Number of pages */
122 };
123 
124 /* ITS collection description. */
125 struct its_col {
126 	uint64_t	col_target;	/* Target Re-Distributor */
127 	uint64_t	col_id;		/* Collection ID */
128 };
129 
130 /* ITS command. Each command is 32 bytes long */
131 struct its_cmd {
132 	uint64_t	cmd_dword[4];	/* ITS command double word */
133 };
134 
135 /* ITS commands encoding */
136 #define	ITS_CMD_SYNC		(0x05)
137 #define	ITS_CMD_MAPD		(0x08)
138 #define	ITS_CMD_MAPC		(0x09)
139 #define	ITS_CMD_MAPVI		(0x0a)
140 #define	ITS_CMD_MAPI		(0x0b)
141 #define	ITS_CMD_INV		(0x0c)
142 #define	ITS_CMD_INVALL		(0x0d)
143 /* Command */
144 #define	CMD_COMMAND_MASK	(0xFFUL)
145 /* PCI device ID */
146 #define	CMD_DEVID_SHIFT		(32)
147 #define	CMD_DEVID_MASK		(0xFFFFFFFFUL << CMD_DEVID_SHIFT)
148 /* Size of IRQ ID bitfield */
149 #define	CMD_SIZE_MASK		(0xFFUL)
150 /* Virtual LPI ID */
151 #define	CMD_ID_MASK		(0xFFFFFFFFUL)
152 /* Physical LPI ID */
153 #define	CMD_PID_SHIFT		(32)
154 #define	CMD_PID_MASK		(0xFFFFFFFFUL << CMD_PID_SHIFT)
155 /* Collection */
156 #define	CMD_COL_MASK		(0xFFFFUL)
157 /* Target (CPU or Re-Distributor) */
158 #define	CMD_TARGET_SHIFT	(16)
159 #define	CMD_TARGET_MASK		(0xFFFFFFFFUL << CMD_TARGET_SHIFT)
160 /* Interrupt Translation Table address */
161 #define	CMD_ITT_MASK		(0xFFFFFFFFFF00UL)
162 /* Valid command bit */
163 #define	CMD_VALID_SHIFT		(63)
164 #define	CMD_VALID_MASK		(1UL << CMD_VALID_SHIFT)
165 
166 /*
167  * ITS command descriptor.
168  * Idea for command description passing taken from Linux.
169  */
170 struct its_cmd_desc {
171 	uint8_t cmd_type;
172 
173 	union {
174 		struct {
175 			struct its_col *col;
176 		} cmd_desc_sync;
177 
178 		struct {
179 			struct its_col *col;
180 			uint8_t valid;
181 		} cmd_desc_mapc;
182 
183 		struct {
184 			struct its_dev *its_dev;
185 			uint32_t pid;
186 			uint32_t id;
187 		} cmd_desc_mapvi;
188 
189 		struct {
190 			struct its_dev *its_dev;
191 			uint32_t lpinum;
192 		} cmd_desc_mapi;
193 
194 		struct {
195 			struct its_dev *its_dev;
196 			uint8_t valid;
197 		} cmd_desc_mapd;
198 
199 		struct {
200 			struct its_dev *its_dev;
201 			uint32_t lpinum;
202 		} cmd_desc_inv;
203 
204 		struct {
205 			struct its_col *col;
206 		} cmd_desc_invall;
207 	};
208 };
209 
210 #define	ITS_CMDQ_SIZE		PAGE_SIZE_64K
211 #define	ITS_CMDQ_NENTRIES	(ITS_CMDQ_SIZE / sizeof(struct its_cmd))
212 
213 #define	ITS_FLAGS_CMDQ_FLUSH	(1UL << 0)
214 
215 #define	ITS_TARGET_NONE		0xFBADBEEF
216 
217 struct gic_v3_its_softc {
218 	device_t		dev;
219 	struct resource	*	its_res;
220 
221 	struct its_cmd *	its_cmdq_base;	/* ITS command queue base */
222 	struct its_cmd *	its_cmdq_write;	/* ITS command queue write ptr */
223 	struct its_ptab		its_ptabs[GITS_BASER_NUM];/* ITS private tables */
224 	struct its_col *	its_cols[MAXCPU];/* Per-CPU collections */
225 
226 	uint64_t		its_flags;
227 
228 	struct its_dev_list	its_dev_list;
229 
230 	unsigned long *		its_lpi_bitmap;
231 	uint32_t		its_lpi_maxid;
232 
233 	struct mtx		its_mtx;
234 	struct mtx		its_spin_mtx;
235 
236 	uint32_t		its_socket;	/* Socket number ITS is attached to */
237 };
238 
239 /* Stuff that is specific to the vendor's implementation */
240 typedef uint32_t (*its_devbits_func_t)(device_t);
241 typedef uint32_t (*its_devid_func_t)(device_t);
242 
243 struct its_quirks {
244 	uint64_t		cpuid;
245 	uint64_t		cpuid_mask;
246 	its_devid_func_t	devid_func;
247 	its_devbits_func_t	devbits_func;
248 };
249 
250 extern devclass_t gic_v3_its_devclass;
251 
252 int gic_v3_its_detach(device_t);
253 
254 int gic_v3_its_alloc_msix(device_t, device_t, int *);
255 int gic_v3_its_alloc_msi(device_t, device_t, int, int *);
256 int gic_v3_its_map_msi(device_t, device_t, int, uint64_t *, uint32_t *);
257 
258 int its_init_cpu(struct gic_v3_its_softc *);
259 
260 void lpi_unmask_irq(device_t, uint32_t);
261 void lpi_mask_irq(device_t, uint32_t);
262 /*
263  * GIC Distributor accessors.
264  * Notice that only GIC sofc can be passed.
265  */
266 #define	gic_d_read(sc, len, reg)		\
267 ({						\
268 	bus_read_##len(sc->gic_dist, reg);	\
269 })
270 
271 #define	gic_d_write(sc, len, reg, val)		\
272 ({						\
273 	bus_write_##len(sc->gic_dist, reg, val);\
274 })
275 
276 /* GIC Re-Distributor accessors (per-CPU) */
277 #define	gic_r_read(sc, len, reg)		\
278 ({						\
279 	u_int cpu = PCPU_GET(cpuid);		\
280 						\
281 	bus_read_##len(				\
282 	    sc->gic_redists.pcpu[cpu],		\
283 	    reg);				\
284 })
285 
286 #define	gic_r_write(sc, len, reg, val)		\
287 ({						\
288 	u_int cpu = PCPU_GET(cpuid);		\
289 						\
290 	bus_write_##len(			\
291 	    sc->gic_redists.pcpu[cpu],		\
292 	    reg, val);				\
293 })
294 
295 #define	PCI_DEVID_GENERIC(pci_dev)				\
296 ({								\
297 	((pci_get_domain(pci_dev) << PCI_RID_DOMAIN_SHIFT) |	\
298 	(pci_get_bus(pci_dev) << PCI_RID_BUS_SHIFT) |		\
299 	(pci_get_slot(pci_dev) << PCI_RID_SLOT_SHIFT) |		\
300 	(pci_get_function(pci_dev) << PCI_RID_FUNC_SHIFT));	\
301 })
302 
303 /*
304  * Request number of maximum MSI-X vectors for this device.
305  * Device can ask for less vectors than maximum supported but not more.
306  */
307 #define	PCI_MSIX_NUM(pci_dev)			\
308 ({						\
309 	struct pci_devinfo *dinfo;		\
310 	pcicfgregs *cfg;			\
311 						\
312 	dinfo = device_get_ivars(pci_dev);	\
313 	cfg = &dinfo->cfg;			\
314 						\
315 	cfg->msix.msix_msgnum;			\
316 })
317 
318 #endif /* _GIC_V3_VAR_H_ */
319