* [Qemu-devel] [PATCH v3 1/5] bcm2835_peripherals: enable sdhci pending-insert quirk for raspberry pi
2016-03-08 20:05 [Qemu-devel] [PATCH v3 0/5] Raspberry Pi framebuffer, DMA and Windows support Andrew Baumann
@ 2016-03-08 20:05 ` Andrew Baumann
2016-03-08 20:05 ` [Qemu-devel] [PATCH v3 2/5] bcm2835_aux: add emulation of BCM2835 AUX (aka UART1) block Andrew Baumann
` (5 subsequent siblings)
6 siblings, 0 replies; 11+ messages in thread
From: Andrew Baumann @ 2016-03-08 20:05 UTC (permalink / raw)
To: qemu-devel
Cc: Peter Maydell, Grégory ESTRADE, Stefan Weil,
Peter Crosthwaite, Andrew Baumann, qemu-arm, Paolo Bonzini
Signed-off-by: Andrew Baumann <Andrew.Baumann@microsoft.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
---
hw/arm/bcm2835_peripherals.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/hw/arm/bcm2835_peripherals.c b/hw/arm/bcm2835_peripherals.c
index 6d66fa0..6ce9cd1 100644
--- a/hw/arm/bcm2835_peripherals.c
+++ b/hw/arm/bcm2835_peripherals.c
@@ -171,6 +171,13 @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
return;
}
+ object_property_set_bool(OBJECT(&s->sdhci), true, "pending-insert-quirk",
+ &err);
+ if (err) {
+ error_propagate(errp, err);
+ return;
+ }
+
object_property_set_bool(OBJECT(&s->sdhci), true, "realized", &err);
if (err) {
error_propagate(errp, err);
--
2.7.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [Qemu-devel] [PATCH v3 2/5] bcm2835_aux: add emulation of BCM2835 AUX (aka UART1) block
2016-03-08 20:05 [Qemu-devel] [PATCH v3 0/5] Raspberry Pi framebuffer, DMA and Windows support Andrew Baumann
2016-03-08 20:05 ` [Qemu-devel] [PATCH v3 1/5] bcm2835_peripherals: enable sdhci pending-insert quirk for raspberry pi Andrew Baumann
@ 2016-03-08 20:05 ` Andrew Baumann
2016-03-08 20:05 ` [Qemu-devel] [PATCH v3 3/5] bcm2835_fb: add framebuffer device for Raspberry Pi Andrew Baumann
` (4 subsequent siblings)
6 siblings, 0 replies; 11+ messages in thread
From: Andrew Baumann @ 2016-03-08 20:05 UTC (permalink / raw)
To: qemu-devel
Cc: Peter Maydell, Grégory ESTRADE, Stefan Weil,
Peter Crosthwaite, Andrew Baumann, qemu-arm, Paolo Bonzini
At present only the core UART functions (data path for tx/rx) are
implemented, which is enough for UEFI to boot. The following
features/registers are unimplemented:
* Line/modem control
* Scratch register
* Extra control
* Baudrate
* SPI interfaces
Signed-off-by: Andrew Baumann <Andrew.Baumann@microsoft.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
---
Notes:
v3:
* use qemu_char_get_next_serial() to configure the chardev prop in
bcm2835_peripherals, rather than reaching into serial_hds[] directly
v2:
* document unimplemented features, log unimplemented register accesses
* model read path as 8-bit
* drop incorrect event (break detection) functionality
* implement AUX_IRQ register
* model interrupt enables as a uint8 rather than 2 bools
* corrected bugs in implementation of IIR bits 0-2
* use chardev prop rather than qemu_char_get_next_serial(); the
soc-level (bcm2835_peripherals) handling is still a little messy
however, because uart0 is a pl011 device which still calls
qemu_char_get_next_serial()
hw/arm/bcm2835_peripherals.c | 32 ++++
hw/char/Makefile.objs | 1 +
hw/char/bcm2835_aux.c | 316 +++++++++++++++++++++++++++++++++++
include/hw/arm/bcm2835_peripherals.h | 2 +
include/hw/char/bcm2835_aux.h | 33 ++++
5 files changed, 384 insertions(+)
create mode 100644 hw/char/bcm2835_aux.c
create mode 100644 include/hw/char/bcm2835_aux.h
diff --git a/hw/arm/bcm2835_peripherals.c b/hw/arm/bcm2835_peripherals.c
index 6ce9cd1..d6453cc 100644
--- a/hw/arm/bcm2835_peripherals.c
+++ b/hw/arm/bcm2835_peripherals.c
@@ -12,6 +12,7 @@
#include "hw/arm/bcm2835_peripherals.h"
#include "hw/misc/bcm2835_mbox_defs.h"
#include "hw/arm/raspi_platform.h"
+#include "sysemu/char.h"
/* Peripheral base address on the VC (GPU) system bus */
#define BCM2835_VC_PERI_BASE 0x7e000000
@@ -48,6 +49,11 @@ static void bcm2835_peripherals_init(Object *obj)
object_property_add_child(obj, "uart0", OBJECT(s->uart0), NULL);
qdev_set_parent_bus(DEVICE(s->uart0), sysbus_get_default());
+ /* AUX / UART1 */
+ object_initialize(&s->aux, sizeof(s->aux), TYPE_BCM2835_AUX);
+ object_property_add_child(obj, "aux", OBJECT(&s->aux), NULL);
+ qdev_set_parent_bus(DEVICE(&s->aux), sysbus_get_default());
+
/* Mailboxes */
object_initialize(&s->mboxes, sizeof(s->mboxes), TYPE_BCM2835_MBOX);
object_property_add_child(obj, "mbox", OBJECT(&s->mboxes), NULL);
@@ -79,6 +85,7 @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
MemoryRegion *ram;
Error *err = NULL;
uint32_t ram_size;
+ CharDriverState *chr;
int n;
obj = object_property_get_link(OBJECT(dev), "ram", &err);
@@ -131,6 +138,29 @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ,
INTERRUPT_UART));
+ /* AUX / UART1 */
+ /* TODO: don't call qemu_char_get_next_serial() here, instead set
+ * chardev properties for each uart at the board level, once pl011
+ * (uart0) has been updated to avoid qemu_char_get_next_serial()
+ */
+ chr = qemu_char_get_next_serial();
+ if (chr == NULL) {
+ chr = qemu_chr_new("bcm2835.uart1", "null", NULL);
+ }
+ qdev_prop_set_chr(DEVICE(&s->aux), "chardev", chr);
+
+ object_property_set_bool(OBJECT(&s->aux), true, "realized", &err);
+ if (err) {
+ error_propagate(errp, err);
+ return;
+ }
+
+ memory_region_add_subregion(&s->peri_mr, UART1_OFFSET,
+ sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->aux), 0));
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->aux), 0,
+ qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ,
+ INTERRUPT_AUX));
+
/* Mailboxes */
object_property_set_bool(OBJECT(&s->mboxes), true, "realized", &err);
if (err) {
@@ -203,6 +233,8 @@ static void bcm2835_peripherals_class_init(ObjectClass *oc, void *data)
DeviceClass *dc = DEVICE_CLASS(oc);
dc->realize = bcm2835_peripherals_realize;
+ /* Reason: realize() method uses qemu_char_get_next_serial() */
+ dc->cannot_instantiate_with_device_add_yet = true;
}
static const TypeInfo bcm2835_peripherals_type_info = {
diff --git a/hw/char/Makefile.objs b/hw/char/Makefile.objs
index 5931cc8..69a553c 100644
--- a/hw/char/Makefile.objs
+++ b/hw/char/Makefile.objs
@@ -16,6 +16,7 @@ obj-$(CONFIG_SH4) += sh_serial.o
obj-$(CONFIG_PSERIES) += spapr_vty.o
obj-$(CONFIG_DIGIC) += digic-uart.o
obj-$(CONFIG_STM32F2XX_USART) += stm32f2xx_usart.o
+obj-$(CONFIG_RASPI) += bcm2835_aux.o
common-obj-$(CONFIG_ETRAXFS) += etraxfs_ser.o
common-obj-$(CONFIG_ISA_DEBUG) += debugcon.o
diff --git a/hw/char/bcm2835_aux.c b/hw/char/bcm2835_aux.c
new file mode 100644
index 0000000..0394d11
--- /dev/null
+++ b/hw/char/bcm2835_aux.c
@@ -0,0 +1,316 @@
+/*
+ * BCM2835 (Raspberry Pi / Pi 2) Aux block (mini UART and SPI).
+ * Copyright (c) 2015, Microsoft
+ * Written by Andrew Baumann
+ * Based on pl011.c, copyright terms below:
+ *
+ * Arm PrimeCell PL011 UART
+ *
+ * Copyright (c) 2006 CodeSourcery.
+ * Written by Paul Brook
+ *
+ * This code is licensed under the GPL.
+ *
+ * At present only the core UART functions (data path for tx/rx) are
+ * implemented. The following features/registers are unimplemented:
+ * - Line/modem control
+ * - Scratch register
+ * - Extra control
+ * - Baudrate
+ * - SPI interfaces
+ */
+
+#include "qemu/osdep.h"
+#include "hw/char/bcm2835_aux.h"
+
+#define AUX_IRQ 0x0
+#define AUX_ENABLES 0x4
+#define AUX_MU_IO_REG 0x40
+#define AUX_MU_IER_REG 0x44
+#define AUX_MU_IIR_REG 0x48
+#define AUX_MU_LCR_REG 0x4c
+#define AUX_MU_MCR_REG 0x50
+#define AUX_MU_LSR_REG 0x54
+#define AUX_MU_MSR_REG 0x58
+#define AUX_MU_SCRATCH 0x5c
+#define AUX_MU_CNTL_REG 0x60
+#define AUX_MU_STAT_REG 0x64
+#define AUX_MU_BAUD_REG 0x68
+
+/* bits in IER/IIR registers */
+#define TX_INT 0x1
+#define RX_INT 0x2
+
+static void bcm2835_aux_update(BCM2835AuxState *s)
+{
+ /* signal an interrupt if either:
+ * 1. rx interrupt is enabled and we have a non-empty rx fifo, or
+ * 2. the tx interrupt is enabled (since we instantly drain the tx fifo)
+ */
+ s->iir = 0;
+ if ((s->ier & RX_INT) && s->read_count != 0) {
+ s->iir |= RX_INT;
+ }
+ if (s->ier & TX_INT) {
+ s->iir |= TX_INT;
+ }
+ qemu_set_irq(s->irq, s->iir != 0);
+}
+
+static uint64_t bcm2835_aux_read(void *opaque, hwaddr offset, unsigned size)
+{
+ BCM2835AuxState *s = opaque;
+ uint32_t c, res;
+
+ switch (offset) {
+ case AUX_IRQ:
+ return s->iir != 0;
+
+ case AUX_ENABLES:
+ return 1; /* mini UART permanently enabled */
+
+ case AUX_MU_IO_REG:
+ /* "DLAB bit set means access baudrate register" is NYI */
+ c = s->read_fifo[s->read_pos];
+ if (s->read_count > 0) {
+ s->read_count--;
+ if (++s->read_pos == BCM2835_AUX_RX_FIFO_LEN) {
+ s->read_pos = 0;
+ }
+ }
+ if (s->chr) {
+ qemu_chr_accept_input(s->chr);
+ }
+ bcm2835_aux_update(s);
+ return c;
+
+ case AUX_MU_IER_REG:
+ /* "DLAB bit set means access baudrate register" is NYI */
+ return 0xc0 | s->ier; /* FIFO enables always read 1 */
+
+ case AUX_MU_IIR_REG:
+ res = 0xc0; /* FIFO enables */
+ /* The spec is unclear on what happens when both tx and rx
+ * interrupts are active, besides that this cannot occur. At
+ * present, we choose to prioritise the rx interrupt, since
+ * the tx fifo is always empty. */
+ if (s->read_count != 0) {
+ res |= 0x4;
+ } else {
+ res |= 0x2;
+ }
+ if (s->iir == 0) {
+ res |= 0x1;
+ }
+ return res;
+
+ case AUX_MU_LCR_REG:
+ qemu_log_mask(LOG_UNIMP, "%s: AUX_MU_LCR_REG unsupported\n", __func__);
+ return 0;
+
+ case AUX_MU_MCR_REG:
+ qemu_log_mask(LOG_UNIMP, "%s: AUX_MU_MCR_REG unsupported\n", __func__);
+ return 0;
+
+ case AUX_MU_LSR_REG:
+ res = 0x60; /* tx idle, empty */
+ if (s->read_count != 0) {
+ res |= 0x1;
+ }
+ return res;
+
+ case AUX_MU_MSR_REG:
+ qemu_log_mask(LOG_UNIMP, "%s: AUX_MU_MSR_REG unsupported\n", __func__);
+ return 0;
+
+ case AUX_MU_SCRATCH:
+ qemu_log_mask(LOG_UNIMP, "%s: AUX_MU_SCRATCH unsupported\n", __func__);
+ return 0;
+
+ case AUX_MU_CNTL_REG:
+ return 0x3; /* tx, rx enabled */
+
+ case AUX_MU_STAT_REG:
+ res = 0x30e; /* space in the output buffer, empty tx fifo, idle tx/rx */
+ if (s->read_count > 0) {
+ res |= 0x1; /* data in input buffer */
+ assert(s->read_count < BCM2835_AUX_RX_FIFO_LEN);
+ res |= ((uint32_t)s->read_count) << 16; /* rx fifo fill level */
+ }
+ return res;
+
+ case AUX_MU_BAUD_REG:
+ qemu_log_mask(LOG_UNIMP, "%s: AUX_MU_BAUD_REG unsupported\n", __func__);
+ return 0;
+
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n",
+ __func__, offset);
+ return 0;
+ }
+}
+
+static void bcm2835_aux_write(void *opaque, hwaddr offset, uint64_t value,
+ unsigned size)
+{
+ BCM2835AuxState *s = opaque;
+ unsigned char ch;
+
+ switch (offset) {
+ case AUX_ENABLES:
+ if (value != 1) {
+ qemu_log_mask(LOG_UNIMP, "%s: unsupported attempt to enable SPI "
+ "or disable UART\n", __func__);
+ }
+ break;
+
+ case AUX_MU_IO_REG:
+ /* "DLAB bit set means access baudrate register" is NYI */
+ ch = value;
+ if (s->chr) {
+ qemu_chr_fe_write(s->chr, &ch, 1);
+ }
+ break;
+
+ case AUX_MU_IER_REG:
+ /* "DLAB bit set means access baudrate register" is NYI */
+ s->ier = value & (TX_INT | RX_INT);
+ bcm2835_aux_update(s);
+ break;
+
+ case AUX_MU_IIR_REG:
+ if (value & 0x2) {
+ s->read_count = 0;
+ }
+ break;
+
+ case AUX_MU_LCR_REG:
+ qemu_log_mask(LOG_UNIMP, "%s: AUX_MU_LCR_REG unsupported\n", __func__);
+ break;
+
+ case AUX_MU_MCR_REG:
+ qemu_log_mask(LOG_UNIMP, "%s: AUX_MU_MCR_REG unsupported\n", __func__);
+ break;
+
+ case AUX_MU_SCRATCH:
+ qemu_log_mask(LOG_UNIMP, "%s: AUX_MU_SCRATCH unsupported\n", __func__);
+ break;
+
+ case AUX_MU_CNTL_REG:
+ qemu_log_mask(LOG_UNIMP, "%s: AUX_MU_CNTL_REG unsupported\n", __func__);
+ break;
+
+ case AUX_MU_BAUD_REG:
+ qemu_log_mask(LOG_UNIMP, "%s: AUX_MU_BAUD_REG unsupported\n", __func__);
+ break;
+
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n",
+ __func__, offset);
+ }
+
+ bcm2835_aux_update(s);
+}
+
+static int bcm2835_aux_can_receive(void *opaque)
+{
+ BCM2835AuxState *s = opaque;
+
+ return s->read_count < BCM2835_AUX_RX_FIFO_LEN;
+}
+
+static void bcm2835_aux_put_fifo(void *opaque, uint8_t value)
+{
+ BCM2835AuxState *s = opaque;
+ int slot;
+
+ slot = s->read_pos + s->read_count;
+ if (slot >= BCM2835_AUX_RX_FIFO_LEN) {
+ slot -= BCM2835_AUX_RX_FIFO_LEN;
+ }
+ s->read_fifo[slot] = value;
+ s->read_count++;
+ if (s->read_count == BCM2835_AUX_RX_FIFO_LEN) {
+ /* buffer full */
+ }
+ bcm2835_aux_update(s);
+}
+
+static void bcm2835_aux_receive(void *opaque, const uint8_t *buf, int size)
+{
+ bcm2835_aux_put_fifo(opaque, *buf);
+}
+
+static const MemoryRegionOps bcm2835_aux_ops = {
+ .read = bcm2835_aux_read,
+ .write = bcm2835_aux_write,
+ .endianness = DEVICE_NATIVE_ENDIAN,
+ .valid.min_access_size = 4,
+ .valid.max_access_size = 4,
+};
+
+static const VMStateDescription vmstate_bcm2835_aux = {
+ .name = TYPE_BCM2835_AUX,
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT8_ARRAY(read_fifo, BCM2835AuxState,
+ BCM2835_AUX_RX_FIFO_LEN),
+ VMSTATE_UINT8(read_pos, BCM2835AuxState),
+ VMSTATE_UINT8(read_count, BCM2835AuxState),
+ VMSTATE_UINT8(ier, BCM2835AuxState),
+ VMSTATE_UINT8(iir, BCM2835AuxState),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static void bcm2835_aux_init(Object *obj)
+{
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+ BCM2835AuxState *s = BCM2835_AUX(obj);
+
+ memory_region_init_io(&s->iomem, OBJECT(s), &bcm2835_aux_ops, s,
+ TYPE_BCM2835_AUX, 0x100);
+ sysbus_init_mmio(sbd, &s->iomem);
+ sysbus_init_irq(sbd, &s->irq);
+}
+
+static void bcm2835_aux_realize(DeviceState *dev, Error **errp)
+{
+ BCM2835AuxState *s = BCM2835_AUX(dev);
+
+ if (s->chr) {
+ qemu_chr_add_handlers(s->chr, bcm2835_aux_can_receive,
+ bcm2835_aux_receive, NULL, s);
+ }
+}
+
+static Property bcm2835_aux_props[] = {
+ DEFINE_PROP_CHR("chardev", BCM2835AuxState, chr),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void bcm2835_aux_class_init(ObjectClass *oc, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(oc);
+
+ dc->realize = bcm2835_aux_realize;
+ dc->vmsd = &vmstate_bcm2835_aux;
+ set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
+ dc->props = bcm2835_aux_props;
+}
+
+static const TypeInfo bcm2835_aux_info = {
+ .name = TYPE_BCM2835_AUX,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(BCM2835AuxState),
+ .instance_init = bcm2835_aux_init,
+ .class_init = bcm2835_aux_class_init,
+};
+
+static void bcm2835_aux_register_types(void)
+{
+ type_register_static(&bcm2835_aux_info);
+}
+
+type_init(bcm2835_aux_register_types)
diff --git a/include/hw/arm/bcm2835_peripherals.h b/include/hw/arm/bcm2835_peripherals.h
index 5d888dc..889adf5 100644
--- a/include/hw/arm/bcm2835_peripherals.h
+++ b/include/hw/arm/bcm2835_peripherals.h
@@ -14,6 +14,7 @@
#include "qemu-common.h"
#include "exec/address-spaces.h"
#include "hw/sysbus.h"
+#include "hw/char/bcm2835_aux.h"
#include "hw/intc/bcm2835_ic.h"
#include "hw/misc/bcm2835_property.h"
#include "hw/misc/bcm2835_mbox.h"
@@ -33,6 +34,7 @@ typedef struct BCM2835PeripheralState {
qemu_irq irq, fiq;
SysBusDevice *uart0;
+ BCM2835AuxState aux;
BCM2835ICState ic;
BCM2835PropertyState property;
BCM2835MboxState mboxes;
diff --git a/include/hw/char/bcm2835_aux.h b/include/hw/char/bcm2835_aux.h
new file mode 100644
index 0000000..42f0ee7
--- /dev/null
+++ b/include/hw/char/bcm2835_aux.h
@@ -0,0 +1,33 @@
+/*
+ * Rasperry Pi 2 emulation and refactoring Copyright (c) 2015, Microsoft
+ * Written by Andrew Baumann
+ *
+ * This code is licensed under the GNU GPLv2 and later.
+ */
+
+#ifndef BCM2835_AUX_H
+#define BCM2835_AUX_H
+
+#include "hw/sysbus.h"
+#include "sysemu/char.h"
+
+#define TYPE_BCM2835_AUX "bcm2835-aux"
+#define BCM2835_AUX(obj) OBJECT_CHECK(BCM2835AuxState, (obj), TYPE_BCM2835_AUX)
+
+#define BCM2835_AUX_RX_FIFO_LEN 8
+
+typedef struct {
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+
+ MemoryRegion iomem;
+ CharDriverState *chr;
+ qemu_irq irq;
+
+ uint8_t read_fifo[BCM2835_AUX_RX_FIFO_LEN];
+ uint8_t read_pos, read_count;
+ uint8_t ier, iir;
+} BCM2835AuxState;
+
+#endif
--
2.7.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [Qemu-devel] [PATCH v3 3/5] bcm2835_fb: add framebuffer device for Raspberry Pi
2016-03-08 20:05 [Qemu-devel] [PATCH v3 0/5] Raspberry Pi framebuffer, DMA and Windows support Andrew Baumann
2016-03-08 20:05 ` [Qemu-devel] [PATCH v3 1/5] bcm2835_peripherals: enable sdhci pending-insert quirk for raspberry pi Andrew Baumann
2016-03-08 20:05 ` [Qemu-devel] [PATCH v3 2/5] bcm2835_aux: add emulation of BCM2835 AUX (aka UART1) block Andrew Baumann
@ 2016-03-08 20:05 ` Andrew Baumann
2016-03-08 20:05 ` [Qemu-devel] [PATCH v3 4/5] bcm2835_property: implement framebuffer control/configuration properties Andrew Baumann
` (3 subsequent siblings)
6 siblings, 0 replies; 11+ messages in thread
From: Andrew Baumann @ 2016-03-08 20:05 UTC (permalink / raw)
To: qemu-devel
Cc: Peter Maydell, Grégory ESTRADE, Stefan Weil,
Peter Crosthwaite, Andrew Baumann, qemu-arm, Paolo Bonzini
From: Grégory ESTRADE <gregory.estrade@gmail.com>
The framebuffer occupies the upper portion of memory (64MiB by
default), but it can only be controlled/configured via a system
mailbox or property channel (to be added by a subsequent patch).
Signed-off-by: Grégory ESTRADE <gregory.estrade@gmail.com>
[AB: added Windows (BGR) support and cleanup/refactoring for upstream submission]
Signed-off-by: Andrew Baumann <Andrew.Baumann@microsoft.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
---
Notes:
v2:
* avoid ldl_phys
* move code to increase default pi2 memory size back to the final patch
hw/arm/bcm2835_peripherals.c | 38 +++-
hw/arm/bcm2836.c | 2 +
hw/arm/raspi.c | 5 +-
hw/display/Makefile.objs | 1 +
hw/display/bcm2835_fb.c | 424 +++++++++++++++++++++++++++++++++++
include/hw/arm/bcm2835_peripherals.h | 2 +
include/hw/display/bcm2835_fb.h | 47 ++++
7 files changed, 517 insertions(+), 2 deletions(-)
create mode 100644 hw/display/bcm2835_fb.c
create mode 100644 include/hw/display/bcm2835_fb.h
diff --git a/hw/arm/bcm2835_peripherals.c b/hw/arm/bcm2835_peripherals.c
index d6453cc..c2fe6b7 100644
--- a/hw/arm/bcm2835_peripherals.c
+++ b/hw/arm/bcm2835_peripherals.c
@@ -62,6 +62,16 @@ static void bcm2835_peripherals_init(Object *obj)
object_property_add_const_link(OBJECT(&s->mboxes), "mbox-mr",
OBJECT(&s->mbox_mr), &error_abort);
+ /* Framebuffer */
+ object_initialize(&s->fb, sizeof(s->fb), TYPE_BCM2835_FB);
+ object_property_add_child(obj, "fb", OBJECT(&s->fb), NULL);
+ object_property_add_alias(obj, "vcram-size", OBJECT(&s->fb), "vcram-size",
+ &error_abort);
+ qdev_set_parent_bus(DEVICE(&s->fb), sysbus_get_default());
+
+ object_property_add_const_link(OBJECT(&s->fb), "dma-mr",
+ OBJECT(&s->gpu_bus_mr), &error_abort);
+
/* Property channel */
object_initialize(&s->property, sizeof(s->property), TYPE_BCM2835_PROPERTY);
object_property_add_child(obj, "property", OBJECT(&s->property), NULL);
@@ -84,7 +94,7 @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
Object *obj;
MemoryRegion *ram;
Error *err = NULL;
- uint32_t ram_size;
+ uint32_t ram_size, vcram_size;
CharDriverState *chr;
int n;
@@ -174,6 +184,32 @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_ARM_IRQ,
INTERRUPT_ARM_MAILBOX));
+ /* Framebuffer */
+ vcram_size = (uint32_t)object_property_get_int(OBJECT(s), "vcram-size",
+ &err);
+ if (err) {
+ error_propagate(errp, err);
+ return;
+ }
+
+ object_property_set_int(OBJECT(&s->fb), ram_size - vcram_size,
+ "vcram-base", &err);
+ if (err) {
+ error_propagate(errp, err);
+ return;
+ }
+
+ object_property_set_bool(OBJECT(&s->fb), true, "realized", &err);
+ if (err) {
+ error_propagate(errp, err);
+ return;
+ }
+
+ memory_region_add_subregion(&s->mbox_mr, MBOX_CHAN_FB << MBOX_AS_CHAN_SHIFT,
+ sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->fb), 0));
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->fb), 0,
+ qdev_get_gpio_in(DEVICE(&s->mboxes), MBOX_CHAN_FB));
+
/* Property channel */
object_property_set_int(OBJECT(&s->property), ram_size, "ram-size", &err);
if (err) {
diff --git a/hw/arm/bcm2836.c b/hw/arm/bcm2836.c
index 0321439..89a6b35 100644
--- a/hw/arm/bcm2836.c
+++ b/hw/arm/bcm2836.c
@@ -42,6 +42,8 @@ static void bcm2836_init(Object *obj)
&error_abort);
object_property_add_alias(obj, "board-rev", OBJECT(&s->peripherals),
"board-rev", &error_abort);
+ object_property_add_alias(obj, "vcram-size", OBJECT(&s->peripherals),
+ "vcram-size", &error_abort);
qdev_set_parent_bus(DEVICE(&s->peripherals), sysbus_get_default());
}
diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c
index 6582279..5498209 100644
--- a/hw/arm/raspi.c
+++ b/hw/arm/raspi.c
@@ -113,6 +113,7 @@ static void setup_boot(MachineState *machine, int version, size_t ram_size)
static void raspi2_init(MachineState *machine)
{
RasPiState *s = g_new0(RasPiState, 1);
+ uint32_t vcram_size;
DriveInfo *di;
BlockBackend *blk;
BusState *bus;
@@ -149,7 +150,9 @@ static void raspi2_init(MachineState *machine)
qdev_prop_set_drive(carddev, "drive", blk, &error_fatal);
object_property_set_bool(OBJECT(carddev), true, "realized", &error_fatal);
- setup_boot(machine, 2, machine->ram_size);
+ vcram_size = object_property_get_int(OBJECT(&s->soc), "vcram-size",
+ &error_abort);
+ setup_boot(machine, 2, machine->ram_size - vcram_size);
}
static void raspi2_machine_init(MachineClass *mc)
diff --git a/hw/display/Makefile.objs b/hw/display/Makefile.objs
index f0cf431..d99780e 100644
--- a/hw/display/Makefile.objs
+++ b/hw/display/Makefile.objs
@@ -27,6 +27,7 @@ endif
obj-$(CONFIG_OMAP) += omap_dss.o
obj-$(CONFIG_OMAP) += omap_lcdc.o
obj-$(CONFIG_PXA2XX) += pxa2xx_lcd.o
+obj-$(CONFIG_RASPI) += bcm2835_fb.o
obj-$(CONFIG_SM501) += sm501.o
obj-$(CONFIG_TCX) += tcx.o
obj-$(CONFIG_CG3) += cg3.o
diff --git a/hw/display/bcm2835_fb.c b/hw/display/bcm2835_fb.c
new file mode 100644
index 0000000..779b56f
--- /dev/null
+++ b/hw/display/bcm2835_fb.c
@@ -0,0 +1,424 @@
+/*
+ * Raspberry Pi emulation (c) 2012 Gregory Estrade
+ * Refactoring for Pi2 Copyright (c) 2015, Microsoft. Written by Andrew Baumann.
+ * This code is licensed under the GNU GPLv2 and later.
+ *
+ * Heavily based on milkymist-vgafb.c, copyright terms below:
+ * QEMU model of the Milkymist VGA framebuffer.
+ *
+ * Copyright (c) 2010-2012 Michael Walle <michael@walle.cc>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "hw/display/bcm2835_fb.h"
+#include "hw/display/framebuffer.h"
+#include "ui/pixel_ops.h"
+#include "hw/misc/bcm2835_mbox_defs.h"
+
+#define DEFAULT_VCRAM_SIZE 0x4000000
+#define BCM2835_FB_OFFSET 0x00100000
+
+static void fb_invalidate_display(void *opaque)
+{
+ BCM2835FBState *s = BCM2835_FB(opaque);
+
+ s->invalidate = true;
+}
+
+static void draw_line_src16(void *opaque, uint8_t *dst, const uint8_t *src,
+ int width, int deststep)
+{
+ BCM2835FBState *s = opaque;
+ uint16_t rgb565;
+ uint32_t rgb888;
+ uint8_t r, g, b;
+ DisplaySurface *surface = qemu_console_surface(s->con);
+ int bpp = surface_bits_per_pixel(surface);
+
+ while (width--) {
+ switch (s->bpp) {
+ case 8:
+ /* lookup palette starting at video ram base
+ * TODO: cache translation, rather than doing this each time!
+ */
+ rgb888 = ldl_le_phys(&s->dma_as, s->vcram_base + (*src << 2));
+ r = (rgb888 >> 0) & 0xff;
+ g = (rgb888 >> 8) & 0xff;
+ b = (rgb888 >> 16) & 0xff;
+ src++;
+ break;
+ case 16:
+ rgb565 = lduw_le_p(src);
+ r = ((rgb565 >> 11) & 0x1f) << 3;
+ g = ((rgb565 >> 5) & 0x3f) << 2;
+ b = ((rgb565 >> 0) & 0x1f) << 3;
+ src += 2;
+ break;
+ case 24:
+ rgb888 = ldl_le_p(src);
+ r = (rgb888 >> 0) & 0xff;
+ g = (rgb888 >> 8) & 0xff;
+ b = (rgb888 >> 16) & 0xff;
+ src += 3;
+ break;
+ case 32:
+ rgb888 = ldl_le_p(src);
+ r = (rgb888 >> 0) & 0xff;
+ g = (rgb888 >> 8) & 0xff;
+ b = (rgb888 >> 16) & 0xff;
+ src += 4;
+ break;
+ default:
+ r = 0;
+ g = 0;
+ b = 0;
+ break;
+ }
+
+ if (s->pixo == 0) {
+ /* swap to BGR pixel format */
+ uint8_t tmp = r;
+ r = b;
+ b = tmp;
+ }
+
+ switch (bpp) {
+ case 8:
+ *dst++ = rgb_to_pixel8(r, g, b);
+ break;
+ case 15:
+ *(uint16_t *)dst = rgb_to_pixel15(r, g, b);
+ dst += 2;
+ break;
+ case 16:
+ *(uint16_t *)dst = rgb_to_pixel16(r, g, b);
+ dst += 2;
+ break;
+ case 24:
+ rgb888 = rgb_to_pixel24(r, g, b);
+ *dst++ = rgb888 & 0xff;
+ *dst++ = (rgb888 >> 8) & 0xff;
+ *dst++ = (rgb888 >> 16) & 0xff;
+ break;
+ case 32:
+ *(uint32_t *)dst = rgb_to_pixel32(r, g, b);
+ dst += 4;
+ break;
+ default:
+ return;
+ }
+ }
+}
+
+static void fb_update_display(void *opaque)
+{
+ BCM2835FBState *s = opaque;
+ DisplaySurface *surface = qemu_console_surface(s->con);
+ int first = 0;
+ int last = 0;
+ int src_width = 0;
+ int dest_width = 0;
+
+ if (s->lock || !s->xres) {
+ return;
+ }
+
+ src_width = s->xres * (s->bpp >> 3);
+ dest_width = s->xres;
+
+ switch (surface_bits_per_pixel(surface)) {
+ case 0:
+ return;
+ case 8:
+ break;
+ case 15:
+ dest_width *= 2;
+ break;
+ case 16:
+ dest_width *= 2;
+ break;
+ case 24:
+ dest_width *= 3;
+ break;
+ case 32:
+ dest_width *= 4;
+ break;
+ default:
+ hw_error("bcm2835_fb: bad color depth\n");
+ break;
+ }
+
+ if (s->invalidate) {
+ framebuffer_update_memory_section(&s->fbsection, s->dma_mr, s->base,
+ s->yres, src_width);
+ }
+
+ framebuffer_update_display(surface, &s->fbsection, s->xres, s->yres,
+ src_width, dest_width, 0, s->invalidate,
+ draw_line_src16, s, &first, &last);
+
+ if (first >= 0) {
+ dpy_gfx_update(s->con, 0, first, s->xres, last - first + 1);
+ }
+
+ s->invalidate = false;
+}
+
+static void bcm2835_fb_mbox_push(BCM2835FBState *s, uint32_t value)
+{
+ value &= ~0xf;
+
+ s->lock = true;
+
+ s->xres = ldl_le_phys(&s->dma_as, value);
+ s->yres = ldl_le_phys(&s->dma_as, value + 4);
+ s->xres_virtual = ldl_le_phys(&s->dma_as, value + 8);
+ s->yres_virtual = ldl_le_phys(&s->dma_as, value + 12);
+ s->bpp = ldl_le_phys(&s->dma_as, value + 20);
+ s->xoffset = ldl_le_phys(&s->dma_as, value + 24);
+ s->yoffset = ldl_le_phys(&s->dma_as, value + 28);
+
+ s->base = s->vcram_base | (value & 0xc0000000);
+ s->base += BCM2835_FB_OFFSET;
+
+ /* TODO - Manage properly virtual resolution */
+
+ s->pitch = s->xres * (s->bpp >> 3);
+ s->size = s->yres * s->pitch;
+
+ stl_le_phys(&s->dma_as, value + 16, s->pitch);
+ stl_le_phys(&s->dma_as, value + 32, s->base);
+ stl_le_phys(&s->dma_as, value + 36, s->size);
+
+ s->invalidate = true;
+ qemu_console_resize(s->con, s->xres, s->yres);
+ s->lock = false;
+}
+
+void bcm2835_fb_reconfigure(BCM2835FBState *s, uint32_t *xres, uint32_t *yres,
+ uint32_t *xoffset, uint32_t *yoffset, uint32_t *bpp,
+ uint32_t *pixo, uint32_t *alpha)
+{
+ s->lock = true;
+
+ /* TODO: input validation! */
+ if (xres) {
+ s->xres = *xres;
+ }
+ if (yres) {
+ s->yres = *yres;
+ }
+ if (xoffset) {
+ s->xoffset = *xoffset;
+ }
+ if (yoffset) {
+ s->yoffset = *yoffset;
+ }
+ if (bpp) {
+ s->bpp = *bpp;
+ }
+ if (pixo) {
+ s->pixo = *pixo;
+ }
+ if (alpha) {
+ s->alpha = *alpha;
+ }
+
+ /* TODO - Manage properly virtual resolution */
+
+ s->pitch = s->xres * (s->bpp >> 3);
+ s->size = s->yres * s->pitch;
+
+ s->invalidate = true;
+ qemu_console_resize(s->con, s->xres, s->yres);
+ s->lock = false;
+}
+
+static uint64_t bcm2835_fb_read(void *opaque, hwaddr offset, unsigned size)
+{
+ BCM2835FBState *s = opaque;
+ uint32_t res = 0;
+
+ switch (offset) {
+ case MBOX_AS_DATA:
+ res = MBOX_CHAN_FB;
+ s->pending = false;
+ qemu_set_irq(s->mbox_irq, 0);
+ break;
+
+ case MBOX_AS_PENDING:
+ res = s->pending;
+ break;
+
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n",
+ __func__, offset);
+ return 0;
+ }
+
+ return res;
+}
+
+static void bcm2835_fb_write(void *opaque, hwaddr offset, uint64_t value,
+ unsigned size)
+{
+ BCM2835FBState *s = opaque;
+
+ switch (offset) {
+ case MBOX_AS_DATA:
+ /* bcm2835_mbox should check our pending status before pushing */
+ assert(!s->pending);
+ s->pending = true;
+ bcm2835_fb_mbox_push(s, value);
+ qemu_set_irq(s->mbox_irq, 1);
+ break;
+
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n",
+ __func__, offset);
+ return;
+ }
+}
+
+static const MemoryRegionOps bcm2835_fb_ops = {
+ .read = bcm2835_fb_read,
+ .write = bcm2835_fb_write,
+ .endianness = DEVICE_NATIVE_ENDIAN,
+ .valid.min_access_size = 4,
+ .valid.max_access_size = 4,
+};
+
+static const VMStateDescription vmstate_bcm2835_fb = {
+ .name = TYPE_BCM2835_FB,
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_BOOL(lock, BCM2835FBState),
+ VMSTATE_BOOL(invalidate, BCM2835FBState),
+ VMSTATE_BOOL(pending, BCM2835FBState),
+ VMSTATE_UINT32(xres, BCM2835FBState),
+ VMSTATE_UINT32(yres, BCM2835FBState),
+ VMSTATE_UINT32(xres_virtual, BCM2835FBState),
+ VMSTATE_UINT32(yres_virtual, BCM2835FBState),
+ VMSTATE_UINT32(xoffset, BCM2835FBState),
+ VMSTATE_UINT32(yoffset, BCM2835FBState),
+ VMSTATE_UINT32(bpp, BCM2835FBState),
+ VMSTATE_UINT32(base, BCM2835FBState),
+ VMSTATE_UINT32(pitch, BCM2835FBState),
+ VMSTATE_UINT32(size, BCM2835FBState),
+ VMSTATE_UINT32(pixo, BCM2835FBState),
+ VMSTATE_UINT32(alpha, BCM2835FBState),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static const GraphicHwOps vgafb_ops = {
+ .invalidate = fb_invalidate_display,
+ .gfx_update = fb_update_display,
+};
+
+static void bcm2835_fb_init(Object *obj)
+{
+ BCM2835FBState *s = BCM2835_FB(obj);
+
+ memory_region_init_io(&s->iomem, obj, &bcm2835_fb_ops, s, TYPE_BCM2835_FB,
+ 0x10);
+ sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem);
+ sysbus_init_irq(SYS_BUS_DEVICE(s), &s->mbox_irq);
+}
+
+static void bcm2835_fb_reset(DeviceState *dev)
+{
+ BCM2835FBState *s = BCM2835_FB(dev);
+
+ s->pending = false;
+
+ s->xres_virtual = s->xres;
+ s->yres_virtual = s->yres;
+ s->xoffset = 0;
+ s->yoffset = 0;
+ s->base = s->vcram_base + BCM2835_FB_OFFSET;
+ s->pitch = s->xres * (s->bpp >> 3);
+ s->size = s->yres * s->pitch;
+
+ s->invalidate = true;
+ s->lock = false;
+}
+
+static void bcm2835_fb_realize(DeviceState *dev, Error **errp)
+{
+ BCM2835FBState *s = BCM2835_FB(dev);
+ Error *err = NULL;
+ Object *obj;
+
+ if (s->vcram_base == 0) {
+ error_setg(errp, "%s: required vcram-base property not set", __func__);
+ return;
+ }
+
+ obj = object_property_get_link(OBJECT(dev), "dma-mr", &err);
+ if (obj == NULL) {
+ error_setg(errp, "%s: required dma-mr link not found: %s",
+ __func__, error_get_pretty(err));
+ return;
+ }
+
+ s->dma_mr = MEMORY_REGION(obj);
+ address_space_init(&s->dma_as, s->dma_mr, NULL);
+
+ bcm2835_fb_reset(dev);
+
+ s->con = graphic_console_init(dev, 0, &vgafb_ops, s);
+ qemu_console_resize(s->con, s->xres, s->yres);
+}
+
+static Property bcm2835_fb_props[] = {
+ DEFINE_PROP_UINT32("vcram-base", BCM2835FBState, vcram_base, 0),/*required*/
+ DEFINE_PROP_UINT32("vcram-size", BCM2835FBState, vcram_size,
+ DEFAULT_VCRAM_SIZE),
+ DEFINE_PROP_UINT32("xres", BCM2835FBState, xres, 640),
+ DEFINE_PROP_UINT32("yres", BCM2835FBState, yres, 480),
+ DEFINE_PROP_UINT32("bpp", BCM2835FBState, bpp, 16),
+ DEFINE_PROP_UINT32("pixo", BCM2835FBState, pixo, 1), /* 1=RGB, 0=BGR */
+ DEFINE_PROP_UINT32("alpha", BCM2835FBState, alpha, 2), /* alpha ignored */
+ DEFINE_PROP_END_OF_LIST()
+};
+
+static void bcm2835_fb_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ dc->props = bcm2835_fb_props;
+ dc->realize = bcm2835_fb_realize;
+ dc->reset = bcm2835_fb_reset;
+ dc->vmsd = &vmstate_bcm2835_fb;
+}
+
+static TypeInfo bcm2835_fb_info = {
+ .name = TYPE_BCM2835_FB,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(BCM2835FBState),
+ .class_init = bcm2835_fb_class_init,
+ .instance_init = bcm2835_fb_init,
+};
+
+static void bcm2835_fb_register_types(void)
+{
+ type_register_static(&bcm2835_fb_info);
+}
+
+type_init(bcm2835_fb_register_types)
diff --git a/include/hw/arm/bcm2835_peripherals.h b/include/hw/arm/bcm2835_peripherals.h
index 889adf5..e19d360 100644
--- a/include/hw/arm/bcm2835_peripherals.h
+++ b/include/hw/arm/bcm2835_peripherals.h
@@ -15,6 +15,7 @@
#include "exec/address-spaces.h"
#include "hw/sysbus.h"
#include "hw/char/bcm2835_aux.h"
+#include "hw/display/bcm2835_fb.h"
#include "hw/intc/bcm2835_ic.h"
#include "hw/misc/bcm2835_property.h"
#include "hw/misc/bcm2835_mbox.h"
@@ -35,6 +36,7 @@ typedef struct BCM2835PeripheralState {
SysBusDevice *uart0;
BCM2835AuxState aux;
+ BCM2835FBState fb;
BCM2835ICState ic;
BCM2835PropertyState property;
BCM2835MboxState mboxes;
diff --git a/include/hw/display/bcm2835_fb.h b/include/hw/display/bcm2835_fb.h
new file mode 100644
index 0000000..9a12d7a
--- /dev/null
+++ b/include/hw/display/bcm2835_fb.h
@@ -0,0 +1,47 @@
+/*
+ * Raspberry Pi emulation (c) 2012 Gregory Estrade
+ * Upstreaming code cleanup [including bcm2835_*] (c) 2013 Jan Petrous
+ *
+ * Rasperry Pi 2 emulation and refactoring Copyright (c) 2015, Microsoft
+ * Written by Andrew Baumann
+ *
+ * This code is licensed under the GNU GPLv2 and later.
+ */
+
+#ifndef BCM2835_FB_H
+#define BCM2835_FB_H
+
+#include "hw/sysbus.h"
+#include "exec/address-spaces.h"
+#include "ui/console.h"
+
+#define TYPE_BCM2835_FB "bcm2835-fb"
+#define BCM2835_FB(obj) OBJECT_CHECK(BCM2835FBState, (obj), TYPE_BCM2835_FB)
+
+typedef struct {
+ /*< private >*/
+ SysBusDevice busdev;
+ /*< public >*/
+
+ uint32_t vcram_base, vcram_size;
+ MemoryRegion *dma_mr;
+ AddressSpace dma_as;
+ MemoryRegion iomem;
+ MemoryRegionSection fbsection;
+ QemuConsole *con;
+ qemu_irq mbox_irq;
+
+ bool lock, invalidate, pending;
+ uint32_t xres, yres;
+ uint32_t xres_virtual, yres_virtual;
+ uint32_t xoffset, yoffset;
+ uint32_t bpp;
+ uint32_t base, pitch, size;
+ uint32_t pixo, alpha;
+} BCM2835FBState;
+
+void bcm2835_fb_reconfigure(BCM2835FBState *s, uint32_t *xres, uint32_t *yres,
+ uint32_t *xoffset, uint32_t *yoffset, uint32_t *bpp,
+ uint32_t *pixo, uint32_t *alpha);
+
+#endif
--
2.7.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [Qemu-devel] [PATCH v3 4/5] bcm2835_property: implement framebuffer control/configuration properties
2016-03-08 20:05 [Qemu-devel] [PATCH v3 0/5] Raspberry Pi framebuffer, DMA and Windows support Andrew Baumann
` (2 preceding siblings ...)
2016-03-08 20:05 ` [Qemu-devel] [PATCH v3 3/5] bcm2835_fb: add framebuffer device for Raspberry Pi Andrew Baumann
@ 2016-03-08 20:05 ` Andrew Baumann
2016-03-08 20:05 ` [Qemu-devel] [PATCH v3 5/5] bcm2835_dma: add emulation of Raspberry Pi DMA controller Andrew Baumann
` (2 subsequent siblings)
6 siblings, 0 replies; 11+ messages in thread
From: Andrew Baumann @ 2016-03-08 20:05 UTC (permalink / raw)
To: qemu-devel
Cc: Peter Maydell, Grégory ESTRADE, Stefan Weil,
Peter Crosthwaite, Andrew Baumann, qemu-arm, Paolo Bonzini
From: Grégory ESTRADE <gregory.estrade@gmail.com>
The property channel driver now interfaces with the framebuffer device
to query and set framebuffer parameters. As a result of this, the "get
ARM RAM size" query now correctly returns the video RAM base address
(not total RAM size), and the ram-size property is no longer relevant
here.
Signed-off-by: Grégory ESTRADE <gregory.estrade@gmail.com>
[AB: cleanup/refactoring for upstream submission]
Signed-off-by: Andrew Baumann <Andrew.Baumann@microsoft.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
---
Notes:
v2:
* avoid ldl/stl_phys
* move code to increase default pi2 memory size from preceding patch here
(it was incorrect without the property channel implementation changes)
hw/arm/bcm2835_peripherals.c | 8 +--
hw/arm/raspi.c | 7 +-
hw/misc/bcm2835_property.c | 139 ++++++++++++++++++++++++++++++++++++-
include/hw/misc/bcm2835_property.h | 5 +-
4 files changed, 144 insertions(+), 15 deletions(-)
diff --git a/hw/arm/bcm2835_peripherals.c b/hw/arm/bcm2835_peripherals.c
index c2fe6b7..4d74a18 100644
--- a/hw/arm/bcm2835_peripherals.c
+++ b/hw/arm/bcm2835_peripherals.c
@@ -79,6 +79,8 @@ static void bcm2835_peripherals_init(Object *obj)
"board-rev", &error_abort);
qdev_set_parent_bus(DEVICE(&s->property), sysbus_get_default());
+ object_property_add_const_link(OBJECT(&s->property), "fb",
+ OBJECT(&s->fb), &error_abort);
object_property_add_const_link(OBJECT(&s->property), "dma-mr",
OBJECT(&s->gpu_bus_mr), &error_abort);
@@ -211,12 +213,6 @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
qdev_get_gpio_in(DEVICE(&s->mboxes), MBOX_CHAN_FB));
/* Property channel */
- object_property_set_int(OBJECT(&s->property), ram_size, "ram-size", &err);
- if (err) {
- error_propagate(errp, err);
- return;
- }
-
object_property_set_bool(OBJECT(&s->property), true, "realized", &err);
if (err) {
error_propagate(errp, err);
diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c
index 5498209..83fe809 100644
--- a/hw/arm/raspi.c
+++ b/hw/arm/raspi.c
@@ -164,11 +164,6 @@ static void raspi2_machine_init(MachineClass *mc)
mc->no_floppy = 1;
mc->no_cdrom = 1;
mc->max_cpus = BCM2836_NCPUS;
-
- /* XXX: Temporary restriction in RAM size from the full 1GB. Since
- * we do not yet support the framebuffer / GPU, we need to limit
- * RAM usable by the OS to sit below the peripherals.
- */
- mc->default_ram_size = 0x3F000000; /* BCM2836_PERI_BASE */
+ mc->default_ram_size = 1024 * 1024 * 1024;
};
DEFINE_MACHINE("raspi2", raspi2_machine_init)
diff --git a/hw/misc/bcm2835_property.c b/hw/misc/bcm2835_property.c
index 41fbbe3..15dcc02 100644
--- a/hw/misc/bcm2835_property.c
+++ b/hw/misc/bcm2835_property.c
@@ -17,6 +17,11 @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
uint32_t tot_len;
size_t resplen;
uint32_t tmp;
+ int n;
+ uint32_t offset, length, color;
+ uint32_t xres, yres, xoffset, yoffset, bpp, pixo, alpha;
+ uint32_t *newxres = NULL, *newyres = NULL, *newxoffset = NULL,
+ *newyoffset = NULL, *newbpp = NULL, *newpixo = NULL, *newalpha = NULL;
value &= ~0xf;
@@ -60,7 +65,14 @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
/* base */
stl_le_phys(&s->dma_as, value + 12, 0);
/* size */
- stl_le_phys(&s->dma_as, value + 16, s->ram_size);
+ stl_le_phys(&s->dma_as, value + 16, s->fbdev->vcram_base);
+ resplen = 8;
+ break;
+ case 0x00010006: /* Get VC memory */
+ /* base */
+ stl_le_phys(&s->dma_as, value + 12, s->fbdev->vcram_base);
+ /* size */
+ stl_le_phys(&s->dma_as, value + 16, s->fbdev->vcram_size);
resplen = 8;
break;
case 0x00028001: /* Set power state */
@@ -122,6 +134,114 @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
resplen = 8;
break;
+ /* Frame buffer */
+
+ case 0x00040001: /* Allocate buffer */
+ stl_le_phys(&s->dma_as, value + 12, s->fbdev->base);
+ stl_le_phys(&s->dma_as, value + 16, s->fbdev->size);
+ resplen = 8;
+ break;
+ case 0x00048001: /* Release buffer */
+ resplen = 0;
+ break;
+ case 0x00040002: /* Blank screen */
+ resplen = 4;
+ break;
+ case 0x00040003: /* Get display width/height */
+ case 0x00040004:
+ stl_le_phys(&s->dma_as, value + 12, s->fbdev->xres);
+ stl_le_phys(&s->dma_as, value + 16, s->fbdev->yres);
+ resplen = 8;
+ break;
+ case 0x00044003: /* Test display width/height */
+ case 0x00044004:
+ resplen = 8;
+ break;
+ case 0x00048003: /* Set display width/height */
+ case 0x00048004:
+ xres = ldl_le_phys(&s->dma_as, value + 12);
+ newxres = &xres;
+ yres = ldl_le_phys(&s->dma_as, value + 16);
+ newyres = &yres;
+ resplen = 8;
+ break;
+ case 0x00040005: /* Get depth */
+ stl_le_phys(&s->dma_as, value + 12, s->fbdev->bpp);
+ resplen = 4;
+ break;
+ case 0x00044005: /* Test depth */
+ resplen = 4;
+ break;
+ case 0x00048005: /* Set depth */
+ bpp = ldl_le_phys(&s->dma_as, value + 12);
+ newbpp = &bpp;
+ resplen = 4;
+ break;
+ case 0x00040006: /* Get pixel order */
+ stl_le_phys(&s->dma_as, value + 12, s->fbdev->pixo);
+ resplen = 4;
+ break;
+ case 0x00044006: /* Test pixel order */
+ resplen = 4;
+ break;
+ case 0x00048006: /* Set pixel order */
+ pixo = ldl_le_phys(&s->dma_as, value + 12);
+ newpixo = &pixo;
+ resplen = 4;
+ break;
+ case 0x00040007: /* Get alpha */
+ stl_le_phys(&s->dma_as, value + 12, s->fbdev->alpha);
+ resplen = 4;
+ break;
+ case 0x00044007: /* Test pixel alpha */
+ resplen = 4;
+ break;
+ case 0x00048007: /* Set alpha */
+ alpha = ldl_le_phys(&s->dma_as, value + 12);
+ newalpha = α
+ resplen = 4;
+ break;
+ case 0x00040008: /* Get pitch */
+ stl_le_phys(&s->dma_as, value + 12, s->fbdev->pitch);
+ resplen = 4;
+ break;
+ case 0x00040009: /* Get virtual offset */
+ stl_le_phys(&s->dma_as, value + 12, s->fbdev->xoffset);
+ stl_le_phys(&s->dma_as, value + 16, s->fbdev->yoffset);
+ resplen = 8;
+ break;
+ case 0x00044009: /* Test virtual offset */
+ resplen = 8;
+ break;
+ case 0x00048009: /* Set virtual offset */
+ xoffset = ldl_le_phys(&s->dma_as, value + 12);
+ newxoffset = &xoffset;
+ yoffset = ldl_le_phys(&s->dma_as, value + 16);
+ newyoffset = &yoffset;
+ resplen = 8;
+ break;
+ case 0x0004000a: /* Get/Test/Set overscan */
+ case 0x0004400a:
+ case 0x0004800a:
+ stl_le_phys(&s->dma_as, value + 12, 0);
+ stl_le_phys(&s->dma_as, value + 16, 0);
+ stl_le_phys(&s->dma_as, value + 20, 0);
+ stl_le_phys(&s->dma_as, value + 24, 0);
+ resplen = 16;
+ break;
+ case 0x0004800b: /* Set palette */
+ offset = ldl_le_phys(&s->dma_as, value + 12);
+ length = ldl_le_phys(&s->dma_as, value + 16);
+ n = 0;
+ while (n < length - offset) {
+ color = ldl_le_phys(&s->dma_as, value + 20 + (n << 2));
+ stl_le_phys(&s->dma_as,
+ s->fbdev->vcram_base + ((offset + n) << 2), color);
+ n++;
+ }
+ stl_le_phys(&s->dma_as, value + 12, 0);
+ resplen = 4;
+ break;
case 0x00060001: /* Get DMA channels */
/* channels 2-5 */
@@ -147,6 +267,13 @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
value += bufsize + 12;
}
+ /* Reconfigure framebuffer if required */
+ if (newxres || newyres || newxoffset || newyoffset || newbpp || newpixo
+ || newalpha) {
+ bcm2835_fb_reconfigure(s->fbdev, newxres, newyres, newxoffset,
+ newyoffset, newbpp, newpixo, newalpha);
+ }
+
/* Buffer response code */
stl_le_phys(&s->dma_as, s->addr + 4, (1 << 31));
}
@@ -241,6 +368,15 @@ static void bcm2835_property_realize(DeviceState *dev, Error **errp)
Object *obj;
Error *err = NULL;
+ obj = object_property_get_link(OBJECT(dev), "fb", &err);
+ if (obj == NULL) {
+ error_setg(errp, "%s: required fb link not found: %s",
+ __func__, error_get_pretty(err));
+ return;
+ }
+
+ s->fbdev = BCM2835_FB(obj);
+
obj = object_property_get_link(OBJECT(dev), "dma-mr", &err);
if (obj == NULL) {
error_setg(errp, "%s: required dma-mr link not found: %s",
@@ -259,7 +395,6 @@ static void bcm2835_property_realize(DeviceState *dev, Error **errp)
static Property bcm2835_property_props[] = {
DEFINE_PROP_UINT32("board-rev", BCM2835PropertyState, board_rev, 0),
- DEFINE_PROP_UINT32("ram-size", BCM2835PropertyState, ram_size, 0),
DEFINE_PROP_END_OF_LIST()
};
diff --git a/include/hw/misc/bcm2835_property.h b/include/hw/misc/bcm2835_property.h
index df889ea..edcab60 100644
--- a/include/hw/misc/bcm2835_property.h
+++ b/include/hw/misc/bcm2835_property.h
@@ -9,6 +9,7 @@
#include "hw/sysbus.h"
#include "exec/address-spaces.h"
#include "net/net.h"
+#include "hw/display/bcm2835_fb.h"
#define TYPE_BCM2835_PROPERTY "bcm2835-property"
#define BCM2835_PROPERTY(obj) \
@@ -18,13 +19,15 @@ typedef struct {
/*< private >*/
SysBusDevice busdev;
/*< public >*/
+
MemoryRegion *dma_mr;
AddressSpace dma_as;
MemoryRegion iomem;
qemu_irq mbox_irq;
+ BCM2835FBState *fbdev;
+
MACAddr macaddr;
uint32_t board_rev;
- uint32_t ram_size;
uint32_t addr;
bool pending;
} BCM2835PropertyState;
--
2.7.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [Qemu-devel] [PATCH v3 5/5] bcm2835_dma: add emulation of Raspberry Pi DMA controller
2016-03-08 20:05 [Qemu-devel] [PATCH v3 0/5] Raspberry Pi framebuffer, DMA and Windows support Andrew Baumann
` (3 preceding siblings ...)
2016-03-08 20:05 ` [Qemu-devel] [PATCH v3 4/5] bcm2835_property: implement framebuffer control/configuration properties Andrew Baumann
@ 2016-03-08 20:05 ` Andrew Baumann
2016-03-16 15:28 ` [Qemu-devel] [PATCH v3 0/5] Raspberry Pi framebuffer, DMA and Windows support Peter Maydell
2016-03-16 16:54 ` Peter Maydell
6 siblings, 0 replies; 11+ messages in thread
From: Andrew Baumann @ 2016-03-08 20:05 UTC (permalink / raw)
To: qemu-devel
Cc: Peter Maydell, Grégory ESTRADE, Stefan Weil,
Peter Crosthwaite, Andrew Baumann, qemu-arm, Paolo Bonzini
From: Grégory ESTRADE <gregory.estrade@gmail.com>
At present, all DMA transfers complete inline (so a looping descriptor
queue will lock up the device). We also do not model pause/abort,
arbitrarion/priority, or debug features.
Signed-off-by: Grégory ESTRADE <gregory.estrade@gmail.com>
[AB: implement 2D mode, cleanup/refactoring for upstream submission]
Signed-off-by: Andrew Baumann <Andrew.Baumann@microsoft.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
---
Notes:
v2:
* avoid ldl_phys/stl_phys
* compute address of channel structure only after asserting its validity
* correctly implement per-channel reset and abort bits
* set channel paused bit when completing DMA
hw/arm/bcm2835_peripherals.c | 26 +++
hw/dma/Makefile.objs | 1 +
hw/dma/bcm2835_dma.c | 408 +++++++++++++++++++++++++++++++++++
include/hw/arm/bcm2835_peripherals.h | 2 +
include/hw/dma/bcm2835_dma.h | 47 ++++
5 files changed, 484 insertions(+)
create mode 100644 hw/dma/bcm2835_dma.c
create mode 100644 include/hw/dma/bcm2835_dma.h
diff --git a/hw/arm/bcm2835_peripherals.c b/hw/arm/bcm2835_peripherals.c
index 4d74a18..8099a8a 100644
--- a/hw/arm/bcm2835_peripherals.c
+++ b/hw/arm/bcm2835_peripherals.c
@@ -88,6 +88,14 @@ static void bcm2835_peripherals_init(Object *obj)
object_initialize(&s->sdhci, sizeof(s->sdhci), TYPE_SYSBUS_SDHCI);
object_property_add_child(obj, "sdhci", OBJECT(&s->sdhci), NULL);
qdev_set_parent_bus(DEVICE(&s->sdhci), sysbus_get_default());
+
+ /* DMA Channels */
+ object_initialize(&s->dma, sizeof(s->dma), TYPE_BCM2835_DMA);
+ object_property_add_child(obj, "dma", OBJECT(&s->dma), NULL);
+ qdev_set_parent_bus(DEVICE(&s->dma), sysbus_get_default());
+
+ object_property_add_const_link(OBJECT(&s->dma), "dma-mr",
+ OBJECT(&s->gpu_bus_mr), &error_abort);
}
static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
@@ -258,6 +266,24 @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
return;
}
+ /* DMA Channels */
+ object_property_set_bool(OBJECT(&s->dma), true, "realized", &err);
+ if (err) {
+ error_propagate(errp, err);
+ return;
+ }
+
+ memory_region_add_subregion(&s->peri_mr, DMA_OFFSET,
+ sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->dma), 0));
+ memory_region_add_subregion(&s->peri_mr, DMA15_OFFSET,
+ sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->dma), 1));
+
+ for (n = 0; n <= 12; n++) {
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->dma), n,
+ qdev_get_gpio_in_named(DEVICE(&s->ic),
+ BCM2835_IC_GPU_IRQ,
+ INTERRUPT_DMA0 + n));
+ }
}
static void bcm2835_peripherals_class_init(ObjectClass *oc, void *data)
diff --git a/hw/dma/Makefile.objs b/hw/dma/Makefile.objs
index 0e65ed0..a1abbcf 100644
--- a/hw/dma/Makefile.objs
+++ b/hw/dma/Makefile.objs
@@ -11,3 +11,4 @@ common-obj-$(CONFIG_SUN4M) += sun4m_iommu.o
obj-$(CONFIG_OMAP) += omap_dma.o soc_dma.o
obj-$(CONFIG_PXA2XX) += pxa2xx_dma.o
+obj-$(CONFIG_RASPI) += bcm2835_dma.o
diff --git a/hw/dma/bcm2835_dma.c b/hw/dma/bcm2835_dma.c
new file mode 100644
index 0000000..c7ce4e4
--- /dev/null
+++ b/hw/dma/bcm2835_dma.c
@@ -0,0 +1,408 @@
+/*
+ * Raspberry Pi emulation (c) 2012 Gregory Estrade
+ * This code is licensed under the GNU GPLv2 and later.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/dma/bcm2835_dma.h"
+
+/* DMA CS Control and Status bits */
+#define BCM2708_DMA_ACTIVE (1 << 0)
+#define BCM2708_DMA_END (1 << 1) /* GE */
+#define BCM2708_DMA_INT (1 << 2)
+#define BCM2708_DMA_ISPAUSED (1 << 4) /* Pause requested or not active */
+#define BCM2708_DMA_ISHELD (1 << 5) /* Is held by DREQ flow control */
+#define BCM2708_DMA_ERR (1 << 8)
+#define BCM2708_DMA_ABORT (1 << 30) /* stop current CB, go to next, WO */
+#define BCM2708_DMA_RESET (1 << 31) /* WO, self clearing */
+
+/* DMA control block "info" field bits */
+#define BCM2708_DMA_INT_EN (1 << 0)
+#define BCM2708_DMA_TDMODE (1 << 1)
+#define BCM2708_DMA_WAIT_RESP (1 << 3)
+#define BCM2708_DMA_D_INC (1 << 4)
+#define BCM2708_DMA_D_WIDTH (1 << 5)
+#define BCM2708_DMA_D_DREQ (1 << 6)
+#define BCM2708_DMA_D_IGNORE (1 << 7)
+#define BCM2708_DMA_S_INC (1 << 8)
+#define BCM2708_DMA_S_WIDTH (1 << 9)
+#define BCM2708_DMA_S_DREQ (1 << 10)
+#define BCM2708_DMA_S_IGNORE (1 << 11)
+
+/* Register offsets */
+#define BCM2708_DMA_CS 0x00 /* Control and Status */
+#define BCM2708_DMA_ADDR 0x04 /* Control block address */
+/* the current control block appears in the following registers - read only */
+#define BCM2708_DMA_INFO 0x08
+#define BCM2708_DMA_SOURCE_AD 0x0c
+#define BCM2708_DMA_DEST_AD 0x10
+#define BCM2708_DMA_TXFR_LEN 0x14
+#define BCM2708_DMA_STRIDE 0x18
+#define BCM2708_DMA_NEXTCB 0x1C
+#define BCM2708_DMA_DEBUG 0x20
+
+#define BCM2708_DMA_INT_STATUS 0xfe0 /* Interrupt status of each channel */
+#define BCM2708_DMA_ENABLE 0xff0 /* Global enable bits for each channel */
+
+#define BCM2708_DMA_CS_RW_MASK 0x30ff0001 /* All RW bits in DMA_CS */
+
+static void bcm2835_dma_update(BCM2835DMAState *s, unsigned c)
+{
+ BCM2835DMAChan *ch = &s->chan[c];
+ uint32_t data, xlen, ylen;
+ int16_t dst_stride, src_stride;
+
+ if (!(s->enable & (1 << c))) {
+ return;
+ }
+
+ while ((s->enable & (1 << c)) && (ch->conblk_ad != 0)) {
+ /* CB fetch */
+ ch->ti = ldl_le_phys(&s->dma_as, ch->conblk_ad);
+ ch->source_ad = ldl_le_phys(&s->dma_as, ch->conblk_ad + 4);
+ ch->dest_ad = ldl_le_phys(&s->dma_as, ch->conblk_ad + 8);
+ ch->txfr_len = ldl_le_phys(&s->dma_as, ch->conblk_ad + 12);
+ ch->stride = ldl_le_phys(&s->dma_as, ch->conblk_ad + 16);
+ ch->nextconbk = ldl_le_phys(&s->dma_as, ch->conblk_ad + 20);
+
+ if (ch->ti & BCM2708_DMA_TDMODE) {
+ /* 2D transfer mode */
+ ylen = (ch->txfr_len >> 16) & 0x3fff;
+ xlen = ch->txfr_len & 0xffff;
+ dst_stride = ch->stride >> 16;
+ src_stride = ch->stride & 0xffff;
+ } else {
+ ylen = 1;
+ xlen = ch->txfr_len;
+ dst_stride = 0;
+ src_stride = 0;
+ }
+
+ while (ylen != 0) {
+ /* Normal transfer mode */
+ while (xlen != 0) {
+ if (ch->ti & BCM2708_DMA_S_IGNORE) {
+ /* Ignore reads */
+ data = 0;
+ } else {
+ data = ldl_le_phys(&s->dma_as, ch->source_ad);
+ }
+ if (ch->ti & BCM2708_DMA_S_INC) {
+ ch->source_ad += 4;
+ }
+
+ if (ch->ti & BCM2708_DMA_D_IGNORE) {
+ /* Ignore writes */
+ } else {
+ stl_le_phys(&s->dma_as, ch->dest_ad, data);
+ }
+ if (ch->ti & BCM2708_DMA_D_INC) {
+ ch->dest_ad += 4;
+ }
+
+ /* update remaining transfer length */
+ xlen -= 4;
+ if (ch->ti & BCM2708_DMA_TDMODE) {
+ ch->txfr_len = (ylen << 16) | xlen;
+ } else {
+ ch->txfr_len = xlen;
+ }
+ }
+
+ if (--ylen != 0) {
+ ch->source_ad += src_stride;
+ ch->dest_ad += dst_stride;
+ }
+ }
+ ch->cs |= BCM2708_DMA_END;
+ if (ch->ti & BCM2708_DMA_INT_EN) {
+ ch->cs |= BCM2708_DMA_INT;
+ s->int_status |= (1 << c);
+ qemu_set_irq(ch->irq, 1);
+ }
+
+ /* Process next CB */
+ ch->conblk_ad = ch->nextconbk;
+ }
+
+ ch->cs &= ~BCM2708_DMA_ACTIVE;
+ ch->cs |= BCM2708_DMA_ISPAUSED;
+}
+
+static void bcm2835_dma_chan_reset(BCM2835DMAChan *ch)
+{
+ ch->cs = 0;
+ ch->conblk_ad = 0;
+}
+
+static uint64_t bcm2835_dma_read(BCM2835DMAState *s, hwaddr offset,
+ unsigned size, unsigned c)
+{
+ BCM2835DMAChan *ch;
+ uint32_t res = 0;
+
+ assert(size == 4);
+ assert(c < BCM2835_DMA_NCHANS);
+
+ ch = &s->chan[c];
+
+ switch (offset) {
+ case BCM2708_DMA_CS:
+ res = ch->cs;
+ break;
+ case BCM2708_DMA_ADDR:
+ res = ch->conblk_ad;
+ break;
+ case BCM2708_DMA_INFO:
+ res = ch->ti;
+ break;
+ case BCM2708_DMA_SOURCE_AD:
+ res = ch->source_ad;
+ break;
+ case BCM2708_DMA_DEST_AD:
+ res = ch->dest_ad;
+ break;
+ case BCM2708_DMA_TXFR_LEN:
+ res = ch->txfr_len;
+ break;
+ case BCM2708_DMA_STRIDE:
+ res = ch->stride;
+ break;
+ case BCM2708_DMA_NEXTCB:
+ res = ch->nextconbk;
+ break;
+ case BCM2708_DMA_DEBUG:
+ res = ch->debug;
+ break;
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n",
+ __func__, offset);
+ break;
+ }
+ return res;
+}
+
+static void bcm2835_dma_write(BCM2835DMAState *s, hwaddr offset,
+ uint64_t value, unsigned size, unsigned c)
+{
+ BCM2835DMAChan *ch;
+ uint32_t oldcs;
+
+ assert(size == 4);
+ assert(c < BCM2835_DMA_NCHANS);
+
+ ch = &s->chan[c];
+
+ switch (offset) {
+ case BCM2708_DMA_CS:
+ oldcs = ch->cs;
+ if (value & BCM2708_DMA_RESET) {
+ bcm2835_dma_chan_reset(ch);
+ }
+ if (value & BCM2708_DMA_ABORT) {
+ /* abort is a no-op, since we always run to completion */
+ }
+ if (value & BCM2708_DMA_END) {
+ ch->cs &= ~BCM2708_DMA_END;
+ }
+ if (value & BCM2708_DMA_INT) {
+ ch->cs &= ~BCM2708_DMA_INT;
+ s->int_status &= ~(1 << c);
+ qemu_set_irq(ch->irq, 0);
+ }
+ ch->cs &= ~BCM2708_DMA_CS_RW_MASK;
+ ch->cs |= (value & BCM2708_DMA_CS_RW_MASK);
+ if (!(oldcs & BCM2708_DMA_ACTIVE) && (ch->cs & BCM2708_DMA_ACTIVE)) {
+ bcm2835_dma_update(s, c);
+ }
+ break;
+ case BCM2708_DMA_ADDR:
+ ch->conblk_ad = value;
+ break;
+ case BCM2708_DMA_DEBUG:
+ ch->debug = value;
+ break;
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n",
+ __func__, offset);
+ break;
+ }
+}
+
+static uint64_t bcm2835_dma0_read(void *opaque, hwaddr offset, unsigned size)
+{
+ BCM2835DMAState *s = opaque;
+
+ if (offset < 0xf00) {
+ return bcm2835_dma_read(s, (offset & 0xff), size, (offset >> 8) & 0xf);
+ } else {
+ switch (offset) {
+ case BCM2708_DMA_INT_STATUS:
+ return s->int_status;
+ case BCM2708_DMA_ENABLE:
+ return s->enable;
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n",
+ __func__, offset);
+ return 0;
+ }
+ }
+}
+
+static uint64_t bcm2835_dma15_read(void *opaque, hwaddr offset, unsigned size)
+{
+ return bcm2835_dma_read(opaque, (offset & 0xff), size, 15);
+}
+
+static void bcm2835_dma0_write(void *opaque, hwaddr offset, uint64_t value,
+ unsigned size)
+{
+ BCM2835DMAState *s = opaque;
+
+ if (offset < 0xf00) {
+ bcm2835_dma_write(s, (offset & 0xff), value, size, (offset >> 8) & 0xf);
+ } else {
+ switch (offset) {
+ case BCM2708_DMA_INT_STATUS:
+ break;
+ case BCM2708_DMA_ENABLE:
+ s->enable = (value & 0xffff);
+ break;
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n",
+ __func__, offset);
+ }
+ }
+
+}
+
+static void bcm2835_dma15_write(void *opaque, hwaddr offset, uint64_t value,
+ unsigned size)
+{
+ bcm2835_dma_write(opaque, (offset & 0xff), value, size, 15);
+}
+
+static const MemoryRegionOps bcm2835_dma0_ops = {
+ .read = bcm2835_dma0_read,
+ .write = bcm2835_dma0_write,
+ .endianness = DEVICE_NATIVE_ENDIAN,
+ .valid.min_access_size = 4,
+ .valid.max_access_size = 4,
+};
+
+static const MemoryRegionOps bcm2835_dma15_ops = {
+ .read = bcm2835_dma15_read,
+ .write = bcm2835_dma15_write,
+ .endianness = DEVICE_NATIVE_ENDIAN,
+ .valid.min_access_size = 4,
+ .valid.max_access_size = 4,
+};
+
+static const VMStateDescription vmstate_bcm2835_dma_chan = {
+ .name = TYPE_BCM2835_DMA "-chan",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(cs, BCM2835DMAChan),
+ VMSTATE_UINT32(conblk_ad, BCM2835DMAChan),
+ VMSTATE_UINT32(ti, BCM2835DMAChan),
+ VMSTATE_UINT32(source_ad, BCM2835DMAChan),
+ VMSTATE_UINT32(dest_ad, BCM2835DMAChan),
+ VMSTATE_UINT32(txfr_len, BCM2835DMAChan),
+ VMSTATE_UINT32(stride, BCM2835DMAChan),
+ VMSTATE_UINT32(nextconbk, BCM2835DMAChan),
+ VMSTATE_UINT32(debug, BCM2835DMAChan),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static const VMStateDescription vmstate_bcm2835_dma = {
+ .name = TYPE_BCM2835_DMA,
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_STRUCT_ARRAY(chan, BCM2835DMAState, BCM2835_DMA_NCHANS, 1,
+ vmstate_bcm2835_dma_chan, BCM2835DMAChan),
+ VMSTATE_UINT32(int_status, BCM2835DMAState),
+ VMSTATE_UINT32(enable, BCM2835DMAState),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static void bcm2835_dma_init(Object *obj)
+{
+ BCM2835DMAState *s = BCM2835_DMA(obj);
+ int n;
+
+ /* DMA channels 0-14 occupy a contiguous block of IO memory, along
+ * with the global enable and interrupt status bits. Channel 15
+ * has the same register map, but is mapped at a discontiguous
+ * address in a separate IO block.
+ */
+ memory_region_init_io(&s->iomem0, OBJECT(s), &bcm2835_dma0_ops, s,
+ TYPE_BCM2835_DMA, 0x1000);
+ sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem0);
+
+ memory_region_init_io(&s->iomem15, OBJECT(s), &bcm2835_dma15_ops, s,
+ TYPE_BCM2835_DMA "-chan15", 0x100);
+ sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem15);
+
+ for (n = 0; n < 16; n++) {
+ sysbus_init_irq(SYS_BUS_DEVICE(s), &s->chan[n].irq);
+ }
+}
+
+static void bcm2835_dma_reset(DeviceState *dev)
+{
+ BCM2835DMAState *s = BCM2835_DMA(dev);
+ int n;
+
+ s->enable = 0xffff;
+ s->int_status = 0;
+ for (n = 0; n < BCM2835_DMA_NCHANS; n++) {
+ bcm2835_dma_chan_reset(&s->chan[n]);
+ }
+}
+
+static void bcm2835_dma_realize(DeviceState *dev, Error **errp)
+{
+ BCM2835DMAState *s = BCM2835_DMA(dev);
+ Error *err = NULL;
+ Object *obj;
+
+ obj = object_property_get_link(OBJECT(dev), "dma-mr", &err);
+ if (obj == NULL) {
+ error_setg(errp, "%s: required dma-mr link not found: %s",
+ __func__, error_get_pretty(err));
+ return;
+ }
+
+ s->dma_mr = MEMORY_REGION(obj);
+ address_space_init(&s->dma_as, s->dma_mr, NULL);
+
+ bcm2835_dma_reset(dev);
+}
+
+static void bcm2835_dma_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ dc->realize = bcm2835_dma_realize;
+ dc->reset = bcm2835_dma_reset;
+ dc->vmsd = &vmstate_bcm2835_dma;
+}
+
+static TypeInfo bcm2835_dma_info = {
+ .name = TYPE_BCM2835_DMA,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(BCM2835DMAState),
+ .class_init = bcm2835_dma_class_init,
+ .instance_init = bcm2835_dma_init,
+};
+
+static void bcm2835_dma_register_types(void)
+{
+ type_register_static(&bcm2835_dma_info);
+}
+
+type_init(bcm2835_dma_register_types)
diff --git a/include/hw/arm/bcm2835_peripherals.h b/include/hw/arm/bcm2835_peripherals.h
index e19d360..e12ae37 100644
--- a/include/hw/arm/bcm2835_peripherals.h
+++ b/include/hw/arm/bcm2835_peripherals.h
@@ -16,6 +16,7 @@
#include "hw/sysbus.h"
#include "hw/char/bcm2835_aux.h"
#include "hw/display/bcm2835_fb.h"
+#include "hw/dma/bcm2835_dma.h"
#include "hw/intc/bcm2835_ic.h"
#include "hw/misc/bcm2835_property.h"
#include "hw/misc/bcm2835_mbox.h"
@@ -37,6 +38,7 @@ typedef struct BCM2835PeripheralState {
SysBusDevice *uart0;
BCM2835AuxState aux;
BCM2835FBState fb;
+ BCM2835DMAState dma;
BCM2835ICState ic;
BCM2835PropertyState property;
BCM2835MboxState mboxes;
diff --git a/include/hw/dma/bcm2835_dma.h b/include/hw/dma/bcm2835_dma.h
new file mode 100644
index 0000000..75312e2
--- /dev/null
+++ b/include/hw/dma/bcm2835_dma.h
@@ -0,0 +1,47 @@
+/*
+ * Raspberry Pi emulation (c) 2012 Gregory Estrade
+ * This code is licensed under the GNU GPLv2 and later.
+ */
+
+#ifndef BCM2835_DMA_H
+#define BCM2835_DMA_H
+
+#include "qemu-common.h"
+#include "exec/address-spaces.h"
+#include "hw/sysbus.h"
+
+typedef struct {
+ uint32_t cs;
+ uint32_t conblk_ad;
+ uint32_t ti;
+ uint32_t source_ad;
+ uint32_t dest_ad;
+ uint32_t txfr_len;
+ uint32_t stride;
+ uint32_t nextconbk;
+ uint32_t debug;
+
+ qemu_irq irq;
+} BCM2835DMAChan;
+
+#define TYPE_BCM2835_DMA "bcm2835-dma"
+#define BCM2835_DMA(obj) \
+ OBJECT_CHECK(BCM2835DMAState, (obj), TYPE_BCM2835_DMA)
+
+#define BCM2835_DMA_NCHANS 16
+
+typedef struct {
+ /*< private >*/
+ SysBusDevice busdev;
+ /*< public >*/
+
+ MemoryRegion iomem0, iomem15;
+ MemoryRegion *dma_mr;
+ AddressSpace dma_as;
+
+ BCM2835DMAChan chan[BCM2835_DMA_NCHANS];
+ uint32_t int_status;
+ uint32_t enable;
+} BCM2835DMAState;
+
+#endif
--
2.7.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [Qemu-devel] [PATCH v3 0/5] Raspberry Pi framebuffer, DMA and Windows support
2016-03-08 20:05 [Qemu-devel] [PATCH v3 0/5] Raspberry Pi framebuffer, DMA and Windows support Andrew Baumann
` (4 preceding siblings ...)
2016-03-08 20:05 ` [Qemu-devel] [PATCH v3 5/5] bcm2835_dma: add emulation of Raspberry Pi DMA controller Andrew Baumann
@ 2016-03-16 15:28 ` Peter Maydell
2016-03-16 16:54 ` Peter Maydell
6 siblings, 0 replies; 11+ messages in thread
From: Peter Maydell @ 2016-03-16 15:28 UTC (permalink / raw)
To: Andrew Baumann
Cc: Grégory ESTRADE, Stefan Weil, Peter Crosthwaite,
QEMU Developers, qemu-arm, Paolo Bonzini
On 8 March 2016 at 20:05, Andrew Baumann <Andrew.Baumann@microsoft.com> wrote:
> This patch series adds support for the AUX (second UART), framebuffer
> and DMA controller on Raspberry Pi 2, and enables booting Windows on
> this device. As with the previous series, it is heavily based on the
> original (out of tree) work of Gregory Estrade, Stefan Weil and others
> to support Raspberry Pi 1.
>
> After this series, it is possible to boot Windows by following the
> instructions at https://github.com/0xabu/qemu/wiki. You also boot
> Raspbian to the GUI using a command such as:
>
> qemu-system-arm -M raspi2 -kernel raspbian-boot/kernel7.img -sd
> 2015-09-24-raspbian-jessie.img -append "rw earlyprintk loglevel=8
> console=ttyAMA0 dwc_otg.lpm_enable=0 root=/dev/mmcblk0p2 rootwait"
> -dtb raspbian-boot/bcm2709-rpi-2-b.dtb -serial stdio
>
> I plan to add USB, and remaining timers / system devices in
> future patch series, along with support for pi1 (bcm2835). In the
> meantime, the complete code is available at https://github.com/0xabu/qemu
Thanks, applied to target-arm.next.
-- PMM
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [Qemu-devel] [PATCH v3 0/5] Raspberry Pi framebuffer, DMA and Windows support
2016-03-08 20:05 [Qemu-devel] [PATCH v3 0/5] Raspberry Pi framebuffer, DMA and Windows support Andrew Baumann
` (5 preceding siblings ...)
2016-03-16 15:28 ` [Qemu-devel] [PATCH v3 0/5] Raspberry Pi framebuffer, DMA and Windows support Peter Maydell
@ 2016-03-16 16:54 ` Peter Maydell
2016-03-16 23:01 ` Andrew Baumann
6 siblings, 1 reply; 11+ messages in thread
From: Peter Maydell @ 2016-03-16 16:54 UTC (permalink / raw)
To: Andrew Baumann
Cc: Grégory ESTRADE, Stefan Weil, Peter Crosthwaite,
QEMU Developers, qemu-arm, Paolo Bonzini
On 8 March 2016 at 20:05, Andrew Baumann <Andrew.Baumann@microsoft.com> wrote:
> This patch series adds support for the AUX (second UART), framebuffer
> and DMA controller on Raspberry Pi 2, and enables booting Windows on
> this device. As with the previous series, it is heavily based on the
> original (out of tree) work of Gregory Estrade, Stefan Weil and others
> to support Raspberry Pi 1.
>
> After this series, it is possible to boot Windows by following the
> instructions at https://github.com/0xabu/qemu/wiki. You also boot
> Raspbian to the GUI using a command such as:
>
> qemu-system-arm -M raspi2 -kernel raspbian-boot/kernel7.img -sd
> 2015-09-24-raspbian-jessie.img -append "rw earlyprintk loglevel=8
> console=ttyAMA0 dwc_otg.lpm_enable=0 root=/dev/mmcblk0p2 rootwait"
> -dtb raspbian-boot/bcm2709-rpi-2-b.dtb -serial stdio
So I tried something like this, and the kernel gives a WARNING with
a backtrace, and then hangs:
[ 5.413943] VFP support v0.3: implementor 41 architecture 4 part 30
variant f rev 0
[ 5.976888] pinctrl core: initialized pinctrl subsystem
[ 6.171197] NET: Registered protocol family 16
[ 6.286799] DMA: preallocated 4096 KiB pool for atomic coherent allocations
[ 6.366889] cpuidle: using governor ladder
[ 6.391665] cpuidle: using governor menu
[ 6.401604] bcm2709.uart_clock = 3000000
[ 6.478063] ------------[ cut here ]------------
[ 6.481052] WARNING: CPU: 0 PID: 1 at
/build/buildd/linux-3.18.0/arch/arm/mach-bcm2709/armctrl.c:148
armctrl_xlate+0x188/0x274()
[ 6.484474] Modules linked in:
[ 6.489783] CPU: 0 PID: 1 Comm: swapper/0 Not tainted
3.18.0-20-rpi2 #21-Ubuntu
[ 6.502781] [<80016ab0>] (unwind_backtrace) from [<800129d0>]
(show_stack+0x10/0x14)
[ 6.506355] [<800129d0>] (show_stack) from [<805fee10>]
(dump_stack+0x9c/0xd4)
[ 6.508946] [<805fee10>] (dump_stack) from [<80026ed8>]
(warn_slowpath_common+0x70/0x8c)
[ 6.511251] [<80026ed8>] (warn_slowpath_common) from [<80026f90>]
(warn_slowpath_null+0x1c/0x24)
[ 6.512797] [<80026f90>] (warn_slowpath_null) from [<80022044>]
(armctrl_xlate+0x188/0x274)
[ 6.514558] [<80022044>] (armctrl_xlate) from [<8007399c>]
(irq_create_of_mapping+0x64/0x110)
[ 6.517173] [<8007399c>] (irq_create_of_mapping) from [<804c4ef4>]
(irq_of_parse_and_map+0x24/0x2c)
[ 6.518741] [<804c4ef4>] (irq_of_parse_and_map) from [<804c4f14>]
(of_irq_to_resource+0x18/0xb8)
[ 6.520209] [<804c4f14>] (of_irq_to_resource) from [<804c4ff0>]
(of_irq_to_resource_table+0x3c/0x54)
[ 6.523598] [<804c4ff0>] (of_irq_to_resource_table) from
[<804c25b8>] (of_device_alloc+0xd8/0x180)
[ 6.528838] [<804c25b8>] (of_device_alloc) from [<804c26a8>]
(of_platform_device_create_pdata+0x48/0x98)
[ 6.535352] [<804c26a8>] (of_platform_device_create_pdata) from
[<804c27f0>] (of_platform_bus_create+0xec/0x3ac)
[ 6.539440] [<804c27f0>] (of_platform_bus_create) from [<804c2860>]
(of_platform_bus_create+0x15c/0x3ac)
[ 6.541217] [<804c2860>] (of_platform_bus_create) from [<804c2c28>]
(of_platform_populate+0x5c/0xa0)
[ 6.542770] [<804c2c28>] (of_platform_populate) from [<8088cad8>]
(bcm2709_init+0x64/0x3fc)
[ 6.546211] [<8088cad8>] (bcm2709_init) from [<80888870>]
(customize_machine+0x20/0x40)
[ 6.547711] [<80888870>] (customize_machine) from [<800088bc>]
(do_one_initcall+0xd8/0x208)
[ 6.549200] [<800088bc>] (do_one_initcall) from [<80885ef4>]
(kernel_init_freeable+0x1fc/0x29c)
[ 6.551771] [<80885ef4>] (kernel_init_freeable) from [<805f9298>]
(kernel_init+0x8/0xf0)
[ 6.553319] [<805f9298>] (kernel_init) from [<8000efe8>]
(ret_from_fork+0x14/0x2c)
[ 6.556670] ---[ end trace 088ba587f0a009cc ]---
[ 6.649948] No ATAGs?
[ 6.658029] hw-breakpoint: found 5 (+1 reserved) breakpoint and 4
watchpoint registers.
[ 6.660393] hw-breakpoint: maximum watchpoint size is 8 bytes.
[ 6.664206] mailbox: Broadcom VideoCore Mailbox driver
[ 6.693912] bcm2708_vcio: mailbox at f300b880
[ 6.703745] bcm_power: Broadcom power driver
[ 6.707642] bcm_power_open() -> 0
[ 6.708671] bcm_power_request(0, 8)
Does that look familiar? (My first guess is just that it wants some
bit of hardware we haven't got a device model for yet. I haven't
tried to investigate at all yet.)
thanks
-- PMM
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [Qemu-devel] [PATCH v3 0/5] Raspberry Pi framebuffer, DMA and Windows support
2016-03-16 16:54 ` Peter Maydell
@ 2016-03-16 23:01 ` Andrew Baumann
2016-03-17 8:48 ` Peter Maydell
2016-03-17 8:54 ` Gerd Hoffmann
0 siblings, 2 replies; 11+ messages in thread
From: Andrew Baumann @ 2016-03-16 23:01 UTC (permalink / raw)
To: Peter Maydell
Cc: Grégory ESTRADE, Stefan Weil, Peter Crosthwaite,
QEMU Developers, qemu-arm, Paolo Bonzini
> From: Peter Maydell [mailto:peter.maydell@linaro.org]
> Sent: Wednesday, 16 March 2016 9:54 AM
>
> On 8 March 2016 at 20:05, Andrew Baumann
> <Andrew.Baumann@microsoft.com> wrote:
> > This patch series adds support for the AUX (second UART), framebuffer
> > and DMA controller on Raspberry Pi 2, and enables booting Windows on
> > this device. As with the previous series, it is heavily based on the
> > original (out of tree) work of Gregory Estrade, Stefan Weil and others
> > to support Raspberry Pi 1.
> >
> > After this series, it is possible to boot Windows by following the
> > instructions at https://github.com/0xabu/qemu/wiki. You also boot
> > Raspbian to the GUI using a command such as:
> >
> > qemu-system-arm -M raspi2 -kernel raspbian-boot/kernel7.img -sd
> > 2015-09-24-raspbian-jessie.img -append "rw earlyprintk loglevel=8
> > console=ttyAMA0 dwc_otg.lpm_enable=0 root=/dev/mmcblk0p2
> rootwait"
> > -dtb raspbian-boot/bcm2709-rpi-2-b.dtb -serial stdio
>
> So I tried something like this, and the kernel gives a WARNING with
> a backtrace, and then hangs:
>
> [ 5.413943] VFP support v0.3: implementor 41 architecture 4 part 30
> variant f rev 0
> [ 5.976888] pinctrl core: initialized pinctrl subsystem
> [ 6.171197] NET: Registered protocol family 16
> [ 6.286799] DMA: preallocated 4096 KiB pool for atomic coherent allocations
> [ 6.366889] cpuidle: using governor ladder
> [ 6.391665] cpuidle: using governor menu
> [ 6.401604] bcm2709.uart_clock = 3000000
> [ 6.478063] ------------[ cut here ]------------
> [ 6.481052] WARNING: CPU: 0 PID: 1 at
> /build/buildd/linux-3.18.0/arch/arm/mach-bcm2709/armctrl.c:148
> armctrl_xlate+0x188/0x274()
> [ 6.484474] Modules linked in:
> [ 6.489783] CPU: 0 PID: 1 Comm: swapper/0 Not tainted
> 3.18.0-20-rpi2 #21-Ubuntu
> [ 6.502781] [<80016ab0>] (unwind_backtrace) from [<800129d0>]
> (show_stack+0x10/0x14)
> [ 6.506355] [<800129d0>] (show_stack) from [<805fee10>]
> (dump_stack+0x9c/0xd4)
> [ 6.508946] [<805fee10>] (dump_stack) from [<80026ed8>]
> (warn_slowpath_common+0x70/0x8c)
> [ 6.511251] [<80026ed8>] (warn_slowpath_common) from [<80026f90>]
> (warn_slowpath_null+0x1c/0x24)
> [ 6.512797] [<80026f90>] (warn_slowpath_null) from [<80022044>]
> (armctrl_xlate+0x188/0x274)
> [ 6.514558] [<80022044>] (armctrl_xlate) from [<8007399c>]
> (irq_create_of_mapping+0x64/0x110)
> [ 6.517173] [<8007399c>] (irq_create_of_mapping) from [<804c4ef4>]
> (irq_of_parse_and_map+0x24/0x2c)
> [ 6.518741] [<804c4ef4>] (irq_of_parse_and_map) from [<804c4f14>]
> (of_irq_to_resource+0x18/0xb8)
> [ 6.520209] [<804c4f14>] (of_irq_to_resource) from [<804c4ff0>]
> (of_irq_to_resource_table+0x3c/0x54)
> [ 6.523598] [<804c4ff0>] (of_irq_to_resource_table) from
> [<804c25b8>] (of_device_alloc+0xd8/0x180)
> [ 6.528838] [<804c25b8>] (of_device_alloc) from [<804c26a8>]
> (of_platform_device_create_pdata+0x48/0x98)
> [ 6.535352] [<804c26a8>] (of_platform_device_create_pdata) from
> [<804c27f0>] (of_platform_bus_create+0xec/0x3ac)
> [ 6.539440] [<804c27f0>] (of_platform_bus_create) from [<804c2860>]
> (of_platform_bus_create+0x15c/0x3ac)
> [ 6.541217] [<804c2860>] (of_platform_bus_create) from [<804c2c28>]
> (of_platform_populate+0x5c/0xa0)
> [ 6.542770] [<804c2c28>] (of_platform_populate) from [<8088cad8>]
> (bcm2709_init+0x64/0x3fc)
> [ 6.546211] [<8088cad8>] (bcm2709_init) from [<80888870>]
> (customize_machine+0x20/0x40)
> [ 6.547711] [<80888870>] (customize_machine) from [<800088bc>]
> (do_one_initcall+0xd8/0x208)
> [ 6.549200] [<800088bc>] (do_one_initcall) from [<80885ef4>]
> (kernel_init_freeable+0x1fc/0x29c)
> [ 6.551771] [<80885ef4>] (kernel_init_freeable) from [<805f9298>]
> (kernel_init+0x8/0xf0)
> [ 6.553319] [<805f9298>] (kernel_init) from [<8000efe8>]
> (ret_from_fork+0x14/0x2c)
> [ 6.556670] ---[ end trace 088ba587f0a009cc ]---
> [ 6.649948] No ATAGs?
> [ 6.658029] hw-breakpoint: found 5 (+1 reserved) breakpoint and 4
> watchpoint registers.
> [ 6.660393] hw-breakpoint: maximum watchpoint size is 8 bytes.
> [ 6.664206] mailbox: Broadcom VideoCore Mailbox driver
> [ 6.693912] bcm2708_vcio: mailbox at f300b880
> [ 6.703745] bcm_power: Broadcom power driver
> [ 6.707642] bcm_power_open() -> 0
> [ 6.708671] bcm_power_request(0, 8)
>
> Does that look familiar? (My first guess is just that it wants some
> bit of hardware we haven't got a device model for yet. I haven't
> tried to investigate at all yet.)
I haven't seen that, probably because I was doing all my testing with an older release (2015-09-24). There appear to be two problems. The warning is something related to the interrupt controller, but it's hard to tell exactly what's wrong there because the function in question (armctl_xlate) doesn't appear to do any hardware access. The bcm_power_request wedge should be expected for anything that tries to interact with power management, because we don't model that device yet (the older Pi2 kernels didn't touch it).
However, I don't seem to be able to repro this. What exactly were you booting? On the current Raspbian (2016-02-26-raspbian-jessie-lite), I run into a different bug, with stalled MMC commands:
[ 9.167683] mmc0: command never completed.
[ 9.172133] mmc0:>cmd op 52 arg 0xc00 flags 0x195 - resp 00000000 00000000 00000000 00000000, err 0
[ 9.180379] mmc0: =========== REGISTER DUMP ===========
[ 9.187193] mmc0: SDCMD 0x00008034
[ 9.190113] mmc0: SDARG 0x00000c00
[ 9.192952] mmc0: SDTOUT 0x00f00000
[ 9.196064] mmc0: SDCDIV 0x0000026f
[ 9.199091] mmc0: SDRSP0 0x00000000
[ 9.201915] mmc0: SDRSP1 0x00000000
[ 9.204915] mmc0: SDRSP2 0x00000000
[ 9.207672] mmc0: SDRSP3 0x00000000
[ 9.210453] mmc0: SDHSTS 0x000007f8
[ 9.213612] mmc0: SDVDD 0x00000001
[ 9.216977] mmc0: SDEDM 0x00010800
[ 9.219728] mmc0: SDHCFG 0x0000040a
[ 9.222666] mmc0: SDHBCT 0x00000000
[ 9.228116] mmc0: SDHBLC 0x00000000
[ 9.230866] mmc0: ===========================================
Cheers,
Andrew
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [Qemu-devel] [PATCH v3 0/5] Raspberry Pi framebuffer, DMA and Windows support
2016-03-16 23:01 ` Andrew Baumann
@ 2016-03-17 8:48 ` Peter Maydell
2016-03-17 8:54 ` Gerd Hoffmann
1 sibling, 0 replies; 11+ messages in thread
From: Peter Maydell @ 2016-03-17 8:48 UTC (permalink / raw)
To: Andrew Baumann
Cc: Grégory ESTRADE, Stefan Weil, Peter Crosthwaite,
QEMU Developers, qemu-arm, Paolo Bonzini
On 16 March 2016 at 23:01, Andrew Baumann <Andrew.Baumann@microsoft.com> wrote:
> However, I don't seem to be able to repro this. What exactly were
> you booting?
This was the Ubuntu kernel from the 2015-04-06-ubuntu-trusty.zip
which is linked to from https://wiki.ubuntu.com/ARM/RaspberryPi
thanks
-- PMM
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [Qemu-devel] [PATCH v3 0/5] Raspberry Pi framebuffer, DMA and Windows support
2016-03-16 23:01 ` Andrew Baumann
2016-03-17 8:48 ` Peter Maydell
@ 2016-03-17 8:54 ` Gerd Hoffmann
1 sibling, 0 replies; 11+ messages in thread
From: Gerd Hoffmann @ 2016-03-17 8:54 UTC (permalink / raw)
To: Andrew Baumann
Cc: Peter Maydell, Peter Crosthwaite, Stefan Weil,
Grégory ESTRADE, QEMU Developers, qemu-arm, Paolo Bonzini
Hi,
> [ 9.167683] mmc0: command never completed.
> [ 9.172133] mmc0:>cmd op 52 arg 0xc00 flags 0x195 - resp 00000000 00000000 00000000 00000000, err 0
> [ 9.180379] mmc0: =========== REGISTER DUMP ===========
> [ 9.187193] mmc0: SDCMD 0x00008034
> [ 9.190113] mmc0: SDARG 0x00000c00
> [ 9.192952] mmc0: SDTOUT 0x00f00000
> [ 9.196064] mmc0: SDCDIV 0x0000026f
> [ 9.199091] mmc0: SDRSP0 0x00000000
> [ 9.201915] mmc0: SDRSP1 0x00000000
> [ 9.204915] mmc0: SDRSP2 0x00000000
> [ 9.207672] mmc0: SDRSP3 0x00000000
> [ 9.210453] mmc0: SDHSTS 0x000007f8
> [ 9.213612] mmc0: SDVDD 0x00000001
> [ 9.216977] mmc0: SDEDM 0x00010800
> [ 9.219728] mmc0: SDHCFG 0x0000040a
> [ 9.222666] mmc0: SDHBCT 0x00000000
> [ 9.228116] mmc0: SDHBLC 0x00000000
> [ 9.230866] mmc0: ===========================================
Saw that one too (4.4 kernel).
Also I had to remove the rng from the device tree to come that far in
the first place, otherwise the kernel hangs earlier when trying to
initialize the rng.
cheers,
Gerd
^ permalink raw reply [flat|nested] 11+ messages in thread