diff options
author | Stefan Hajnoczi <stefanha@redhat.com> | 2016-11-07 14:02:15 +0000 |
---|---|---|
committer | Stefan Hajnoczi <stefanha@redhat.com> | 2016-11-07 14:02:15 +0000 |
commit | 207faf24c58859f5240f66bf6decc33b87a1776e (patch) | |
tree | 077b7005139b02e99476986b1af66242b12a5b7d | |
parent | 0ea3eb65e84c5d4665dbeee3e3e5ed56b43f7648 (diff) | |
parent | 9706e0162d2405218fd7376ffdf13baed8569a4b (diff) |
Merge remote-tracking branch 'pm215/tags/pull-target-arm-20161107' into staging
target-arm queue:
* bitbang_i2c: Handle NACKs from devices
* Fix corruption of CPSR when SCTLR.EE is set
* nvic: set pending status for not active interrupts
* char: cadence: check baud rate generator and divider values
# gpg: Signature made Mon 07 Nov 2016 10:43:07 AM GMT
# gpg: using RSA key 0x3C2525ED14360CDE
# gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>"
# gpg: aka "Peter Maydell <pmaydell@gmail.com>"
# gpg: aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>"
# Primary key fingerprint: E1A5 C593 CD41 9DE2 8E83 15CF 3C25 25ED 1436 0CDE
* pm215/tags/pull-target-arm-20161107:
hw/i2c/bitbang_i2c: Handle NACKs from devices
Fix corruption of CPSR when SCTLR.EE is set
nvic: set pending status for not active interrupts
char: cadence: check baud rate generator and divider values
Message-id: 1478515653-6361-1-git-send-email-peter.maydell@linaro.org
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
-rw-r--r-- | hw/char/cadence_uart.c | 15 | ||||
-rw-r--r-- | hw/i2c/bitbang_i2c.c | 19 | ||||
-rw-r--r-- | hw/intc/arm_gic.c | 22 | ||||
-rw-r--r-- | target-arm/helper.c | 2 |
4 files changed, 51 insertions, 7 deletions
diff --git a/hw/char/cadence_uart.c b/hw/char/cadence_uart.c index def34cd0d2..0215d6518d 100644 --- a/hw/char/cadence_uart.c +++ b/hw/char/cadence_uart.c @@ -1,6 +1,11 @@ /* * Device model for Cadence UART * + * Reference: Xilinx Zynq 7000 reference manual + * - http://www.xilinx.com/support/documentation/user_guides/ug585-Zynq-7000-TRM.pdf + * - Chapter 19 UART Controller + * - Appendix B for Register details + * * Copyright (c) 2010 Xilinx Inc. * Copyright (c) 2012 Peter A.G. Crosthwaite (peter.crosthwaite@petalogix.com) * Copyright (c) 2012 PetaLogix Pty Ltd. @@ -402,6 +407,16 @@ static void uart_write(void *opaque, hwaddr offset, break; } break; + case R_BRGR: /* Baud rate generator */ + if (value >= 0x01) { + s->r[offset] = value & 0xFFFF; + } + break; + case R_BDIV: /* Baud rate divider */ + if (value >= 0x04) { + s->r[offset] = value & 0xFF; + } + break; default: s->r[offset] = value; } diff --git a/hw/i2c/bitbang_i2c.c b/hw/i2c/bitbang_i2c.c index d3a29891f8..8be88ee265 100644 --- a/hw/i2c/bitbang_i2c.c +++ b/hw/i2c/bitbang_i2c.c @@ -130,14 +130,25 @@ int bitbang_i2c_set(bitbang_i2c_interface *i2c, int line, int level) return bitbang_i2c_ret(i2c, 1); case WAITING_FOR_ACK: + { + int ret; + if (i2c->current_addr < 0) { i2c->current_addr = i2c->buffer; DPRINTF("Address 0x%02x\n", i2c->current_addr); - i2c_start_transfer(i2c->bus, i2c->current_addr >> 1, - i2c->current_addr & 1); + ret = i2c_start_transfer(i2c->bus, i2c->current_addr >> 1, + i2c->current_addr & 1); } else { DPRINTF("Sent 0x%02x\n", i2c->buffer); - i2c_send(i2c->bus, i2c->buffer); + ret = i2c_send(i2c->bus, i2c->buffer); + } + if (ret) { + /* NACK (either addressing a nonexistent device, or the + * device we were sending to decided to NACK us). + */ + DPRINTF("Got NACK\n"); + bitbang_i2c_enter_stop(i2c); + return bitbang_i2c_ret(i2c, 1); } if (i2c->current_addr & 1) { i2c->state = RECEIVING_BIT7; @@ -145,7 +156,7 @@ int bitbang_i2c_set(bitbang_i2c_interface *i2c, int line, int level) i2c->state = SENDING_BIT7; } return bitbang_i2c_ret(i2c, 0); - + } case RECEIVING_BIT7: i2c->buffer = i2c_recv(i2c->bus); DPRINTF("RX byte 0x%02x\n", i2c->buffer); diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c index b30cc91745..521aac3cc6 100644 --- a/hw/intc/arm_gic.c +++ b/hw/intc/arm_gic.c @@ -156,6 +156,17 @@ static void gic_set_irq_11mpcore(GICState *s, int irq, int level, } } +static void gic_set_irq_nvic(GICState *s, int irq, int level, + int cm, int target) +{ + if (level) { + GIC_SET_LEVEL(irq, cm); + GIC_SET_PENDING(irq, target); + } else { + GIC_CLEAR_LEVEL(irq, cm); + } +} + static void gic_set_irq_generic(GICState *s, int irq, int level, int cm, int target) { @@ -201,8 +212,10 @@ static void gic_set_irq(void *opaque, int irq, int level) return; } - if (s->revision == REV_11MPCORE || s->revision == REV_NVIC) { + if (s->revision == REV_11MPCORE) { gic_set_irq_11mpcore(s, irq, level, cm, target); + } else if (s->revision == REV_NVIC) { + gic_set_irq_nvic(s, irq, level, cm, target); } else { gic_set_irq_generic(s, irq, level, cm, target); } @@ -568,7 +581,7 @@ void gic_complete_irq(GICState *s, int cpu, int irq, MemTxAttrs attrs) return; /* No active IRQ. */ } - if (s->revision == REV_11MPCORE || s->revision == REV_NVIC) { + if (s->revision == REV_11MPCORE) { /* Mark level triggered interrupts as pending if they are still raised. */ if (!GIC_TEST_EDGE_TRIGGER(irq) && GIC_TEST_ENABLED(irq, cm) @@ -576,6 +589,11 @@ void gic_complete_irq(GICState *s, int cpu, int irq, MemTxAttrs attrs) DPRINTF("Set %d pending mask %x\n", irq, cm); GIC_SET_PENDING(irq, cm); } + } else if (s->revision == REV_NVIC) { + if (GIC_TEST_LEVEL(irq, cm)) { + DPRINTF("Set nvic %d pending mask %x\n", irq, cm); + GIC_SET_PENDING(irq, cm); + } } group = gic_has_groups(s) && GIC_TEST_GROUP(irq, cm); diff --git a/target-arm/helper.c b/target-arm/helper.c index 25b15dc100..b5b65caadf 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -6438,7 +6438,7 @@ static void arm_cpu_do_interrupt_aarch32(CPUState *cs) /* Set new mode endianness */ env->uncached_cpsr &= ~CPSR_E; if (env->cp15.sctlr_el[arm_current_el(env)] & SCTLR_EE) { - env->uncached_cpsr |= ~CPSR_E; + env->uncached_cpsr |= CPSR_E; } env->daif |= mask; /* this is a lie, as the was no c1_sys on V4T/V5, but who cares |