aboutsummaryrefslogtreecommitdiff
path: root/hw/intc/omap_intc.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/intc/omap_intc.c')
-rw-r--r--hw/intc/omap_intc.c448
1 files changed, 82 insertions, 366 deletions
diff --git a/hw/intc/omap_intc.c b/hw/intc/omap_intc.c
index 435c476..c61158b 100644
--- a/hw/intc/omap_intc.c
+++ b/hw/intc/omap_intc.c
@@ -50,8 +50,6 @@ struct OMAPIntcState {
int level_only;
uint32_t size;
- uint8_t revision;
-
/* state */
uint32_t new_agr[2];
int sir_intr[2];
@@ -104,8 +102,8 @@ static inline void omap_inth_update(OMAPIntcState *s, int is_fiq)
}
}
-#define INT_FALLING_EDGE 0
-#define INT_LOW_LEVEL 1
+#define INT_FALLING_EDGE 0
+#define INT_LOW_LEVEL 1
static void omap_set_intr(void *opaque, int irq, int req)
{
@@ -133,26 +131,6 @@ static void omap_set_intr(void *opaque, int irq, int req)
}
}
-/* Simplified version with no edge detection */
-static void omap_set_intr_noedge(void *opaque, int irq, int req)
-{
- OMAPIntcState *ih = opaque;
- uint32_t rise;
-
- struct omap_intr_handler_bank_s *bank = &ih->bank[irq >> 5];
- int n = irq & 31;
-
- if (req) {
- rise = ~bank->inputs & (1 << n);
- if (rise) {
- bank->irqs |= bank->inputs |= rise;
- omap_inth_update(ih, 0);
- omap_inth_update(ih, 1);
- }
- } else
- bank->irqs = (bank->inputs &= ~(1 << n)) | bank->swi;
-}
-
static uint64_t omap_inth_read(void *opaque, hwaddr addr,
unsigned size)
{
@@ -164,13 +142,13 @@ static uint64_t omap_inth_read(void *opaque, hwaddr addr,
offset &= 0xff;
switch (offset) {
- case 0x00: /* ITR */
+ case 0x00: /* ITR */
return bank->irqs;
- case 0x04: /* MIR */
+ case 0x04: /* MIR */
return bank->mask;
- case 0x10: /* SIR_IRQ_CODE */
+ case 0x10: /* SIR_IRQ_CODE */
case 0x14: /* SIR_FIQ_CODE */
if (bank_no != 0)
break;
@@ -181,49 +159,49 @@ static uint64_t omap_inth_read(void *opaque, hwaddr addr,
bank->irqs &= ~(1 << i);
return line_no;
- case 0x18: /* CONTROL_REG */
+ case 0x18: /* CONTROL_REG */
if (bank_no != 0)
break;
return 0;
- case 0x1c: /* ILR0 */
- case 0x20: /* ILR1 */
- case 0x24: /* ILR2 */
- case 0x28: /* ILR3 */
- case 0x2c: /* ILR4 */
- case 0x30: /* ILR5 */
- case 0x34: /* ILR6 */
- case 0x38: /* ILR7 */
- case 0x3c: /* ILR8 */
- case 0x40: /* ILR9 */
- case 0x44: /* ILR10 */
- case 0x48: /* ILR11 */
- case 0x4c: /* ILR12 */
- case 0x50: /* ILR13 */
- case 0x54: /* ILR14 */
- case 0x58: /* ILR15 */
- case 0x5c: /* ILR16 */
- case 0x60: /* ILR17 */
- case 0x64: /* ILR18 */
- case 0x68: /* ILR19 */
- case 0x6c: /* ILR20 */
- case 0x70: /* ILR21 */
- case 0x74: /* ILR22 */
- case 0x78: /* ILR23 */
- case 0x7c: /* ILR24 */
- case 0x80: /* ILR25 */
- case 0x84: /* ILR26 */
- case 0x88: /* ILR27 */
- case 0x8c: /* ILR28 */
- case 0x90: /* ILR29 */
- case 0x94: /* ILR30 */
- case 0x98: /* ILR31 */
+ case 0x1c: /* ILR0 */
+ case 0x20: /* ILR1 */
+ case 0x24: /* ILR2 */
+ case 0x28: /* ILR3 */
+ case 0x2c: /* ILR4 */
+ case 0x30: /* ILR5 */
+ case 0x34: /* ILR6 */
+ case 0x38: /* ILR7 */
+ case 0x3c: /* ILR8 */
+ case 0x40: /* ILR9 */
+ case 0x44: /* ILR10 */
+ case 0x48: /* ILR11 */
+ case 0x4c: /* ILR12 */
+ case 0x50: /* ILR13 */
+ case 0x54: /* ILR14 */
+ case 0x58: /* ILR15 */
+ case 0x5c: /* ILR16 */
+ case 0x60: /* ILR17 */
+ case 0x64: /* ILR18 */
+ case 0x68: /* ILR19 */
+ case 0x6c: /* ILR20 */
+ case 0x70: /* ILR21 */
+ case 0x74: /* ILR22 */
+ case 0x78: /* ILR23 */
+ case 0x7c: /* ILR24 */
+ case 0x80: /* ILR25 */
+ case 0x84: /* ILR26 */
+ case 0x88: /* ILR27 */
+ case 0x8c: /* ILR28 */
+ case 0x90: /* ILR29 */
+ case 0x94: /* ILR30 */
+ case 0x98: /* ILR31 */
i = (offset - 0x1c) >> 2;
return (bank->priority[i] << 2) |
(((bank->sens_edge >> i) & 1) << 1) |
((bank->fiq >> i) & 1);
- case 0x9c: /* ISR */
+ case 0x9c: /* ISR */
return 0x00000000;
}
@@ -241,24 +219,24 @@ static void omap_inth_write(void *opaque, hwaddr addr,
offset &= 0xff;
switch (offset) {
- case 0x00: /* ITR */
+ case 0x00: /* ITR */
/* Important: ignore the clearing if the IRQ is level-triggered and
the input bit is 1 */
bank->irqs &= value | (bank->inputs & bank->sens_edge);
return;
- case 0x04: /* MIR */
+ case 0x04: /* MIR */
bank->mask = value;
omap_inth_update(s, 0);
omap_inth_update(s, 1);
return;
- case 0x10: /* SIR_IRQ_CODE */
- case 0x14: /* SIR_FIQ_CODE */
+ case 0x10: /* SIR_IRQ_CODE */
+ case 0x14: /* SIR_FIQ_CODE */
OMAP_RO_REG(addr);
break;
- case 0x18: /* CONTROL_REG */
+ case 0x18: /* CONTROL_REG */
if (bank_no != 0)
break;
if (value & 2) {
@@ -273,38 +251,38 @@ static void omap_inth_write(void *opaque, hwaddr addr,
}
return;
- case 0x1c: /* ILR0 */
- case 0x20: /* ILR1 */
- case 0x24: /* ILR2 */
- case 0x28: /* ILR3 */
- case 0x2c: /* ILR4 */
- case 0x30: /* ILR5 */
- case 0x34: /* ILR6 */
- case 0x38: /* ILR7 */
- case 0x3c: /* ILR8 */
- case 0x40: /* ILR9 */
- case 0x44: /* ILR10 */
- case 0x48: /* ILR11 */
- case 0x4c: /* ILR12 */
- case 0x50: /* ILR13 */
- case 0x54: /* ILR14 */
- case 0x58: /* ILR15 */
- case 0x5c: /* ILR16 */
- case 0x60: /* ILR17 */
- case 0x64: /* ILR18 */
- case 0x68: /* ILR19 */
- case 0x6c: /* ILR20 */
- case 0x70: /* ILR21 */
- case 0x74: /* ILR22 */
- case 0x78: /* ILR23 */
- case 0x7c: /* ILR24 */
- case 0x80: /* ILR25 */
- case 0x84: /* ILR26 */
- case 0x88: /* ILR27 */
- case 0x8c: /* ILR28 */
- case 0x90: /* ILR29 */
- case 0x94: /* ILR30 */
- case 0x98: /* ILR31 */
+ case 0x1c: /* ILR0 */
+ case 0x20: /* ILR1 */
+ case 0x24: /* ILR2 */
+ case 0x28: /* ILR3 */
+ case 0x2c: /* ILR4 */
+ case 0x30: /* ILR5 */
+ case 0x34: /* ILR6 */
+ case 0x38: /* ILR7 */
+ case 0x3c: /* ILR8 */
+ case 0x40: /* ILR9 */
+ case 0x44: /* ILR10 */
+ case 0x48: /* ILR11 */
+ case 0x4c: /* ILR12 */
+ case 0x50: /* ILR13 */
+ case 0x54: /* ILR14 */
+ case 0x58: /* ILR15 */
+ case 0x5c: /* ILR16 */
+ case 0x60: /* ILR17 */
+ case 0x64: /* ILR18 */
+ case 0x68: /* ILR19 */
+ case 0x6c: /* ILR20 */
+ case 0x70: /* ILR21 */
+ case 0x74: /* ILR22 */
+ case 0x78: /* ILR23 */
+ case 0x7c: /* ILR24 */
+ case 0x80: /* ILR25 */
+ case 0x84: /* ILR26 */
+ case 0x88: /* ILR27 */
+ case 0x8c: /* ILR28 */
+ case 0x90: /* ILR29 */
+ case 0x94: /* ILR30 */
+ case 0x98: /* ILR31 */
i = (offset - 0x1c) >> 2;
bank->priority[i] = (value >> 2) & 0x1f;
bank->sens_edge &= ~(1 << i);
@@ -313,7 +291,7 @@ static void omap_inth_write(void *opaque, hwaddr addr,
bank->fiq |= (value & 1) << i;
return;
- case 0x9c: /* ISR */
+ case 0x9c: /* ISR */
for (i = 0; i < 32; i ++)
if (value & (1 << i)) {
omap_set_intr(s, 32 * bank_no + i, 1);
@@ -397,16 +375,15 @@ void omap_intc_set_fclk(OMAPIntcState *intc, omap_clk clk)
intc->fclk = clk;
}
-static Property omap_intc_properties[] = {
+static const Property omap_intc_properties[] = {
DEFINE_PROP_UINT32("size", OMAPIntcState, size, 0x100),
- DEFINE_PROP_END_OF_LIST(),
};
-static void omap_intc_class_init(ObjectClass *klass, void *data)
+static void omap_intc_class_init(ObjectClass *klass, const void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
- dc->reset = omap_inth_reset;
+ device_class_set_legacy_reset(dc, omap_inth_reset);
device_class_set_props(dc, omap_intc_properties);
/* Reason: pointer property "clk" */
dc->user_creatable = false;
@@ -414,277 +391,16 @@ static void omap_intc_class_init(ObjectClass *klass, void *data)
}
static const TypeInfo omap_intc_info = {
- .name = "omap-intc",
- .parent = TYPE_OMAP_INTC,
- .instance_init = omap_intc_init,
- .class_init = omap_intc_class_init,
-};
-
-static uint64_t omap2_inth_read(void *opaque, hwaddr addr,
- unsigned size)
-{
- OMAPIntcState *s = opaque;
- int offset = addr;
- int bank_no, line_no;
- struct omap_intr_handler_bank_s *bank = NULL;
-
- if ((offset & 0xf80) == 0x80) {
- bank_no = (offset & 0x60) >> 5;
- if (bank_no < s->nbanks) {
- offset &= ~0x60;
- bank = &s->bank[bank_no];
- } else {
- OMAP_BAD_REG(addr);
- return 0;
- }
- }
-
- switch (offset) {
- case 0x00: /* INTC_REVISION */
- return s->revision;
-
- case 0x10: /* INTC_SYSCONFIG */
- return (s->autoidle >> 2) & 1;
-
- case 0x14: /* INTC_SYSSTATUS */
- return 1; /* RESETDONE */
-
- case 0x40: /* INTC_SIR_IRQ */
- return s->sir_intr[0];
-
- case 0x44: /* INTC_SIR_FIQ */
- return s->sir_intr[1];
-
- case 0x48: /* INTC_CONTROL */
- return (!s->mask) << 2; /* GLOBALMASK */
-
- case 0x4c: /* INTC_PROTECTION */
- return 0;
-
- case 0x50: /* INTC_IDLE */
- return s->autoidle & 3;
-
- /* Per-bank registers */
- case 0x80: /* INTC_ITR */
- return bank->inputs;
-
- case 0x84: /* INTC_MIR */
- return bank->mask;
-
- case 0x88: /* INTC_MIR_CLEAR */
- case 0x8c: /* INTC_MIR_SET */
- return 0;
-
- case 0x90: /* INTC_ISR_SET */
- return bank->swi;
-
- case 0x94: /* INTC_ISR_CLEAR */
- return 0;
-
- case 0x98: /* INTC_PENDING_IRQ */
- return bank->irqs & ~bank->mask & ~bank->fiq;
-
- case 0x9c: /* INTC_PENDING_FIQ */
- return bank->irqs & ~bank->mask & bank->fiq;
-
- /* Per-line registers */
- case 0x100 ... 0x300: /* INTC_ILR */
- bank_no = (offset - 0x100) >> 7;
- if (bank_no > s->nbanks)
- break;
- bank = &s->bank[bank_no];
- line_no = (offset & 0x7f) >> 2;
- return (bank->priority[line_no] << 2) |
- ((bank->fiq >> line_no) & 1);
- }
- OMAP_BAD_REG(addr);
- return 0;
-}
-
-static void omap2_inth_write(void *opaque, hwaddr addr,
- uint64_t value, unsigned size)
-{
- OMAPIntcState *s = opaque;
- int offset = addr;
- int bank_no, line_no;
- struct omap_intr_handler_bank_s *bank = NULL;
-
- if ((offset & 0xf80) == 0x80) {
- bank_no = (offset & 0x60) >> 5;
- if (bank_no < s->nbanks) {
- offset &= ~0x60;
- bank = &s->bank[bank_no];
- } else {
- OMAP_BAD_REG(addr);
- return;
- }
- }
-
- switch (offset) {
- case 0x10: /* INTC_SYSCONFIG */
- s->autoidle &= 4;
- s->autoidle |= (value & 1) << 2;
- if (value & 2) { /* SOFTRESET */
- omap_inth_reset(DEVICE(s));
- }
- return;
-
- case 0x48: /* INTC_CONTROL */
- s->mask = (value & 4) ? 0 : ~0; /* GLOBALMASK */
- if (value & 2) { /* NEWFIQAGR */
- qemu_set_irq(s->parent_intr[1], 0);
- s->new_agr[1] = ~0;
- omap_inth_update(s, 1);
- }
- if (value & 1) { /* NEWIRQAGR */
- qemu_set_irq(s->parent_intr[0], 0);
- s->new_agr[0] = ~0;
- omap_inth_update(s, 0);
- }
- return;
-
- case 0x4c: /* INTC_PROTECTION */
- /* TODO: Make a bitmap (or sizeof(char)map) of access privileges
- * for every register, see Chapter 3 and 4 for privileged mode. */
- if (value & 1)
- fprintf(stderr, "%s: protection mode enable attempt\n",
- __func__);
- return;
-
- case 0x50: /* INTC_IDLE */
- s->autoidle &= ~3;
- s->autoidle |= value & 3;
- return;
-
- /* Per-bank registers */
- case 0x84: /* INTC_MIR */
- bank->mask = value;
- omap_inth_update(s, 0);
- omap_inth_update(s, 1);
- return;
-
- case 0x88: /* INTC_MIR_CLEAR */
- bank->mask &= ~value;
- omap_inth_update(s, 0);
- omap_inth_update(s, 1);
- return;
-
- case 0x8c: /* INTC_MIR_SET */
- bank->mask |= value;
- return;
-
- case 0x90: /* INTC_ISR_SET */
- bank->irqs |= bank->swi |= value;
- omap_inth_update(s, 0);
- omap_inth_update(s, 1);
- return;
-
- case 0x94: /* INTC_ISR_CLEAR */
- bank->swi &= ~value;
- bank->irqs = bank->swi & bank->inputs;
- return;
-
- /* Per-line registers */
- case 0x100 ... 0x300: /* INTC_ILR */
- bank_no = (offset - 0x100) >> 7;
- if (bank_no > s->nbanks)
- break;
- bank = &s->bank[bank_no];
- line_no = (offset & 0x7f) >> 2;
- bank->priority[line_no] = (value >> 2) & 0x3f;
- bank->fiq &= ~(1 << line_no);
- bank->fiq |= (value & 1) << line_no;
- return;
-
- case 0x00: /* INTC_REVISION */
- case 0x14: /* INTC_SYSSTATUS */
- case 0x40: /* INTC_SIR_IRQ */
- case 0x44: /* INTC_SIR_FIQ */
- case 0x80: /* INTC_ITR */
- case 0x98: /* INTC_PENDING_IRQ */
- case 0x9c: /* INTC_PENDING_FIQ */
- OMAP_RO_REG(addr);
- return;
- }
- OMAP_BAD_REG(addr);
-}
-
-static const MemoryRegionOps omap2_inth_mem_ops = {
- .read = omap2_inth_read,
- .write = omap2_inth_write,
- .endianness = DEVICE_NATIVE_ENDIAN,
- .valid = {
- .min_access_size = 4,
- .max_access_size = 4,
- },
-};
-
-static void omap2_intc_init(Object *obj)
-{
- DeviceState *dev = DEVICE(obj);
- OMAPIntcState *s = OMAP_INTC(obj);
- SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
-
- s->level_only = 1;
- s->nbanks = 3;
- sysbus_init_irq(sbd, &s->parent_intr[0]);
- sysbus_init_irq(sbd, &s->parent_intr[1]);
- qdev_init_gpio_in(dev, omap_set_intr_noedge, s->nbanks * 32);
- memory_region_init_io(&s->mmio, obj, &omap2_inth_mem_ops, s,
- "omap2-intc", 0x1000);
- sysbus_init_mmio(sbd, &s->mmio);
-}
-
-static void omap2_intc_realize(DeviceState *dev, Error **errp)
-{
- OMAPIntcState *s = OMAP_INTC(dev);
-
- if (!s->iclk) {
- error_setg(errp, "omap2-intc: iclk not connected");
- return;
- }
- if (!s->fclk) {
- error_setg(errp, "omap2-intc: fclk not connected");
- return;
- }
-}
-
-static Property omap2_intc_properties[] = {
- DEFINE_PROP_UINT8("revision", OMAPIntcState,
- revision, 0x21),
- DEFINE_PROP_END_OF_LIST(),
-};
-
-static void omap2_intc_class_init(ObjectClass *klass, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(klass);
-
- dc->reset = omap_inth_reset;
- device_class_set_props(dc, omap2_intc_properties);
- /* Reason: pointer property "iclk", "fclk" */
- dc->user_creatable = false;
- dc->realize = omap2_intc_realize;
-}
-
-static const TypeInfo omap2_intc_info = {
- .name = "omap2-intc",
- .parent = TYPE_OMAP_INTC,
- .instance_init = omap2_intc_init,
- .class_init = omap2_intc_class_init,
-};
-
-static const TypeInfo omap_intc_type_info = {
.name = TYPE_OMAP_INTC,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(OMAPIntcState),
- .abstract = true,
+ .instance_init = omap_intc_init,
+ .class_init = omap_intc_class_init,
};
static void omap_intc_register_types(void)
{
- type_register_static(&omap_intc_type_info);
type_register_static(&omap_intc_info);
- type_register_static(&omap2_intc_info);
}
type_init(omap_intc_register_types)