aboutsummaryrefslogtreecommitdiff
path: root/hw/char/pl011.c
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2019-02-21 18:58:35 +0000
committerPeter Maydell <peter.maydell@linaro.org>2019-02-21 18:58:35 +0000
commitfaf840a359edb53485bc710fbb3adca9498655dd (patch)
tree42c2e7141ebdefd2ae8e3c2c60b27d49265181b7 /hw/char/pl011.c
parentfc3dbb90f2eb069801bfb4cfe9cbc83cf9c5f4a9 (diff)
parent3733f80308d2a7f23f5e39b039e0547aba6c07f1 (diff)
Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20190221' into staging
target-arm queue: * Model the Arm "Musca" development boards: "musca-a" and "musca-b1" * Implement the ARMv8.3-JSConv extension * v8M MPU should use background region as default, not always * Stop unintentional sign extension in pmu_init # gpg: Signature made Thu 21 Feb 2019 18:56:32 GMT # gpg: using RSA key E1A5C593CD419DE28E8315CF3C2525ED14360CDE # gpg: issuer "peter.maydell@linaro.org" # gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" [ultimate] # gpg: aka "Peter Maydell <pmaydell@gmail.com>" [ultimate] # gpg: aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>" [ultimate] # Primary key fingerprint: E1A5 C593 CD41 9DE2 8E83 15CF 3C25 25ED 1436 0CDE * remotes/pmaydell/tags/pull-target-arm-20190221: (21 commits) hw/arm/armsse: Make 0x5... alias region work for per-CPU devices hw/arm/musca: Wire up PL011 UARTs hw/arm/musca: Wire up PL031 RTC hw/arm/musca: Add MPCs hw/arm/musca: Add PPCs hw/arm/musca.c: Implement models of the Musca-A and -B1 boards hw/arm/armsse: Allow boards to specify init-svtor hw/arm/armsse: Document SRAM_ADDR_WIDTH property in header comment hw/char/pl011: Use '0x' prefix when logging hex numbers hw/char/pl011: Support all interrupt lines hw/char/pl011: Allow use as an embedded-struct device hw/timer/pl031: Convert to using trace events hw/timer/pl031: Allow use as an embedded-struct device hw/misc/tz-ppc: Support having unused ports in the middle of the range target/arm: Implement ARMv8.3-JSConv target/arm: Rearrange Floating-point data-processing (2 regs) target/arm: Split out vfp_helper.c target/arm: Restructure disas_fp_int_conv target/arm: Stop unintentional sign extension in pmu_init target/arm: v8M MPU should use background region as default, not always ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw/char/pl011.c')
-rw-r--r--hw/char/pl011.c81
1 files changed, 48 insertions, 33 deletions
diff --git a/hw/char/pl011.c b/hw/char/pl011.c
index 2aa277fc4f..e5dd448f85 100644
--- a/hw/char/pl011.c
+++ b/hw/char/pl011.c
@@ -7,40 +7,24 @@
* This code is licensed under the GPL.
*/
+/*
+ * QEMU interface:
+ * + sysbus MMIO region 0: device registers
+ * + sysbus IRQ 0: UARTINTR (combined interrupt line)
+ * + sysbus IRQ 1: UARTRXINTR (receive FIFO interrupt line)
+ * + sysbus IRQ 2: UARTTXINTR (transmit FIFO interrupt line)
+ * + sysbus IRQ 3: UARTRTINTR (receive timeout interrupt line)
+ * + sysbus IRQ 4: UARTMSINTR (momem status interrupt line)
+ * + sysbus IRQ 5: UARTEINTR (error interrupt line)
+ */
+
#include "qemu/osdep.h"
+#include "hw/char/pl011.h"
#include "hw/sysbus.h"
#include "chardev/char-fe.h"
#include "qemu/log.h"
#include "trace.h"
-#define TYPE_PL011 "pl011"
-#define PL011(obj) OBJECT_CHECK(PL011State, (obj), TYPE_PL011)
-
-typedef struct PL011State {
- SysBusDevice parent_obj;
-
- MemoryRegion iomem;
- uint32_t readbuff;
- uint32_t flags;
- uint32_t lcr;
- uint32_t rsr;
- uint32_t cr;
- uint32_t dmacr;
- uint32_t int_enabled;
- uint32_t int_level;
- uint32_t read_fifo[16];
- uint32_t ilpr;
- uint32_t ibrd;
- uint32_t fbrd;
- uint32_t ifl;
- int read_pos;
- int read_count;
- int read_trigger;
- CharBackend chr;
- qemu_irq irq;
- const unsigned char *id;
-} PL011State;
-
#define PL011_INT_TX 0x20
#define PL011_INT_RX 0x10
@@ -49,18 +33,46 @@ typedef struct PL011State {
#define PL011_FLAG_TXFF 0x20
#define PL011_FLAG_RXFE 0x10
+/* Interrupt status bits in UARTRIS, UARTMIS, UARTIMSC */
+#define INT_OE (1 << 10)
+#define INT_BE (1 << 9)
+#define INT_PE (1 << 8)
+#define INT_FE (1 << 7)
+#define INT_RT (1 << 6)
+#define INT_TX (1 << 5)
+#define INT_RX (1 << 4)
+#define INT_DSR (1 << 3)
+#define INT_DCD (1 << 2)
+#define INT_CTS (1 << 1)
+#define INT_RI (1 << 0)
+#define INT_E (INT_OE | INT_BE | INT_PE | INT_FE)
+#define INT_MS (INT_RI | INT_DSR | INT_DCD | INT_CTS)
+
static const unsigned char pl011_id_arm[8] =
{ 0x11, 0x10, 0x14, 0x00, 0x0d, 0xf0, 0x05, 0xb1 };
static const unsigned char pl011_id_luminary[8] =
{ 0x11, 0x00, 0x18, 0x01, 0x0d, 0xf0, 0x05, 0xb1 };
+/* Which bits in the interrupt status matter for each outbound IRQ line ? */
+static const uint32_t irqmask[] = {
+ INT_E | INT_MS | INT_RT | INT_TX | INT_RX, /* combined IRQ */
+ INT_RX,
+ INT_TX,
+ INT_RT,
+ INT_MS,
+ INT_E,
+};
+
static void pl011_update(PL011State *s)
{
uint32_t flags;
+ int i;
flags = s->int_level & s->int_enabled;
trace_pl011_irq_state(flags != 0);
- qemu_set_irq(s->irq, flags != 0);
+ for (i = 0; i < ARRAY_SIZE(s->irq); i++) {
+ qemu_set_irq(s->irq[i], (flags & irqmask[i]) != 0);
+ }
}
static uint64_t pl011_read(void *opaque, hwaddr offset,
@@ -131,7 +143,7 @@ static uint64_t pl011_read(void *opaque, hwaddr offset,
break;
default:
qemu_log_mask(LOG_GUEST_ERROR,
- "pl011_read: Bad offset %x\n", (int)offset);
+ "pl011_read: Bad offset 0x%x\n", (int)offset);
r = 0;
break;
}
@@ -220,7 +232,7 @@ static void pl011_write(void *opaque, hwaddr offset,
break;
default:
qemu_log_mask(LOG_GUEST_ERROR,
- "pl011_write: Bad offset %x\n", (int)offset);
+ "pl011_write: Bad offset 0x%x\n", (int)offset);
}
}
@@ -311,10 +323,13 @@ static void pl011_init(Object *obj)
{
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
PL011State *s = PL011(obj);
+ int i;
memory_region_init_io(&s->iomem, OBJECT(s), &pl011_ops, s, "pl011", 0x1000);
sysbus_init_mmio(sbd, &s->iomem);
- sysbus_init_irq(sbd, &s->irq);
+ for (i = 0; i < ARRAY_SIZE(s->irq); i++) {
+ sysbus_init_irq(sbd, &s->irq[i]);
+ }
s->read_trigger = 1;
s->ifl = 0x12;
@@ -357,7 +372,7 @@ static void pl011_luminary_init(Object *obj)
}
static const TypeInfo pl011_luminary_info = {
- .name = "pl011_luminary",
+ .name = TYPE_PL011_LUMINARY,
.parent = TYPE_PL011,
.instance_init = pl011_luminary_init,
};