1 /* 2 * i.MX31 Vectored Interrupt Controller 3 * 4 * Note this is NOT the PL192 provided by ARM, but 5 * a custom implementation by Freescale. 6 * 7 * Copyright (c) 2008 OKL 8 * Copyright (c) 2011 NICTA Pty Ltd 9 * Originally written by Hans Jiang 10 * Updated by Jean-Christophe Dubois <jcd@tribudubois.net> 11 * 12 * This code is licensed under the GPL version 2 or later. See 13 * the COPYING file in the top-level directory. 14 * 15 * TODO: implement vectors. 16 */ 17 18 #include "hw/intc/imx_avic.h" 19 20 #define DEBUG_INT 1 21 #undef DEBUG_INT /* comment out for debugging */ 22 23 #ifdef DEBUG_INT 24 #define DPRINTF(fmt, args...) \ 25 do { printf("imx_avic: " fmt , ##args); } while (0) 26 #else 27 #define DPRINTF(fmt, args...) do {} while (0) 28 #endif 29 30 /* 31 * Define to 1 for messages about attempts to 32 * access unimplemented registers or similar. 33 */ 34 #define DEBUG_IMPLEMENTATION 1 35 #if DEBUG_IMPLEMENTATION 36 # define IPRINTF(fmt, args...) \ 37 do { fprintf(stderr, "imx_avic: " fmt, ##args); } while (0) 38 #else 39 # define IPRINTF(fmt, args...) do {} while (0) 40 #endif 41 42 static const VMStateDescription vmstate_imx_avic = { 43 .name = "imx-avic", 44 .version_id = 1, 45 .minimum_version_id = 1, 46 .fields = (VMStateField[]) { 47 VMSTATE_UINT64(pending, IMXAVICState), 48 VMSTATE_UINT64(enabled, IMXAVICState), 49 VMSTATE_UINT64(is_fiq, IMXAVICState), 50 VMSTATE_UINT32(intcntl, IMXAVICState), 51 VMSTATE_UINT32(intmask, IMXAVICState), 52 VMSTATE_UINT32_ARRAY(prio, IMXAVICState, PRIO_WORDS), 53 VMSTATE_END_OF_LIST() 54 }, 55 }; 56 57 58 59 static inline int imx_avic_prio(IMXAVICState *s, int irq) 60 { 61 uint32_t word = irq / PRIO_PER_WORD; 62 uint32_t part = 4 * (irq % PRIO_PER_WORD); 63 return 0xf & (s->prio[word] >> part); 64 } 65 66 /* Update interrupts. */ 67 static void imx_avic_update(IMXAVICState *s) 68 { 69 int i; 70 uint64_t new = s->pending & s->enabled; 71 uint64_t flags; 72 73 flags = new & s->is_fiq; 74 qemu_set_irq(s->fiq, !!flags); 75 76 flags = new & ~s->is_fiq; 77 if (!flags || (s->intmask == 0x1f)) { 78 qemu_set_irq(s->irq, !!flags); 79 return; 80 } 81 82 /* 83 * Take interrupt if there's a pending interrupt with 84 * priority higher than the value of intmask 85 */ 86 for (i = 0; i < IMX_AVIC_NUM_IRQS; i++) { 87 if (flags & (1UL << i)) { 88 if (imx_avic_prio(s, i) > s->intmask) { 89 qemu_set_irq(s->irq, 1); 90 return; 91 } 92 } 93 } 94 qemu_set_irq(s->irq, 0); 95 } 96 97 static void imx_avic_set_irq(void *opaque, int irq, int level) 98 { 99 IMXAVICState *s = (IMXAVICState *)opaque; 100 101 if (level) { 102 DPRINTF("Raising IRQ %d, prio %d\n", 103 irq, imx_avic_prio(s, irq)); 104 s->pending |= (1ULL << irq); 105 } else { 106 DPRINTF("Clearing IRQ %d, prio %d\n", 107 irq, imx_avic_prio(s, irq)); 108 s->pending &= ~(1ULL << irq); 109 } 110 111 imx_avic_update(s); 112 } 113 114 115 static uint64_t imx_avic_read(void *opaque, 116 hwaddr offset, unsigned size) 117 { 118 IMXAVICState *s = (IMXAVICState *)opaque; 119 120 121 DPRINTF("read(offset = 0x%x)\n", offset >> 2); 122 switch (offset >> 2) { 123 case 0: /* INTCNTL */ 124 return s->intcntl; 125 126 case 1: /* Normal Interrupt Mask Register, NIMASK */ 127 return s->intmask; 128 129 case 2: /* Interrupt Enable Number Register, INTENNUM */ 130 case 3: /* Interrupt Disable Number Register, INTDISNUM */ 131 return 0; 132 133 case 4: /* Interrupt Enabled Number Register High */ 134 return s->enabled >> 32; 135 136 case 5: /* Interrupt Enabled Number Register Low */ 137 return s->enabled & 0xffffffffULL; 138 139 case 6: /* Interrupt Type Register High */ 140 return s->is_fiq >> 32; 141 142 case 7: /* Interrupt Type Register Low */ 143 return s->is_fiq & 0xffffffffULL; 144 145 case 8: /* Normal Interrupt Priority Register 7 */ 146 case 9: /* Normal Interrupt Priority Register 6 */ 147 case 10:/* Normal Interrupt Priority Register 5 */ 148 case 11:/* Normal Interrupt Priority Register 4 */ 149 case 12:/* Normal Interrupt Priority Register 3 */ 150 case 13:/* Normal Interrupt Priority Register 2 */ 151 case 14:/* Normal Interrupt Priority Register 1 */ 152 case 15:/* Normal Interrupt Priority Register 0 */ 153 return s->prio[15-(offset>>2)]; 154 155 case 16: /* Normal interrupt vector and status register */ 156 { 157 /* 158 * This returns the highest priority 159 * outstanding interrupt. Where there is more than 160 * one pending IRQ with the same priority, 161 * take the highest numbered one. 162 */ 163 uint64_t flags = s->pending & s->enabled & ~s->is_fiq; 164 int i; 165 int prio = -1; 166 int irq = -1; 167 for (i = 63; i >= 0; --i) { 168 if (flags & (1ULL<<i)) { 169 int irq_prio = imx_avic_prio(s, i); 170 if (irq_prio > prio) { 171 irq = i; 172 prio = irq_prio; 173 } 174 } 175 } 176 if (irq >= 0) { 177 imx_avic_set_irq(s, irq, 0); 178 return irq << 16 | prio; 179 } 180 return 0xffffffffULL; 181 } 182 case 17:/* Fast Interrupt vector and status register */ 183 { 184 uint64_t flags = s->pending & s->enabled & s->is_fiq; 185 int i = ctz64(flags); 186 if (i < 64) { 187 imx_avic_set_irq(opaque, i, 0); 188 return i; 189 } 190 return 0xffffffffULL; 191 } 192 case 18:/* Interrupt source register high */ 193 return s->pending >> 32; 194 195 case 19:/* Interrupt source register low */ 196 return s->pending & 0xffffffffULL; 197 198 case 20:/* Interrupt Force Register high */ 199 case 21:/* Interrupt Force Register low */ 200 return 0; 201 202 case 22:/* Normal Interrupt Pending Register High */ 203 return (s->pending & s->enabled & ~s->is_fiq) >> 32; 204 205 case 23:/* Normal Interrupt Pending Register Low */ 206 return (s->pending & s->enabled & ~s->is_fiq) & 0xffffffffULL; 207 208 case 24: /* Fast Interrupt Pending Register High */ 209 return (s->pending & s->enabled & s->is_fiq) >> 32; 210 211 case 25: /* Fast Interrupt Pending Register Low */ 212 return (s->pending & s->enabled & s->is_fiq) & 0xffffffffULL; 213 214 case 0x40: /* AVIC vector 0, use for WFI WAR */ 215 return 0x4; 216 217 default: 218 IPRINTF("imx_avic_read: Bad offset 0x%x\n", (int)offset); 219 return 0; 220 } 221 } 222 223 static void imx_avic_write(void *opaque, hwaddr offset, 224 uint64_t val, unsigned size) 225 { 226 IMXAVICState *s = (IMXAVICState *)opaque; 227 228 /* Vector Registers not yet supported */ 229 if (offset >= 0x100 && offset <= 0x2fc) { 230 IPRINTF("imx_avic_write to vector register %d ignored\n", 231 (unsigned int)((offset - 0x100) >> 2)); 232 return; 233 } 234 235 DPRINTF("imx_avic_write(0x%x) = %x\n", 236 (unsigned int)offset>>2, (unsigned int)val); 237 switch (offset >> 2) { 238 case 0: /* Interrupt Control Register, INTCNTL */ 239 s->intcntl = val & (ABFEN | NIDIS | FIDIS | NIAD | FIAD | NM); 240 if (s->intcntl & ABFEN) { 241 s->intcntl &= ~(val & ABFLAG); 242 } 243 break; 244 245 case 1: /* Normal Interrupt Mask Register, NIMASK */ 246 s->intmask = val & 0x1f; 247 break; 248 249 case 2: /* Interrupt Enable Number Register, INTENNUM */ 250 DPRINTF("enable(%d)\n", (int)val); 251 val &= 0x3f; 252 s->enabled |= (1ULL << val); 253 break; 254 255 case 3: /* Interrupt Disable Number Register, INTDISNUM */ 256 DPRINTF("disable(%d)\n", (int)val); 257 val &= 0x3f; 258 s->enabled &= ~(1ULL << val); 259 break; 260 261 case 4: /* Interrupt Enable Number Register High */ 262 s->enabled = (s->enabled & 0xffffffffULL) | (val << 32); 263 break; 264 265 case 5: /* Interrupt Enable Number Register Low */ 266 s->enabled = (s->enabled & 0xffffffff00000000ULL) | val; 267 break; 268 269 case 6: /* Interrupt Type Register High */ 270 s->is_fiq = (s->is_fiq & 0xffffffffULL) | (val << 32); 271 break; 272 273 case 7: /* Interrupt Type Register Low */ 274 s->is_fiq = (s->is_fiq & 0xffffffff00000000ULL) | val; 275 break; 276 277 case 8: /* Normal Interrupt Priority Register 7 */ 278 case 9: /* Normal Interrupt Priority Register 6 */ 279 case 10:/* Normal Interrupt Priority Register 5 */ 280 case 11:/* Normal Interrupt Priority Register 4 */ 281 case 12:/* Normal Interrupt Priority Register 3 */ 282 case 13:/* Normal Interrupt Priority Register 2 */ 283 case 14:/* Normal Interrupt Priority Register 1 */ 284 case 15:/* Normal Interrupt Priority Register 0 */ 285 s->prio[15-(offset>>2)] = val; 286 break; 287 288 /* Read-only registers, writes ignored */ 289 case 16:/* Normal Interrupt Vector and Status register */ 290 case 17:/* Fast Interrupt vector and status register */ 291 case 18:/* Interrupt source register high */ 292 case 19:/* Interrupt source register low */ 293 return; 294 295 case 20:/* Interrupt Force Register high */ 296 s->pending = (s->pending & 0xffffffffULL) | (val << 32); 297 break; 298 299 case 21:/* Interrupt Force Register low */ 300 s->pending = (s->pending & 0xffffffff00000000ULL) | val; 301 break; 302 303 case 22:/* Normal Interrupt Pending Register High */ 304 case 23:/* Normal Interrupt Pending Register Low */ 305 case 24: /* Fast Interrupt Pending Register High */ 306 case 25: /* Fast Interrupt Pending Register Low */ 307 return; 308 309 default: 310 IPRINTF("imx_avic_write: Bad offset %x\n", (int)offset); 311 } 312 imx_avic_update(s); 313 } 314 315 static const MemoryRegionOps imx_avic_ops = { 316 .read = imx_avic_read, 317 .write = imx_avic_write, 318 .endianness = DEVICE_NATIVE_ENDIAN, 319 }; 320 321 static void imx_avic_reset(DeviceState *dev) 322 { 323 IMXAVICState *s = IMX_AVIC(dev); 324 325 s->pending = 0; 326 s->enabled = 0; 327 s->is_fiq = 0; 328 s->intmask = 0x1f; 329 s->intcntl = 0; 330 memset(s->prio, 0, sizeof s->prio); 331 } 332 333 static int imx_avic_init(SysBusDevice *sbd) 334 { 335 DeviceState *dev = DEVICE(sbd); 336 IMXAVICState *s = IMX_AVIC(dev); 337 338 memory_region_init_io(&s->iomem, OBJECT(s), &imx_avic_ops, s, 339 TYPE_IMX_AVIC, 0x1000); 340 sysbus_init_mmio(sbd, &s->iomem); 341 342 qdev_init_gpio_in(dev, imx_avic_set_irq, IMX_AVIC_NUM_IRQS); 343 sysbus_init_irq(sbd, &s->irq); 344 sysbus_init_irq(sbd, &s->fiq); 345 346 return 0; 347 } 348 349 350 static void imx_avic_class_init(ObjectClass *klass, void *data) 351 { 352 DeviceClass *dc = DEVICE_CLASS(klass); 353 SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); 354 k->init = imx_avic_init; 355 dc->vmsd = &vmstate_imx_avic; 356 dc->reset = imx_avic_reset; 357 dc->desc = "i.MX Advanced Vector Interrupt Controller"; 358 } 359 360 static const TypeInfo imx_avic_info = { 361 .name = TYPE_IMX_AVIC, 362 .parent = TYPE_SYS_BUS_DEVICE, 363 .instance_size = sizeof(IMXAVICState), 364 .class_init = imx_avic_class_init, 365 }; 366 367 static void imx_avic_register_types(void) 368 { 369 type_register_static(&imx_avic_info); 370 } 371 372 type_init(imx_avic_register_types) 373