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