]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/arm64/arm64/gic_v3_var.h
Add quirk for ThunderX ITS device table size
[FreeBSD/FreeBSD.git] / sys / arm64 / arm64 / gic_v3_var.h
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;       /* 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
237 /* Stuff that is specific to the vendor's implementation */
238 typedef uint32_t (*its_devbits_func_t)(device_t);
239 typedef uint32_t (*its_devid_func_t)(device_t);
240
241 struct its_quirks {
242         uint64_t                cpuid;
243         uint64_t                cpuid_mask;
244         its_devid_func_t        devid_func;
245         its_devbits_func_t      devbits_func;
246 };
247
248 extern devclass_t gic_v3_its_devclass;
249
250 int gic_v3_its_detach(device_t);
251
252 int gic_v3_its_alloc_msix(device_t, device_t, int *);
253 int gic_v3_its_alloc_msi(device_t, device_t, int, int *);
254 int gic_v3_its_map_msix(device_t, device_t, int, uint64_t *, uint32_t *);
255
256 void lpi_unmask_irq(device_t, uint32_t);
257 void lpi_mask_irq(device_t, uint32_t);
258 /*
259  * GIC Distributor accessors.
260  * Notice that only GIC sofc can be passed.
261  */
262 #define gic_d_read(sc, len, reg)                \
263 ({                                              \
264         bus_read_##len(sc->gic_dist, reg);      \
265 })
266
267 #define gic_d_write(sc, len, reg, val)          \
268 ({                                              \
269         bus_write_##len(sc->gic_dist, reg, val);\
270 })
271
272 /* GIC Re-Distributor accessors (per-CPU) */
273 #define gic_r_read(sc, len, reg)                \
274 ({                                              \
275         u_int cpu = PCPU_GET(cpuid);            \
276                                                 \
277         bus_read_##len(                         \
278             sc->gic_redists.pcpu[cpu],          \
279             reg);                               \
280 })
281
282 #define gic_r_write(sc, len, reg, val)          \
283 ({                                              \
284         u_int cpu = PCPU_GET(cpuid);            \
285                                                 \
286         bus_write_##len(                        \
287             sc->gic_redists.pcpu[cpu],          \
288             reg, val);                          \
289 })
290
291 #define PCI_DEVID_GENERIC(pci_dev)                              \
292 ({                                                              \
293         ((pci_get_domain(pci_dev) << PCI_RID_DOMAIN_SHIFT) |    \
294         (pci_get_bus(pci_dev) << PCI_RID_BUS_SHIFT) |           \
295         (pci_get_slot(pci_dev) << PCI_RID_SLOT_SHIFT) |         \
296         (pci_get_function(pci_dev) << PCI_RID_FUNC_SHIFT));     \
297 })
298
299 /*
300  * Request number of maximum MSI-X vectors for this device.
301  * Device can ask for less vectors than maximum supported but not more.
302  */
303 #define PCI_MSIX_NUM(pci_dev)                   \
304 ({                                              \
305         struct pci_devinfo *dinfo;              \
306         pcicfgregs *cfg;                        \
307                                                 \
308         dinfo = device_get_ivars(pci_dev);      \
309         cfg = &dinfo->cfg;                      \
310                                                 \
311         cfg->msix.msix_msgnum;                  \
312 })
313
314 #endif /* _GIC_V3_VAR_H_ */