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