diff options
Diffstat (limited to 'hw')
-rw-r--r-- | hw/arm/kzm.c | 5 | ||||
-rw-r--r-- | hw/arm/virt.c | 32 | ||||
-rw-r--r-- | hw/char/imx_serial.c | 159 | ||||
-rw-r--r-- | hw/cpu/a15mpcore.c | 29 | ||||
-rw-r--r-- | hw/intc/arm_gic.c | 64 | ||||
-rw-r--r-- | hw/intc/arm_gic_common.c | 41 | ||||
-rw-r--r-- | hw/intc/arm_gic_kvm.c | 28 | ||||
-rw-r--r-- | hw/intc/imx_avic.c | 56 | ||||
-rw-r--r-- | hw/misc/imx_ccm.c | 81 | ||||
-rw-r--r-- | hw/timer/imx_epit.c | 64 | ||||
-rw-r--r-- | hw/timer/imx_gpt.c | 85 |
11 files changed, 177 insertions, 467 deletions
diff --git a/hw/arm/kzm.c b/hw/arm/kzm.c index 5be0369..d7af230 100644 --- a/hw/arm/kzm.c +++ b/hw/arm/kzm.c @@ -22,6 +22,7 @@ #include "sysemu/sysemu.h" #include "hw/boards.h" #include "hw/char/serial.h" +#include "hw/intc/imx_avic.h" #include "hw/arm/imx.h" /* Memory map for Kzm Emulation Baseboard: @@ -106,7 +107,7 @@ static void kzm_init(MachineState *machine) memory_region_init_ram(sram, NULL, "kzm.sram", 0x4000, &error_abort); memory_region_add_subregion(address_space_mem, 0x1FFFC000, sram); - dev = sysbus_create_varargs("imx_avic", 0x68000000, + dev = sysbus_create_varargs(TYPE_IMX_AVIC, 0x68000000, qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_IRQ), qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_FIQ), NULL); @@ -114,7 +115,7 @@ static void kzm_init(MachineState *machine) imx_serial_create(0, 0x43f90000, qdev_get_gpio_in(dev, 45)); imx_serial_create(1, 0x43f94000, qdev_get_gpio_in(dev, 32)); - ccm = sysbus_create_simple("imx_ccm", 0x53f80000, NULL); + ccm = sysbus_create_simple(TYPE_IMX_CCM, 0x53f80000, NULL); imx_timerp_create(0x53f94000, qdev_get_gpio_in(dev, 28), ccm); imx_timerp_create(0x53f98000, qdev_get_gpio_in(dev, 27), ccm); diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 4846892..d5a8417 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -48,6 +48,8 @@ #include "hw/arm/sysbus-fdt.h" #include "hw/platform-bus.h" #include "hw/arm/fdt.h" +#include "hw/intc/arm_gic_common.h" +#include "kvm_arm.h" /* Number of external interrupt lines to configure the GIC with */ #define NUM_IRQS 256 @@ -365,12 +367,10 @@ static void create_gic(VirtBoardInfo *vbi, qemu_irq *pic) /* We create a standalone GIC v2 */ DeviceState *gicdev; SysBusDevice *gicbusdev; - const char *gictype = "arm_gic"; + const char *gictype; int i; - if (kvm_irqchip_in_kernel()) { - gictype = "kvm-arm-gic"; - } + gictype = gic_class_name(); gicdev = qdev_create(NULL, gictype); qdev_prop_set_uint32(gicdev, "revision", 2); @@ -390,15 +390,23 @@ static void create_gic(VirtBoardInfo *vbi, qemu_irq *pic) */ for (i = 0; i < smp_cpus; i++) { DeviceState *cpudev = DEVICE(qemu_get_cpu(i)); - int ppibase = NUM_IRQS + i * 32; - /* physical timer; we wire it up to the non-secure timer's ID, - * since a real A15 always has TrustZone but QEMU doesn't. + int ppibase = NUM_IRQS + i * GIC_INTERNAL + GIC_NR_SGIS; + int irq; + /* Mapping from the output timer irq lines from the CPU to the + * GIC PPI inputs we use for the virt board. */ - qdev_connect_gpio_out(cpudev, 0, - qdev_get_gpio_in(gicdev, ppibase + 30)); - /* virtual timer */ - qdev_connect_gpio_out(cpudev, 1, - qdev_get_gpio_in(gicdev, ppibase + 27)); + const int timer_irq[] = { + [GTIMER_PHYS] = ARCH_TIMER_NS_EL1_IRQ, + [GTIMER_VIRT] = ARCH_TIMER_VIRT_IRQ, + [GTIMER_HYP] = ARCH_TIMER_NS_EL2_IRQ, + [GTIMER_SEC] = ARCH_TIMER_S_EL1_IRQ, + }; + + for (irq = 0; irq < ARRAY_SIZE(timer_irq); irq++) { + qdev_connect_gpio_out(cpudev, irq, + qdev_get_gpio_in(gicdev, + ppibase + timer_irq[irq])); + } sysbus_connect_irq(gicbusdev, i, qdev_get_gpio_in(cpudev, ARM_CPU_IRQ)); sysbus_connect_irq(gicbusdev, i + smp_cpus, diff --git a/hw/char/imx_serial.c b/hw/char/imx_serial.c index f3fbc77..801156d 100644 --- a/hw/char/imx_serial.c +++ b/hw/char/imx_serial.c @@ -4,6 +4,7 @@ * Copyright (c) 2008 OKL * Originally Written by Hans Jiang * Copyright (c) 2011 NICTA Pty Ltd. + * Updated by Jean-Christophe Dubois <jcd@tribudubois.net> * * This work is licensed under the terms of the GNU GPL, version 2 or later. * See the COPYING file in the top-level directory. @@ -17,8 +18,7 @@ * is a real serial device. */ -#include "hw/hw.h" -#include "hw/sysbus.h" +#include "hw/char/imx_serial.h" #include "sysemu/sysemu.h" #include "sysemu/char.h" #include "hw/arm/imx.h" @@ -26,7 +26,7 @@ //#define DEBUG_SERIAL 1 #ifdef DEBUG_SERIAL #define DPRINTF(fmt, args...) \ -do { printf("imx_serial: " fmt , ##args); } while (0) +do { printf("%s: " fmt , TYPE_IMX_SERIAL, ##args); } while (0) #else #define DPRINTF(fmt, args...) do {} while (0) #endif @@ -38,42 +38,13 @@ do { printf("imx_serial: " fmt , ##args); } while (0) //#define DEBUG_IMPLEMENTATION 1 #ifdef DEBUG_IMPLEMENTATION # define IPRINTF(fmt, args...) \ - do { fprintf(stderr, "imx_serial: " fmt, ##args); } while (0) + do { fprintf(stderr, "%s: " fmt, TYPE_IMX_SERIAL, ##args); } while (0) #else # define IPRINTF(fmt, args...) do {} while (0) #endif -#define TYPE_IMX_SERIAL "imx-serial" -#define IMX_SERIAL(obj) OBJECT_CHECK(IMXSerialState, (obj), TYPE_IMX_SERIAL) - -typedef struct IMXSerialState { - SysBusDevice parent_obj; - - MemoryRegion iomem; - int32_t readbuff; - - uint32_t usr1; - uint32_t usr2; - uint32_t ucr1; - uint32_t ucr2; - uint32_t uts1; - - /* - * The registers below are implemented just so that the - * guest OS sees what it has written - */ - uint32_t onems; - uint32_t ufcr; - uint32_t ubmr; - uint32_t ubrc; - uint32_t ucr3; - - qemu_irq irq; - CharDriverState *chr; -} IMXSerialState; - static const VMStateDescription vmstate_imx_serial = { - .name = "imx-serial", + .name = TYPE_IMX_SERIAL, .version_id = 1, .minimum_version_id = 1, .fields = (VMStateField[]) { @@ -91,55 +62,6 @@ static const VMStateDescription vmstate_imx_serial = { }, }; - -#define URXD_CHARRDY (1<<15) /* character read is valid */ -#define URXD_ERR (1<<14) /* Character has error */ -#define URXD_BRK (1<<11) /* Break received */ - -#define USR1_PARTYER (1<<15) /* Parity Error */ -#define USR1_RTSS (1<<14) /* RTS pin status */ -#define USR1_TRDY (1<<13) /* Tx ready */ -#define USR1_RTSD (1<<12) /* RTS delta: pin changed state */ -#define USR1_ESCF (1<<11) /* Escape sequence interrupt */ -#define USR1_FRAMERR (1<<10) /* Framing error */ -#define USR1_RRDY (1<<9) /* receiver ready */ -#define USR1_AGTIM (1<<8) /* Aging timer interrupt */ -#define USR1_DTRD (1<<7) /* DTR changed */ -#define USR1_RXDS (1<<6) /* Receiver is idle */ -#define USR1_AIRINT (1<<5) /* Aysnch IR interrupt */ -#define USR1_AWAKE (1<<4) /* Falling edge detected on RXd pin */ - -#define USR2_ADET (1<<15) /* Autobaud complete */ -#define USR2_TXFE (1<<14) /* Transmit FIFO empty */ -#define USR2_DTRF (1<<13) /* DTR/DSR transition */ -#define USR2_IDLE (1<<12) /* UART has been idle for too long */ -#define USR2_ACST (1<<11) /* Autobaud counter stopped */ -#define USR2_RIDELT (1<<10) /* Ring Indicator delta */ -#define USR2_RIIN (1<<9) /* Ring Indicator Input */ -#define USR2_IRINT (1<<8) /* Serial Infrared Interrupt */ -#define USR2_WAKE (1<<7) /* Start bit detected */ -#define USR2_DCDDELT (1<<6) /* Data Carrier Detect delta */ -#define USR2_DCDIN (1<<5) /* Data Carrier Detect Input */ -#define USR2_RTSF (1<<4) /* RTS transition */ -#define USR2_TXDC (1<<3) /* Transmission complete */ -#define USR2_BRCD (1<<2) /* Break condition detected */ -#define USR2_ORE (1<<1) /* Overrun error */ -#define USR2_RDR (1<<0) /* Receive data ready */ - -#define UCR1_TRDYEN (1<<13) /* Tx Ready Interrupt Enable */ -#define UCR1_RRDYEN (1<<9) /* Rx Ready Interrupt Enable */ -#define UCR1_TXMPTYEN (1<<6) /* Tx Empty Interrupt Enable */ -#define UCR1_UARTEN (1<<0) /* UART Enable */ - -#define UCR2_TXEN (1<<2) /* Transmitter enable */ -#define UCR2_RXEN (1<<1) /* Receiver enable */ -#define UCR2_SRST (1<<0) /* Reset complete */ - -#define UTS1_TXEMPTY (1<<6) -#define UTS1_RXEMPTY (1<<5) -#define UTS1_TXFULL (1<<4) -#define UTS1_RXFULL (1<<3) - static void imx_update(IMXSerialState *s) { uint32_t flags; @@ -203,7 +125,9 @@ static uint64_t imx_serial_read(void *opaque, hwaddr offset, s->usr2 &= ~USR2_RDR; s->uts1 |= UTS1_RXEMPTY; imx_update(s); - qemu_chr_accept_input(s->chr); + if (s->chr) { + qemu_chr_accept_input(s->chr); + } } return c; @@ -242,13 +166,13 @@ static uint64_t imx_serial_read(void *opaque, hwaddr offset, return 0x0; /* TODO */ default: - IPRINTF("imx_serial_read: bad offset: 0x%x\n", (int)offset); + IPRINTF("%s: bad offset: 0x%x\n", __func__, (int)offset); return 0; } } static void imx_serial_write(void *opaque, hwaddr offset, - uint64_t value, unsigned size) + uint64_t value, unsigned size) { IMXSerialState *s = (IMXSerialState *)opaque; unsigned char ch; @@ -290,7 +214,9 @@ static void imx_serial_write(void *opaque, hwaddr offset, } if (value & UCR2_RXEN) { if (!(s->ucr2 & UCR2_RXEN)) { - qemu_chr_accept_input(s->chr); + if (s->chr) { + qemu_chr_accept_input(s->chr); + } } } s->ucr2 = value & 0xffff; @@ -298,25 +224,25 @@ static void imx_serial_write(void *opaque, hwaddr offset, case 0x25: /* USR1 */ value &= USR1_AWAKE | USR1_AIRINT | USR1_DTRD | USR1_AGTIM | - USR1_FRAMERR | USR1_ESCF | USR1_RTSD | USR1_PARTYER; + USR1_FRAMERR | USR1_ESCF | USR1_RTSD | USR1_PARTYER; s->usr1 &= ~value; break; case 0x26: /* USR2 */ - /* - * Writing 1 to some bits clears them; all other - * values are ignored - */ + /* + * Writing 1 to some bits clears them; all other + * values are ignored + */ value &= USR2_ADET | USR2_DTRF | USR2_IDLE | USR2_ACST | - USR2_RIDELT | USR2_IRINT | USR2_WAKE | - USR2_DCDDELT | USR2_RTSF | USR2_BRCD | USR2_ORE; + USR2_RIDELT | USR2_IRINT | USR2_WAKE | + USR2_DCDDELT | USR2_RTSF | USR2_BRCD | USR2_ORE; s->usr2 &= ~value; break; - /* - * Linux expects to see what it writes to these registers - * We don't currently alter the baud rate - */ + /* + * Linux expects to see what it writes to these registers + * We don't currently alter the baud rate + */ case 0x29: /* UBIR */ s->ubrc = value & 0xffff; break; @@ -344,7 +270,7 @@ static void imx_serial_write(void *opaque, hwaddr offset, break; default: - IPRINTF("imx_serial_write: Bad offset 0x%x\n", (int)offset); + IPRINTF("%s: Bad offset 0x%x\n", __func__, (int)offset); } } @@ -384,16 +310,10 @@ static const struct MemoryRegionOps imx_serial_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; -static int imx_serial_init(SysBusDevice *dev) +static void imx_serial_realize(DeviceState *dev, Error **errp) { IMXSerialState *s = IMX_SERIAL(dev); - - memory_region_init_io(&s->iomem, OBJECT(s), &imx_serial_ops, s, - "imx-serial", 0x1000); - sysbus_init_mmio(dev, &s->iomem); - sysbus_init_irq(dev, &s->irq); - if (s->chr) { qemu_chr_add_handlers(s->chr, imx_can_receive, imx_receive, imx_event, s); @@ -401,8 +321,17 @@ static int imx_serial_init(SysBusDevice *dev) DPRINTF("No char dev for uart at 0x%lx\n", (unsigned long)s->iomem.ram_addr); } +} - return 0; +static void imx_serial_init(Object *obj) +{ + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + IMXSerialState *s = IMX_SERIAL(obj); + + memory_region_init_io(&s->iomem, obj, &imx_serial_ops, s, + TYPE_IMX_SERIAL, 0x1000); + sysbus_init_mmio(sbd, &s->iomem); + sysbus_init_irq(sbd, &s->irq); } void imx_serial_create(int uart, const hwaddr addr, qemu_irq irq) @@ -439,7 +368,7 @@ void imx_serial_create(int uart, const hwaddr addr, qemu_irq irq) } -static Property imx32_serial_properties[] = { +static Property imx_serial_properties[] = { DEFINE_PROP_CHR("chardev", IMXSerialState, chr), DEFINE_PROP_END_OF_LIST(), }; @@ -447,21 +376,21 @@ static Property imx32_serial_properties[] = { static void imx_serial_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - k->init = imx_serial_init; + dc->realize = imx_serial_realize; dc->vmsd = &vmstate_imx_serial; dc->reset = imx_serial_reset_at_boot; set_bit(DEVICE_CATEGORY_INPUT, dc->categories); dc->desc = "i.MX series UART"; - dc->props = imx32_serial_properties; + dc->props = imx_serial_properties; } static const TypeInfo imx_serial_info = { - .name = TYPE_IMX_SERIAL, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(IMXSerialState), - .class_init = imx_serial_class_init, + .name = TYPE_IMX_SERIAL, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(IMXSerialState), + .instance_init = imx_serial_init, + .class_init = imx_serial_class_init, }; static void imx_serial_register_types(void) diff --git a/hw/cpu/a15mpcore.c b/hw/cpu/a15mpcore.c index acc419e..58ac02e 100644 --- a/hw/cpu/a15mpcore.c +++ b/hw/cpu/a15mpcore.c @@ -20,6 +20,7 @@ #include "hw/cpu/a15mpcore.h" #include "sysemu/kvm.h" +#include "kvm_arm.h" static void a15mp_priv_set_irq(void *opaque, int irq, int level) { @@ -33,16 +34,11 @@ static void a15mp_priv_initfn(Object *obj) SysBusDevice *sbd = SYS_BUS_DEVICE(obj); A15MPPrivState *s = A15MPCORE_PRIV(obj); DeviceState *gicdev; - const char *gictype = "arm_gic"; - - if (kvm_irqchip_in_kernel()) { - gictype = "kvm-arm-gic"; - } memory_region_init(&s->container, obj, "a15mp-priv-container", 0x8000); sysbus_init_mmio(sbd, &s->container); - object_initialize(&s->gic, sizeof(s->gic), gictype); + object_initialize(&s->gic, sizeof(s->gic), gic_class_name()); gicdev = DEVICE(&s->gic); qdev_set_parent_bus(gicdev, sysbus_get_default()); qdev_prop_set_uint32(gicdev, "revision", 2); @@ -79,14 +75,21 @@ static void a15mp_priv_realize(DeviceState *dev, Error **errp) for (i = 0; i < s->num_cpu; i++) { DeviceState *cpudev = DEVICE(qemu_get_cpu(i)); int ppibase = s->num_irq - 32 + i * 32; - /* physical timer; we wire it up to the non-secure timer's ID, - * since a real A15 always has TrustZone but QEMU doesn't. + int irq; + /* Mapping from the output timer irq lines from the CPU to the + * GIC PPI inputs used on the A15: */ - qdev_connect_gpio_out(cpudev, 0, - qdev_get_gpio_in(gicdev, ppibase + 30)); - /* virtual timer */ - qdev_connect_gpio_out(cpudev, 1, - qdev_get_gpio_in(gicdev, ppibase + 27)); + const int timer_irq[] = { + [GTIMER_PHYS] = 30, + [GTIMER_VIRT] = 27, + [GTIMER_HYP] = 26, + [GTIMER_SEC] = 29, + }; + for (irq = 0; irq < ARRAY_SIZE(timer_irq); irq++) { + qdev_connect_gpio_out(cpudev, irq, + qdev_get_gpio_in(gicdev, + ppibase + timer_irq[irq])); + } } /* Memory map (addresses are offsets from PERIPHBASE): diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c index 454bfd7..a8c5d19 100644 --- a/hw/intc/arm_gic.c +++ b/hw/intc/arm_gic.c @@ -922,12 +922,6 @@ static MemTxResult gic_dist_write(void *opaque, hwaddr offset, uint64_t data, } } -static const MemoryRegionOps gic_dist_ops = { - .read_with_attrs = gic_dist_read, - .write_with_attrs = gic_dist_write, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - static MemTxResult gic_cpu_read(GICState *s, int cpu, int offset, uint64_t *data, MemTxAttrs attrs) { @@ -1056,10 +1050,17 @@ static MemTxResult gic_do_cpu_write(void *opaque, hwaddr addr, return gic_cpu_write(s, id, addr, value, attrs); } -static const MemoryRegionOps gic_thiscpu_ops = { - .read_with_attrs = gic_thiscpu_read, - .write_with_attrs = gic_thiscpu_write, - .endianness = DEVICE_NATIVE_ENDIAN, +static const MemoryRegionOps gic_ops[2] = { + { + .read_with_attrs = gic_dist_read, + .write_with_attrs = gic_dist_write, + .endianness = DEVICE_NATIVE_ENDIAN, + }, + { + .read_with_attrs = gic_thiscpu_read, + .write_with_attrs = gic_thiscpu_write, + .endianness = DEVICE_NATIVE_ENDIAN, + } }; static const MemoryRegionOps gic_cpu_ops = { @@ -1068,31 +1069,10 @@ static const MemoryRegionOps gic_cpu_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; +/* This function is used by nvic model */ void gic_init_irqs_and_distributor(GICState *s) { - SysBusDevice *sbd = SYS_BUS_DEVICE(s); - int i; - - i = s->num_irq - GIC_INTERNAL; - /* For the GIC, also expose incoming GPIO lines for PPIs for each CPU. - * GPIO array layout is thus: - * [0..N-1] SPIs - * [N..N+31] PPIs for CPU 0 - * [N+32..N+63] PPIs for CPU 1 - * ... - */ - if (s->revision != REV_NVIC) { - i += (GIC_INTERNAL * s->num_cpu); - } - qdev_init_gpio_in(DEVICE(s), gic_set_irq, i); - for (i = 0; i < NUM_CPU(s); i++) { - sysbus_init_irq(sbd, &s->parent_irq[i]); - } - for (i = 0; i < NUM_CPU(s); i++) { - sysbus_init_irq(sbd, &s->parent_fiq[i]); - } - memory_region_init_io(&s->iomem, OBJECT(s), &gic_dist_ops, s, - "gic_dist", 0x1000); + gic_init_irqs_and_mmio(s, gic_set_irq, gic_ops); } static void arm_gic_realize(DeviceState *dev, Error **errp) @@ -1110,28 +1090,22 @@ static void arm_gic_realize(DeviceState *dev, Error **errp) return; } - gic_init_irqs_and_distributor(s); + /* This creates distributor and main CPU interface (s->cpuiomem[0]) */ + gic_init_irqs_and_mmio(s, gic_set_irq, gic_ops); - /* Memory regions for the CPU interfaces (NVIC doesn't have these): - * a region for "CPU interface for this core", then a region for - * "CPU interface for core 0", "for core 1", ... + /* Extra core-specific regions for the CPU interfaces. This is + * necessary for "franken-GIC" implementations, for example on + * Exynos 4. * NB that the memory region size of 0x100 applies for the 11MPCore * and also cores following the GIC v1 spec (ie A9). * GIC v2 defines a larger memory region (0x1000) so this will need * to be extended when we implement A15. */ - memory_region_init_io(&s->cpuiomem[0], OBJECT(s), &gic_thiscpu_ops, s, - "gic_cpu", 0x100); for (i = 0; i < NUM_CPU(s); i++) { s->backref[i] = s; memory_region_init_io(&s->cpuiomem[i+1], OBJECT(s), &gic_cpu_ops, &s->backref[i], "gic_cpu", 0x100); - } - /* Distributor */ - sysbus_init_mmio(sbd, &s->iomem); - /* cpu interfaces (one for "current cpu" plus one per cpu) */ - for (i = 0; i <= NUM_CPU(s); i++) { - sysbus_init_mmio(sbd, &s->cpuiomem[i]); + sysbus_init_mmio(sbd, &s->cpuiomem[i+1]); } } diff --git a/hw/intc/arm_gic_common.c b/hw/intc/arm_gic_common.c index a64d071..fe64b51 100644 --- a/hw/intc/arm_gic_common.c +++ b/hw/intc/arm_gic_common.c @@ -84,6 +84,47 @@ static const VMStateDescription vmstate_gic = { } }; +void gic_init_irqs_and_mmio(GICState *s, qemu_irq_handler handler, + const MemoryRegionOps *ops) +{ + SysBusDevice *sbd = SYS_BUS_DEVICE(s); + int i = s->num_irq - GIC_INTERNAL; + + /* For the GIC, also expose incoming GPIO lines for PPIs for each CPU. + * GPIO array layout is thus: + * [0..N-1] SPIs + * [N..N+31] PPIs for CPU 0 + * [N+32..N+63] PPIs for CPU 1 + * ... + */ + if (s->revision != REV_NVIC) { + i += (GIC_INTERNAL * s->num_cpu); + } + qdev_init_gpio_in(DEVICE(s), handler, i); + + for (i = 0; i < s->num_cpu; i++) { + sysbus_init_irq(sbd, &s->parent_irq[i]); + } + for (i = 0; i < s->num_cpu; i++) { + sysbus_init_irq(sbd, &s->parent_fiq[i]); + } + + /* Distributor */ + memory_region_init_io(&s->iomem, OBJECT(s), ops, s, "gic_dist", 0x1000); + sysbus_init_mmio(sbd, &s->iomem); + + if (s->revision != REV_NVIC) { + /* This is the main CPU interface "for this core". It is always + * present because it is required by both software emulation and KVM. + * NVIC is not handled here because its CPU interface is different, + * neither it can use KVM. + */ + memory_region_init_io(&s->cpuiomem[0], OBJECT(s), ops ? &ops[1] : NULL, + s, "gic_cpu", s->revision == 2 ? 0x1000 : 0x100); + sysbus_init_mmio(sbd, &s->cpuiomem[0]); + } +} + static void arm_gic_common_realize(DeviceState *dev, Error **errp) { GICState *s = ARM_GIC_COMMON(dev); diff --git a/hw/intc/arm_gic_kvm.c b/hw/intc/arm_gic_kvm.c index f56bff1..e5d0f67 100644 --- a/hw/intc/arm_gic_kvm.c +++ b/hw/intc/arm_gic_kvm.c @@ -543,7 +543,6 @@ static void kvm_arm_gic_realize(DeviceState *dev, Error **errp) { int i; GICState *s = KVM_ARM_GIC(dev); - SysBusDevice *sbd = SYS_BUS_DEVICE(dev); KVMARMGICClass *kgc = KVM_ARM_GIC_GET_CLASS(s); Error *local_err = NULL; int ret; @@ -560,32 +559,13 @@ static void kvm_arm_gic_realize(DeviceState *dev, Error **errp) return; } - i = s->num_irq - GIC_INTERNAL; - /* For the GIC, also expose incoming GPIO lines for PPIs for each CPU. - * GPIO array layout is thus: - * [0..N-1] SPIs - * [N..N+31] PPIs for CPU 0 - * [N+32..N+63] PPIs for CPU 1 - * ... - */ - i += (GIC_INTERNAL * s->num_cpu); - qdev_init_gpio_in(dev, kvm_arm_gic_set_irq, i); + gic_init_irqs_and_mmio(s, kvm_arm_gic_set_irq, NULL); for (i = 0; i < s->num_irq - GIC_INTERNAL; i++) { qemu_irq irq = qdev_get_gpio_in(dev, i); kvm_irqchip_set_qemuirq_gsi(kvm_state, irq, i); } - /* We never use our outbound IRQ/FIQ lines but provide them so that - * we maintain the same interface as the non-KVM GIC. - */ - for (i = 0; i < s->num_cpu; i++) { - sysbus_init_irq(sbd, &s->parent_irq[i]); - } - for (i = 0; i < s->num_cpu; i++) { - sysbus_init_irq(sbd, &s->parent_fiq[i]); - } - /* Try to create the device via the device control API */ s->dev_fd = -1; ret = kvm_create_device(kvm_state, KVM_DEV_TYPE_ARM_VGIC_V2, false); @@ -609,9 +589,6 @@ static void kvm_arm_gic_realize(DeviceState *dev, Error **errp) } /* Distributor */ - memory_region_init_reservation(&s->iomem, OBJECT(s), - "kvm-gic_dist", 0x1000); - sysbus_init_mmio(sbd, &s->iomem); kvm_arm_register_device(&s->iomem, (KVM_ARM_DEVICE_VGIC_V2 << KVM_ARM_DEVICE_ID_SHIFT) | KVM_VGIC_V2_ADDR_TYPE_DIST, @@ -622,9 +599,6 @@ static void kvm_arm_gic_realize(DeviceState *dev, Error **errp) * provide the "interface for core #N" memory regions, because * cores with a VGIC don't have those. */ - memory_region_init_reservation(&s->cpuiomem[0], OBJECT(s), - "kvm-gic_cpu", 0x1000); - sysbus_init_mmio(sbd, &s->cpuiomem[0]); kvm_arm_register_device(&s->cpuiomem[0], (KVM_ARM_DEVICE_VGIC_V2 << KVM_ARM_DEVICE_ID_SHIFT) | KVM_VGIC_V2_ADDR_TYPE_CPU, diff --git a/hw/intc/imx_avic.c b/hw/intc/imx_avic.c index e48f66c..96c376b 100644 --- a/hw/intc/imx_avic.c +++ b/hw/intc/imx_avic.c @@ -7,6 +7,7 @@ * Copyright (c) 2008 OKL * Copyright (c) 2011 NICTA Pty Ltd * Originally written by Hans Jiang + * Updated by Jean-Christophe Dubois <jcd@tribudubois.net> * * This code is licensed under the GPL version 2 or later. See * the COPYING file in the top-level directory. @@ -14,16 +15,14 @@ * TODO: implement vectors. */ -#include "hw/hw.h" -#include "hw/sysbus.h" -#include "qemu/host-utils.h" +#include "hw/intc/imx_avic.h" #define DEBUG_INT 1 #undef DEBUG_INT /* comment out for debugging */ #ifdef DEBUG_INT #define DPRINTF(fmt, args...) \ -do { printf("imx_avic: " fmt , ##args); } while (0) +do { printf("%s: " fmt , TYPE_IMX_AVIC, ##args); } while (0) #else #define DPRINTF(fmt, args...) do {} while (0) #endif @@ -35,46 +34,13 @@ do { printf("imx_avic: " fmt , ##args); } while (0) #define DEBUG_IMPLEMENTATION 1 #if DEBUG_IMPLEMENTATION # define IPRINTF(fmt, args...) \ - do { fprintf(stderr, "imx_avic: " fmt, ##args); } while (0) + do { fprintf(stderr, "%s: " fmt, TYPE_IMX_AVIC, ##args); } while (0) #else # define IPRINTF(fmt, args...) do {} while (0) #endif -#define IMX_AVIC_NUM_IRQS 64 - -/* Interrupt Control Bits */ -#define ABFLAG (1<<25) -#define ABFEN (1<<24) -#define NIDIS (1<<22) /* Normal Interrupt disable */ -#define FIDIS (1<<21) /* Fast interrupt disable */ -#define NIAD (1<<20) /* Normal Interrupt Arbiter Rise ARM level */ -#define FIAD (1<<19) /* Fast Interrupt Arbiter Rise ARM level */ -#define NM (1<<18) /* Normal interrupt mode */ - - -#define PRIO_PER_WORD (sizeof(uint32_t) * 8 / 4) -#define PRIO_WORDS (IMX_AVIC_NUM_IRQS/PRIO_PER_WORD) - -#define TYPE_IMX_AVIC "imx_avic" -#define IMX_AVIC(obj) \ - OBJECT_CHECK(IMXAVICState, (obj), TYPE_IMX_AVIC) - -typedef struct IMXAVICState { - SysBusDevice parent_obj; - - MemoryRegion iomem; - uint64_t pending; - uint64_t enabled; - uint64_t is_fiq; - uint32_t intcntl; - uint32_t intmask; - qemu_irq irq; - qemu_irq fiq; - uint32_t prio[PRIO_WORDS]; /* Priorities are 4-bits each */ -} IMXAVICState; - static const VMStateDescription vmstate_imx_avic = { - .name = "imx-avic", + .name = TYPE_IMX_AVIC, .version_id = 1, .minimum_version_id = 1, .fields = (VMStateField[]) { @@ -88,8 +54,6 @@ static const VMStateDescription vmstate_imx_avic = { }, }; - - static inline int imx_avic_prio(IMXAVICState *s, int irq) { uint32_t word = irq / PRIO_PER_WORD; @@ -249,7 +213,7 @@ static uint64_t imx_avic_read(void *opaque, return 0x4; default: - IPRINTF("imx_avic_read: Bad offset 0x%x\n", (int)offset); + IPRINTF("%s: Bad offset 0x%x\n", __func__, (int)offset); return 0; } } @@ -261,12 +225,12 @@ static void imx_avic_write(void *opaque, hwaddr offset, /* Vector Registers not yet supported */ if (offset >= 0x100 && offset <= 0x2fc) { - IPRINTF("imx_avic_write to vector register %d ignored\n", + IPRINTF("%s to vector register %d ignored\n", __func__, (unsigned int)((offset - 0x100) >> 2)); return; } - DPRINTF("imx_avic_write(0x%x) = %x\n", + DPRINTF("%s(0x%x) = %x\n", __func__, (unsigned int)offset>>2, (unsigned int)val); switch (offset >> 2) { case 0: /* Interrupt Control Register, INTCNTL */ @@ -341,7 +305,7 @@ static void imx_avic_write(void *opaque, hwaddr offset, return; default: - IPRINTF("imx_avic_write: Bad offset %x\n", (int)offset); + IPRINTF("%s: Bad offset %x\n", __func__, (int)offset); } imx_avic_update(s); } @@ -370,7 +334,7 @@ static int imx_avic_init(SysBusDevice *sbd) IMXAVICState *s = IMX_AVIC(dev); memory_region_init_io(&s->iomem, OBJECT(s), &imx_avic_ops, s, - "imx_avic", 0x1000); + TYPE_IMX_AVIC, 0x1000); sysbus_init_mmio(sbd, &s->iomem); qdev_init_gpio_in(dev, imx_avic_set_irq, IMX_AVIC_NUM_IRQS); diff --git a/hw/misc/imx_ccm.c b/hw/misc/imx_ccm.c index 0920288..2e19dbb 100644 --- a/hw/misc/imx_ccm.c +++ b/hw/misc/imx_ccm.c @@ -2,6 +2,7 @@ * IMX31 Clock Control Module * * Copyright (C) 2012 NICTA + * Updated by Jean-Christophe Dubois <jcd@tribudubois.net> * * This work is licensed under the terms of the GNU GPL, version 2 or later. * See the COPYING file in the top-level directory. @@ -10,51 +11,23 @@ * the CCM. */ -#include "hw/hw.h" -#include "hw/sysbus.h" -#include "sysemu/sysemu.h" -#include "hw/arm/imx.h" +#include "hw/misc/imx_ccm.h" #define CKIH_FREQ 26000000 /* 26MHz crystal input */ #define CKIL_FREQ 32768 /* nominal 32khz clock */ - //#define DEBUG_CCM 1 #ifdef DEBUG_CCM #define DPRINTF(fmt, args...) \ -do { printf("imx_ccm: " fmt , ##args); } while (0) +do { printf("%s: " fmt , TYPE_IMX_CCM, ##args); } while (0) #else #define DPRINTF(fmt, args...) do {} while (0) #endif static int imx_ccm_post_load(void *opaque, int version_id); -#define TYPE_IMX_CCM "imx_ccm" -#define IMX_CCM(obj) OBJECT_CHECK(IMXCCMState, (obj), TYPE_IMX_CCM) - -typedef struct IMXCCMState { - SysBusDevice parent_obj; - - MemoryRegion iomem; - - uint32_t ccmr; - uint32_t pdr0; - uint32_t pdr1; - uint32_t mpctl; - uint32_t spctl; - uint32_t cgr[3]; - uint32_t pmcr0; - uint32_t pmcr1; - - /* Frequencies precalculated on register changes */ - uint32_t pll_refclk_freq; - uint32_t mcu_clk_freq; - uint32_t hsp_clk_freq; - uint32_t ipg_clk_freq; -} IMXCCMState; - static const VMStateDescription vmstate_imx_ccm = { - .name = "imx-ccm", + .name = TYPE_IMX_CCM, .version_id = 1, .minimum_version_id = 1, .fields = (VMStateField[]) { @@ -72,44 +45,6 @@ static const VMStateDescription vmstate_imx_ccm = { .post_load = imx_ccm_post_load, }; -/* CCMR */ -#define CCMR_FPME (1<<0) -#define CCMR_MPE (1<<3) -#define CCMR_MDS (1<<7) -#define CCMR_FPMF (1<<26) -#define CCMR_PRCS (3<<1) - -/* PDR0 */ -#define PDR0_MCU_PODF_SHIFT (0) -#define PDR0_MCU_PODF_MASK (0x7) -#define PDR0_MAX_PODF_SHIFT (3) -#define PDR0_MAX_PODF_MASK (0x7) -#define PDR0_IPG_PODF_SHIFT (6) -#define PDR0_IPG_PODF_MASK (0x3) -#define PDR0_NFC_PODF_SHIFT (8) -#define PDR0_NFC_PODF_MASK (0x7) -#define PDR0_HSP_PODF_SHIFT (11) -#define PDR0_HSP_PODF_MASK (0x7) -#define PDR0_PER_PODF_SHIFT (16) -#define PDR0_PER_PODF_MASK (0x1f) -#define PDR0_CSI_PODF_SHIFT (23) -#define PDR0_CSI_PODF_MASK (0x1ff) - -#define EXTRACT(value, name) (((value) >> PDR0_##name##_PODF_SHIFT) \ - & PDR0_##name##_PODF_MASK) -#define INSERT(value, name) (((value) & PDR0_##name##_PODF_MASK) << \ - PDR0_##name##_PODF_SHIFT) -/* PLL control registers */ -#define PD(v) (((v) >> 26) & 0xf) -#define MFD(v) (((v) >> 16) & 0x3ff) -#define MFI(v) (((v) >> 10) & 0xf); -#define MFN(v) ((v) & 0x3ff) - -#define PLL_PD(x) (((x) & 0xf) << 26) -#define PLL_MFD(x) (((x) & 0x3ff) << 16) -#define PLL_MFI(x) (((x) & 0xf) << 10) -#define PLL_MFN(x) (((x) & 0x3ff) << 0) - uint32_t imx_clock_frequency(DeviceState *dev, IMXClk clock) { IMXCCMState *s = IMX_CCM(dev); @@ -174,7 +109,7 @@ static void update_clocks(IMXCCMState *s) s->hsp_clk_freq = s->mcu_clk_freq / (1 + EXTRACT(s->pdr0, HSP)); s->ipg_clk_freq = s->hsp_clk_freq / (1 + EXTRACT(s->pdr0, IPG)); - DPRINTF("Clocks: mcu %uMHz, HSP %uMHz, IPG %uHz\n", + DPRINTF("%s: mcu %uMHz, HSP %uMHz, IPG %uHz\n", __func__, s->mcu_clk_freq / 1000000, s->hsp_clk_freq / 1000000, s->ipg_clk_freq); @@ -200,7 +135,7 @@ static uint64_t imx_ccm_read(void *opaque, hwaddr offset, { IMXCCMState *s = (IMXCCMState *)opaque; - DPRINTF("read(offset=%x)", offset >> 2); + DPRINTF("%s(offset=%x)", __func__, offset >> 2); switch (offset >> 2) { case 0: /* CCMR */ DPRINTF(" ccmr = 0x%x\n", s->ccmr); @@ -241,7 +176,7 @@ static void imx_ccm_write(void *opaque, hwaddr offset, { IMXCCMState *s = (IMXCCMState *)opaque; - DPRINTF("write(offset=%x, value = %x)\n", + DPRINTF("%s(offset=%x, value = %x)\n", __func__, offset >> 2, (unsigned int)value); switch (offset >> 2) { case 0: @@ -286,7 +221,7 @@ static int imx_ccm_init(SysBusDevice *dev) IMXCCMState *s = IMX_CCM(dev); memory_region_init_io(&s->iomem, OBJECT(dev), &imx_ccm_ops, s, - "imx_ccm", 0x1000); + TYPE_IMX_CCM, 0x1000); sysbus_init_mmio(dev, &s->iomem); return 0; diff --git a/hw/timer/imx_epit.c b/hw/timer/imx_epit.c index ffefc22..10c5d2b 100644 --- a/hw/timer/imx_epit.c +++ b/hw/timer/imx_epit.c @@ -5,23 +5,18 @@ * Copyright (c) 2011 NICTA Pty Ltd * Originally written by Hans Jiang * Updated by Peter Chubb - * Updated by Jean-Christophe Dubois + * Updated by Jean-Christophe Dubois <jcd@tribudubois.net> * * This code is licensed under GPL version 2 or later. See * the COPYING file in the top-level directory. * */ -#include "hw/hw.h" -#include "qemu/bitops.h" -#include "qemu/timer.h" -#include "hw/ptimer.h" -#include "hw/sysbus.h" #include "hw/arm/imx.h" +#include "hw/timer/imx_epit.h" +#include "hw/misc/imx_ccm.h" #include "qemu/main-loop.h" -#define TYPE_IMX_EPIT "imx.epit" - #define DEBUG_TIMER 0 #if DEBUG_TIMER @@ -61,30 +56,6 @@ static char const *imx_epit_reg_name(uint32_t reg) # define IPRINTF(fmt, args...) do {} while (0) #endif -#define IMX_EPIT(obj) \ - OBJECT_CHECK(IMXEPITState, (obj), TYPE_IMX_EPIT) - -/* - * EPIT: Enhanced periodic interrupt timer - */ - -#define CR_EN (1 << 0) -#define CR_ENMOD (1 << 1) -#define CR_OCIEN (1 << 2) -#define CR_RLD (1 << 3) -#define CR_PRESCALE_SHIFT (4) -#define CR_PRESCALE_MASK (0xfff) -#define CR_SWR (1 << 16) -#define CR_IOVW (1 << 17) -#define CR_DBGEN (1 << 18) -#define CR_WAITEN (1 << 19) -#define CR_DOZEN (1 << 20) -#define CR_STOPEN (1 << 21) -#define CR_CLKSRC_SHIFT (24) -#define CR_CLKSRC_MASK (0x3 << CR_CLKSRC_SHIFT) - -#define EPIT_TIMER_MAX 0XFFFFFFFFUL - /* * Exact clock frequencies vary from board to board. * These are typical. @@ -96,23 +67,6 @@ static const IMXClk imx_epit_clocks[] = { CLK_32k, /* 11 ipg_clk_32k -- ~32kHz */ }; -typedef struct { - SysBusDevice busdev; - ptimer_state *timer_reload; - ptimer_state *timer_cmp; - MemoryRegion iomem; - DeviceState *ccm; - - uint32_t cr; - uint32_t sr; - uint32_t lr; - uint32_t cmp; - uint32_t cnt; - - uint32_t freq; - qemu_irq irq; -} IMXEPITState; - /* * Update interrupt status */ @@ -174,9 +128,9 @@ static void imx_epit_reset(DeviceState *dev) static uint32_t imx_epit_update_count(IMXEPITState *s) { - s->cnt = ptimer_get_count(s->timer_reload); + s->cnt = ptimer_get_count(s->timer_reload); - return s->cnt; + return s->cnt; } static uint64_t imx_epit_read(void *opaque, hwaddr offset, unsigned size) @@ -344,13 +298,13 @@ void imx_timerp_create(const hwaddr addr, qemu_irq irq, DeviceState *ccm) } static const MemoryRegionOps imx_epit_ops = { - .read = imx_epit_read, - .write = imx_epit_write, - .endianness = DEVICE_NATIVE_ENDIAN, + .read = imx_epit_read, + .write = imx_epit_write, + .endianness = DEVICE_NATIVE_ENDIAN, }; static const VMStateDescription vmstate_imx_timer_epit = { - .name = "imx.epit", + .name = TYPE_IMX_EPIT, .version_id = 2, .minimum_version_id = 2, .fields = (VMStateField[]) { diff --git a/hw/timer/imx_gpt.c b/hw/timer/imx_gpt.c index 3b31010..01f802e 100644 --- a/hw/timer/imx_gpt.c +++ b/hw/timer/imx_gpt.c @@ -5,23 +5,18 @@ * Copyright (c) 2011 NICTA Pty Ltd * Originally written by Hans Jiang * Updated by Peter Chubb - * Updated by Jean-Christophe Dubois + * Updated by Jean-Christophe Dubois <jcd@tribudubois.net> * * This code is licensed under GPL version 2 or later. See * the COPYING file in the top-level directory. * */ -#include "hw/hw.h" -#include "qemu/bitops.h" -#include "qemu/timer.h" -#include "hw/ptimer.h" -#include "hw/sysbus.h" #include "hw/arm/imx.h" +#include "hw/timer/imx_gpt.h" +#include "hw/misc/imx_ccm.h" #include "qemu/main-loop.h" -#define TYPE_IMX_GPT "imx.gpt" - /* * Define to 1 for debug messages */ @@ -74,76 +69,8 @@ static char const *imx_gpt_reg_name(uint32_t reg) # define IPRINTF(fmt, args...) do {} while (0) #endif -#define IMX_GPT(obj) \ - OBJECT_CHECK(IMXGPTState, (obj), TYPE_IMX_GPT) -/* - * GPT : General purpose timer - * - * This timer counts up continuously while it is enabled, resetting itself - * to 0 when it reaches GPT_TIMER_MAX (in freerun mode) or when it - * reaches the value of one of the ocrX (in periodic mode). - */ - -#define GPT_TIMER_MAX 0XFFFFFFFFUL - -/* Control register. Not all of these bits have any effect (yet) */ -#define GPT_CR_EN (1 << 0) /* GPT Enable */ -#define GPT_CR_ENMOD (1 << 1) /* GPT Enable Mode */ -#define GPT_CR_DBGEN (1 << 2) /* GPT Debug mode enable */ -#define GPT_CR_WAITEN (1 << 3) /* GPT Wait Mode Enable */ -#define GPT_CR_DOZEN (1 << 4) /* GPT Doze mode enable */ -#define GPT_CR_STOPEN (1 << 5) /* GPT Stop Mode Enable */ -#define GPT_CR_CLKSRC_SHIFT (6) -#define GPT_CR_CLKSRC_MASK (0x7) - -#define GPT_CR_FRR (1 << 9) /* Freerun or Restart */ -#define GPT_CR_SWR (1 << 15) /* Software Reset */ -#define GPT_CR_IM1 (3 << 16) /* Input capture channel 1 mode (2 bits) */ -#define GPT_CR_IM2 (3 << 18) /* Input capture channel 2 mode (2 bits) */ -#define GPT_CR_OM1 (7 << 20) /* Output Compare Channel 1 Mode (3 bits) */ -#define GPT_CR_OM2 (7 << 23) /* Output Compare Channel 2 Mode (3 bits) */ -#define GPT_CR_OM3 (7 << 26) /* Output Compare Channel 3 Mode (3 bits) */ -#define GPT_CR_FO1 (1 << 29) /* Force Output Compare Channel 1 */ -#define GPT_CR_FO2 (1 << 30) /* Force Output Compare Channel 2 */ -#define GPT_CR_FO3 (1 << 31) /* Force Output Compare Channel 3 */ - -#define GPT_SR_OF1 (1 << 0) -#define GPT_SR_OF2 (1 << 1) -#define GPT_SR_OF3 (1 << 2) -#define GPT_SR_ROV (1 << 5) - -#define GPT_IR_OF1IE (1 << 0) -#define GPT_IR_OF2IE (1 << 1) -#define GPT_IR_OF3IE (1 << 2) -#define GPT_IR_ROVIE (1 << 5) - -typedef struct { - SysBusDevice busdev; - ptimer_state *timer; - MemoryRegion iomem; - DeviceState *ccm; - - uint32_t cr; - uint32_t pr; - uint32_t sr; - uint32_t ir; - uint32_t ocr1; - uint32_t ocr2; - uint32_t ocr3; - uint32_t icr1; - uint32_t icr2; - uint32_t cnt; - - uint32_t next_timeout; - uint32_t next_int; - - uint32_t freq; - - qemu_irq irq; -} IMXGPTState; - static const VMStateDescription vmstate_imx_timer_gpt = { - .name = "imx.gpt", + .name = TYPE_IMX_GPT, .version_id = 3, .minimum_version_id = 3, .fields = (VMStateField[]) { @@ -180,7 +107,7 @@ static void imx_gpt_set_freq(IMXGPTState *s) { uint32_t clksrc = extract32(s->cr, GPT_CR_CLKSRC_SHIFT, 3); uint32_t freq = imx_clock_frequency(s->ccm, imx_gpt_clocks[clksrc]) - / (1 + s->pr); + / (1 + s->pr); s->freq = freq; DPRINTF("Setting clksrc %d to frequency %d\n", clksrc, freq); @@ -207,7 +134,7 @@ static uint32_t imx_gpt_update_count(IMXGPTState *s) } static inline uint32_t imx_gpt_find_limit(uint32_t count, uint32_t reg, - uint32_t timeout) + uint32_t timeout) { if ((count < reg) && (timeout > reg)) { timeout = reg; |