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