cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

omap_intc.c (18740B)


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