summaryrefslogtreecommitdiffstats
path: root/hw/gpio
diff options
context:
space:
mode:
authorPeter Maydell2014-09-12 16:12:26 +0200
committerPeter Maydell2014-09-12 16:12:26 +0200
commit4c24f4004089a308c5de8ed720cf6bd1746aedd8 (patch)
treed83f318edd5b987a94d0a16ed8a25a215c645fca /hw/gpio
parentlibqos virtio: Increase ISR timeout (diff)
parenthw/arm/boot: enable DTB support when booting ELF images (diff)
downloadqemu-4c24f4004089a308c5de8ed720cf6bd1746aedd8.tar.gz
qemu-4c24f4004089a308c5de8ed720cf6bd1746aedd8.tar.xz
qemu-4c24f4004089a308c5de8ed720cf6bd1746aedd8.zip
Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20140912' into staging
target-arm: * add "linux,stdout-path" to the virt DTB * fix a long standing bug with IRQ disabling on Cortex-M CPUs * implement input interrupt logic in the PL061 * fix failure to load correct SP/PC on reset of Cortex-M CPUs if the vector table is not in a ROM-blob-in-RAM * provide flash devices for boot ROMs in the virt board * implement architectural watchpoints * fix misimplementation of Inner Shareable TLB operations that caused instability of guests in TCG SMP configurations * configure PL011 and PL031 in the virt board correctly with level-triggered interrupts rather than edge-triggered * support providing a device tree blob to ROM (firmware) images as well as to kernels # gpg: Signature made Fri 12 Sep 2014 14:19:08 BST using RSA key ID 14360CDE # gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" * remotes/pmaydell/tags/pull-target-arm-20140912: (23 commits) hw/arm/boot: enable DTB support when booting ELF images hw/arm/boot: load device tree to base of DRAM if no -kernel option was passed hw/arm/boot: pass an address limit to and return size from load_dtb() hw/arm/boot: load DTB as a ROM image hw/arm/virt: fix pl011 and pl031 irq flags target-arm: Make *IS TLB maintenance ops affect all CPUs target-arm: Push legacy wildcard TLB ops back into v6 target-arm: Implement minimal DBGVCR, OSDLR_EL1, MDCCSR_EL0 target-arm: Remove comment about MDSCR_EL1 being dummy implementation target-arm: Set DBGDSCR.MOE for debug exceptions taken to AArch32 target-arm: Implement handling of fired watchpoints target-arm: Move extended_addresses_enabled() to internals.h target-arm: Implement setting of watchpoints cpu-exec: Make debug_excp_handler a QOM CPU method exec.c: Record watchpoint fault address and direction exec.c: Provide full set of dummy wp remove functions in user-mode exec.c: Relax restrictions on watchpoint length and alignment hw/arm/virt: Provide flash devices for boot ROMs target-arm: Fix broken indentation in arm_cpu_reest() target-arm: Fix resetting issues on ARMv7-M CPUs ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw/gpio')
-rw-r--r--hw/gpio/pl061.c59
1 files changed, 45 insertions, 14 deletions
diff --git a/hw/gpio/pl061.c b/hw/gpio/pl061.c
index dd4ea293e2..bd03e99975 100644
--- a/hw/gpio/pl061.c
+++ b/hw/gpio/pl061.c
@@ -37,7 +37,8 @@ typedef struct PL061State {
MemoryRegion iomem;
uint32_t locked;
uint32_t data;
- uint32_t old_data;
+ uint32_t old_out_data;
+ uint32_t old_in_data;
uint32_t dir;
uint32_t isense;
uint32_t ibe;
@@ -63,12 +64,13 @@ typedef struct PL061State {
static const VMStateDescription vmstate_pl061 = {
.name = "pl061",
- .version_id = 2,
- .minimum_version_id = 1,
+ .version_id = 3,
+ .minimum_version_id = 3,
.fields = (VMStateField[]) {
VMSTATE_UINT32(locked, PL061State),
VMSTATE_UINT32(data, PL061State),
- VMSTATE_UINT32(old_data, PL061State),
+ VMSTATE_UINT32(old_out_data, PL061State),
+ VMSTATE_UINT32(old_in_data, PL061State),
VMSTATE_UINT32(dir, PL061State),
VMSTATE_UINT32(isense, PL061State),
VMSTATE_UINT32(ibe, PL061State),
@@ -98,23 +100,52 @@ static void pl061_update(PL061State *s)
uint8_t out;
int i;
+ DPRINTF("dir = %d, data = %d\n", s->dir, s->data);
+
/* Outputs float high. */
/* FIXME: This is board dependent. */
out = (s->data & s->dir) | ~s->dir;
- changed = s->old_data ^ out;
- if (!changed)
- return;
+ changed = s->old_out_data ^ out;
+ if (changed) {
+ s->old_out_data = out;
+ for (i = 0; i < 8; i++) {
+ mask = 1 << i;
+ if (changed & mask) {
+ DPRINTF("Set output %d = %d\n", i, (out & mask) != 0);
+ qemu_set_irq(s->out[i], (out & mask) != 0);
+ }
+ }
+ }
- s->old_data = out;
- for (i = 0; i < 8; i++) {
- mask = 1 << i;
- if (changed & mask) {
- DPRINTF("Set output %d = %d\n", i, (out & mask) != 0);
- qemu_set_irq(s->out[i], (out & mask) != 0);
+ /* Inputs */
+ changed = (s->old_in_data ^ s->data) & ~s->dir;
+ if (changed) {
+ s->old_in_data = s->data;
+ for (i = 0; i < 8; i++) {
+ mask = 1 << i;
+ if (changed & mask) {
+ DPRINTF("Changed input %d = %d\n", i, (s->data & mask) != 0);
+
+ if (!(s->isense & mask)) {
+ /* Edge interrupt */
+ if (s->ibe & mask) {
+ /* Any edge triggers the interrupt */
+ s->istate |= mask;
+ } else {
+ /* Edge is selected by IEV */
+ s->istate |= ~(s->data ^ s->iev) & mask;
+ }
+ }
+ }
}
}
- /* FIXME: Implement input interrupts. */
+ /* Level interrupt */
+ s->istate |= ~(s->data ^ s->iev) & s->isense;
+
+ DPRINTF("istate = %02X\n", s->istate);
+
+ qemu_set_irq(s->irq, (s->istate & s->im) != 0);
}
static uint64_t pl061_read(void *opaque, hwaddr offset,