target-arm queue

-----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.11 (GNU/Linux)
 
 iQIcBAABCAAGBQJSE3WMAAoJEDwlJe0UNgzetMcP/0lKE1tRvXjUk78Jazqff/ET
 op01vY5FiMurt9/ncV2kwTKGd5S/o8zmqf+3vbGijX9zlWMD1h1eJ/k8UeQxuCBf
 XYIPZhLESpBl7ex6b7G4Z0TUTT3qdLqHKTrdEzzTiwbmo1eu8cF2zWGh7eeeK/pA
 hX0BFlkBUo7SmlDOq4vj+88N3C+igcvE1UtOa9l17XpoLURkXZ0BFmy8Ew0f9iPj
 uWH9prnUpYAvzektZqEEGZQV9p1CM8O06GkdMFMqSSEU/YBnZY1pJrS+dOOZ3676
 PQuGGdkOEPqBsz0dHPVifFXySg471LIYFUJWYGY69Uw4kGIkb1rEBuO8d5eJuFbn
 2UYUnxOSNw3atBaE2E3TCKCQSBjrlZ/WSnuz873I50qz+DBnQ5fagG5RYKySQJcR
 UReC5WnWWwQh8oynx10lG6eggTSQZNxdHxF6VGTeygYPtuxlXdMPw+eveySxk6IH
 a4fP1GzlDKIKh7O0yc2pyPF5UsqZ1JmIwrkmBuR7sgml7r0T4AaEndu8b9xYg94j
 fHCgdLMFg5z8uWlzv5WzWX6PwYI9t46EWxHCk7x/Nrnp0WyF/XHhGipiS3AUOAQK
 pQlLOA+ru0UVAHSFM4nCikNDqo4kxuM3BOt+ypw69f56ImnpqAGruUUgH/Ua9vze
 DevOaXopdfsYczg6I+AF
 =Qnph
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'pmaydell/tags/pull-target-arm-20130820' into staging

target-arm queue

# gpg: Signature made Tue 20 Aug 2013 08:56:28 AM CDT using RSA key ID 14360CDE
# gpg: Can't check signature: public key not found

# By Peter Maydell (20) and Peter Chubb (1)
# Via Peter Maydell
* pmaydell/tags/pull-target-arm-20130820: (21 commits)
  hw/timer/imx_epit: Simplify and fix imx_epit implementation
  default-configs: Fix A9MP and A15MP config names
  hw/cpu/a15mpcore: Wire generic timer outputs to GIC inputs
  target-arm: Implement the generic timer
  target-arm: Support coprocessor registers which do I/O
  target-arm: Allow raw_read() and raw_write() to handle 64 bit regs
  hw/arm/pic_cpu: Remove the now-unneeded arm_pic_init_cpu()
  hw/arm/xilinx_zynq: Don't use arm_pic_init_cpu()
  hw/arm/vexpress: Don't use arm_pic_init_cpu()
  hw/arm/versatilepb: Don't use arm_pic_init_cpu()
  hw/arm/strongarm: Don't use arm_pic_init_cpu()
  hw/arm/realview: Don't use arm_pic_init_cpu()
  hw/arm/omap*: Don't use arm_pic_init_cpu()
  hw/arm/musicpal: Don't use arm_pic_init_cpu()
  hw/arm/kzm: Don't use arm_pic_init_cpu()
  hw/arm/integratorcp: Don't use arm_pic_init_cpu()
  hw/arm/highbank: Don't use arm_pic_init_cpu()
  hw/arm/exynos4210: Don't use arm_pic_init_cpu()
  hw/arm/armv7m: Don't use arm_pic_init_cpu()
  target-arm: Make IRQ and FIQ gpio lines on the CPU object
  ...

Message-id: 1377007680-4934-1-git-send-email-peter.maydell@linaro.org
Signed-off-by: Anthony Liguori <anthony@codemonkey.ws>
This commit is contained in:
Anthony Liguori 2013-08-20 11:23:52 -05:00
commit ecfe10c9a6
26 changed files with 514 additions and 210 deletions

View file

@ -1,6 +1,6 @@
obj-y += boot.o collie.o exynos4_boards.o gumstix.o highbank.o
obj-y += integratorcp.o kzm.o mainstone.o musicpal.o nseries.o
obj-y += omap_sx1.o palm.o pic_cpu.o realview.o spitz.o stellaris.o
obj-y += omap_sx1.o palm.o realview.o spitz.o stellaris.o
obj-y += tosa.o versatilepb.o vexpress.o xilinx_zynq.o z2.o
obj-y += armv7m.o exynos4210.o pxa2xx.o pxa2xx_gpio.o pxa2xx_pic.o

View file

@ -173,7 +173,6 @@ qemu_irq *armv7m_init(MemoryRegion *address_space_mem,
DeviceState *nvic;
/* FIXME: make this local state. */
static qemu_irq pic[64];
qemu_irq *cpu_pic;
int image_size;
uint64_t entry;
uint64_t lowaddr;
@ -221,8 +220,8 @@ qemu_irq *armv7m_init(MemoryRegion *address_space_mem,
nvic = qdev_create(NULL, "armv7m_nvic");
env->nvic = nvic;
qdev_init_nofail(nvic);
cpu_pic = arm_pic_init_cpu(cpu);
sysbus_connect_irq(SYS_BUS_DEVICE(nvic), 0, cpu_pic[ARM_PIC_CPU_IRQ]);
sysbus_connect_irq(SYS_BUS_DEVICE(nvic), 0,
qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_IRQ));
for (i = 0; i < 64; i++) {
pic[i] = qdev_get_gpio_in(nvic, i);
}

View file

@ -137,10 +137,8 @@ void exynos4210_write_secondary(ARMCPU *cpu,
Exynos4210State *exynos4210_init(MemoryRegion *system_mem,
unsigned long ram_size)
{
qemu_irq cpu_irq[EXYNOS4210_NCPUS];
int i, n;
Exynos4210State *s = g_new(Exynos4210State, 1);
qemu_irq *irqp;
qemu_irq gate_irq[EXYNOS4210_NCPUS][EXYNOS4210_IRQ_GATE_NINPUTS];
unsigned long mem_size;
DeviceState *dev;
@ -152,15 +150,6 @@ Exynos4210State *exynos4210_init(MemoryRegion *system_mem,
fprintf(stderr, "Unable to find CPU %d definition\n", n);
exit(1);
}
/* Create PIC controller for each processor instance */
irqp = arm_pic_init_cpu(s->cpu[n]);
/*
* Get GICs gpio_in cpu_irq to connect a combiner to them later.
* Use only IRQ for a while.
*/
cpu_irq[n] = irqp[ARM_PIC_CPU_IRQ];
}
/*** IRQs ***/
@ -178,8 +167,9 @@ Exynos4210State *exynos4210_init(MemoryRegion *system_mem,
}
busdev = SYS_BUS_DEVICE(dev);
/* Connect IRQ Gate output to cpu_irq */
sysbus_connect_irq(busdev, 0, cpu_irq[i]);
/* Connect IRQ Gate output to CPU's IRQ line */
sysbus_connect_irq(busdev, 0,
qdev_get_gpio_in(DEVICE(s->cpu[i]), ARM_CPU_IRQ));
}
/* Private memory region and Internal GIC */

View file

@ -209,7 +209,6 @@ static void calxeda_init(QEMUMachineInitArgs *args, enum cxmachines machine)
const char *initrd_filename = args->initrd_filename;
DeviceState *dev = NULL;
SysBusDevice *busdev;
qemu_irq *irqp;
qemu_irq pic[128];
int n;
qemu_irq cpu_irq[4];
@ -239,8 +238,7 @@ static void calxeda_init(QEMUMachineInitArgs *args, enum cxmachines machine)
/* This will become a QOM property eventually */
cpu->reset_cbar = GIC_BASE_ADDR;
irqp = arm_pic_init_cpu(cpu);
cpu_irq[n] = irqp[ARM_PIC_CPU_IRQ];
cpu_irq[n] = qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_IRQ);
}
sysmem = get_system_memory();

View file

@ -465,7 +465,6 @@ static void integratorcp_init(QEMUMachineInitArgs *args)
MemoryRegion *ram = g_new(MemoryRegion, 1);
MemoryRegion *ram_alias = g_new(MemoryRegion, 1);
qemu_irq pic[32];
qemu_irq *cpu_pic;
DeviceState *dev;
int i;
@ -493,10 +492,10 @@ static void integratorcp_init(QEMUMachineInitArgs *args)
qdev_init_nofail(dev);
sysbus_mmio_map((SysBusDevice *)dev, 0, 0x10000000);
cpu_pic = arm_pic_init_cpu(cpu);
dev = sysbus_create_varargs(TYPE_INTEGRATOR_PIC, 0x14000000,
cpu_pic[ARM_PIC_CPU_IRQ],
cpu_pic[ARM_PIC_CPU_FIQ], NULL);
qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_IRQ),
qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_FIQ),
NULL);
for (i = 0; i < 32; i++) {
pic[i] = qdev_get_gpio_in(dev, i);
}

View file

@ -82,7 +82,6 @@ static void kzm_init(QEMUMachineInitArgs *args)
MemoryRegion *ram = g_new(MemoryRegion, 1);
MemoryRegion *sram = g_new(MemoryRegion, 1);
MemoryRegion *ram_alias = g_new(MemoryRegion, 1);
qemu_irq *cpu_pic;
DeviceState *dev;
DeviceState *ccm;
@ -108,11 +107,10 @@ static void kzm_init(QEMUMachineInitArgs *args)
memory_region_init_ram(sram, NULL, "kzm.sram", 0x4000);
memory_region_add_subregion(address_space_mem, 0x1FFFC000, sram);
cpu_pic = arm_pic_init_cpu(cpu);
dev = sysbus_create_varargs("imx_avic", 0x68000000,
cpu_pic[ARM_PIC_CPU_IRQ],
cpu_pic[ARM_PIC_CPU_FIQ], NULL);
qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_IRQ),
qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_FIQ),
NULL);
imx_serial_create(0, 0x43f90000, qdev_get_gpio_in(dev, 45));
imx_serial_create(1, 0x43f94000, qdev_get_gpio_in(dev, 32));

View file

@ -1586,7 +1586,6 @@ static void musicpal_init(QEMUMachineInitArgs *args)
const char *kernel_cmdline = args->kernel_cmdline;
const char *initrd_filename = args->initrd_filename;
ARMCPU *cpu;
qemu_irq *cpu_pic;
qemu_irq pic[32];
DeviceState *dev;
DeviceState *i2c_dev;
@ -1610,7 +1609,6 @@ static void musicpal_init(QEMUMachineInitArgs *args)
fprintf(stderr, "Unable to find CPU definition\n");
exit(1);
}
cpu_pic = arm_pic_init_cpu(cpu);
/* For now we use a fixed - the original - RAM size */
memory_region_init_ram(ram, NULL, "musicpal.ram", MP_RAM_DEFAULT_SIZE);
@ -1622,7 +1620,7 @@ static void musicpal_init(QEMUMachineInitArgs *args)
memory_region_add_subregion(address_space_mem, MP_SRAM_BASE, sram);
dev = sysbus_create_simple(TYPE_MV88W8618_PIC, MP_PIC_BASE,
cpu_pic[ARM_PIC_CPU_IRQ]);
qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_IRQ));
for (i = 0; i < 32; i++) {
pic[i] = qdev_get_gpio_in(dev, i);
}

View file

@ -3827,7 +3827,6 @@ struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *system_memory,
int i;
struct omap_mpu_state_s *s = (struct omap_mpu_state_s *)
g_malloc0(sizeof(struct omap_mpu_state_s));
qemu_irq *cpu_irq;
qemu_irq dma_irqs[6];
DriveInfo *dinfo;
SysBusDevice *busdev;
@ -3860,14 +3859,15 @@ struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *system_memory,
omap_clkm_init(system_memory, 0xfffece00, 0xe1008000, s);
cpu_irq = arm_pic_init_cpu(s->cpu);
s->ih[0] = qdev_create(NULL, "omap-intc");
qdev_prop_set_uint32(s->ih[0], "size", 0x100);
qdev_prop_set_ptr(s->ih[0], "clk", omap_findclk(s, "arminth_ck"));
qdev_init_nofail(s->ih[0]);
busdev = SYS_BUS_DEVICE(s->ih[0]);
sysbus_connect_irq(busdev, 0, cpu_irq[ARM_PIC_CPU_IRQ]);
sysbus_connect_irq(busdev, 1, cpu_irq[ARM_PIC_CPU_FIQ]);
sysbus_connect_irq(busdev, 0,
qdev_get_gpio_in(DEVICE(s->cpu), ARM_CPU_IRQ));
sysbus_connect_irq(busdev, 1,
qdev_get_gpio_in(DEVICE(s->cpu), ARM_CPU_FIQ));
sysbus_mmio_map(busdev, 0, 0xfffecb00);
s->ih[1] = qdev_create(NULL, "omap-intc");
qdev_prop_set_uint32(s->ih[1], "size", 0x800);

View file

@ -2244,7 +2244,6 @@ struct omap_mpu_state_s *omap2420_mpu_init(MemoryRegion *sysmem,
{
struct omap_mpu_state_s *s = (struct omap_mpu_state_s *)
g_malloc0(sizeof(struct omap_mpu_state_s));
qemu_irq *cpu_irq;
qemu_irq dma_irqs[4];
DriveInfo *dinfo;
int i;
@ -2277,15 +2276,16 @@ struct omap_mpu_state_s *omap2420_mpu_init(MemoryRegion *sysmem,
s->l4 = omap_l4_init(sysmem, OMAP2_L4_BASE, 54);
/* Actually mapped at any 2K boundary in the ARM11 private-peripheral if */
cpu_irq = arm_pic_init_cpu(s->cpu);
s->ih[0] = qdev_create(NULL, "omap2-intc");
qdev_prop_set_uint8(s->ih[0], "revision", 0x21);
qdev_prop_set_ptr(s->ih[0], "fclk", omap_findclk(s, "mpu_intc_fclk"));
qdev_prop_set_ptr(s->ih[0], "iclk", omap_findclk(s, "mpu_intc_iclk"));
qdev_init_nofail(s->ih[0]);
busdev = SYS_BUS_DEVICE(s->ih[0]);
sysbus_connect_irq(busdev, 0, cpu_irq[ARM_PIC_CPU_IRQ]);
sysbus_connect_irq(busdev, 1, cpu_irq[ARM_PIC_CPU_FIQ]);
sysbus_connect_irq(busdev, 0,
qdev_get_gpio_in(DEVICE(s->cpu), ARM_CPU_IRQ));
sysbus_connect_irq(busdev, 1,
qdev_get_gpio_in(DEVICE(s->cpu), ARM_CPU_FIQ));
sysbus_mmio_map(busdev, 0, 0x480fe000);
s->prcm = omap_prcm_init(omap_l4tao(s->l4, 3),
qdev_get_gpio_in(s->ih[0],

View file

@ -1,68 +0,0 @@
/*
* Generic ARM Programmable Interrupt Controller support.
*
* Copyright (c) 2006 CodeSourcery.
* Written by Paul Brook
*
* This code is licensed under the LGPL
*/
#include "hw/hw.h"
#include "hw/arm/arm.h"
#include "sysemu/kvm.h"
/* Input 0 is IRQ and input 1 is FIQ. */
static void arm_pic_cpu_handler(void *opaque, int irq, int level)
{
ARMCPU *cpu = opaque;
CPUState *cs = CPU(cpu);
switch (irq) {
case ARM_PIC_CPU_IRQ:
if (level) {
cpu_interrupt(cs, CPU_INTERRUPT_HARD);
} else {
cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
}
break;
case ARM_PIC_CPU_FIQ:
if (level) {
cpu_interrupt(cs, CPU_INTERRUPT_FIQ);
} else {
cpu_reset_interrupt(cs, CPU_INTERRUPT_FIQ);
}
break;
default:
hw_error("arm_pic_cpu_handler: Bad interrupt line %d\n", irq);
}
}
static void kvm_arm_pic_cpu_handler(void *opaque, int irq, int level)
{
#ifdef CONFIG_KVM
ARMCPU *cpu = opaque;
CPUState *cs = CPU(cpu);
int kvm_irq = KVM_ARM_IRQ_TYPE_CPU << KVM_ARM_IRQ_TYPE_SHIFT;
switch (irq) {
case ARM_PIC_CPU_IRQ:
kvm_irq |= KVM_ARM_IRQ_CPU_IRQ;
break;
case ARM_PIC_CPU_FIQ:
kvm_irq |= KVM_ARM_IRQ_CPU_FIQ;
break;
default:
hw_error("kvm_arm_pic_cpu_handler: Bad interrupt line %d\n", irq);
}
kvm_irq |= cs->cpu_index << KVM_ARM_IRQ_VCPU_SHIFT;
kvm_set_irq(kvm_state, kvm_irq, level ? 1 : 0);
#endif
}
qemu_irq *arm_pic_init_cpu(ARMCPU *cpu)
{
if (kvm_enabled()) {
return qemu_allocate_irqs(kvm_arm_pic_cpu_handler, cpu, 2);
}
return qemu_allocate_irqs(arm_pic_cpu_handler, cpu, 2);
}

View file

@ -56,7 +56,6 @@ static void realview_init(QEMUMachineInitArgs *args,
MemoryRegion *ram_hack = g_new(MemoryRegion, 1);
DeviceState *dev, *sysctl, *gpio2, *pl041;
SysBusDevice *busdev;
qemu_irq *irqp;
qemu_irq pic[64];
qemu_irq mmc_irq[2];
PCIBus *pci_bus = NULL;
@ -92,8 +91,7 @@ static void realview_init(QEMUMachineInitArgs *args,
fprintf(stderr, "Unable to find CPU definition\n");
exit(1);
}
irqp = arm_pic_init_cpu(cpu);
cpu_irq[n] = irqp[ARM_PIC_CPU_IRQ];
cpu_irq[n] = qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_IRQ);
}
env = &cpu->env;
if (arm_feature(env, ARM_FEATURE_V7)) {

View file

@ -1588,7 +1588,6 @@ StrongARMState *sa1110_init(MemoryRegion *sysmem,
unsigned int sdram_size, const char *rev)
{
StrongARMState *s;
qemu_irq *pic;
int i;
s = g_malloc0(sizeof(StrongARMState));
@ -1613,9 +1612,10 @@ StrongARMState *sa1110_init(MemoryRegion *sysmem,
vmstate_register_ram_global(&s->sdram);
memory_region_add_subregion(sysmem, SA_SDCS0, &s->sdram);
pic = arm_pic_init_cpu(s->cpu);
s->pic = sysbus_create_varargs("strongarm_pic", 0x90050000,
pic[ARM_PIC_CPU_IRQ], pic[ARM_PIC_CPU_FIQ], NULL);
qdev_get_gpio_in(DEVICE(s->cpu), ARM_CPU_IRQ),
qdev_get_gpio_in(DEVICE(s->cpu), ARM_CPU_FIQ),
NULL);
sysbus_create_varargs("pxa25x-timer", 0x90000000,
qdev_get_gpio_in(s->pic, SA_PIC_OSTC0),

View file

@ -178,7 +178,6 @@ static void versatile_init(QEMUMachineInitArgs *args, int board_id)
ARMCPU *cpu;
MemoryRegion *sysmem = get_system_memory();
MemoryRegion *ram = g_new(MemoryRegion, 1);
qemu_irq *cpu_pic;
qemu_irq pic[32];
qemu_irq sic[32];
DeviceState *dev, *sysctl;
@ -211,10 +210,10 @@ static void versatile_init(QEMUMachineInitArgs *args, int board_id)
qdev_init_nofail(sysctl);
sysbus_mmio_map(SYS_BUS_DEVICE(sysctl), 0, 0x10000000);
cpu_pic = arm_pic_init_cpu(cpu);
dev = sysbus_create_varargs("pl190", 0x10140000,
cpu_pic[ARM_PIC_CPU_IRQ],
cpu_pic[ARM_PIC_CPU_FIQ], NULL);
qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_IRQ),
qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_FIQ),
NULL);
for (n = 0; n < 32; n++) {
pic[n] = qdev_get_gpio_in(dev, n);
}

View file

@ -183,7 +183,6 @@ static void a9_daughterboard_init(const VEDBoardInfo *daughterboard,
MemoryRegion *lowram = g_new(MemoryRegion, 1);
DeviceState *dev;
SysBusDevice *busdev;
qemu_irq *irqp;
int n;
qemu_irq cpu_irq[4];
ram_addr_t low_ram_size;
@ -198,8 +197,7 @@ static void a9_daughterboard_init(const VEDBoardInfo *daughterboard,
fprintf(stderr, "Unable to find CPU definition\n");
exit(1);
}
irqp = arm_pic_init_cpu(cpu);
cpu_irq[n] = irqp[ARM_PIC_CPU_IRQ];
cpu_irq[n] = qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_IRQ);
}
if (ram_size > 0x40000000) {
@ -312,15 +310,13 @@ static void a15_daughterboard_init(const VEDBoardInfo *daughterboard,
for (n = 0; n < smp_cpus; n++) {
ARMCPU *cpu;
qemu_irq *irqp;
cpu = cpu_arm_init(cpu_model);
if (!cpu) {
fprintf(stderr, "Unable to find CPU definition\n");
exit(1);
}
irqp = arm_pic_init_cpu(cpu);
cpu_irq[n] = irqp[ARM_PIC_CPU_IRQ];
cpu_irq[n] = qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_IRQ);
}
{

View file

@ -108,11 +108,9 @@ static void zynq_init(QEMUMachineInitArgs *args)
MemoryRegion *ocm_ram = g_new(MemoryRegion, 1);
DeviceState *dev;
SysBusDevice *busdev;
qemu_irq *irqp;
qemu_irq pic[64];
NICInfo *nd;
int n;
qemu_irq cpu_irq;
if (!cpu_model) {
cpu_model = "cortex-a9";
@ -123,8 +121,6 @@ static void zynq_init(QEMUMachineInitArgs *args)
fprintf(stderr, "Unable to find CPU definition\n");
exit(1);
}
irqp = arm_pic_init_cpu(cpu);
cpu_irq = irqp[ARM_PIC_CPU_IRQ];
/* max 2GB ram */
if (ram_size > 0x80000000) {
@ -159,7 +155,8 @@ static void zynq_init(QEMUMachineInitArgs *args)
qdev_init_nofail(dev);
busdev = SYS_BUS_DEVICE(dev);
sysbus_mmio_map(busdev, 0, 0xF8F00000);
sysbus_connect_irq(busdev, 0, cpu_irq);
sysbus_connect_irq(busdev, 0,
qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_IRQ));
for (n = 0; n < 64; n++) {
pic[n] = qdev_get_gpio_in(dev, n);

View file

@ -1,5 +1,5 @@
obj-$(CONFIG_ARM11MPCORE) += arm11mpcore.o
obj-$(CONFIG_ARM9MPCORE) += a9mpcore.o
obj-$(CONFIG_ARM15MPCORE) += a15mpcore.o
obj-$(CONFIG_A9MPCORE) += a9mpcore.o
obj-$(CONFIG_A15MPCORE) += a15mpcore.o
obj-$(CONFIG_ICC_BUS) += icc_bus.o

View file

@ -49,6 +49,8 @@ static int a15mp_priv_init(SysBusDevice *dev)
A15MPPrivState *s = A15MPCORE_PRIV(dev);
SysBusDevice *busdev;
const char *gictype = "arm_gic";
int i;
CPUState *cpu;
if (kvm_irqchip_in_kernel()) {
gictype = "kvm-arm-gic";
@ -67,6 +69,22 @@ static int a15mp_priv_init(SysBusDevice *dev)
/* Pass through inbound GPIO lines to the GIC */
qdev_init_gpio_in(DEVICE(dev), a15mp_priv_set_irq, s->num_irq - 32);
/* Wire the outputs from each CPU's generic timer to the
* appropriate GIC PPI inputs
*/
for (i = 0, cpu = first_cpu; i < s->num_cpu; i++, cpu = cpu->next_cpu) {
DeviceState *cpudev = DEVICE(cpu);
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.
*/
qdev_connect_gpio_out(cpudev, 0,
qdev_get_gpio_in(s->gic, ppibase + 30));
/* virtual timer */
qdev_connect_gpio_out(cpudev, 1,
qdev_get_gpio_in(s->gic, ppibase + 27));
}
/* Memory map (addresses are offsets from PERIPHBASE):
* 0x0000-0x0fff -- reserved
* 0x1000-0x1fff -- GIC Distributor

View file

@ -43,7 +43,7 @@ static char const *imx_epit_reg_name(uint32_t reg)
}
# define DPRINTF(fmt, args...) \
do { printf("%s: " fmt , __func__, ##args); } while (0)
do { fprintf(stderr, "%s: " fmt , __func__, ##args); } while (0)
#else
# define DPRINTF(fmt, args...) do {} while (0)
#endif
@ -152,7 +152,7 @@ static void imx_epit_reset(DeviceState *dev)
/*
* Soft reset doesn't touch some bits; hard reset clears them
*/
s->cr &= ~(CR_EN|CR_ENMOD|CR_STOPEN|CR_DOZEN|CR_WAITEN|CR_DBGEN);
s->cr &= (CR_EN|CR_ENMOD|CR_STOPEN|CR_DOZEN|CR_WAITEN|CR_DBGEN);
s->sr = 0;
s->lr = TIMER_MAX;
s->cmp = 0;
@ -167,7 +167,7 @@ static void imx_epit_reset(DeviceState *dev)
ptimer_set_limit(s->timer_reload, TIMER_MAX, 1);
if (s->freq && (s->cr & CR_EN)) {
/* if the timer is still enabled, restart it */
ptimer_run(s->timer_reload, 1);
ptimer_run(s->timer_reload, 0);
}
}
@ -218,17 +218,17 @@ static uint64_t imx_epit_read(void *opaque, hwaddr offset, unsigned size)
static void imx_epit_reload_compare_timer(IMXEPITState *s)
{
if ((s->cr & CR_OCIEN) && s->cmp) {
/* if the compare feature is on */
if ((s->cr & (CR_EN | CR_OCIEN)) == (CR_EN | CR_OCIEN)) {
/* if the compare feature is on and timers are running */
uint32_t tmp = imx_epit_update_count(s);
uint64_t next;
if (tmp > s->cmp) {
/* reinit the cmp timer if required */
ptimer_set_count(s->timer_cmp, tmp - s->cmp);
if ((s->cr & CR_EN)) {
/* Restart the cmp timer if required */
ptimer_run(s->timer_cmp, 0);
}
/* It'll fire in this round of the timer */
next = tmp - s->cmp;
} else { /* catch it next time around */
next = tmp - s->cmp + ((s->cr & CR_RLD) ? TIMER_MAX : s->lr);
}
ptimer_set_count(s->timer_cmp, next);
}
}
@ -237,11 +237,14 @@ static void imx_epit_write(void *opaque, hwaddr offset, uint64_t value,
{
IMXEPITState *s = IMX_EPIT(opaque);
uint32_t reg = offset >> 2;
uint64_t oldcr;
DPRINTF("(%s, value = 0x%08x)\n", imx_epit_reg_name(reg), (uint32_t)value);
switch (reg) {
case 0: /* CR */
oldcr = s->cr;
s->cr = value & 0x03ffffff;
if (s->cr & CR_SWR) {
/* handle the reset */
@ -250,22 +253,35 @@ static void imx_epit_write(void *opaque, hwaddr offset, uint64_t value,
imx_epit_set_freq(s);
}
if (s->freq && (s->cr & CR_EN)) {
if (s->freq && (s->cr & CR_EN) && !(oldcr & CR_EN)) {
if (s->cr & CR_ENMOD) {
if (s->cr & CR_RLD) {
ptimer_set_limit(s->timer_reload, s->lr, 1);
ptimer_set_limit(s->timer_cmp, s->lr, 1);
} else {
ptimer_set_limit(s->timer_reload, TIMER_MAX, 1);
ptimer_set_limit(s->timer_cmp, TIMER_MAX, 1);
}
}
imx_epit_reload_compare_timer(s);
ptimer_run(s->timer_reload, 1);
} else {
ptimer_run(s->timer_reload, 0);
if (s->cr & CR_OCIEN) {
ptimer_run(s->timer_cmp, 0);
} else {
ptimer_stop(s->timer_cmp);
}
} else if (!(s->cr & CR_EN)) {
/* stop both timers */
ptimer_stop(s->timer_reload);
ptimer_stop(s->timer_cmp);
} else if (s->cr & CR_OCIEN) {
if (!(oldcr & CR_OCIEN)) {
imx_epit_reload_compare_timer(s);
ptimer_run(s->timer_cmp, 0);
}
} else {
ptimer_stop(s->timer_cmp);
}
break;
@ -284,13 +300,13 @@ static void imx_epit_write(void *opaque, hwaddr offset, uint64_t value,
/* Also set the limit if the LRD bit is set */
/* If IOVW bit is set then set the timer value */
ptimer_set_limit(s->timer_reload, s->lr, s->cr & CR_IOVW);
ptimer_set_limit(s->timer_cmp, s->lr, 0);
} else if (s->cr & CR_IOVW) {
/* If IOVW bit is set then set the timer value */
ptimer_set_count(s->timer_reload, s->lr);
}
imx_epit_reload_compare_timer(s);
break;
case 3: /* CMP */
@ -306,51 +322,14 @@ static void imx_epit_write(void *opaque, hwaddr offset, uint64_t value,
break;
}
}
static void imx_epit_timeout(void *opaque)
{
IMXEPITState *s = IMX_EPIT(opaque);
DPRINTF("\n");
if (!(s->cr & CR_EN)) {
return;
}
if (s->cr & CR_RLD) {
ptimer_set_limit(s->timer_reload, s->lr, 1);
} else {
ptimer_set_limit(s->timer_reload, TIMER_MAX, 1);
}
if (s->cr & CR_OCIEN) {
/* if compare register is 0 then we handle the interrupt here */
if (s->cmp == 0) {
s->sr = 1;
imx_epit_update_int(s);
} else if (s->cmp <= s->lr) {
/* We should launch the compare register */
ptimer_set_count(s->timer_cmp, s->lr - s->cmp);
ptimer_run(s->timer_cmp, 0);
} else {
IPRINTF("s->lr < s->cmp\n");
}
}
}
static void imx_epit_cmp(void *opaque)
{
IMXEPITState *s = IMX_EPIT(opaque);
DPRINTF("\n");
DPRINTF("sr was %d\n", s->sr);
ptimer_stop(s->timer_cmp);
/* compare register is not 0 */
if (s->cmp) {
s->sr = 1;
imx_epit_update_int(s);
}
s->sr = 1;
imx_epit_update_int(s);
}
void imx_timerp_create(const hwaddr addr, qemu_irq irq, DeviceState *ccm)
@ -400,8 +379,7 @@ static void imx_epit_realize(DeviceState *dev, Error **errp)
0x00001000);
sysbus_init_mmio(sbd, &s->iomem);
bh = qemu_bh_new(imx_epit_timeout, s);
s->timer_reload = ptimer_init(bh);
s->timer_reload = ptimer_init(NULL);
bh = qemu_bh_new(imx_epit_cmp, s);
s->timer_cmp = ptimer_init(bh);