qemu/hw/omap_intc.c
<<
>>
Prefs
   1/*
   2 * TI OMAP interrupt controller emulation.
   3 *
   4 * Copyright (C) 2006-2008 Andrzej Zaborowski  <balrog@zabor.org>
   5 * Copyright (C) 2007-2008 Nokia Corporation
   6 *
   7 * This program is free software; you can redistribute it and/or
   8 * modify it under the terms of the GNU General Public License as
   9 * published by the Free Software Foundation; either version 2 or
  10 * (at your option) version 3 of the License.
  11 *
  12 * This program is distributed in the hope that it will be useful,
  13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15 * GNU General Public License for more details.
  16 *
  17 * You should have received a copy of the GNU General Public License along
  18 * with this program; if not, see <http://www.gnu.org/licenses/>.
  19 */
  20#include "hw.h"
  21#include "omap.h"
  22#include "sysbus.h"
  23
  24/* Interrupt Handlers */
  25struct omap_intr_handler_bank_s {
  26    uint32_t irqs;
  27    uint32_t inputs;
  28    uint32_t mask;
  29    uint32_t fiq;
  30    uint32_t sens_edge;
  31    uint32_t swi;
  32    unsigned char priority[32];
  33};
  34
  35struct omap_intr_handler_s {
  36    SysBusDevice busdev;
  37    qemu_irq *pins;
  38    qemu_irq parent_intr[2];
  39    MemoryRegion mmio;
  40    void *iclk;
  41    void *fclk;
  42    unsigned char nbanks;
  43    int level_only;
  44    uint32_t size;
  45
  46    uint8_t revision;
  47
  48    /* state */
  49    uint32_t new_agr[2];
  50    int sir_intr[2];
  51    int autoidle;
  52    uint32_t mask;
  53    struct omap_intr_handler_bank_s bank[3];
  54};
  55
  56static void omap_inth_sir_update(struct omap_intr_handler_s *s, int is_fiq)
  57{
  58    int i, j, sir_intr, p_intr, p, f;
  59    uint32_t level;
  60    sir_intr = 0;
  61    p_intr = 255;
  62
  63    /* Find the interrupt line with the highest dynamic priority.
  64     * Note: 0 denotes the hightest priority.
  65     * If all interrupts have the same priority, the default order is IRQ_N,
  66     * IRQ_N-1,...,IRQ_0. */
  67    for (j = 0; j < s->nbanks; ++j) {
  68        level = s->bank[j].irqs & ~s->bank[j].mask &
  69                (is_fiq ? s->bank[j].fiq : ~s->bank[j].fiq);
  70        for (f = ffs(level), i = f - 1, level >>= f - 1; f; i += f,
  71                        level >>= f) {
  72            p = s->bank[j].priority[i];
  73            if (p <= p_intr) {
  74                p_intr = p;
  75                sir_intr = 32 * j + i;
  76            }
  77            f = ffs(level >> 1);
  78        }
  79    }
  80    s->sir_intr[is_fiq] = sir_intr;
  81}
  82
  83static inline void omap_inth_update(struct omap_intr_handler_s *s, int is_fiq)
  84{
  85    int i;
  86    uint32_t has_intr = 0;
  87
  88    for (i = 0; i < s->nbanks; ++i)
  89        has_intr |= s->bank[i].irqs & ~s->bank[i].mask &
  90                (is_fiq ? s->bank[i].fiq : ~s->bank[i].fiq);
  91
  92    if (s->new_agr[is_fiq] & has_intr & s->mask) {
  93        s->new_agr[is_fiq] = 0;
  94        omap_inth_sir_update(s, is_fiq);
  95        qemu_set_irq(s->parent_intr[is_fiq], 1);
  96    }
  97}
  98
  99#define INT_FALLING_EDGE        0
 100#define INT_LOW_LEVEL           1
 101
 102static void omap_set_intr(void *opaque, int irq, int req)
 103{
 104    struct omap_intr_handler_s *ih = (struct omap_intr_handler_s *) opaque;
 105    uint32_t rise;
 106
 107    struct omap_intr_handler_bank_s *bank = &ih->bank[irq >> 5];
 108    int n = irq & 31;
 109
 110    if (req) {
 111        rise = ~bank->irqs & (1 << n);
 112        if (~bank->sens_edge & (1 << n))
 113            rise &= ~bank->inputs;
 114
 115        bank->inputs |= (1 << n);
 116        if (rise) {
 117            bank->irqs |= rise;
 118            omap_inth_update(ih, 0);
 119            omap_inth_update(ih, 1);
 120        }
 121    } else {
 122        rise = bank->sens_edge & bank->irqs & (1 << n);
 123        bank->irqs &= ~rise;
 124        bank->inputs &= ~(1 << n);
 125    }
 126}
 127
 128/* Simplified version with no edge detection */
 129static void omap_set_intr_noedge(void *opaque, int irq, int req)
 130{
 131    struct omap_intr_handler_s *ih = (struct omap_intr_handler_s *) opaque;
 132    uint32_t rise;
 133
 134    struct omap_intr_handler_bank_s *bank = &ih->bank[irq >> 5];
 135    int n = irq & 31;
 136
 137    if (req) {
 138        rise = ~bank->inputs & (1 << n);
 139        if (rise) {
 140            bank->irqs |= bank->inputs |= rise;
 141            omap_inth_update(ih, 0);
 142            omap_inth_update(ih, 1);
 143        }
 144    } else
 145        bank->irqs = (bank->inputs &= ~(1 << n)) | bank->swi;
 146}
 147
 148static uint64_t omap_inth_read(void *opaque, target_phys_addr_t addr,
 149                               unsigned size)
 150{
 151    struct omap_intr_handler_s *s = (struct omap_intr_handler_s *) opaque;
 152    int i, offset = addr;
 153    int bank_no = offset >> 8;
 154    int line_no;
 155    struct omap_intr_handler_bank_s *bank = &s->bank[bank_no];
 156    offset &= 0xff;
 157
 158    switch (offset) {
 159    case 0x00:  /* ITR */
 160        return bank->irqs;
 161
 162    case 0x04:  /* MIR */
 163        return bank->mask;
 164
 165    case 0x10:  /* SIR_IRQ_CODE */
 166    case 0x14:  /* SIR_FIQ_CODE */
 167        if (bank_no != 0)
 168            break;
 169        line_no = s->sir_intr[(offset - 0x10) >> 2];
 170        bank = &s->bank[line_no >> 5];
 171        i = line_no & 31;
 172        if (((bank->sens_edge >> i) & 1) == INT_FALLING_EDGE)
 173            bank->irqs &= ~(1 << i);
 174        return line_no;
 175
 176    case 0x18:  /* CONTROL_REG */
 177        if (bank_no != 0)
 178            break;
 179        return 0;
 180
 181    case 0x1c:  /* ILR0 */
 182    case 0x20:  /* ILR1 */
 183    case 0x24:  /* ILR2 */
 184    case 0x28:  /* ILR3 */
 185    case 0x2c:  /* ILR4 */
 186    case 0x30:  /* ILR5 */
 187    case 0x34:  /* ILR6 */
 188    case 0x38:  /* ILR7 */
 189    case 0x3c:  /* ILR8 */
 190    case 0x40:  /* ILR9 */
 191    case 0x44:  /* ILR10 */
 192    case 0x48:  /* ILR11 */
 193    case 0x4c:  /* ILR12 */
 194    case 0x50:  /* ILR13 */
 195    case 0x54:  /* ILR14 */
 196    case 0x58:  /* ILR15 */
 197    case 0x5c:  /* ILR16 */
 198    case 0x60:  /* ILR17 */
 199    case 0x64:  /* ILR18 */
 200    case 0x68:  /* ILR19 */
 201    case 0x6c:  /* ILR20 */
 202    case 0x70:  /* ILR21 */
 203    case 0x74:  /* ILR22 */
 204    case 0x78:  /* ILR23 */
 205    case 0x7c:  /* ILR24 */
 206    case 0x80:  /* ILR25 */
 207    case 0x84:  /* ILR26 */
 208    case 0x88:  /* ILR27 */
 209    case 0x8c:  /* ILR28 */
 210    case 0x90:  /* ILR29 */
 211    case 0x94:  /* ILR30 */
 212    case 0x98:  /* ILR31 */
 213        i = (offset - 0x1c) >> 2;
 214        return (bank->priority[i] << 2) |
 215                (((bank->sens_edge >> i) & 1) << 1) |
 216                ((bank->fiq >> i) & 1);
 217
 218    case 0x9c:  /* ISR */
 219        return 0x00000000;
 220
 221    }
 222    OMAP_BAD_REG(addr);
 223    return 0;
 224}
 225
 226static void omap_inth_write(void *opaque, target_phys_addr_t addr,
 227                            uint64_t value, unsigned size)
 228{
 229    struct omap_intr_handler_s *s = (struct omap_intr_handler_s *) opaque;
 230    int i, offset = addr;
 231    int bank_no = offset >> 8;
 232    struct omap_intr_handler_bank_s *bank = &s->bank[bank_no];
 233    offset &= 0xff;
 234
 235    switch (offset) {
 236    case 0x00:  /* ITR */
 237        /* Important: ignore the clearing if the IRQ is level-triggered and
 238           the input bit is 1 */
 239        bank->irqs &= value | (bank->inputs & bank->sens_edge);
 240        return;
 241
 242    case 0x04:  /* MIR */
 243        bank->mask = value;
 244        omap_inth_update(s, 0);
 245        omap_inth_update(s, 1);
 246        return;
 247
 248    case 0x10:  /* SIR_IRQ_CODE */
 249    case 0x14:  /* SIR_FIQ_CODE */
 250        OMAP_RO_REG(addr);
 251        break;
 252
 253    case 0x18:  /* CONTROL_REG */
 254        if (bank_no != 0)
 255            break;
 256        if (value & 2) {
 257            qemu_set_irq(s->parent_intr[1], 0);
 258            s->new_agr[1] = ~0;
 259            omap_inth_update(s, 1);
 260        }
 261        if (value & 1) {
 262            qemu_set_irq(s->parent_intr[0], 0);
 263            s->new_agr[0] = ~0;
 264            omap_inth_update(s, 0);
 265        }
 266        return;
 267
 268    case 0x1c:  /* ILR0 */
 269    case 0x20:  /* ILR1 */
 270    case 0x24:  /* ILR2 */
 271    case 0x28:  /* ILR3 */
 272    case 0x2c:  /* ILR4 */
 273    case 0x30:  /* ILR5 */
 274    case 0x34:  /* ILR6 */
 275    case 0x38:  /* ILR7 */
 276    case 0x3c:  /* ILR8 */
 277    case 0x40:  /* ILR9 */
 278    case 0x44:  /* ILR10 */
 279    case 0x48:  /* ILR11 */
 280    case 0x4c:  /* ILR12 */
 281    case 0x50:  /* ILR13 */
 282    case 0x54:  /* ILR14 */
 283    case 0x58:  /* ILR15 */
 284    case 0x5c:  /* ILR16 */
 285    case 0x60:  /* ILR17 */
 286    case 0x64:  /* ILR18 */
 287    case 0x68:  /* ILR19 */
 288    case 0x6c:  /* ILR20 */
 289    case 0x70:  /* ILR21 */
 290    case 0x74:  /* ILR22 */
 291    case 0x78:  /* ILR23 */
 292    case 0x7c:  /* ILR24 */
 293    case 0x80:  /* ILR25 */
 294    case 0x84:  /* ILR26 */
 295    case 0x88:  /* ILR27 */
 296    case 0x8c:  /* ILR28 */
 297    case 0x90:  /* ILR29 */
 298    case 0x94:  /* ILR30 */
 299    case 0x98:  /* ILR31 */
 300        i = (offset - 0x1c) >> 2;
 301        bank->priority[i] = (value >> 2) & 0x1f;
 302        bank->sens_edge &= ~(1 << i);
 303        bank->sens_edge |= ((value >> 1) & 1) << i;
 304        bank->fiq &= ~(1 << i);
 305        bank->fiq |= (value & 1) << i;
 306        return;
 307
 308    case 0x9c:  /* ISR */
 309        for (i = 0; i < 32; i ++)
 310            if (value & (1 << i)) {
 311                omap_set_intr(s, 32 * bank_no + i, 1);
 312                return;
 313            }
 314        return;
 315    }
 316    OMAP_BAD_REG(addr);
 317}
 318
 319static const MemoryRegionOps omap_inth_mem_ops = {
 320    .read = omap_inth_read,
 321    .write = omap_inth_write,
 322    .endianness = DEVICE_NATIVE_ENDIAN,
 323    .valid = {
 324        .min_access_size = 4,
 325        .max_access_size = 4,
 326    },
 327};
 328
 329static void omap_inth_reset(DeviceState *dev)
 330{
 331    struct omap_intr_handler_s *s = FROM_SYSBUS(struct omap_intr_handler_s,
 332                                                sysbus_from_qdev(dev));
 333    int i;
 334
 335    for (i = 0; i < s->nbanks; ++i){
 336        s->bank[i].irqs = 0x00000000;
 337        s->bank[i].mask = 0xffffffff;
 338        s->bank[i].sens_edge = 0x00000000;
 339        s->bank[i].fiq = 0x00000000;
 340        s->bank[i].inputs = 0x00000000;
 341        s->bank[i].swi = 0x00000000;
 342        memset(s->bank[i].priority, 0, sizeof(s->bank[i].priority));
 343
 344        if (s->level_only)
 345            s->bank[i].sens_edge = 0xffffffff;
 346    }
 347
 348    s->new_agr[0] = ~0;
 349    s->new_agr[1] = ~0;
 350    s->sir_intr[0] = 0;
 351    s->sir_intr[1] = 0;
 352    s->autoidle = 0;
 353    s->mask = ~0;
 354
 355    qemu_set_irq(s->parent_intr[0], 0);
 356    qemu_set_irq(s->parent_intr[1], 0);
 357}
 358
 359static int omap_intc_init(SysBusDevice *dev)
 360{
 361    struct omap_intr_handler_s *s;
 362    s = FROM_SYSBUS(struct omap_intr_handler_s, dev);
 363    if (!s->iclk) {
 364        hw_error("omap-intc: clk not connected\n");
 365    }
 366    s->nbanks = 1;
 367    sysbus_init_irq(dev, &s->parent_intr[0]);
 368    sysbus_init_irq(dev, &s->parent_intr[1]);
 369    qdev_init_gpio_in(&dev->qdev, omap_set_intr, s->nbanks * 32);
 370    memory_region_init_io(&s->mmio, &omap_inth_mem_ops, s,
 371                          "omap-intc", s->size);
 372    sysbus_init_mmio(dev, &s->mmio);
 373    return 0;
 374}
 375
 376static Property omap_intc_properties[] = {
 377    DEFINE_PROP_UINT32("size", struct omap_intr_handler_s, size, 0x100),
 378    DEFINE_PROP_PTR("clk", struct omap_intr_handler_s, iclk),
 379    DEFINE_PROP_END_OF_LIST(),
 380};
 381
 382static void omap_intc_class_init(ObjectClass *klass, void *data)
 383{
 384    DeviceClass *dc = DEVICE_CLASS(klass);
 385    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
 386
 387    k->init = omap_intc_init;
 388    dc->reset = omap_inth_reset;
 389    dc->props = omap_intc_properties;
 390}
 391
 392static TypeInfo omap_intc_info = {
 393    .name          = "omap-intc",
 394    .parent        = TYPE_SYS_BUS_DEVICE,
 395    .instance_size = sizeof(struct omap_intr_handler_s),
 396    .class_init    = omap_intc_class_init,
 397};
 398
 399static uint64_t omap2_inth_read(void *opaque, target_phys_addr_t addr,
 400                                unsigned size)
 401{
 402    struct omap_intr_handler_s *s = (struct omap_intr_handler_s *) opaque;
 403    int offset = addr;
 404    int bank_no, line_no;
 405    struct omap_intr_handler_bank_s *bank = NULL;
 406
 407    if ((offset & 0xf80) == 0x80) {
 408        bank_no = (offset & 0x60) >> 5;
 409        if (bank_no < s->nbanks) {
 410            offset &= ~0x60;
 411            bank = &s->bank[bank_no];
 412        } else {
 413            OMAP_BAD_REG(addr);
 414            return 0;
 415        }
 416    }
 417
 418    switch (offset) {
 419    case 0x00:  /* INTC_REVISION */
 420        return s->revision;
 421
 422    case 0x10:  /* INTC_SYSCONFIG */
 423        return (s->autoidle >> 2) & 1;
 424
 425    case 0x14:  /* INTC_SYSSTATUS */
 426        return 1;                                               /* RESETDONE */
 427
 428    case 0x40:  /* INTC_SIR_IRQ */
 429        return s->sir_intr[0];
 430
 431    case 0x44:  /* INTC_SIR_FIQ */
 432        return s->sir_intr[1];
 433
 434    case 0x48:  /* INTC_CONTROL */
 435        return (!s->mask) << 2;                                 /* GLOBALMASK */
 436
 437    case 0x4c:  /* INTC_PROTECTION */
 438        return 0;
 439
 440    case 0x50:  /* INTC_IDLE */
 441        return s->autoidle & 3;
 442
 443    /* Per-bank registers */
 444    case 0x80:  /* INTC_ITR */
 445        return bank->inputs;
 446
 447    case 0x84:  /* INTC_MIR */
 448        return bank->mask;
 449
 450    case 0x88:  /* INTC_MIR_CLEAR */
 451    case 0x8c:  /* INTC_MIR_SET */
 452        return 0;
 453
 454    case 0x90:  /* INTC_ISR_SET */
 455        return bank->swi;
 456
 457    case 0x94:  /* INTC_ISR_CLEAR */
 458        return 0;
 459
 460    case 0x98:  /* INTC_PENDING_IRQ */
 461        return bank->irqs & ~bank->mask & ~bank->fiq;
 462
 463    case 0x9c:  /* INTC_PENDING_FIQ */
 464        return bank->irqs & ~bank->mask & bank->fiq;
 465
 466    /* Per-line registers */
 467    case 0x100 ... 0x300:       /* INTC_ILR */
 468        bank_no = (offset - 0x100) >> 7;
 469        if (bank_no > s->nbanks)
 470            break;
 471        bank = &s->bank[bank_no];
 472        line_no = (offset & 0x7f) >> 2;
 473        return (bank->priority[line_no] << 2) |
 474                ((bank->fiq >> line_no) & 1);
 475    }
 476    OMAP_BAD_REG(addr);
 477    return 0;
 478}
 479
 480static void omap2_inth_write(void *opaque, target_phys_addr_t addr,
 481                             uint64_t value, unsigned size)
 482{
 483    struct omap_intr_handler_s *s = (struct omap_intr_handler_s *) opaque;
 484    int offset = addr;
 485    int bank_no, line_no;
 486    struct omap_intr_handler_bank_s *bank = NULL;
 487
 488    if ((offset & 0xf80) == 0x80) {
 489        bank_no = (offset & 0x60) >> 5;
 490        if (bank_no < s->nbanks) {
 491            offset &= ~0x60;
 492            bank = &s->bank[bank_no];
 493        } else {
 494            OMAP_BAD_REG(addr);
 495            return;
 496        }
 497    }
 498
 499    switch (offset) {
 500    case 0x10:  /* INTC_SYSCONFIG */
 501        s->autoidle &= 4;
 502        s->autoidle |= (value & 1) << 2;
 503        if (value & 2)                                          /* SOFTRESET */
 504            omap_inth_reset(&s->busdev.qdev);
 505        return;
 506
 507    case 0x48:  /* INTC_CONTROL */
 508        s->mask = (value & 4) ? 0 : ~0;                         /* GLOBALMASK */
 509        if (value & 2) {                                        /* NEWFIQAGR */
 510            qemu_set_irq(s->parent_intr[1], 0);
 511            s->new_agr[1] = ~0;
 512            omap_inth_update(s, 1);
 513        }
 514        if (value & 1) {                                        /* NEWIRQAGR */
 515            qemu_set_irq(s->parent_intr[0], 0);
 516            s->new_agr[0] = ~0;
 517            omap_inth_update(s, 0);
 518        }
 519        return;
 520
 521    case 0x4c:  /* INTC_PROTECTION */
 522        /* TODO: Make a bitmap (or sizeof(char)map) of access privileges
 523         * for every register, see Chapter 3 and 4 for privileged mode.  */
 524        if (value & 1)
 525            fprintf(stderr, "%s: protection mode enable attempt\n",
 526                            __FUNCTION__);
 527        return;
 528
 529    case 0x50:  /* INTC_IDLE */
 530        s->autoidle &= ~3;
 531        s->autoidle |= value & 3;
 532        return;
 533
 534    /* Per-bank registers */
 535    case 0x84:  /* INTC_MIR */
 536        bank->mask = value;
 537        omap_inth_update(s, 0);
 538        omap_inth_update(s, 1);
 539        return;
 540
 541    case 0x88:  /* INTC_MIR_CLEAR */
 542        bank->mask &= ~value;
 543        omap_inth_update(s, 0);
 544        omap_inth_update(s, 1);
 545        return;
 546
 547    case 0x8c:  /* INTC_MIR_SET */
 548        bank->mask |= value;
 549        return;
 550
 551    case 0x90:  /* INTC_ISR_SET */
 552        bank->irqs |= bank->swi |= value;
 553        omap_inth_update(s, 0);
 554        omap_inth_update(s, 1);
 555        return;
 556
 557    case 0x94:  /* INTC_ISR_CLEAR */
 558        bank->swi &= ~value;
 559        bank->irqs = bank->swi & bank->inputs;
 560        return;
 561
 562    /* Per-line registers */
 563    case 0x100 ... 0x300:       /* INTC_ILR */
 564        bank_no = (offset - 0x100) >> 7;
 565        if (bank_no > s->nbanks)
 566            break;
 567        bank = &s->bank[bank_no];
 568        line_no = (offset & 0x7f) >> 2;
 569        bank->priority[line_no] = (value >> 2) & 0x3f;
 570        bank->fiq &= ~(1 << line_no);
 571        bank->fiq |= (value & 1) << line_no;
 572        return;
 573
 574    case 0x00:  /* INTC_REVISION */
 575    case 0x14:  /* INTC_SYSSTATUS */
 576    case 0x40:  /* INTC_SIR_IRQ */
 577    case 0x44:  /* INTC_SIR_FIQ */
 578    case 0x80:  /* INTC_ITR */
 579    case 0x98:  /* INTC_PENDING_IRQ */
 580    case 0x9c:  /* INTC_PENDING_FIQ */
 581        OMAP_RO_REG(addr);
 582        return;
 583    }
 584    OMAP_BAD_REG(addr);
 585}
 586
 587static const MemoryRegionOps omap2_inth_mem_ops = {
 588    .read = omap2_inth_read,
 589    .write = omap2_inth_write,
 590    .endianness = DEVICE_NATIVE_ENDIAN,
 591    .valid = {
 592        .min_access_size = 4,
 593        .max_access_size = 4,
 594    },
 595};
 596
 597static int omap2_intc_init(SysBusDevice *dev)
 598{
 599    struct omap_intr_handler_s *s;
 600    s = FROM_SYSBUS(struct omap_intr_handler_s, dev);
 601    if (!s->iclk) {
 602        hw_error("omap2-intc: iclk not connected\n");
 603    }
 604    if (!s->fclk) {
 605        hw_error("omap2-intc: fclk not connected\n");
 606    }
 607    s->level_only = 1;
 608    s->nbanks = 3;
 609    sysbus_init_irq(dev, &s->parent_intr[0]);
 610    sysbus_init_irq(dev, &s->parent_intr[1]);
 611    qdev_init_gpio_in(&dev->qdev, omap_set_intr_noedge, s->nbanks * 32);
 612    memory_region_init_io(&s->mmio, &omap2_inth_mem_ops, s,
 613                          "omap2-intc", 0x1000);
 614    sysbus_init_mmio(dev, &s->mmio);
 615    return 0;
 616}
 617
 618static Property omap2_intc_properties[] = {
 619    DEFINE_PROP_UINT8("revision", struct omap_intr_handler_s,
 620    revision, 0x21),
 621    DEFINE_PROP_PTR("iclk", struct omap_intr_handler_s, iclk),
 622    DEFINE_PROP_PTR("fclk", struct omap_intr_handler_s, fclk),
 623    DEFINE_PROP_END_OF_LIST(),
 624};
 625
 626static void omap2_intc_class_init(ObjectClass *klass, void *data)
 627{
 628    DeviceClass *dc = DEVICE_CLASS(klass);
 629    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
 630
 631    k->init = omap2_intc_init;
 632    dc->reset = omap_inth_reset;
 633    dc->props = omap2_intc_properties;
 634}
 635
 636static TypeInfo omap2_intc_info = {
 637    .name          = "omap2-intc",
 638    .parent        = TYPE_SYS_BUS_DEVICE,
 639    .instance_size = sizeof(struct omap_intr_handler_s),
 640    .class_init    = omap2_intc_class_init,
 641};
 642
 643static void omap_intc_register_types(void)
 644{
 645    type_register_static(&omap_intc_info);
 646    type_register_static(&omap2_intc_info);
 647}
 648
 649type_init(omap_intc_register_types)
 650