1 /* 2 * Copyright (C) 2016, Red Hat Inc, Andrew Jones <drjones@redhat.com> 3 * 4 * This work is licensed under the terms of the GNU LGPL, version 2. 5 */ 6 #include <acpi.h> 7 #include <devicetree.h> 8 #include <asm/gic.h> 9 #include <asm/io.h> 10 11 struct gicv2_data gicv2_data; 12 struct gicv3_data gicv3_data; 13 struct its_data its_data; 14 15 struct gic_common_ops { 16 void (*enable_defaults)(void); 17 u32 (*read_iar)(void); 18 u32 (*iar_irqnr)(u32 iar); 19 void (*write_eoir)(u32 irqstat); 20 void (*ipi_send_single)(int irq, int cpu); 21 void (*ipi_send_mask)(int irq, const cpumask_t *dest); 22 }; 23 24 static const struct gic_common_ops *gic_common_ops; 25 26 static const struct gic_common_ops gicv2_common_ops = { 27 .enable_defaults = gicv2_enable_defaults, 28 .read_iar = gicv2_read_iar, 29 .iar_irqnr = gicv2_iar_irqnr, 30 .write_eoir = gicv2_write_eoir, 31 .ipi_send_single = gicv2_ipi_send_single, 32 .ipi_send_mask = gicv2_ipi_send_mask, 33 }; 34 35 static const struct gic_common_ops gicv3_common_ops = { 36 .enable_defaults = gicv3_enable_defaults, 37 .read_iar = gicv3_read_iar, 38 .iar_irqnr = gicv3_iar_irqnr, 39 .write_eoir = gicv3_write_eoir, 40 .ipi_send_single = gicv3_ipi_send_single, 41 .ipi_send_mask = gicv3_ipi_send_mask, 42 }; 43 44 /* 45 * Documentation/devicetree/bindings/interrupt-controller/arm,gic.txt 46 * Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.txt 47 */ 48 static bool 49 gic_get_dt_bases(const char *compatible, void **base1, void **base2, void **base3) 50 { 51 struct dt_pbus_reg reg; 52 struct dt_device gic, its; 53 struct dt_bus bus; 54 int node, subnode, ret, i, len; 55 const void *fdt = dt_fdt(); 56 57 dt_bus_init_defaults(&bus); 58 dt_device_init(&gic, &bus, NULL); 59 60 node = dt_device_find_compatible(&gic, compatible); 61 assert(node >= 0 || node == -FDT_ERR_NOTFOUND); 62 63 if (node == -FDT_ERR_NOTFOUND) 64 return false; 65 66 dt_device_bind_node(&gic, node); 67 68 ret = dt_pbus_translate(&gic, 0, ®); 69 assert(ret == 0); 70 *base1 = ioremap(reg.addr, reg.size); 71 72 for (i = 0; i < GICV3_NR_REDISTS; ++i) { 73 ret = dt_pbus_translate(&gic, i + 1, ®); 74 if (ret == -FDT_ERR_NOTFOUND) 75 break; 76 assert(ret == 0); 77 base2[i] = ioremap(reg.addr, reg.size); 78 } 79 80 if (!base3) { 81 assert(!strcmp(compatible, "arm,cortex-a15-gic")); 82 return true; 83 } 84 85 assert(!strcmp(compatible, "arm,gic-v3")); 86 87 dt_for_each_subnode(node, subnode) { 88 const struct fdt_property *prop; 89 90 prop = fdt_get_property(fdt, subnode, "compatible", &len); 91 if (!strcmp((char *)prop->data, "arm,gic-v3-its")) { 92 dt_device_bind_node(&its, subnode); 93 ret = dt_pbus_translate(&its, 0, ®); 94 assert(ret == 0); 95 *base3 = ioremap(reg.addr, reg.size); 96 break; 97 } 98 } 99 100 return true; 101 } 102 103 int gicv2_init(void) 104 { 105 return gic_get_dt_bases("arm,cortex-a15-gic", 106 &gicv2_data.dist_base, &gicv2_data.cpu_base, NULL); 107 } 108 109 int gicv3_init(void) 110 { 111 return gic_get_dt_bases("arm,gic-v3", &gicv3_data.dist_base, 112 &gicv3_data.redist_bases[0], &its_data.base); 113 } 114 115 int gic_version(void) 116 { 117 if (gic_common_ops == &gicv2_common_ops) 118 return 2; 119 else if (gic_common_ops == &gicv3_common_ops) 120 return 3; 121 return 0; 122 } 123 124 static int gic_init_fdt(void) 125 { 126 if (gicv2_init()) { 127 gic_common_ops = &gicv2_common_ops; 128 } else if (gicv3_init()) { 129 gic_common_ops = &gicv3_common_ops; 130 #ifdef __aarch64__ 131 its_init(); 132 #endif 133 } 134 return gic_version(); 135 } 136 137 #ifdef CONFIG_EFI 138 139 #define ACPI_GICV2_DIST_MEM_SIZE (SZ_4K) 140 #define ACPI_GIC_CPU_IF_MEM_SIZE (SZ_8K) 141 #define ACPI_GICV3_DIST_MEM_SIZE (SZ_64K) 142 #define ACPI_GICV3_ITS_MEM_SIZE (SZ_128K) 143 144 static int gic_acpi_version(struct acpi_subtable_header *header) 145 { 146 struct acpi_madt_generic_distributor *dist = (void *)header; 147 int version = dist->version; 148 149 if (version == 2) 150 gic_common_ops = &gicv2_common_ops; 151 else if (version == 3) 152 gic_common_ops = &gicv3_common_ops; 153 154 return version; 155 } 156 157 static int gicv2_acpi_parse_madt_cpu(struct acpi_subtable_header *header) 158 { 159 struct acpi_madt_generic_interrupt *gicc = (void *)header; 160 static phys_addr_t gicc_base_address; 161 162 if (!(gicc->flags & ACPI_MADT_ENABLED)) 163 return 0; 164 165 if (!gicc_base_address) { 166 gicc_base_address = gicc->base_address; 167 gicv2_data.cpu_base = ioremap(gicc_base_address, ACPI_GIC_CPU_IF_MEM_SIZE); 168 } 169 assert(gicc_base_address == gicc->base_address); 170 171 return 0; 172 } 173 174 static int gicv2_acpi_parse_madt_dist(struct acpi_subtable_header *header) 175 { 176 struct acpi_madt_generic_distributor *dist = (void *)header; 177 178 gicv2_data.dist_base = ioremap(dist->base_address, ACPI_GICV2_DIST_MEM_SIZE); 179 180 return 0; 181 } 182 183 static int gicv3_acpi_parse_madt_gicc(struct acpi_subtable_header *header) 184 { 185 struct acpi_madt_generic_interrupt *gicc = (void *)header; 186 static phys_addr_t gicr_base_address; 187 188 if (!(gicc->flags & ACPI_MADT_ENABLED)) 189 return 0; 190 191 if (!gicr_base_address) { 192 gicr_base_address = gicc->gicr_base_address; 193 gicv3_data.redist_bases[0] = ioremap(gicr_base_address, SZ_64K * 2); 194 } 195 assert(gicr_base_address == gicc->gicr_base_address); 196 197 return 0; 198 } 199 200 static int gicv3_acpi_parse_madt_dist(struct acpi_subtable_header *header) 201 { 202 struct acpi_madt_generic_distributor *dist = (void *)header; 203 204 gicv3_data.dist_base = ioremap(dist->base_address, ACPI_GICV3_DIST_MEM_SIZE); 205 206 return 0; 207 } 208 209 static int gicv3_acpi_parse_madt_redist(struct acpi_subtable_header *header) 210 { 211 static int i; 212 struct acpi_madt_generic_redistributor *redist = (void *)header; 213 214 gicv3_data.redist_bases[i++] = ioremap(redist->base_address, redist->length); 215 216 return 0; 217 } 218 219 static int gicv3_acpi_parse_madt_its(struct acpi_subtable_header *header) 220 { 221 struct acpi_madt_generic_translator *its_entry = (void *)header; 222 223 its_data.base = ioremap(its_entry->base_address, ACPI_GICV3_ITS_MEM_SIZE - 1); 224 225 return 0; 226 } 227 228 static int gic_init_acpi(void) 229 { 230 int count; 231 232 acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR, gic_acpi_version); 233 if (gic_version() == 2) { 234 acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_INTERRUPT, 235 gicv2_acpi_parse_madt_cpu); 236 acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR, 237 gicv2_acpi_parse_madt_dist); 238 } else if (gic_version() == 3) { 239 acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR, 240 gicv3_acpi_parse_madt_dist); 241 count = acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR, 242 gicv3_acpi_parse_madt_redist); 243 if (!count) 244 acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_INTERRUPT, 245 gicv3_acpi_parse_madt_gicc); 246 acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_TRANSLATOR, 247 gicv3_acpi_parse_madt_its); 248 #ifdef __aarch64__ 249 its_init(); 250 #endif 251 } 252 253 return gic_version(); 254 } 255 256 #else 257 258 static int gic_init_acpi(void) 259 { 260 assert_msg(false, "ACPI not available"); 261 } 262 263 #endif /* CONFIG_EFI */ 264 265 int gic_init(void) 266 { 267 if (dt_available()) 268 return gic_init_fdt(); 269 else 270 return gic_init_acpi(); 271 } 272 273 void gic_enable_defaults(void) 274 { 275 if (!gic_common_ops) { 276 int ret = gic_init(); 277 assert(ret != 0); 278 } else 279 assert(gic_common_ops->enable_defaults); 280 gic_common_ops->enable_defaults(); 281 } 282 283 u32 gic_read_iar(void) 284 { 285 assert(gic_common_ops && gic_common_ops->read_iar); 286 return gic_common_ops->read_iar(); 287 } 288 289 u32 gic_iar_irqnr(u32 iar) 290 { 291 assert(gic_common_ops && gic_common_ops->iar_irqnr); 292 return gic_common_ops->iar_irqnr(iar); 293 } 294 295 void gic_write_eoir(u32 irqstat) 296 { 297 assert(gic_common_ops && gic_common_ops->write_eoir); 298 gic_common_ops->write_eoir(irqstat); 299 } 300 301 void gic_ipi_send_single(int irq, int cpu) 302 { 303 assert(gic_common_ops && gic_common_ops->ipi_send_single); 304 gic_common_ops->ipi_send_single(irq, cpu); 305 } 306 307 void gic_ipi_send_mask(int irq, const cpumask_t *dest) 308 { 309 assert(gic_common_ops && gic_common_ops->ipi_send_mask); 310 gic_common_ops->ipi_send_mask(irq, dest); 311 } 312 313 void gic_irq_set_clr_enable(int irq, bool enable) 314 { 315 u32 offset, split = 32, shift = (irq % 32); 316 void *base; 317 318 assert(irq < 1020); 319 320 switch (gic_version()) { 321 case 2: 322 offset = enable ? GICD_ISENABLER : GICD_ICENABLER; 323 base = gicv2_dist_base(); 324 break; 325 case 3: 326 if (irq < 32) { 327 offset = enable ? GICR_ISENABLER0 : GICR_ICENABLER0; 328 base = gicv3_sgi_base(); 329 } else { 330 offset = enable ? GICD_ISENABLER : GICD_ICENABLER; 331 base = gicv3_dist_base(); 332 } 333 break; 334 default: 335 assert(0); 336 } 337 base += offset + (irq / split) * 4; 338 writel(BIT(shift), base); 339 } 340 341 enum gic_irq_state gic_irq_state(int irq) 342 { 343 enum gic_irq_state state; 344 void *ispendr, *isactiver; 345 bool pending, active; 346 int offset, mask; 347 348 assert(gic_common_ops); 349 assert(irq < 1020); 350 351 switch (gic_version()) { 352 case 2: 353 ispendr = gicv2_dist_base() + GICD_ISPENDR; 354 isactiver = gicv2_dist_base() + GICD_ISACTIVER; 355 break; 356 case 3: 357 if (irq < GIC_NR_PRIVATE_IRQS) { 358 ispendr = gicv3_sgi_base() + GICR_ISPENDR0; 359 isactiver = gicv3_sgi_base() + GICR_ISACTIVER0; 360 } else { 361 ispendr = gicv3_dist_base() + GICD_ISPENDR; 362 isactiver = gicv3_dist_base() + GICD_ISACTIVER; 363 } 364 break; 365 default: 366 assert(0); 367 } 368 369 offset = irq / 32 * 4; 370 mask = 1 << (irq % 32); 371 pending = readl(ispendr + offset) & mask; 372 active = readl(isactiver + offset) & mask; 373 374 if (!active && !pending) 375 state = GIC_IRQ_STATE_INACTIVE; 376 if (pending) 377 state = GIC_IRQ_STATE_PENDING; 378 if (active) 379 state = GIC_IRQ_STATE_ACTIVE; 380 if (active && pending) 381 state = GIC_IRQ_STATE_ACTIVE_PENDING; 382 383 return state; 384 } 385 386