Revision 0919ac78 hw/omap_intc.c
b/hw/omap_intc.c | ||
---|---|---|
19 | 19 |
*/ |
20 | 20 |
#include "hw.h" |
21 | 21 |
#include "omap.h" |
22 |
#include "exec-memory.h"
|
|
22 |
#include "sysbus.h"
|
|
23 | 23 |
|
24 | 24 |
/* Interrupt Handlers */ |
25 | 25 |
struct omap_intr_handler_bank_s { |
... | ... | |
33 | 33 |
}; |
34 | 34 |
|
35 | 35 |
struct omap_intr_handler_s { |
36 |
SysBusDevice busdev; |
|
36 | 37 |
qemu_irq *pins; |
37 | 38 |
qemu_irq parent_intr[2]; |
38 | 39 |
MemoryRegion mmio; |
40 |
void *iclk; |
|
41 |
void *fclk; |
|
39 | 42 |
unsigned char nbanks; |
40 | 43 |
int level_only; |
44 |
uint32_t size; |
|
45 |
|
|
46 |
uint8_t revision; |
|
41 | 47 |
|
42 | 48 |
/* state */ |
43 | 49 |
uint32_t new_agr[2]; |
44 | 50 |
int sir_intr[2]; |
45 | 51 |
int autoidle; |
46 | 52 |
uint32_t mask; |
47 |
struct omap_intr_handler_bank_s bank[]; |
|
53 |
struct omap_intr_handler_bank_s bank[3];
|
|
48 | 54 |
}; |
49 | 55 |
|
50 |
inline qemu_irq omap_inth_get_pin(struct omap_intr_handler_s *s, int n) |
|
51 |
{ |
|
52 |
return s->pins[n]; |
|
53 |
} |
|
54 |
|
|
55 | 56 |
static void omap_inth_sir_update(struct omap_intr_handler_s *s, int is_fiq) |
56 | 57 |
{ |
57 | 58 |
int i, j, sir_intr, p_intr, p, f; |
... | ... | |
325 | 326 |
}, |
326 | 327 |
}; |
327 | 328 |
|
328 |
void omap_inth_reset(struct omap_intr_handler_s *s)
|
|
329 |
static void omap_inth_reset(DeviceState *dev)
|
|
329 | 330 |
{ |
331 |
struct omap_intr_handler_s *s = FROM_SYSBUS(struct omap_intr_handler_s, |
|
332 |
sysbus_from_qdev(dev)); |
|
330 | 333 |
int i; |
331 | 334 |
|
332 | 335 |
for (i = 0; i < s->nbanks; ++i){ |
... | ... | |
353 | 356 |
qemu_set_irq(s->parent_intr[1], 0); |
354 | 357 |
} |
355 | 358 |
|
356 |
struct omap_intr_handler_s *omap_inth_init(target_phys_addr_t base, |
|
357 |
unsigned long size, unsigned char nbanks, qemu_irq **pins, |
|
358 |
qemu_irq parent_irq, qemu_irq parent_fiq, omap_clk clk) |
|
359 |
static int omap_intc_init(SysBusDevice *dev) |
|
359 | 360 |
{ |
360 |
struct omap_intr_handler_s *s = (struct omap_intr_handler_s *) |
|
361 |
g_malloc0(sizeof(struct omap_intr_handler_s) + |
|
362 |
sizeof(struct omap_intr_handler_bank_s) * nbanks); |
|
363 |
|
|
364 |
s->parent_intr[0] = parent_irq; |
|
365 |
s->parent_intr[1] = parent_fiq; |
|
366 |
s->nbanks = nbanks; |
|
367 |
s->pins = qemu_allocate_irqs(omap_set_intr, s, nbanks * 32); |
|
368 |
if (pins) |
|
369 |
*pins = s->pins; |
|
370 |
|
|
371 |
memory_region_init_io(&s->mmio, &omap_inth_mem_ops, s, "omap-intc", size); |
|
372 |
memory_region_add_subregion(get_system_memory(), base, &s->mmio); |
|
373 |
|
|
374 |
omap_inth_reset(s); |
|
375 |
|
|
376 |
return s; |
|
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_region(dev, &s->mmio); |
|
373 |
return 0; |
|
377 | 374 |
} |
378 | 375 |
|
376 |
static SysBusDeviceInfo omap_intc_info = { |
|
377 |
.init = omap_intc_init, |
|
378 |
.qdev.name = "omap-intc", |
|
379 |
.qdev.size = sizeof(struct omap_intr_handler_s), |
|
380 |
.qdev.reset = omap_inth_reset, |
|
381 |
.qdev.props = (Property[]) { |
|
382 |
DEFINE_PROP_UINT32("size", struct omap_intr_handler_s, size, 0x100), |
|
383 |
DEFINE_PROP_PTR("clk", struct omap_intr_handler_s, iclk), |
|
384 |
DEFINE_PROP_END_OF_LIST() |
|
385 |
} |
|
386 |
}; |
|
387 |
|
|
379 | 388 |
static uint64_t omap2_inth_read(void *opaque, target_phys_addr_t addr, |
380 | 389 |
unsigned size) |
381 | 390 |
{ |
... | ... | |
394 | 403 |
|
395 | 404 |
switch (offset) { |
396 | 405 |
case 0x00: /* INTC_REVISION */ |
397 |
return 0x21;
|
|
406 |
return s->revision;
|
|
398 | 407 |
|
399 | 408 |
case 0x10: /* INTC_SYSCONFIG */ |
400 | 409 |
return (s->autoidle >> 2) & 1; |
... | ... | |
475 | 484 |
s->autoidle &= 4; |
476 | 485 |
s->autoidle |= (value & 1) << 2; |
477 | 486 |
if (value & 2) /* SOFTRESET */ |
478 |
omap_inth_reset(s);
|
|
487 |
omap_inth_reset(&s->busdev.qdev);
|
|
479 | 488 |
return; |
480 | 489 |
|
481 | 490 |
case 0x48: /* INTC_CONTROL */ |
... | ... | |
568 | 577 |
}, |
569 | 578 |
}; |
570 | 579 |
|
571 |
struct omap_intr_handler_s *omap2_inth_init(target_phys_addr_t base, |
|
572 |
int size, int nbanks, qemu_irq **pins, |
|
573 |
qemu_irq parent_irq, qemu_irq parent_fiq, |
|
574 |
omap_clk fclk, omap_clk iclk) |
|
580 |
static int omap2_intc_init(SysBusDevice *dev) |
|
575 | 581 |
{ |
576 |
struct omap_intr_handler_s *s = (struct omap_intr_handler_s *) |
|
577 |
g_malloc0(sizeof(struct omap_intr_handler_s) + |
|
578 |
sizeof(struct omap_intr_handler_bank_s) * nbanks); |
|
579 |
|
|
580 |
s->parent_intr[0] = parent_irq; |
|
581 |
s->parent_intr[1] = parent_fiq; |
|
582 |
s->nbanks = nbanks; |
|
582 |
struct omap_intr_handler_s *s; |
|
583 |
s = FROM_SYSBUS(struct omap_intr_handler_s, dev); |
|
584 |
if (!s->iclk) { |
|
585 |
hw_error("omap2-intc: iclk not connected\n"); |
|
586 |
} |
|
587 |
if (!s->fclk) { |
|
588 |
hw_error("omap2-intc: fclk not connected\n"); |
|
589 |
} |
|
583 | 590 |
s->level_only = 1; |
584 |
s->pins = qemu_allocate_irqs(omap_set_intr_noedge, s, nbanks * 32); |
|
585 |
if (pins) |
|
586 |
*pins = s->pins; |
|
587 |
|
|
588 |
memory_region_init_io(&s->mmio, &omap2_inth_mem_ops, s, "omap2-intc", size); |
|
589 |
memory_region_add_subregion(get_system_memory(), base, &s->mmio); |
|
591 |
s->nbanks = 3; |
|
592 |
sysbus_init_irq(dev, &s->parent_intr[0]); |
|
593 |
sysbus_init_irq(dev, &s->parent_intr[1]); |
|
594 |
qdev_init_gpio_in(&dev->qdev, omap_set_intr_noedge, s->nbanks * 32); |
|
595 |
memory_region_init_io(&s->mmio, &omap2_inth_mem_ops, s, |
|
596 |
"omap2-intc", 0x1000); |
|
597 |
sysbus_init_mmio_region(dev, &s->mmio); |
|
598 |
return 0; |
|
599 |
} |
|
590 | 600 |
|
591 |
omap_inth_reset(s); |
|
601 |
static SysBusDeviceInfo omap2_intc_info = { |
|
602 |
.init = omap2_intc_init, |
|
603 |
.qdev.name = "omap2-intc", |
|
604 |
.qdev.size = sizeof(struct omap_intr_handler_s), |
|
605 |
.qdev.reset = omap_inth_reset, |
|
606 |
.qdev.props = (Property[]) { |
|
607 |
DEFINE_PROP_UINT8("revision", struct omap_intr_handler_s, |
|
608 |
revision, 0x21), |
|
609 |
DEFINE_PROP_PTR("iclk", struct omap_intr_handler_s, iclk), |
|
610 |
DEFINE_PROP_PTR("fclk", struct omap_intr_handler_s, fclk), |
|
611 |
DEFINE_PROP_END_OF_LIST() |
|
612 |
} |
|
613 |
}; |
|
592 | 614 |
|
593 |
return s; |
|
615 |
static void omap_intc_register_device(void) |
|
616 |
{ |
|
617 |
sysbus_register_withprop(&omap_intc_info); |
|
618 |
sysbus_register_withprop(&omap2_intc_info); |
|
594 | 619 |
} |
620 |
|
|
621 |
device_init(omap_intc_register_device) |
Also available in: Unified diff