aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
Diffstat (limited to 'hw')
-rw-r--r--hw/arm/virt.c2
-rw-r--r--hw/display/pl110.c30
-rw-r--r--hw/intc/arm_gic.c25
-rw-r--r--hw/net/imx_fec.c8
-rw-r--r--hw/sd/sdhci.c1
-rw-r--r--hw/ssi/xilinx_spips.c18
6 files changed, 71 insertions, 13 deletions
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index a4537af400..b334c82eda 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -1404,7 +1404,7 @@ static void machvirt_init(MachineState *machine)
"secure-memory", &error_abort);
}
- object_property_set_bool(cpuobj, true, "realized", NULL);
+ object_property_set_bool(cpuobj, true, "realized", &error_fatal);
object_unref(cpuobj);
}
fdt_add_timer_nodes(vms);
diff --git a/hw/display/pl110.c b/hw/display/pl110.c
index 8c7dcc6f0a..cf68457fd1 100644
--- a/hw/display/pl110.c
+++ b/hw/display/pl110.c
@@ -12,6 +12,7 @@
#include "ui/console.h"
#include "framebuffer.h"
#include "ui/pixel_ops.h"
+#include "qemu/timer.h"
#include "qemu/log.h"
#define PL110_CR_EN 0x001
@@ -19,6 +20,8 @@
#define PL110_CR_BEBO 0x200
#define PL110_CR_BEPO 0x400
#define PL110_CR_PWR 0x800
+#define PL110_IE_NB 0x004
+#define PL110_IE_VC 0x008
enum pl110_bppmode
{
@@ -50,6 +53,7 @@ typedef struct PL110State {
MemoryRegion iomem;
MemoryRegionSection fbsection;
QemuConsole *con;
+ QEMUTimer *vblank_timer;
int version;
uint32_t timing[4];
@@ -320,7 +324,24 @@ static void pl110_resize(PL110State *s, int width, int height)
/* Update interrupts. */
static void pl110_update(PL110State *s)
{
- /* TODO: Implement interrupts. */
+ /* Raise IRQ if enabled and any status bit is 1 */
+ if (s->int_status & s->int_mask) {
+ qemu_irq_raise(s->irq);
+ } else {
+ qemu_irq_lower(s->irq);
+ }
+}
+
+static void pl110_vblank_interrupt(void *opaque)
+{
+ PL110State *s = opaque;
+
+ /* Fire the vertical compare and next base IRQs and re-arm */
+ s->int_status |= (PL110_IE_NB | PL110_IE_VC);
+ timer_mod(s->vblank_timer,
+ qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
+ NANOSECONDS_PER_SECOND / 60);
+ pl110_update(s);
}
static uint64_t pl110_read(void *opaque, hwaddr offset,
@@ -429,6 +450,11 @@ static void pl110_write(void *opaque, hwaddr offset,
s->bpp = (val >> 1) & 7;
if (pl110_enabled(s)) {
qemu_console_resize(s->con, s->cols, s->rows);
+ timer_mod(s->vblank_timer,
+ qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
+ NANOSECONDS_PER_SECOND / 60);
+ } else {
+ timer_del(s->vblank_timer);
}
break;
case 10: /* LCDICR */
@@ -474,6 +500,8 @@ static void pl110_realize(DeviceState *dev, Error **errp)
memory_region_init_io(&s->iomem, OBJECT(s), &pl110_ops, s, "pl110", 0x1000);
sysbus_init_mmio(sbd, &s->iomem);
sysbus_init_irq(sbd, &s->irq);
+ s->vblank_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
+ pl110_vblank_interrupt, s);
qdev_init_gpio_in(dev, pl110_mux_ctrl_set, 1);
s->con = graphic_console_init(dev, 0, &pl110_gfx_ops, s);
}
diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c
index d701e49ff9..724bc9fa61 100644
--- a/hw/intc/arm_gic.c
+++ b/hw/intc/arm_gic.c
@@ -93,6 +93,7 @@ void gic_update(GICState *s)
best_irq = 1023;
for (irq = 0; irq < s->num_irq; irq++) {
if (GIC_TEST_ENABLED(irq, cm) && gic_test_pending(s, irq, cm) &&
+ (!GIC_TEST_ACTIVE(irq, cm)) &&
(irq < GIC_INTERNAL || GIC_TARGET(irq) & cm)) {
if (GIC_GET_PRIORITY(irq, cpu) < best_prio) {
best_prio = GIC_GET_PRIORITY(irq, cpu);
@@ -255,7 +256,8 @@ static int gic_get_group_priority(GICState *s, int cpu, int irq)
if (gic_has_groups(s) &&
!(s->cpu_ctlr[cpu] & GICC_CTLR_CBPR) &&
GIC_TEST_GROUP(irq, (1 << cpu))) {
- bpr = s->abpr[cpu];
+ bpr = s->abpr[cpu] - 1;
+ assert(bpr >= 0);
} else {
bpr = s->bpr[cpu];
}
@@ -503,6 +505,11 @@ static void gic_set_cpu_control(GICState *s, int cpu, uint32_t value,
static uint8_t gic_get_running_priority(GICState *s, int cpu, MemTxAttrs attrs)
{
+ if ((s->revision != REV_11MPCORE) && (s->running_priority[cpu] > 0xff)) {
+ /* Idle priority */
+ return 0xff;
+ }
+
if (s->security_extn && !attrs.secure) {
if (s->running_priority[cpu] & 0x80) {
/* Running priority in upper half of range: return the Non-secure
@@ -1205,8 +1212,13 @@ static MemTxResult gic_cpu_read(GICState *s, int cpu, int offset,
break;
case 0x08: /* Binary Point */
if (s->security_extn && !attrs.secure) {
- /* BPR is banked. Non-secure copy stored in ABPR. */
- *data = s->abpr[cpu];
+ if (s->cpu_ctlr[cpu] & GICC_CTLR_CBPR) {
+ /* NS view of BPR when CBPR is 1 */
+ *data = MIN(s->bpr[cpu] + 1, 7);
+ } else {
+ /* BPR is banked. Non-secure copy stored in ABPR. */
+ *data = s->abpr[cpu];
+ }
} else {
*data = s->bpr[cpu];
}
@@ -1279,7 +1291,12 @@ static MemTxResult gic_cpu_write(GICState *s, int cpu, int offset,
break;
case 0x08: /* Binary Point */
if (s->security_extn && !attrs.secure) {
- s->abpr[cpu] = MAX(value & 0x7, GIC_MIN_ABPR);
+ if (s->cpu_ctlr[cpu] & GICC_CTLR_CBPR) {
+ /* WI when CBPR is 1 */
+ return MEMTX_OK;
+ } else {
+ s->abpr[cpu] = MAX(value & 0x7, GIC_MIN_ABPR);
+ }
} else {
s->bpr[cpu] = MAX(value & 0x7, GIC_MIN_BPR);
}
diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c
index 4fb48f62ba..9506f9b69f 100644
--- a/hw/net/imx_fec.c
+++ b/hw/net/imx_fec.c
@@ -595,19 +595,16 @@ static void imx_eth_do_tx(IMXFECState *s, uint32_t index)
static void imx_eth_enable_rx(IMXFECState *s, bool flush)
{
IMXFECBufDesc bd;
- bool rx_ring_full;
imx_fec_read_bd(&bd, s->rx_descriptor);
- rx_ring_full = !(bd.flags & ENET_BD_E);
+ s->regs[ENET_RDAR] = (bd.flags & ENET_BD_E) ? ENET_RDAR_RDAR : 0;
- if (rx_ring_full) {
+ if (!s->regs[ENET_RDAR]) {
FEC_PRINTF("RX buffer full\n");
} else if (flush) {
qemu_flush_queued_packets(qemu_get_queue(s->nic));
}
-
- s->regs[ENET_RDAR] = rx_ring_full ? 0 : ENET_RDAR_RDAR;
}
static void imx_eth_reset(DeviceState *d)
@@ -866,7 +863,6 @@ static void imx_eth_write(void *opaque, hwaddr offset, uint64_t value,
case ENET_RDAR:
if (s->regs[ENET_ECR] & ENET_ECR_ETHEREN) {
if (!s->regs[index]) {
- s->regs[index] = ENET_RDAR_RDAR;
imx_eth_enable_rx(s, true);
}
} else {
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
index f9264d3be5..fac7fa5c72 100644
--- a/hw/sd/sdhci.c
+++ b/hw/sd/sdhci.c
@@ -1388,6 +1388,7 @@ static void sdhci_sysbus_realize(DeviceState *dev, Error ** errp)
}
if (s->dma_mr) {
+ s->dma_as = &s->sysbus_dma_as;
address_space_init(s->dma_as, s->dma_mr, "sdhci-dma");
} else {
/* use system_memory() if property "dma" not set */
diff --git a/hw/ssi/xilinx_spips.c b/hw/ssi/xilinx_spips.c
index 85c5d0cb92..8af36ca3d4 100644
--- a/hw/ssi/xilinx_spips.c
+++ b/hw/ssi/xilinx_spips.c
@@ -210,6 +210,9 @@
#define SNOOP_NONE 0xEE
#define SNOOP_STRIPING 0
+#define MIN_NUM_BUSSES 1
+#define MAX_NUM_BUSSES 2
+
static inline int num_effective_busses(XilinxSPIPS *s)
{
return (s->regs[R_LQSPI_CFG] & LQSPI_CFG_SEP_BUS &&
@@ -573,7 +576,7 @@ static void xilinx_spips_flush_txfifo(XilinxSPIPS *s)
for (;;) {
int i;
uint8_t tx = 0;
- uint8_t tx_rx[num_effective_busses(s)];
+ uint8_t tx_rx[MAX_NUM_BUSSES] = { 0 };
uint8_t dummy_cycles = 0;
uint8_t addr_length;
@@ -1221,6 +1224,19 @@ static void xilinx_spips_realize(DeviceState *dev, Error **errp)
DB_PRINT_L(0, "realized spips\n");
+ if (s->num_busses > MAX_NUM_BUSSES) {
+ error_setg(errp,
+ "requested number of SPI busses %u exceeds maximum %d",
+ s->num_busses, MAX_NUM_BUSSES);
+ return;
+ }
+ if (s->num_busses < MIN_NUM_BUSSES) {
+ error_setg(errp,
+ "requested number of SPI busses %u is below minimum %d",
+ s->num_busses, MIN_NUM_BUSSES);
+ return;
+ }
+
s->spi = g_new(SSIBus *, s->num_busses);
for (i = 0; i < s->num_busses; ++i) {
char bus_name[16];