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>
diff --git a/hw/char/cadence_uart.c b/hw/char/cadence_uart.c
index def34cd..0215d65 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 @@
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 d3a2989..8be88ee 100644
--- a/hw/i2c/bitbang_i2c.c
+++ b/hw/i2c/bitbang_i2c.c
@@ -130,14 +130,25 @@
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 @@
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 b30cc91..521aac3 100644
--- a/hw/intc/arm_gic.c
+++ b/hw/intc/arm_gic.c
@@ -156,6 +156,17 @@
}
}
+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 @@
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 @@
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 @@
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 25b15dc..b5b65ca 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -6438,7 +6438,7 @@
/* 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