Signed-off-by: Steffen Görtz <cont...@steffen-goertz.de> --- hw/arm/nrf51_soc.c | 30 ++++++++++++++++++++++-------- hw/char/nrf51_uart.c | 10 ++++++---- include/hw/char/nrf51_uart.h | 26 ++++++++------------------ 3 files changed, 36 insertions(+), 30 deletions(-)
diff --git a/hw/arm/nrf51_soc.c b/hw/arm/nrf51_soc.c index 175a009e65..bfcacdf447 100644 --- a/hw/arm/nrf51_soc.c +++ b/hw/arm/nrf51_soc.c @@ -35,8 +35,9 @@ #define UART_BASE 0x40002000 #define UART_SIZE 0x1000 +#define UART_INT 2 -#define PAGE_SIZE 0x0400 +#define PAGE_SIZE 1024 struct { @@ -148,7 +149,7 @@ static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp) return; } - /** SRAM **/ + /* SRAM */ memory_region_init_ram(&s->sram, NULL, "nrf51_soc.sram", NRF51VariantAttributes[s->part_variant].ram_size * PAGE_SIZE, &err); if (err) { @@ -157,7 +158,7 @@ static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp) } memory_region_add_subregion(&s->container, SRAM_BASE, &s->sram); - /** FLASH **/ + /* FLASH */ memory_region_init_ram(&s->flash, NULL, "nrf51_soc.flash", NRF51VariantAttributes[s->part_variant].flash_size * PAGE_SIZE, &err); @@ -167,7 +168,7 @@ static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp) } memory_region_add_subregion(&s->container, FLASH_BASE, &s->flash); - /** MCU **/ + /* MCU */ qdev_prop_set_uint32(DEVICE(&s->armv7m), "num-irq", 60); object_property_set_link(OBJECT(&s->armv7m), OBJECT(&s->container), "memory", &err); @@ -184,15 +185,28 @@ static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp) } /* IO space */ - object_property_set_bool(OBJECT(&s->mmio), true, "realized", &error_fatal); + object_property_set_bool(OBJECT(&s->mmio), true, "realized", &err); + if (err) { + error_propagate(errp, err); + return; + } mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->mmio), 0); memory_region_add_subregion_overlap(&s->container, IOMEM_BASE, mr, -1500); + /* UART */ qdev_prop_set_chr(DEVICE(&s->uart), "chardev", serial_hd(0)); - qdev_init_nofail(DEVICE(&s->uart)); -/* sysbus_mmio_map(s, 0, UART_BASE); - sysbus_connect_irq(s, 0, qdev_get_gpio_in(s->nvic, 2)); */ + object_property_set_bool(OBJECT(&s->uart), true, "realized", &err); + if (err) { + error_propagate(errp, err); + return; + } + + mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->uart), 0); + memory_region_add_subregion_overlap(&s->container, UART_BASE, mr, 0); + qdev_connect_gpio_out_named(DEVICE(&s->uart), "irq", 0, + qdev_get_gpio_in(DEVICE(&s->armv7m), UART_INT)); + /* STUB Peripherals */ memory_region_init_io(&s->clock, NULL, &clock_ops, NULL, "nrf51_soc.clock", 0x1000); memory_region_add_subregion_overlap(&s->container, IOMEM_BASE, &s->clock, -1); diff --git a/hw/char/nrf51_uart.c b/hw/char/nrf51_uart.c index 2da97aa0c4..9c9f4a9c3f 100644 --- a/hw/char/nrf51_uart.c +++ b/hw/char/nrf51_uart.c @@ -13,6 +13,8 @@ #include "hw/registerfields.h" #include "hw/char/nrf51_uart.h" +#define NRF51_UART_SIZE 0x1000 + REG32(STARTRX, 0x000) REG32(STOPRX, 0x004) REG32(STARTTX, 0x008) @@ -196,10 +198,10 @@ static void nrf51_uart_init(Object *obj) Nrf51UART *s = NRF51_UART(obj); SysBusDevice *sbd = SYS_BUS_DEVICE(obj); - memory_region_init_io(&s->mmio, obj, &uart_ops, s, - "nrf51_soc.uart", 0x1000); - sysbus_init_mmio(sbd, &s->mmio); - sysbus_init_irq(sbd, &s->irq); + memory_region_init_io(&s->iomem, obj, &uart_ops, s, + "nrf51_soc.uart", NRF51_UART_SIZE); + sysbus_init_mmio(sbd, &s->iomem); + qdev_init_gpio_out_named(DEVICE(s), &s->irq, "irq", 1); } static Property nrf51_uart_properties[] = { diff --git a/include/hw/char/nrf51_uart.h b/include/hw/char/nrf51_uart.h index 758203f1c3..e0769b90fb 100644 --- a/include/hw/char/nrf51_uart.h +++ b/include/hw/char/nrf51_uart.h @@ -6,6 +6,13 @@ * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 or * (at your option) any later version. + * + * QEMU interface: + * + sysbus MMIO regions 0: Memory Region with tasks, events and registers + * to be mapped to the peripherals instance address by the SOC. + * + Named GPIO output "irq": Interrupt line of the peripheral. Must be + * connected to the respective peripheral interrupt line of the NVIC. + * */ #ifndef NRF51_UART_H @@ -21,8 +28,8 @@ typedef struct Nrf51UART { SysBusDevice parent_obj; + MemoryRegion iomem; - MemoryRegion mmio; CharBackend chr; qemu_irq irq; guint watch_tag; @@ -34,21 +41,4 @@ typedef struct Nrf51UART { uint32_t reg[0x1000]; } Nrf51UART; -static inline DeviceState *nrf51_uart_create(hwaddr addr, - qemu_irq irq, - Chardev *chr) -{ - DeviceState *dev; - SysBusDevice *s; - - dev = qdev_create(NULL, "nrf51_soc.uart"); - s = SYS_BUS_DEVICE(dev); - qdev_prop_set_chr(dev, "chardev", chr); - qdev_init_nofail(dev); - sysbus_mmio_map(s, 0, addr); - sysbus_connect_irq(s, 0, irq); - - return dev; -} - #endif -- 2.17.1