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 49 if (irq >= aic->num_ints) { 50 qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid interrupt number: %d\n", 51 __func__, irq); 52 return; 53 } 54 55 trace_aspeed_intc_update_irq(irq, level); 56 qemu_set_irq(s->output_pins[irq], level); 57 } 58 59 /* 60 * The address of GICINT128 to GICINT136 are from 0x1000 to 0x1804. 61 * Utilize "address & 0x0f00" to get the irq and irq output pin index 62 * The value of irq should be 0 to num_ints. 63 * The irq 0 indicates GICINT128, irq 1 indicates GICINT129 and so on. 64 */ 65 static void aspeed_intc_set_irq(void *opaque, int irq, int level) 66 { 67 AspeedINTCState *s = (AspeedINTCState *)opaque; 68 AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s); 69 uint32_t status_reg = GICINT_STATUS_BASE + ((0x100 * irq) >> 2); 70 uint32_t select = 0; 71 uint32_t enable; 72 int i; 73 74 if (irq >= aic->num_ints) { 75 qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid interrupt number: %d\n", 76 __func__, irq); 77 return; 78 } 79 80 trace_aspeed_intc_set_irq(irq, level); 81 enable = s->enable[irq]; 82 83 if (!level) { 84 return; 85 } 86 87 for (i = 0; i < aic->num_lines; i++) { 88 if (s->orgates[irq].levels[i]) { 89 if (enable & BIT(i)) { 90 select |= BIT(i); 91 } 92 } 93 } 94 95 if (!select) { 96 return; 97 } 98 99 trace_aspeed_intc_select(select); 100 101 if (s->mask[irq] || s->regs[status_reg]) { 102 /* 103 * a. mask is not 0 means in ISR mode 104 * sources interrupt routine are executing. 105 * b. status register value is not 0 means previous 106 * source interrupt does not be executed, yet. 107 * 108 * save source interrupt to pending variable. 109 */ 110 s->pending[irq] |= select; 111 trace_aspeed_intc_pending_irq(irq, s->pending[irq]); 112 } else { 113 /* 114 * notify firmware which source interrupt are coming 115 * by setting status register 116 */ 117 s->regs[status_reg] = select; 118 trace_aspeed_intc_trigger_irq(irq, s->regs[status_reg]); 119 aspeed_intc_update(s, irq, 1); 120 } 121 } 122 123 static uint64_t aspeed_intc_read(void *opaque, hwaddr offset, unsigned int size) 124 { 125 AspeedINTCState *s = ASPEED_INTC(opaque); 126 uint32_t reg = offset >> 2; 127 uint32_t value = 0; 128 129 value = s->regs[reg]; 130 trace_aspeed_intc_read(offset, size, value); 131 132 return value; 133 } 134 135 static void aspeed_intc_write(void *opaque, hwaddr offset, uint64_t data, 136 unsigned size) 137 { 138 AspeedINTCState *s = ASPEED_INTC(opaque); 139 AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s); 140 uint32_t reg = offset >> 2; 141 uint32_t old_enable; 142 uint32_t change; 143 uint32_t irq; 144 145 trace_aspeed_intc_write(offset, size, data); 146 147 switch (reg) { 148 case R_GICINT128_EN: 149 case R_GICINT129_EN: 150 case R_GICINT130_EN: 151 case R_GICINT131_EN: 152 case R_GICINT132_EN: 153 case R_GICINT133_EN: 154 case R_GICINT134_EN: 155 case R_GICINT135_EN: 156 case R_GICINT136_EN: 157 irq = (offset & 0x0f00) >> 8; 158 159 if (irq >= aic->num_ints) { 160 qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid interrupt number: %d\n", 161 __func__, irq); 162 return; 163 } 164 165 /* 166 * These registers are used for enable sources interrupt and 167 * mask and unmask source interrupt while executing source ISR. 168 */ 169 170 /* disable all source interrupt */ 171 if (!data && !s->enable[irq]) { 172 s->regs[reg] = data; 173 return; 174 } 175 176 old_enable = s->enable[irq]; 177 s->enable[irq] |= data; 178 179 /* enable new source interrupt */ 180 if (old_enable != s->enable[irq]) { 181 trace_aspeed_intc_enable(s->enable[irq]); 182 s->regs[reg] = data; 183 return; 184 } 185 186 /* mask and unmask source interrupt */ 187 change = s->regs[reg] ^ data; 188 if (change & data) { 189 s->mask[irq] &= ~change; 190 trace_aspeed_intc_unmask(change, s->mask[irq]); 191 } else { 192 s->mask[irq] |= change; 193 trace_aspeed_intc_mask(change, s->mask[irq]); 194 } 195 s->regs[reg] = data; 196 break; 197 case R_GICINT128_STATUS: 198 case R_GICINT129_STATUS: 199 case R_GICINT130_STATUS: 200 case R_GICINT131_STATUS: 201 case R_GICINT132_STATUS: 202 case R_GICINT133_STATUS: 203 case R_GICINT134_STATUS: 204 case R_GICINT135_STATUS: 205 case R_GICINT136_STATUS: 206 irq = (offset & 0x0f00) >> 8; 207 208 if (irq >= aic->num_ints) { 209 qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid interrupt number: %d\n", 210 __func__, irq); 211 return; 212 } 213 214 /* clear status */ 215 s->regs[reg] &= ~data; 216 217 /* 218 * These status registers are used for notify sources ISR are executed. 219 * If one source ISR is executed, it will clear one bit. 220 * If it clear all bits, it means to initialize this register status 221 * rather than sources ISR are executed. 222 */ 223 if (data == 0xffffffff) { 224 return; 225 } 226 227 /* All source ISR execution are done */ 228 if (!s->regs[reg]) { 229 trace_aspeed_intc_all_isr_done(irq); 230 if (s->pending[irq]) { 231 /* 232 * handle pending source interrupt 233 * notify firmware which source interrupt are pending 234 * by setting status register 235 */ 236 s->regs[reg] = s->pending[irq]; 237 s->pending[irq] = 0; 238 trace_aspeed_intc_trigger_irq(irq, s->regs[reg]); 239 aspeed_intc_update(s, irq, 1); 240 } else { 241 /* clear irq */ 242 trace_aspeed_intc_clear_irq(irq, 0); 243 aspeed_intc_update(s, irq, 0); 244 } 245 } 246 break; 247 default: 248 s->regs[reg] = data; 249 break; 250 } 251 252 return; 253 } 254 255 static const MemoryRegionOps aspeed_intc_ops = { 256 .read = aspeed_intc_read, 257 .write = aspeed_intc_write, 258 .endianness = DEVICE_LITTLE_ENDIAN, 259 .valid = { 260 .min_access_size = 4, 261 .max_access_size = 4, 262 } 263 }; 264 265 static void aspeed_intc_instance_init(Object *obj) 266 { 267 AspeedINTCState *s = ASPEED_INTC(obj); 268 AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s); 269 int i; 270 271 assert(aic->num_ints <= ASPEED_INTC_NR_INTS); 272 for (i = 0; i < aic->num_ints; i++) { 273 object_initialize_child(obj, "intc-orgates[*]", &s->orgates[i], 274 TYPE_OR_IRQ); 275 object_property_set_int(OBJECT(&s->orgates[i]), "num-lines", 276 aic->num_lines, &error_abort); 277 } 278 } 279 280 static void aspeed_intc_reset(DeviceState *dev) 281 { 282 AspeedINTCState *s = ASPEED_INTC(dev); 283 AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s); 284 285 memset(s->regs, 0, aic->nr_regs << 2); 286 memset(s->enable, 0, sizeof(s->enable)); 287 memset(s->mask, 0, sizeof(s->mask)); 288 memset(s->pending, 0, sizeof(s->pending)); 289 } 290 291 static void aspeed_intc_realize(DeviceState *dev, Error **errp) 292 { 293 SysBusDevice *sbd = SYS_BUS_DEVICE(dev); 294 AspeedINTCState *s = ASPEED_INTC(dev); 295 AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s); 296 int i; 297 298 memory_region_init(&s->iomem_container, OBJECT(s), 299 TYPE_ASPEED_INTC ".container", aic->mem_size); 300 301 sysbus_init_mmio(sbd, &s->iomem_container); 302 303 s->regs = g_new(uint32_t, aic->nr_regs); 304 memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_intc_ops, s, 305 TYPE_ASPEED_INTC ".regs", aic->nr_regs << 2); 306 307 memory_region_add_subregion(&s->iomem_container, aic->reg_offset, 308 &s->iomem); 309 310 qdev_init_gpio_in(dev, aspeed_intc_set_irq, aic->num_ints); 311 312 for (i = 0; i < aic->num_ints; i++) { 313 if (!qdev_realize(DEVICE(&s->orgates[i]), NULL, errp)) { 314 return; 315 } 316 sysbus_init_irq(sbd, &s->output_pins[i]); 317 } 318 } 319 320 static void aspeed_intc_unrealize(DeviceState *dev) 321 { 322 AspeedINTCState *s = ASPEED_INTC(dev); 323 324 g_free(s->regs); 325 s->regs = NULL; 326 } 327 328 static void aspeed_intc_class_init(ObjectClass *klass, void *data) 329 { 330 DeviceClass *dc = DEVICE_CLASS(klass); 331 332 dc->desc = "ASPEED INTC Controller"; 333 dc->realize = aspeed_intc_realize; 334 dc->unrealize = aspeed_intc_unrealize; 335 device_class_set_legacy_reset(dc, aspeed_intc_reset); 336 dc->vmsd = NULL; 337 } 338 339 static const TypeInfo aspeed_intc_info = { 340 .name = TYPE_ASPEED_INTC, 341 .parent = TYPE_SYS_BUS_DEVICE, 342 .instance_init = aspeed_intc_instance_init, 343 .instance_size = sizeof(AspeedINTCState), 344 .class_init = aspeed_intc_class_init, 345 .class_size = sizeof(AspeedINTCClass), 346 .abstract = true, 347 }; 348 349 static void aspeed_2700_intc_class_init(ObjectClass *klass, void *data) 350 { 351 DeviceClass *dc = DEVICE_CLASS(klass); 352 AspeedINTCClass *aic = ASPEED_INTC_CLASS(klass); 353 354 dc->desc = "ASPEED 2700 INTC Controller"; 355 aic->num_lines = 32; 356 aic->num_ints = 9; 357 aic->mem_size = 0x4000; 358 aic->nr_regs = 0x808 >> 2; 359 aic->reg_offset = 0x1000; 360 } 361 362 static const TypeInfo aspeed_2700_intc_info = { 363 .name = TYPE_ASPEED_2700_INTC, 364 .parent = TYPE_ASPEED_INTC, 365 .class_init = aspeed_2700_intc_class_init, 366 }; 367 368 static void aspeed_intc_register_types(void) 369 { 370 type_register_static(&aspeed_intc_info); 371 type_register_static(&aspeed_2700_intc_info); 372 } 373 374 type_init(aspeed_intc_register_types); 375