1 /* 2 * ASPEED INTC Controller 3 * 4 * Copyright (C) 2024 ASPEED Technology Inc. 5 * 6 * SPDX-License-Identifier: GPL-2.0-or-later 7 */ 8 9 #include "qemu/osdep.h" 10 #include "hw/intc/aspeed_intc.h" 11 #include "hw/irq.h" 12 #include "qemu/log.h" 13 #include "trace.h" 14 #include "hw/registerfields.h" 15 #include "qapi/error.h" 16 17 /* 18 * INTC Registers 19 * 20 * values below are offset by - 0x1000 from datasheet 21 * because its memory region is start at 0x1000 22 * 23 */ 24 REG32(GICINT128_EN, 0x000) 25 REG32(GICINT128_STATUS, 0x004) 26 REG32(GICINT129_EN, 0x100) 27 REG32(GICINT129_STATUS, 0x104) 28 REG32(GICINT130_EN, 0x200) 29 REG32(GICINT130_STATUS, 0x204) 30 REG32(GICINT131_EN, 0x300) 31 REG32(GICINT131_STATUS, 0x304) 32 REG32(GICINT132_EN, 0x400) 33 REG32(GICINT132_STATUS, 0x404) 34 REG32(GICINT133_EN, 0x500) 35 REG32(GICINT133_STATUS, 0x504) 36 REG32(GICINT134_EN, 0x600) 37 REG32(GICINT134_STATUS, 0x604) 38 REG32(GICINT135_EN, 0x700) 39 REG32(GICINT135_STATUS, 0x704) 40 REG32(GICINT136_EN, 0x800) 41 REG32(GICINT136_STATUS, 0x804) 42 43 #define GICINT_STATUS_BASE R_GICINT128_STATUS 44 45 static void aspeed_intc_update(AspeedINTCState *s, int irq, int level) 46 { 47 AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s); 48 const char *name = object_get_typename(OBJECT(s)); 49 50 if (irq >= aic->num_ints) { 51 qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid interrupt number: %d\n", 52 __func__, irq); 53 return; 54 } 55 56 trace_aspeed_intc_update_irq(name, irq, level); 57 qemu_set_irq(s->output_pins[irq], level); 58 } 59 60 /* 61 * The address of GICINT128 to GICINT136 are from 0x1000 to 0x1804. 62 * Utilize "address & 0x0f00" to get the irq and irq output pin index 63 * The value of irq should be 0 to num_ints. 64 * The irq 0 indicates GICINT128, irq 1 indicates GICINT129 and so on. 65 */ 66 static void aspeed_intc_set_irq(void *opaque, int irq, int level) 67 { 68 AspeedINTCState *s = (AspeedINTCState *)opaque; 69 AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s); 70 const char *name = object_get_typename(OBJECT(s)); 71 uint32_t status_reg = GICINT_STATUS_BASE + ((0x100 * irq) >> 2); 72 uint32_t select = 0; 73 uint32_t enable; 74 int i; 75 76 if (irq >= aic->num_ints) { 77 qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid interrupt number: %d\n", 78 __func__, irq); 79 return; 80 } 81 82 trace_aspeed_intc_set_irq(name, irq, level); 83 enable = s->enable[irq]; 84 85 if (!level) { 86 return; 87 } 88 89 for (i = 0; i < aic->num_lines; i++) { 90 if (s->orgates[irq].levels[i]) { 91 if (enable & BIT(i)) { 92 select |= BIT(i); 93 } 94 } 95 } 96 97 if (!select) { 98 return; 99 } 100 101 trace_aspeed_intc_select(name, select); 102 103 if (s->mask[irq] || s->regs[status_reg]) { 104 /* 105 * a. mask is not 0 means in ISR mode 106 * sources interrupt routine are executing. 107 * b. status register value is not 0 means previous 108 * source interrupt does not be executed, yet. 109 * 110 * save source interrupt to pending variable. 111 */ 112 s->pending[irq] |= select; 113 trace_aspeed_intc_pending_irq(name, irq, s->pending[irq]); 114 } else { 115 /* 116 * notify firmware which source interrupt are coming 117 * by setting status register 118 */ 119 s->regs[status_reg] = select; 120 trace_aspeed_intc_trigger_irq(name, irq, s->regs[status_reg]); 121 aspeed_intc_update(s, irq, 1); 122 } 123 } 124 125 static void aspeed_intc_enable_handler(AspeedINTCState *s, hwaddr offset, 126 uint64_t data) 127 { 128 AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s); 129 const char *name = object_get_typename(OBJECT(s)); 130 uint32_t reg = offset >> 2; 131 uint32_t old_enable; 132 uint32_t change; 133 uint32_t irq; 134 135 irq = (offset & 0x0f00) >> 8; 136 137 if (irq >= aic->num_ints) { 138 qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid interrupt number: %d\n", 139 __func__, irq); 140 return; 141 } 142 143 /* 144 * The enable registers are used to enable source interrupts. 145 * They also handle masking and unmasking of source interrupts 146 * during the execution of the source ISR. 147 */ 148 149 /* disable all source interrupt */ 150 if (!data && !s->enable[irq]) { 151 s->regs[reg] = data; 152 return; 153 } 154 155 old_enable = s->enable[irq]; 156 s->enable[irq] |= data; 157 158 /* enable new source interrupt */ 159 if (old_enable != s->enable[irq]) { 160 trace_aspeed_intc_enable(name, s->enable[irq]); 161 s->regs[reg] = data; 162 return; 163 } 164 165 /* mask and unmask source interrupt */ 166 change = s->regs[reg] ^ data; 167 if (change & data) { 168 s->mask[irq] &= ~change; 169 trace_aspeed_intc_unmask(name, change, s->mask[irq]); 170 } else { 171 s->mask[irq] |= change; 172 trace_aspeed_intc_mask(name, change, s->mask[irq]); 173 } 174 175 s->regs[reg] = data; 176 } 177 178 static void aspeed_intc_status_handler(AspeedINTCState *s, hwaddr offset, 179 uint64_t data) 180 { 181 AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s); 182 const char *name = object_get_typename(OBJECT(s)); 183 uint32_t reg = offset >> 2; 184 uint32_t irq; 185 186 if (!data) { 187 qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid data 0\n", __func__); 188 return; 189 } 190 191 irq = (offset & 0x0f00) >> 8; 192 193 if (irq >= aic->num_ints) { 194 qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid interrupt number: %d\n", 195 __func__, irq); 196 return; 197 } 198 199 /* clear status */ 200 s->regs[reg] &= ~data; 201 202 /* 203 * These status registers are used for notify sources ISR are executed. 204 * If one source ISR is executed, it will clear one bit. 205 * If it clear all bits, it means to initialize this register status 206 * rather than sources ISR are executed. 207 */ 208 if (data == 0xffffffff) { 209 return; 210 } 211 212 /* All source ISR execution are done */ 213 if (!s->regs[reg]) { 214 trace_aspeed_intc_all_isr_done(name, irq); 215 if (s->pending[irq]) { 216 /* 217 * handle pending source interrupt 218 * notify firmware which source interrupt are pending 219 * by setting status register 220 */ 221 s->regs[reg] = s->pending[irq]; 222 s->pending[irq] = 0; 223 trace_aspeed_intc_trigger_irq(name, irq, s->regs[reg]); 224 aspeed_intc_update(s, irq, 1); 225 } else { 226 /* clear irq */ 227 trace_aspeed_intc_clear_irq(name, irq, 0); 228 aspeed_intc_update(s, irq, 0); 229 } 230 } 231 } 232 233 static uint64_t aspeed_intc_read(void *opaque, hwaddr offset, unsigned int size) 234 { 235 AspeedINTCState *s = ASPEED_INTC(opaque); 236 const char *name = object_get_typename(OBJECT(s)); 237 uint32_t reg = offset >> 2; 238 uint32_t value = 0; 239 240 value = s->regs[reg]; 241 trace_aspeed_intc_read(name, offset, size, value); 242 243 return value; 244 } 245 246 static void aspeed_intc_write(void *opaque, hwaddr offset, uint64_t data, 247 unsigned size) 248 { 249 AspeedINTCState *s = ASPEED_INTC(opaque); 250 const char *name = object_get_typename(OBJECT(s)); 251 uint32_t reg = offset >> 2; 252 253 trace_aspeed_intc_write(name, offset, size, data); 254 255 switch (reg) { 256 case R_GICINT128_EN: 257 case R_GICINT129_EN: 258 case R_GICINT130_EN: 259 case R_GICINT131_EN: 260 case R_GICINT132_EN: 261 case R_GICINT133_EN: 262 case R_GICINT134_EN: 263 case R_GICINT135_EN: 264 case R_GICINT136_EN: 265 aspeed_intc_enable_handler(s, offset, data); 266 break; 267 case R_GICINT128_STATUS: 268 case R_GICINT129_STATUS: 269 case R_GICINT130_STATUS: 270 case R_GICINT131_STATUS: 271 case R_GICINT132_STATUS: 272 case R_GICINT133_STATUS: 273 case R_GICINT134_STATUS: 274 case R_GICINT135_STATUS: 275 case R_GICINT136_STATUS: 276 aspeed_intc_status_handler(s, offset, data); 277 break; 278 default: 279 s->regs[reg] = data; 280 break; 281 } 282 283 return; 284 } 285 286 static const MemoryRegionOps aspeed_intc_ops = { 287 .read = aspeed_intc_read, 288 .write = aspeed_intc_write, 289 .endianness = DEVICE_LITTLE_ENDIAN, 290 .valid = { 291 .min_access_size = 4, 292 .max_access_size = 4, 293 } 294 }; 295 296 static void aspeed_intc_instance_init(Object *obj) 297 { 298 AspeedINTCState *s = ASPEED_INTC(obj); 299 AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s); 300 int i; 301 302 assert(aic->num_ints <= ASPEED_INTC_NR_INTS); 303 for (i = 0; i < aic->num_ints; i++) { 304 object_initialize_child(obj, "intc-orgates[*]", &s->orgates[i], 305 TYPE_OR_IRQ); 306 object_property_set_int(OBJECT(&s->orgates[i]), "num-lines", 307 aic->num_lines, &error_abort); 308 } 309 } 310 311 static void aspeed_intc_reset(DeviceState *dev) 312 { 313 AspeedINTCState *s = ASPEED_INTC(dev); 314 AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s); 315 316 memset(s->regs, 0, aic->nr_regs << 2); 317 memset(s->enable, 0, sizeof(s->enable)); 318 memset(s->mask, 0, sizeof(s->mask)); 319 memset(s->pending, 0, sizeof(s->pending)); 320 } 321 322 static void aspeed_intc_realize(DeviceState *dev, Error **errp) 323 { 324 SysBusDevice *sbd = SYS_BUS_DEVICE(dev); 325 AspeedINTCState *s = ASPEED_INTC(dev); 326 AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s); 327 int i; 328 329 memory_region_init(&s->iomem_container, OBJECT(s), 330 TYPE_ASPEED_INTC ".container", aic->mem_size); 331 332 sysbus_init_mmio(sbd, &s->iomem_container); 333 334 s->regs = g_new(uint32_t, aic->nr_regs); 335 memory_region_init_io(&s->iomem, OBJECT(s), aic->reg_ops, s, 336 TYPE_ASPEED_INTC ".regs", aic->nr_regs << 2); 337 338 memory_region_add_subregion(&s->iomem_container, aic->reg_offset, 339 &s->iomem); 340 341 qdev_init_gpio_in(dev, aspeed_intc_set_irq, aic->num_ints); 342 343 for (i = 0; i < aic->num_ints; i++) { 344 if (!qdev_realize(DEVICE(&s->orgates[i]), NULL, errp)) { 345 return; 346 } 347 sysbus_init_irq(sbd, &s->output_pins[i]); 348 } 349 } 350 351 static void aspeed_intc_unrealize(DeviceState *dev) 352 { 353 AspeedINTCState *s = ASPEED_INTC(dev); 354 355 g_free(s->regs); 356 s->regs = NULL; 357 } 358 359 static void aspeed_intc_class_init(ObjectClass *klass, void *data) 360 { 361 DeviceClass *dc = DEVICE_CLASS(klass); 362 AspeedINTCClass *aic = ASPEED_INTC_CLASS(klass); 363 364 dc->desc = "ASPEED INTC Controller"; 365 dc->realize = aspeed_intc_realize; 366 dc->unrealize = aspeed_intc_unrealize; 367 device_class_set_legacy_reset(dc, aspeed_intc_reset); 368 dc->vmsd = NULL; 369 370 aic->reg_ops = &aspeed_intc_ops; 371 } 372 373 static const TypeInfo aspeed_intc_info = { 374 .name = TYPE_ASPEED_INTC, 375 .parent = TYPE_SYS_BUS_DEVICE, 376 .instance_init = aspeed_intc_instance_init, 377 .instance_size = sizeof(AspeedINTCState), 378 .class_init = aspeed_intc_class_init, 379 .class_size = sizeof(AspeedINTCClass), 380 .abstract = true, 381 }; 382 383 static void aspeed_2700_intc_class_init(ObjectClass *klass, void *data) 384 { 385 DeviceClass *dc = DEVICE_CLASS(klass); 386 AspeedINTCClass *aic = ASPEED_INTC_CLASS(klass); 387 388 dc->desc = "ASPEED 2700 INTC Controller"; 389 aic->num_lines = 32; 390 aic->num_ints = 9; 391 aic->mem_size = 0x4000; 392 aic->nr_regs = 0x808 >> 2; 393 aic->reg_offset = 0x1000; 394 } 395 396 static const TypeInfo aspeed_2700_intc_info = { 397 .name = TYPE_ASPEED_2700_INTC, 398 .parent = TYPE_ASPEED_INTC, 399 .class_init = aspeed_2700_intc_class_init, 400 }; 401 402 static void aspeed_intc_register_types(void) 403 { 404 type_register_static(&aspeed_intc_info); 405 type_register_static(&aspeed_2700_intc_info); 406 } 407 408 type_init(aspeed_intc_register_types); 409