All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [RFC 0/8] arm: Changes to Microbit Board and NRF51 SOC
@ 2018-06-27  7:33 Steffen Görtz
  2018-06-27  7:33 ` [Qemu-devel] [RFC 1/8] arm: NRF51/Microbit Memory container and SOC variants Steffen Görtz
                   ` (8 more replies)
  0 siblings, 9 replies; 14+ messages in thread
From: Steffen Görtz @ 2018-06-27  7:33 UTC (permalink / raw)
  To: qemu-devel
  Cc: Stefan Hajnoczi, Joel Stanley, Jim Mussared, Julia Suvorova,
	Steffen Görtz

This is a series of changes to the NRF51 SOC and the microbit board.
The changes can not be posted as patches as the nrf51 is not mergable
yet due to missing cortex-m0/armv6 support.

"arm: Add NRF51 random number generator peripheral" was already
posted to devel and is being discussed in <20180626104943.2756-1-contrib@steffen-goertz.de>

"arm: Add NRF51 SOC non-volatile memory controller" was already 
posted to devel and is being discussed in
<20180626093204.27612-1-contrib@steffen-goertz.de>

Steffen Görtz (8):
  arm: NRF51/Microbit Memory container and SOC variants
  arm: NRF51 Add unimplemented device for MMIO
  arm: NRF51 create UART in-place, error handling
  arm: NRF51 Calculate peripheral id from base address
  arm: Add NRF51 random number generator peripheral
  arm: Add UICR/FICR handling to NRF51 SOC
  arm: Add NRF51 SOC non-volatile memory controller
  arm: Instantiate NVMC in NRF51.

 hw/arm/microbit.c             |   8 +-
 hw/arm/nrf51_soc.c            | 332 ++++++++++++++++++++++++++--------
 hw/char/nrf51_uart.c          |  10 +-
 hw/misc/Makefile.objs         |   1 +
 hw/misc/nrf51_rng.c           | 243 +++++++++++++++++++++++++
 hw/nvram/Makefile.objs        |   1 +
 hw/nvram/nrf51_nvmc.c         | 168 +++++++++++++++++
 include/hw/arm/nrf51_soc.h    |  38 +++-
 include/hw/char/nrf51_uart.h  |  26 +--
 include/hw/misc/nrf51_rng.h   |  73 ++++++++
 include/hw/nvram/nrf51_nvmc.h |  51 ++++++
 11 files changed, 845 insertions(+), 106 deletions(-)
 create mode 100644 hw/misc/nrf51_rng.c
 create mode 100644 hw/nvram/nrf51_nvmc.c
 create mode 100644 include/hw/misc/nrf51_rng.h
 create mode 100644 include/hw/nvram/nrf51_nvmc.h

-- 
2.17.1

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Qemu-devel] [RFC 1/8] arm: NRF51/Microbit Memory container and SOC variants
  2018-06-27  7:33 [Qemu-devel] [RFC 0/8] arm: Changes to Microbit Board and NRF51 SOC Steffen Görtz
@ 2018-06-27  7:33 ` Steffen Görtz
  2018-06-27  9:53   ` Stefan Hajnoczi
  2018-06-27  7:33 ` [Qemu-devel] [RFC 2/8] arm: NRF51 Add unimplemented device for MMIO Steffen Görtz
                   ` (7 subsequent siblings)
  8 siblings, 1 reply; 14+ messages in thread
From: Steffen Görtz @ 2018-06-27  7:33 UTC (permalink / raw)
  To: qemu-devel
  Cc: Stefan Hajnoczi, Joel Stanley, Jim Mussared, Julia Suvorova,
	Steffen Görtz, Peter Maydell, open list:ARM

Signed-off-by: Steffen Görtz <contrib@steffen-goertz.de>
---
 hw/arm/microbit.c          |  8 ++--
 hw/arm/nrf51_soc.c         | 98 +++++++++++++++++++++++++++-----------
 include/hw/arm/nrf51_soc.h | 24 ++++++++--
 3 files changed, 95 insertions(+), 35 deletions(-)

diff --git a/hw/arm/microbit.c b/hw/arm/microbit.c
index b61d0747fe..9deb1a36ca 100644
--- a/hw/arm/microbit.c
+++ b/hw/arm/microbit.c
@@ -10,6 +10,7 @@
 #include "qemu/osdep.h"
 #include "qapi/error.h"
 #include "hw/boards.h"
+#include "hw/arm/arm.h"
 
 #include "hw/arm/nrf51_soc.h"
 
@@ -18,10 +19,11 @@ static void microbit_init(MachineState *machine)
     DeviceState *dev;
 
     dev = qdev_create(NULL, TYPE_NRF51_SOC);
-    if (machine->kernel_filename) {
-        qdev_prop_set_string(dev, "kernel-filename", machine->kernel_filename);
-    }
+    qdev_prop_set_uint32(DEVICE(dev), "VARIANT", NRF51_VARIANT_AA);
     object_property_set_bool(OBJECT(dev), true, "realized", &error_fatal);
+
+    armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename,
+            0x00000000);
 }
 
 static void microbit_machine_init(MachineClass *mc)
diff --git a/hw/arm/nrf51_soc.c b/hw/arm/nrf51_soc.c
index b9f309aa6b..1f7c159edf 100644
--- a/hw/arm/nrf51_soc.c
+++ b/hw/arm/nrf51_soc.c
@@ -22,23 +22,33 @@
 #include "crypto/random.h"
 
 #include "hw/arm/nrf51_soc.h"
-#include "hw/char/nrf51_uart.h"
 
 #define IOMEM_BASE      0x40000000
 #define IOMEM_SIZE      0x20000000
 
 #define FLASH_BASE      0x00000000
-#define FLASH_SIZE      (256 * 1024)
 
 #define FICR_BASE       0x10000000
 #define FICR_SIZE       0x100
 
 #define SRAM_BASE       0x20000000
-#define SRAM_SIZE       (16 * 1024)
 
 #define UART_BASE       0x40002000
 #define UART_SIZE       0x1000
 
+#define PAGE_SIZE       0x0400
+
+
+struct {
+  hwaddr ram_size;
+  hwaddr flash_size;
+} NRF51VariantAttributes[] = {
+        {.ram_size = 16, .flash_size = 256 },
+        {.ram_size = 16, .flash_size = 128 },
+        {.ram_size = 32, .flash_size = 256 },
+};
+
+
 static uint64_t clock_read(void *opaque, hwaddr addr, unsigned int size)
 {
     qemu_log_mask(LOG_UNIMP, "%s: 0x%" HWADDR_PRIx " [%u]\n", __func__, addr, size);
@@ -101,62 +111,93 @@ static const MemoryRegionOps rng_ops = {
     .write = rng_write
 };
 
+static void nrf51_soc_init(Object *obj)
+{
+    NRF51State *s = NRF51_SOC(obj);
+
+    memory_region_init(&s->container, obj, "microbit-container",
+            UINT64_MAX);
+
+    /* TODO: Change to armv6m when cortex-m0 core is available */
+    object_initialize(&s->armv7m, sizeof(s->armv7m), TYPE_ARMV7M);
+    object_property_add_child(obj, "armv7m", OBJECT(&s->armv7m), &error_abort);
+    qdev_set_parent_bus(DEVICE(&s->armv7m), sysbus_get_default());
+    qdev_prop_set_string(DEVICE(&s->armv7m), "cpu-type",
+                         ARM_CPU_TYPE_NAME("cortex-m3"));
+
+    object_initialize(&s->uart, sizeof(s->uart), TYPE_NRF51_UART);
+    object_property_add_child(obj, "uart", OBJECT(&s->uart), &error_abort);
+    qdev_set_parent_bus(DEVICE(&s->uart), sysbus_get_default());
+}
+
 
 static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp)
 {
     NRF51State *s = NRF51_SOC(dev_soc);
     Error *err = NULL;
 
-    /* IO space */
-    create_unimplemented_device("nrf51_soc.io", IOMEM_BASE, IOMEM_SIZE);
-
-    /* FICR */
-    create_unimplemented_device("nrf51_soc.ficr", FICR_BASE, FICR_SIZE);
+    if (!(s->part_variant > NRF51_VARIANT_INVALID
+            && s->part_variant < NRF51_VARIANT_MAX)) {
+        error_setg(errp, "VARIANT not set or invalid");
+        return;
+    }
 
-    MemoryRegion *system_memory = get_system_memory();
-    MemoryRegion *sram = g_new(MemoryRegion, 1);
-    MemoryRegion *flash = g_new(MemoryRegion, 1);
+    memory_region_init_ram(&s->sram, NULL, "nrf51_soc.sram",
+            NRF51VariantAttributes[s->part_variant].ram_size * PAGE_SIZE, &err);
+    if (err) {
+        error_propagate(errp, err);
+        return;
+    }
+    memory_region_add_subregion(&s->container, SRAM_BASE, &s->sram);
 
-    memory_region_init_ram_nomigrate(flash, NULL, "nrf51.flash", FLASH_SIZE,
+    memory_region_init_ram(&s->flash, NULL, "nrf51_soc.flash",
+            NRF51VariantAttributes[s->part_variant].flash_size * PAGE_SIZE,
             &err);
     if (err) {
         error_propagate(errp, err);
         return;
     }
+    memory_region_add_subregion(&s->container, FLASH_BASE, &s->flash);
 
-    vmstate_register_ram_global(flash);
-    memory_region_set_readonly(flash, true);
+    qdev_prop_set_uint32(DEVICE(&s->armv7m), "num-irq", 60);
+    object_property_set_link(OBJECT(&s->armv7m), OBJECT(&s->container),
+                                         "memory", &err);
+    if (err) {
+        error_propagate(errp, err);
+        return;
+    }
 
-    memory_region_add_subregion(system_memory, FLASH_BASE, flash);
 
-    memory_region_init_ram_nomigrate(sram, NULL, "nrf51.sram", SRAM_SIZE,
-            &err);
+    object_property_set_bool(OBJECT(&s->armv7m), true, "realized", &err);
     if (err) {
         error_propagate(errp, err);
         return;
     }
-    vmstate_register_ram_global(sram);
-    memory_region_add_subregion(system_memory, SRAM_BASE, sram);
 
-    /* TODO: implement a cortex m0 and update this */
-    s->nvic = armv7m_init(get_system_memory(), FLASH_SIZE, 96,
-               s->kernel_filename, ARM_CPU_TYPE_NAME("cortex-m3"));
+    /* IO space */
+    create_unimplemented_device("nrf51_soc.io", IOMEM_BASE, IOMEM_SIZE);
+
+    /* FICR */
+    create_unimplemented_device("nrf51_soc.ficr", FICR_BASE, FICR_SIZE);
 
-    s->uart = nrf51_uart_create(UART_BASE, qdev_get_gpio_in(s->nvic, 2),
-                                serial_hd(0));
+    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)); */
 
     memory_region_init_io(&s->clock, NULL, &clock_ops, NULL, "nrf51_soc.clock", 0x1000);
-    memory_region_add_subregion_overlap(get_system_memory(), IOMEM_BASE, &s->clock, -1);
+    memory_region_add_subregion_overlap(&s->container, IOMEM_BASE, &s->clock, -1);
 
     memory_region_init_io(&s->nvmc, NULL, &nvmc_ops, NULL, "nrf51_soc.nvmc", 0x1000);
-    memory_region_add_subregion_overlap(get_system_memory(), 0x4001E000, &s->nvmc, -1);
+    memory_region_add_subregion_overlap(&s->container, 0x4001E000, &s->nvmc, -1);
 
     memory_region_init_io(&s->rng, NULL, &rng_ops, NULL, "nrf51_soc.rng", 0x1000);
-    memory_region_add_subregion_overlap(get_system_memory(), 0x4000D000, &s->rng, -1);
+    memory_region_add_subregion_overlap(&s->container, 0x4000D000, &s->rng, -1);
 }
 
 static Property nrf51_soc_properties[] = {
-    DEFINE_PROP_STRING("kernel-filename", NRF51State, kernel_filename),
+    DEFINE_PROP_INT32("VARIANT", NRF51State, part_variant,
+            NRF51_VARIANT_INVALID),
     DEFINE_PROP_END_OF_LIST(),
 };
 
@@ -172,6 +213,7 @@ static const TypeInfo nrf51_soc_info = {
     .name          = TYPE_NRF51_SOC,
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(NRF51State),
+    .instance_init = nrf51_soc_init,
     .class_init    = nrf51_soc_class_init,
 };
 
diff --git a/include/hw/arm/nrf51_soc.h b/include/hw/arm/nrf51_soc.h
index f81cbbe3ce..c9af9659e9 100644
--- a/include/hw/arm/nrf51_soc.h
+++ b/include/hw/arm/nrf51_soc.h
@@ -12,6 +12,8 @@
 
 #include "qemu/osdep.h"
 #include "hw/sysbus.h"
+#include "hw/arm/armv7m.h"
+#include "hw/char/nrf51_uart.h"
 
 #define TYPE_NRF51_SOC "nrf51-soc"
 #define NRF51_SOC(obj) \
@@ -22,16 +24,30 @@ typedef struct NRF51State {
     SysBusDevice parent_obj;
 
     /*< public >*/
-    char *kernel_filename;
-    DeviceState *nvic;
-    DeviceState *uart;
+    /* TODO: Change to armv6m when cortex-m0 core is available */
+    ARMv7MState armv7m;
 
-    MemoryRegion iomem;
+    Nrf51UART uart;
 
+    MemoryRegion container;
+    MemoryRegion sram;
+    MemoryRegion flash;
+    MemoryRegion iomem;
     MemoryRegion clock;
     MemoryRegion nvmc;
     MemoryRegion rng;
+
+    /* Properties */
+    int32_t part_variant;
 } NRF51State;
 
+typedef enum {
+    NRF51_VARIANT_INVALID = -1,
+    NRF51_VARIANT_AA = 0,
+    NRF51_VARIANT_AB = 1,
+    NRF51_VARIANT_AC = 2,
+    NRF51_VARIANT_MAX = 3
+} NRF51Variants;
+
 #endif
 
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [Qemu-devel] [RFC 2/8] arm: NRF51 Add unimplemented device for MMIO
  2018-06-27  7:33 [Qemu-devel] [RFC 0/8] arm: Changes to Microbit Board and NRF51 SOC Steffen Görtz
  2018-06-27  7:33 ` [Qemu-devel] [RFC 1/8] arm: NRF51/Microbit Memory container and SOC variants Steffen Görtz
@ 2018-06-27  7:33 ` Steffen Görtz
  2018-06-27  7:33 ` [Qemu-devel] [RFC 3/8] arm: NRF51 create UART in-place, error handling Steffen Görtz
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 14+ messages in thread
From: Steffen Görtz @ 2018-06-27  7:33 UTC (permalink / raw)
  To: qemu-devel
  Cc: Stefan Hajnoczi, Joel Stanley, Jim Mussared, Julia Suvorova,
	Steffen Görtz, Peter Maydell, open list:ARM

Signed-off-by: Steffen Görtz <contrib@steffen-goertz.de>
---
 hw/arm/nrf51_soc.c         | 18 +++++++++++++-----
 include/hw/arm/nrf51_soc.h |  4 +++-
 2 files changed, 16 insertions(+), 6 deletions(-)

diff --git a/hw/arm/nrf51_soc.c b/hw/arm/nrf51_soc.c
index 1f7c159edf..175a009e65 100644
--- a/hw/arm/nrf51_soc.c
+++ b/hw/arm/nrf51_soc.c
@@ -48,7 +48,6 @@ struct {
         {.ram_size = 32, .flash_size = 256 },
 };
 
-
 static uint64_t clock_read(void *opaque, hwaddr addr, unsigned int size)
 {
     qemu_log_mask(LOG_UNIMP, "%s: 0x%" HWADDR_PRIx " [%u]\n", __func__, addr, size);
@@ -125,6 +124,12 @@ static void nrf51_soc_init(Object *obj)
     qdev_prop_set_string(DEVICE(&s->armv7m), "cpu-type",
                          ARM_CPU_TYPE_NAME("cortex-m3"));
 
+    object_initialize(&s->mmio, sizeof(s->mmio), TYPE_UNIMPLEMENTED_DEVICE);
+    object_property_add_child(obj, "iomem", OBJECT(&s->mmio), &error_abort);
+    qdev_set_parent_bus(DEVICE(&s->mmio), sysbus_get_default());
+    qdev_prop_set_string(DEVICE(&s->mmio), "name", "nrf51.iomem");
+    qdev_prop_set_uint64(DEVICE(&s->mmio), "size", IOMEM_SIZE);
+
     object_initialize(&s->uart, sizeof(s->uart), TYPE_NRF51_UART);
     object_property_add_child(obj, "uart", OBJECT(&s->uart), &error_abort);
     qdev_set_parent_bus(DEVICE(&s->uart), sysbus_get_default());
@@ -135,6 +140,7 @@ static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp)
 {
     NRF51State *s = NRF51_SOC(dev_soc);
     Error *err = NULL;
+    MemoryRegion *mr = NULL;
 
     if (!(s->part_variant > NRF51_VARIANT_INVALID
             && s->part_variant < NRF51_VARIANT_MAX)) {
@@ -142,6 +148,7 @@ static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp)
         return;
     }
 
+    /** SRAM **/
     memory_region_init_ram(&s->sram, NULL, "nrf51_soc.sram",
             NRF51VariantAttributes[s->part_variant].ram_size * PAGE_SIZE, &err);
     if (err) {
@@ -150,6 +157,7 @@ static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp)
     }
     memory_region_add_subregion(&s->container, SRAM_BASE, &s->sram);
 
+    /** FLASH **/
     memory_region_init_ram(&s->flash, NULL, "nrf51_soc.flash",
             NRF51VariantAttributes[s->part_variant].flash_size * PAGE_SIZE,
             &err);
@@ -159,6 +167,7 @@ static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp)
     }
     memory_region_add_subregion(&s->container, FLASH_BASE, &s->flash);
 
+    /** MCU **/
     qdev_prop_set_uint32(DEVICE(&s->armv7m), "num-irq", 60);
     object_property_set_link(OBJECT(&s->armv7m), OBJECT(&s->container),
                                          "memory", &err);
@@ -175,10 +184,9 @@ static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp)
     }
 
     /* IO space */
-    create_unimplemented_device("nrf51_soc.io", IOMEM_BASE, IOMEM_SIZE);
-
-    /* FICR */
-    create_unimplemented_device("nrf51_soc.ficr", FICR_BASE, FICR_SIZE);
+    object_property_set_bool(OBJECT(&s->mmio), true, "realized", &error_fatal);
+    mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->mmio), 0);
+    memory_region_add_subregion_overlap(&s->container, IOMEM_BASE, mr, -1500);
 
     qdev_prop_set_chr(DEVICE(&s->uart), "chardev", serial_hd(0));
     qdev_init_nofail(DEVICE(&s->uart));
diff --git a/include/hw/arm/nrf51_soc.h b/include/hw/arm/nrf51_soc.h
index c9af9659e9..86bc304b57 100644
--- a/include/hw/arm/nrf51_soc.h
+++ b/include/hw/arm/nrf51_soc.h
@@ -13,8 +13,10 @@
 #include "qemu/osdep.h"
 #include "hw/sysbus.h"
 #include "hw/arm/armv7m.h"
+#include "hw/misc/unimp.h"
 #include "hw/char/nrf51_uart.h"
 
+
 #define TYPE_NRF51_SOC "nrf51-soc"
 #define NRF51_SOC(obj) \
     OBJECT_CHECK(NRF51State, (obj), TYPE_NRF51_SOC)
@@ -27,12 +29,12 @@ typedef struct NRF51State {
     /* TODO: Change to armv6m when cortex-m0 core is available */
     ARMv7MState armv7m;
 
+    UnimplementedDeviceState mmio;
     Nrf51UART uart;
 
     MemoryRegion container;
     MemoryRegion sram;
     MemoryRegion flash;
-    MemoryRegion iomem;
     MemoryRegion clock;
     MemoryRegion nvmc;
     MemoryRegion rng;
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [Qemu-devel] [RFC 3/8] arm: NRF51 create UART in-place, error handling
  2018-06-27  7:33 [Qemu-devel] [RFC 0/8] arm: Changes to Microbit Board and NRF51 SOC Steffen Görtz
  2018-06-27  7:33 ` [Qemu-devel] [RFC 1/8] arm: NRF51/Microbit Memory container and SOC variants Steffen Görtz
  2018-06-27  7:33 ` [Qemu-devel] [RFC 2/8] arm: NRF51 Add unimplemented device for MMIO Steffen Görtz
@ 2018-06-27  7:33 ` Steffen Görtz
  2018-06-27  7:33 ` [Qemu-devel] [RFC 4/8] arm: NRF51 Calculate peripheral id from base address Steffen Görtz
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 14+ messages in thread
From: Steffen Görtz @ 2018-06-27  7:33 UTC (permalink / raw)
  To: qemu-devel
  Cc: Stefan Hajnoczi, Joel Stanley, Jim Mussared, Julia Suvorova,
	Steffen Görtz, Peter Maydell, Paolo Bonzini, open list:ARM

Signed-off-by: Steffen Görtz <contrib@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

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [Qemu-devel] [RFC 4/8] arm: NRF51 Calculate peripheral id from base address
  2018-06-27  7:33 [Qemu-devel] [RFC 0/8] arm: Changes to Microbit Board and NRF51 SOC Steffen Görtz
                   ` (2 preceding siblings ...)
  2018-06-27  7:33 ` [Qemu-devel] [RFC 3/8] arm: NRF51 create UART in-place, error handling Steffen Görtz
@ 2018-06-27  7:33 ` Steffen Görtz
  2018-06-27  7:33 ` [Qemu-devel] [RFC 5/8] arm: Add NRF51 random number generator peripheral Steffen Görtz
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 14+ messages in thread
From: Steffen Görtz @ 2018-06-27  7:33 UTC (permalink / raw)
  To: qemu-devel
  Cc: Stefan Hajnoczi, Joel Stanley, Jim Mussared, Julia Suvorova,
	Steffen Görtz, Peter Maydell, open list:ARM

The base address determines a peripherals id, which identifies its
interrupt line, see NRF51 reference manual section 10 peripheral
interface. This little gem calculates the peripheral id based
on its base address.

Signed-off-by: Steffen Görtz <contrib@steffen-goertz.de>
---
 hw/arm/nrf51_soc.c | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/hw/arm/nrf51_soc.c b/hw/arm/nrf51_soc.c
index bfcacdf447..e93699a4b0 100644
--- a/hw/arm/nrf51_soc.c
+++ b/hw/arm/nrf51_soc.c
@@ -23,8 +23,6 @@
 
 #include "hw/arm/nrf51_soc.h"
 
-#define IOMEM_BASE      0x40000000
-#define IOMEM_SIZE      0x20000000
 
 #define FLASH_BASE      0x00000000
 
@@ -33,12 +31,19 @@
 
 #define SRAM_BASE       0x20000000
 
+#define IOMEM_BASE      0x40000000
+#define IOMEM_SIZE      0x20000000
+
 #define UART_BASE       0x40002000
 #define UART_SIZE       0x1000
 #define UART_INT        2
 
+#define RNG_BASE        0x4000D000
+
 #define PAGE_SIZE       1024
 
+#define BASE_TO_IRQ(base) ((base >> 12) & 0x1F)
+
 
 struct {
   hwaddr ram_size;
@@ -177,7 +182,6 @@ static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp)
         return;
     }
 
-
     object_property_set_bool(OBJECT(&s->armv7m), true, "realized", &err);
     if (err) {
         error_propagate(errp, err);
@@ -204,7 +208,7 @@ static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp)
     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));
+            qdev_get_gpio_in(DEVICE(&s->armv7m), BASE_TO_IRQ(UART_BASE)));
 
     /* STUB Peripherals */
     memory_region_init_io(&s->clock, NULL, &clock_ops, NULL, "nrf51_soc.clock", 0x1000);
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [Qemu-devel] [RFC 5/8] arm: Add NRF51 random number generator peripheral
  2018-06-27  7:33 [Qemu-devel] [RFC 0/8] arm: Changes to Microbit Board and NRF51 SOC Steffen Görtz
                   ` (3 preceding siblings ...)
  2018-06-27  7:33 ` [Qemu-devel] [RFC 4/8] arm: NRF51 Calculate peripheral id from base address Steffen Görtz
@ 2018-06-27  7:33 ` Steffen Görtz
  2018-07-05 16:51   ` Peter Maydell
  2018-06-27  7:33 ` [Qemu-devel] [RFC 6/8] arm: Add UICR/FICR handling to NRF51 SOC Steffen Görtz
                   ` (3 subsequent siblings)
  8 siblings, 1 reply; 14+ messages in thread
From: Steffen Görtz @ 2018-06-27  7:33 UTC (permalink / raw)
  To: qemu-devel
  Cc: Stefan Hajnoczi, Joel Stanley, Jim Mussared, Julia Suvorova,
	Steffen Görtz

Add a model of the NRF51 random number generator peripheral.

Changes since v2:
  - Add missing 'qapi/error.h' for error_abort

Changes since v1:
  - Add implementation access size hints to MemoryRegionOps
  - Fail on error if qcrypto_random_bytes fails
  - Add references to Nrf51 datasheets

Signed-off-by: Steffen Görtz <contrib@steffen-goertz.de>
---
 hw/misc/Makefile.objs       |   1 +
 hw/misc/nrf51_rng.c         | 243 ++++++++++++++++++++++++++++++++++++
 include/hw/misc/nrf51_rng.h |  73 +++++++++++
 3 files changed, 317 insertions(+)
 create mode 100644 hw/misc/nrf51_rng.c
 create mode 100644 include/hw/misc/nrf51_rng.h

diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
index 00e834d0f0..fd8cc97249 100644
--- a/hw/misc/Makefile.objs
+++ b/hw/misc/Makefile.objs
@@ -70,3 +70,4 @@ obj-$(CONFIG_AUX) += auxbus.o
 obj-$(CONFIG_ASPEED_SOC) += aspeed_scu.o aspeed_sdmc.o
 obj-y += mmio_interface.o
 obj-$(CONFIG_MSF2) += msf2-sysreg.o
+obj-$(CONFIG_NRF51_SOC) += nrf51_rng.o
diff --git a/hw/misc/nrf51_rng.c b/hw/misc/nrf51_rng.c
new file mode 100644
index 0000000000..46bdb21850
--- /dev/null
+++ b/hw/misc/nrf51_rng.c
@@ -0,0 +1,243 @@
+/*
+ * nrf51_rng.c
+ *
+ * Copyright 2018 Steffen Görtz <contrib@steffen-goertz.de>
+ *
+ * This code is licensed under the GPL version 2 or later.  See
+ * the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "qapi/error.h"
+#include "hw/misc/nrf51_rng.h"
+#include "crypto/random.h"
+
+#define NRF51_RNG_SIZE         0x1000
+
+#define NRF51_RNG_TASK_START   0x000
+#define NRF51_RNG_TASK_STOP    0x004
+#define NRF51_RNG_EVENT_VALRDY 0x100
+#define NRF51_RNG_REG_SHORTS   0x200
+#define NRF51_RNG_REG_SHORTS_VALRDY_STOP 0
+#define NRF51_RNG_REG_INTEN    0x300
+#define NRF51_RNG_REG_INTEN_VALRDY 0
+#define NRF51_RNG_REG_INTENSET 0x304
+#define NRF51_RNG_REG_INTENCLR 0x308
+#define NRF51_RNG_REG_CONFIG   0x504
+#define NRF51_RNG_REG_CONFIG_DECEN 0
+#define NRF51_RNG_REG_VALUE    0x508
+
+#define NRF51_TRIGGER_TASK 0x01
+#define NRF51_EVENT_CLEAR  0x00
+
+
+static uint64_t rng_read(void *opaque, hwaddr offset, unsigned int size)
+{
+    Nrf51RNGState *s = NRF51_RNG(opaque);
+    uint64_t r = 0;
+
+    switch (offset) {
+    case NRF51_RNG_EVENT_VALRDY:
+        r = s->state.event_valrdy;
+        break;
+    case NRF51_RNG_REG_SHORTS:
+        r = s->state.shortcut_stop_on_valrdy;
+        break;
+    case NRF51_RNG_REG_INTEN:
+    case NRF51_RNG_REG_INTENSET:
+    case NRF51_RNG_REG_INTENCLR:
+        r = s->state.interrupt_enabled;
+        break;
+    case NRF51_RNG_REG_CONFIG:
+        r = s->state.filter_enabled;
+        break;
+    case NRF51_RNG_REG_VALUE:
+        r = s->value;
+        break;
+
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "%s: bad read offset 0x%" HWADDR_PRIx "\n",
+                      __func__, offset);
+    }
+
+    return r;
+}
+
+static int64_t calc_next_timeout(Nrf51RNGState *s)
+{
+    int64_t timeout = qemu_clock_get_us(QEMU_CLOCK_VIRTUAL);
+    if (s->state.filter_enabled) {
+        timeout += s->period_filtered_us;
+    } else {
+        timeout += s->period_unfiltered_us;
+    }
+
+    return timeout;
+}
+
+
+static void rng_update_timer(Nrf51RNGState *s)
+{
+    if (s->state.active) {
+        timer_mod(&s->timer, calc_next_timeout(s));
+    } else {
+        timer_del(&s->timer);
+    }
+}
+
+
+static void rng_write(void *opaque, hwaddr offset,
+                       uint64_t value, unsigned int size)
+{
+    Nrf51RNGState *s = NRF51_RNG(opaque);
+
+    switch (offset) {
+    case NRF51_RNG_TASK_START:
+        if (value == NRF51_TRIGGER_TASK) {
+            s->state.active = 1;
+            rng_update_timer(s);
+        }
+        break;
+    case NRF51_RNG_TASK_STOP:
+        if (value == NRF51_TRIGGER_TASK) {
+            s->state.active = 0;
+            rng_update_timer(s);
+        }
+        break;
+    case NRF51_RNG_EVENT_VALRDY:
+        if (value == NRF51_EVENT_CLEAR) {
+            s->state.event_valrdy = 0;
+            qemu_set_irq(s->eep_valrdy, 0);
+        }
+        break;
+    case NRF51_RNG_REG_SHORTS:
+        s->state.shortcut_stop_on_valrdy =
+                (value & BIT_MASK(NRF51_RNG_REG_SHORTS_VALRDY_STOP)) ? 1 : 0;
+        break;
+    case NRF51_RNG_REG_INTEN:
+        s->state.interrupt_enabled =
+                (value & BIT_MASK(NRF51_RNG_REG_INTEN_VALRDY)) ? 1 : 0;
+        break;
+    case NRF51_RNG_REG_INTENSET:
+        if (value & BIT_MASK(NRF51_RNG_REG_INTEN_VALRDY)) {
+            s->state.interrupt_enabled = 1;
+        }
+        break;
+    case NRF51_RNG_REG_INTENCLR:
+        if (value & BIT_MASK(NRF51_RNG_REG_INTEN_VALRDY)) {
+            s->state.interrupt_enabled = 0;
+        }
+        break;
+    case NRF51_RNG_REG_CONFIG:
+        s->state.filter_enabled =
+                      (value & BIT_MASK(NRF51_RNG_REG_CONFIG_DECEN)) ? 1 : 0;
+        break;
+
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "%s: bad write offset 0x%" HWADDR_PRIx "\n",
+                      __func__, offset);
+    }
+}
+
+static const MemoryRegionOps rng_ops = {
+    .read =  rng_read,
+    .write = rng_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .impl.min_access_size = 4,
+    .impl.max_access_size = 4
+};
+
+static void nrf51_rng_timer_expire(void *opaque)
+{
+    Nrf51RNGState *s = NRF51_RNG(opaque);
+
+    qcrypto_random_bytes(&s->value, 1, &error_abort);
+
+    s->state.event_valrdy = 1;
+    qemu_set_irq(s->eep_valrdy, 1);
+
+    if (s->state.interrupt_enabled) {
+        qemu_irq_pulse(s->irq);
+    }
+
+    if (s->state.shortcut_stop_on_valrdy) {
+        s->state.active = 0;
+    }
+
+    rng_update_timer(s);
+}
+
+static void nrf51_rng_tep_start(void *opaque, int n, int level)
+{
+    Nrf51RNGState *s = NRF51_RNG(opaque);
+
+    if (level) {
+        s->state.active = 1;
+        rng_update_timer(s);
+    }
+}
+
+static void nrf51_rng_tep_stop(void *opaque, int n, int level)
+{
+    Nrf51RNGState *s = NRF51_RNG(opaque);
+
+    if (level) {
+        s->state.active = 0;
+        rng_update_timer(s);
+    }
+}
+
+
+static void nrf51_rng_init(Object *obj)
+{
+    Nrf51RNGState *s = NRF51_RNG(obj);
+    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+
+    memory_region_init_io(&s->mmio, obj, &rng_ops, s,
+            TYPE_NRF51_RNG, NRF51_RNG_SIZE);
+    sysbus_init_mmio(sbd, &s->mmio);
+
+    timer_init_us(&s->timer, QEMU_CLOCK_VIRTUAL, nrf51_rng_timer_expire, s);
+
+    qdev_init_gpio_out_named(DEVICE(s), &s->irq, "irq", 1);
+
+    /* Tasks */
+    qdev_init_gpio_in_named(DEVICE(s), nrf51_rng_tep_start, "tep_start", 1);
+    qdev_init_gpio_in_named(DEVICE(s), nrf51_rng_tep_stop, "tep_stop", 1);
+
+    /* Events */
+    qdev_init_gpio_out_named(DEVICE(s), &s->eep_valrdy, "eep_valrdy", 1);
+}
+
+static Property nrf51_rng_properties[] = {
+    DEFINE_PROP_UINT16("period_unfiltered_us", Nrf51RNGState,
+            period_unfiltered_us, 167),
+    DEFINE_PROP_UINT16("period_filtered_us", Nrf51RNGState,
+            period_filtered_us, 660),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void nrf51_rng_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->props = nrf51_rng_properties;
+}
+
+static const TypeInfo nrf51_rng_info = {
+    .name = TYPE_NRF51_RNG,
+    .parent = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(Nrf51RNGState),
+    .instance_init = nrf51_rng_init,
+    .class_init = nrf51_rng_class_init
+};
+
+static void nrf51_rng_register_types(void)
+{
+    type_register_static(&nrf51_rng_info);
+}
+
+type_init(nrf51_rng_register_types)
diff --git a/include/hw/misc/nrf51_rng.h b/include/hw/misc/nrf51_rng.h
new file mode 100644
index 0000000000..a8f0630a98
--- /dev/null
+++ b/include/hw/misc/nrf51_rng.h
@@ -0,0 +1,73 @@
+/*
+ * nrf51_rng.h
+ *
+ * Copyright 2018 Steffen Görtz <contrib@steffen-goertz.de>
+ *
+ * This code is licensed under the GPL version 2 or later.  See
+ * the COPYING file in the top-level directory.
+ *
+ * See NRF51 reference manual section 21 Random Number Generator
+ * See NRF51 product specification section 8.16 Random Number Generator
+ *
+ * QEMU interface:
+ * + Property "period_unfiltered_us": Time between two biased values in
+ *   microseconds.
+ * + Property "period_filtered_us": Time between two unbiased values in
+ *   microseconds.
+ * + 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 associated peripheral interrupt line of the NVIC.
+ * + Named GPIO output "eep_valrdy": Event set when new random value is ready
+ *   to be read.
+ * + Named GPIO input "tep_start": Task that triggers start of continuous
+ *   generation of random values.
+ * + Named GPIO input "tep_stop": Task that ends continuous generation of
+ *   random values.
+ *
+ * Accuracy of the peripheral model:
+ * + Stochastic properties of different configurations of the random source
+ *   are not modeled.
+ * + Generation of unfiltered and filtered random values take at least the
+ *   average generation time stated in the production specification;
+ *   non-deterministic generation times are not modeled.
+ *
+ */
+#ifndef NRF51_RNG_H
+#define NRF51_RNG_H
+
+#include "hw/sysbus.h"
+#include "qemu/timer.h"
+#define TYPE_NRF51_RNG "nrf51_soc.rng"
+#define NRF51_RNG(obj) OBJECT_CHECK(Nrf51RNGState, (obj), TYPE_NRF51_RNG)
+
+typedef struct Nrf51RNGState {
+    SysBusDevice parent_obj;
+
+    MemoryRegion mmio;
+    qemu_irq irq;
+
+    /* Event End Points */
+    qemu_irq eep_valrdy;
+
+    QEMUTimer timer;
+
+    /* Time between generation of successive unfiltered values in us */
+    uint16_t period_unfiltered_us;
+    /* Time between generation of successive filtered values in us */
+    uint16_t period_filtered_us;
+
+    uint8_t value;
+
+    struct {
+        uint32_t active:1;
+        uint32_t event_valrdy:1;
+        uint32_t shortcut_stop_on_valrdy:1;
+        uint32_t interrupt_enabled:1;
+        uint32_t filter_enabled:1;
+    } state;
+
+} Nrf51RNGState;
+
+
+#endif /* NRF51_RNG_H_ */
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [Qemu-devel] [RFC 6/8] arm: Add UICR/FICR handling to NRF51 SOC
  2018-06-27  7:33 [Qemu-devel] [RFC 0/8] arm: Changes to Microbit Board and NRF51 SOC Steffen Görtz
                   ` (4 preceding siblings ...)
  2018-06-27  7:33 ` [Qemu-devel] [RFC 5/8] arm: Add NRF51 random number generator peripheral Steffen Görtz
@ 2018-06-27  7:33 ` Steffen Görtz
  2018-06-27  9:57   ` Stefan Hajnoczi
  2018-06-27  7:33 ` [Qemu-devel] [RFC 7/8] arm: Add NRF51 SOC non-volatile memory controller Steffen Görtz
                   ` (2 subsequent siblings)
  8 siblings, 1 reply; 14+ messages in thread
From: Steffen Görtz @ 2018-06-27  7:33 UTC (permalink / raw)
  To: qemu-devel
  Cc: Stefan Hajnoczi, Joel Stanley, Jim Mussared, Julia Suvorova,
	Steffen Görtz, Peter Maydell, open list:ARM

This patch maps preallocated user/factory information
configuration registers to the NRF51 SOC.
See NRF51 reference manual section 7 and 8.

Signed-off-by: Steffen Görtz <contrib@steffen-goertz.de>
---
 hw/arm/nrf51_soc.c         | 174 ++++++++++++++++++++++++++++++-------
 include/hw/arm/nrf51_soc.h |   5 +-
 2 files changed, 145 insertions(+), 34 deletions(-)

diff --git a/hw/arm/nrf51_soc.c b/hw/arm/nrf51_soc.c
index e93699a4b0..82e4c2d833 100644
--- a/hw/arm/nrf51_soc.c
+++ b/hw/arm/nrf51_soc.c
@@ -19,7 +19,6 @@
 #include "sysemu/sysemu.h"
 #include "qemu/log.h"
 #include "cpu.h"
-#include "crypto/random.h"
 
 #include "hw/arm/nrf51_soc.h"
 
@@ -29,6 +28,9 @@
 #define FICR_BASE       0x10000000
 #define FICR_SIZE       0x100
 
+#define UICR_BASE       0x10001000
+#define UICR_SIZE       0x100
+
 #define SRAM_BASE       0x20000000
 
 #define IOMEM_BASE      0x40000000
@@ -54,9 +56,118 @@ struct {
         {.ram_size = 32, .flash_size = 256 },
 };
 
+/*
+FICR Registers Assignments
+CODEPAGESIZE      0x010      [4,
+CODESIZE          0x014       5,
+CLENR0            0x028       10,
+PPFC              0x02C       11,
+NUMRAMBLOCK       0x034       13,
+SIZERAMBLOCKS     0x038       14,
+SIZERAMBLOCK[0]   0x038       14,
+SIZERAMBLOCK[1]   0x03C       15,
+SIZERAMBLOCK[2]   0x040       16,
+SIZERAMBLOCK[3]   0x044       17,
+CONFIGID          0x05C       23,
+DEVICEID[0]       0x060       24,
+DEVICEID[1]       0x064       25,
+ER[0]             0x080       32,
+ER[1]             0x084       33,
+ER[2]             0x088       34,
+ER[3]             0x08C       35,
+IR[0]             0x090       36,
+IR[1]             0x094       37,
+IR[2]             0x098       38,
+IR[3]             0x09C       39,
+DEVICEADDRTYPE    0x0A0       40,
+DEVICEADDR[0]     0x0A4       41,
+DEVICEADDR[1]     0x0A8       42,
+OVERRIDEEN        0x0AC       43,
+NRF_1MBIT[0]      0x0B0       44,
+NRF_1MBIT[1]      0x0B4       45,
+NRF_1MBIT[2]      0x0B8       46,
+NRF_1MBIT[3]      0x0BC       47,
+NRF_1MBIT[4]      0x0C0       48,
+BLE_1MBIT[0]      0x0EC       59,
+BLE_1MBIT[1]      0x0F0       60,
+BLE_1MBIT[2]      0x0F4       61,
+BLE_1MBIT[3]      0x0F8       62,
+BLE_1MBIT[4]      0x0FC       63]
+*/
+
+static const uint32_t ficr_content[64] = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+        0xFFFFFFFF, 0x00000400, 0x00000100, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000002,
+        0x00002000, 0x00002000, 0x00002000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+        0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+        0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000003, 0x12345678, 0x9ABCDEF1,
+        0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+        0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+        0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+        0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+        0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+        0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+        0xFFFFFFFF, };
+
+static uint64_t ficr_read(void *opaque, hwaddr offset, unsigned int size)
+{
+    qemu_log_mask(LOG_TRACE, "%s: 0x%" HWADDR_PRIx " [%u]\n",
+            __func__, offset, size);
+
+    if (offset > (ARRAY_SIZE(ficr_content) - size)) {
+        qemu_log_mask(LOG_GUEST_ERROR,
+                "%s: bad read offset 0x%" HWADDR_PRIx "\n", __func__, offset);
+        return 0;
+    }
+
+    return ficr_content[offset >> 2];
+}
+
+static const MemoryRegionOps ficr_ops = {
+    .read = ficr_read,
+    .impl.min_access_size = 4,
+    .impl.max_access_size = 4,
+    .impl.unaligned = false,
+};
+
+static const uint32_t uicr_content[64] = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+        0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+        0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+        0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+        0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+        0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+        0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+        0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+        0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+        0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+        0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+        0xFFFFFFFF, };
+
+static uint64_t uicr_read(void *opaque, hwaddr offset, unsigned int size)
+{
+    qemu_log_mask(LOG_TRACE, "%s: 0x%" HWADDR_PRIx " [%u]\n",
+            __func__, offset, size);
+
+    if (offset > (ARRAY_SIZE(uicr_content) - size)) {
+        qemu_log_mask(LOG_GUEST_ERROR,
+                "%s: bad read offset 0x%" HWADDR_PRIx "\n", __func__, offset);
+        return 0;
+    }
+
+    return uicr_content[offset >> 2];
+}
+
+static const MemoryRegionOps uicr_ops = {
+    .read = uicr_read,
+    .impl.min_access_size = 4,
+    .impl.max_access_size = 4,
+    .impl.unaligned = false,
+};
+
+
 static uint64_t clock_read(void *opaque, hwaddr addr, unsigned int size)
 {
-    qemu_log_mask(LOG_UNIMP, "%s: 0x%" HWADDR_PRIx " [%u]\n", __func__, addr, size);
+    qemu_log_mask(LOG_UNIMP, "%s: 0x%" HWADDR_PRIx " [%u]\n",
+            __func__, addr, size);
     return 1;
 }
 
@@ -88,34 +199,6 @@ static const MemoryRegionOps nvmc_ops = {
     .write = nvmc_write
 };
 
-static uint64_t rng_read(void *opaque, hwaddr addr, unsigned int size)
-{
-    uint64_t r = 0;
-
-    qemu_log_mask(LOG_UNIMP, "%s: 0x%" HWADDR_PRIx " [%u]\n", __func__, addr, size);
-
-    switch (addr) {
-    case 0x508:
-        qcrypto_random_bytes((uint8_t *)&r, 1, NULL);
-        break;
-    default:
-        r = 1;
-        break;
-    }
-    return r;
-}
-
-static void rng_write(void *opaque, hwaddr addr, uint64_t data, unsigned int size)
-{
-    qemu_log_mask(LOG_UNIMP, "%s: 0x%" HWADDR_PRIx " <- 0x%" PRIx64 " [%u]\n", __func__, addr, data, size);
-}
-
-
-static const MemoryRegionOps rng_ops = {
-    .read = rng_read,
-    .write = rng_write
-};
-
 static void nrf51_soc_init(Object *obj)
 {
     NRF51State *s = NRF51_SOC(obj);
@@ -139,6 +222,10 @@ static void nrf51_soc_init(Object *obj)
     object_initialize(&s->uart, sizeof(s->uart), TYPE_NRF51_UART);
     object_property_add_child(obj, "uart", OBJECT(&s->uart), &error_abort);
     qdev_set_parent_bus(DEVICE(&s->uart), sysbus_get_default());
+
+    object_initialize(&s->rng, sizeof(s->rng), TYPE_NRF51_RNG);
+    object_property_add_child(obj, "rng", OBJECT(&s->rng), &error_abort);
+    qdev_set_parent_bus(DEVICE(&s->rng), sysbus_get_default());
 }
 
 
@@ -197,6 +284,18 @@ static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp)
     mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->mmio), 0);
     memory_region_add_subregion_overlap(&s->container, IOMEM_BASE, mr, -1500);
 
+    /* FICR */
+    memory_region_init_io(&s->ficr, NULL, &ficr_ops, NULL, "nrf51_soc.ficr",
+            FICR_SIZE);
+    memory_region_set_readonly(&s->ficr, true);
+    memory_region_add_subregion_overlap(&s->container, FICR_BASE, &s->ficr, 0);
+
+    /* UICR */
+    memory_region_init_io(&s->uicr, NULL, &uicr_ops, NULL, "nrf51_soc.uicr",
+            UICR_SIZE);
+    memory_region_set_readonly(&s->uicr, true);
+    memory_region_add_subregion_overlap(&s->container, UICR_BASE, &s->uicr, 0);
+
     /* UART */
     qdev_prop_set_chr(DEVICE(&s->uart), "chardev", serial_hd(0));
     object_property_set_bool(OBJECT(&s->uart), true, "realized", &err);
@@ -210,15 +309,24 @@ static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp)
     qdev_connect_gpio_out_named(DEVICE(&s->uart), "irq", 0,
             qdev_get_gpio_in(DEVICE(&s->armv7m), BASE_TO_IRQ(UART_BASE)));
 
+    /* RNG */
+    object_property_set_bool(OBJECT(&s->rng), true, "realized", &err);
+    if (err) {
+        error_propagate(errp, err);
+        return;
+    }
+
+    mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->rng), 0);
+    memory_region_add_subregion_overlap(&s->container, RNG_BASE, mr, 0);
+    qdev_connect_gpio_out_named(DEVICE(&s->rng), "irq", 0,
+            qdev_get_gpio_in(DEVICE(&s->armv7m), BASE_TO_IRQ(RNG_BASE)));
+
     /* 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);
 
     memory_region_init_io(&s->nvmc, NULL, &nvmc_ops, NULL, "nrf51_soc.nvmc", 0x1000);
     memory_region_add_subregion_overlap(&s->container, 0x4001E000, &s->nvmc, -1);
-
-    memory_region_init_io(&s->rng, NULL, &rng_ops, NULL, "nrf51_soc.rng", 0x1000);
-    memory_region_add_subregion_overlap(&s->container, 0x4000D000, &s->rng, -1);
 }
 
 static Property nrf51_soc_properties[] = {
diff --git a/include/hw/arm/nrf51_soc.h b/include/hw/arm/nrf51_soc.h
index 86bc304b57..35dd71c3db 100644
--- a/include/hw/arm/nrf51_soc.h
+++ b/include/hw/arm/nrf51_soc.h
@@ -15,6 +15,7 @@
 #include "hw/arm/armv7m.h"
 #include "hw/misc/unimp.h"
 #include "hw/char/nrf51_uart.h"
+#include "hw/misc/nrf51_rng.h"
 
 
 #define TYPE_NRF51_SOC "nrf51-soc"
@@ -31,13 +32,15 @@ typedef struct NRF51State {
 
     UnimplementedDeviceState mmio;
     Nrf51UART uart;
+    Nrf51RNGState rng;
 
     MemoryRegion container;
     MemoryRegion sram;
     MemoryRegion flash;
+    MemoryRegion ficr;
+    MemoryRegion uicr;
     MemoryRegion clock;
     MemoryRegion nvmc;
-    MemoryRegion rng;
 
     /* Properties */
     int32_t part_variant;
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [Qemu-devel] [RFC 7/8] arm: Add NRF51 SOC non-volatile memory controller
  2018-06-27  7:33 [Qemu-devel] [RFC 0/8] arm: Changes to Microbit Board and NRF51 SOC Steffen Görtz
                   ` (5 preceding siblings ...)
  2018-06-27  7:33 ` [Qemu-devel] [RFC 6/8] arm: Add UICR/FICR handling to NRF51 SOC Steffen Görtz
@ 2018-06-27  7:33 ` Steffen Görtz
  2018-06-27  7:33 ` [Qemu-devel] [RFC 8/8] arm: Instantiate NVMC in NRF51 Steffen Görtz
  2018-06-27  9:46 ` [Qemu-devel] [RFC 0/8] arm: Changes to Microbit Board and NRF51 SOC Stefan Hajnoczi
  8 siblings, 0 replies; 14+ messages in thread
From: Steffen Görtz @ 2018-06-27  7:33 UTC (permalink / raw)
  To: qemu-devel
  Cc: Stefan Hajnoczi, Joel Stanley, Jim Mussared, Julia Suvorova,
	Steffen Görtz

Changes since V1:
- Code style changes

Signed-off-by: Steffen Görtz <contrib@steffen-goertz.de>
---
 hw/nvram/Makefile.objs        |   1 +
 hw/nvram/nrf51_nvmc.c         | 168 ++++++++++++++++++++++++++++++++++
 include/hw/nvram/nrf51_nvmc.h |  51 +++++++++++
 3 files changed, 220 insertions(+)
 create mode 100644 hw/nvram/nrf51_nvmc.c
 create mode 100644 include/hw/nvram/nrf51_nvmc.h

diff --git a/hw/nvram/Makefile.objs b/hw/nvram/Makefile.objs
index a912d25391..9edd61e8af 100644
--- a/hw/nvram/Makefile.objs
+++ b/hw/nvram/Makefile.objs
@@ -5,3 +5,4 @@ common-obj-y += fw_cfg.o
 common-obj-y += chrp_nvram.o
 common-obj-$(CONFIG_MAC_NVRAM) += mac_nvram.o
 obj-$(CONFIG_PSERIES) += spapr_nvram.o
+obj-$(CONFIG_NRF51_SOC) += nrf51_nvmc.o
diff --git a/hw/nvram/nrf51_nvmc.c b/hw/nvram/nrf51_nvmc.c
new file mode 100644
index 0000000000..5dde3088a8
--- /dev/null
+++ b/hw/nvram/nrf51_nvmc.c
@@ -0,0 +1,168 @@
+/*
+ * nrf51_nvmc.c
+ *
+ * Copyright 2018 Steffen Görtz <contrib@steffen-goertz.de>
+ *
+ * This code is licensed under the GPL version 2 or later.  See
+ * the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qemu/log.h"
+#include "hw/nvram/nrf51_nvmc.h"
+#include "exec/address-spaces.h"
+
+#define NRF51_NVMC_SIZE         0x1000
+
+#define NRF51_NVMC_READY        0x400
+#define NRF51_NVMC_READY_READY  0x01
+#define NRF51_NVMC_CONFIG       0x504
+#define NRF51_NVMC_CONFIG_MASK  0x03
+#define NRF51_NVMC_CONFIG_WEN   0x01
+#define NRF51_NVMC_CONFIG_EEN   0x02
+#define NRF51_NVMC_ERASEPCR1    0x508
+#define NRF51_NVMC_ERASEPCR0    0x510
+#define NRF51_NVMC_ERASEALL     0x50C
+#define NRF51_NVMC_ERASEUICR    0x512
+#define NRF51_NVMC_ERASE        0x01
+
+#define NRF51_UICR_OFFSET       0x10001000UL
+#define NRF51_UICR_SIZE         0x100
+
+static uint64_t io_read(void *opaque, hwaddr offset, unsigned int size)
+{
+    Nrf51NVMCState *s = NRF51_NVMC(opaque);
+    uint64_t r = 0;
+
+    switch (offset) {
+    case NRF51_NVMC_READY:
+        r = NRF51_NVMC_READY_READY;
+        break;
+    case NRF51_NVMC_CONFIG:
+        r = s->state.config;
+        break;
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR,
+                "%s: bad read offset 0x%" HWADDR_PRIx "\n", __func__, offset);
+    }
+
+    return r;
+}
+
+static void io_write(void *opaque, hwaddr offset, uint64_t value,
+        unsigned int size)
+{
+    Nrf51NVMCState *s = NRF51_NVMC(opaque);
+
+    switch (offset) {
+    case NRF51_NVMC_CONFIG:
+        s->state.config = value & NRF51_NVMC_CONFIG_MASK;
+        break;
+    case NRF51_NVMC_ERASEPCR0:
+    case NRF51_NVMC_ERASEPCR1:
+        value &= ~(s->page_size - 1);
+        if (value < (s->code_size * s->page_size)) {
+            address_space_write(&s->as, value, MEMTXATTRS_UNSPECIFIED,
+                    s->empty_page, s->page_size);
+        }
+        break;
+    case NRF51_NVMC_ERASEALL:
+        if (value == NRF51_NVMC_ERASE) {
+            for (uint32_t i = 0; i < s->code_size; i++) {
+                address_space_write(&s->as, i * s->page_size,
+                MEMTXATTRS_UNSPECIFIED, s->empty_page, s->page_size);
+            }
+            address_space_write(&s->as, NRF51_UICR_OFFSET,
+            MEMTXATTRS_UNSPECIFIED, s->empty_page, NRF51_UICR_SIZE);
+        }
+        break;
+    case NRF51_NVMC_ERASEUICR:
+        if (value == NRF51_NVMC_ERASE) {
+            address_space_write(&s->as, NRF51_UICR_OFFSET,
+            MEMTXATTRS_UNSPECIFIED, s->empty_page, NRF51_UICR_SIZE);
+        }
+        break;
+
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR,
+                "%s: bad write offset 0x%" HWADDR_PRIx "\n", __func__, offset);
+    }
+}
+
+static const MemoryRegionOps io_ops = {
+        .read = io_read,
+        .write = io_write,
+        .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static void nrf51_nvmc_init(Object *obj)
+{
+    Nrf51NVMCState *s = NRF51_NVMC(obj);
+    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+
+    memory_region_init_io(&s->mmio, obj, &io_ops, s,
+                          TYPE_NRF51_NVMC, NRF51_NVMC_SIZE);
+    sysbus_init_mmio(sbd, &s->mmio);
+}
+
+static void nrf51_nvmc_realize(DeviceState *dev, Error **errp)
+{
+    Nrf51NVMCState *s = NRF51_NVMC(dev);
+
+    if (!s->mr) {
+        error_setg(errp, "memory property was not set");
+        return;
+    }
+
+    if (s->page_size < NRF51_UICR_SIZE) {
+        error_setg(errp, "page size too small");
+        return;
+    }
+
+    s->empty_page = g_malloc(s->page_size);
+    memset(s->empty_page, 0xFF, s->page_size);
+
+    address_space_init(&s->as, s->mr, "system-memory");
+}
+
+static void nrf51_nvmc_unrealize(DeviceState *dev, Error **errp)
+{
+    Nrf51NVMCState *s = NRF51_NVMC(dev);
+
+    g_free(s->empty_page);
+    s->empty_page = NULL;
+
+}
+
+static Property nrf51_nvmc_properties[] = {
+    DEFINE_PROP_UINT16("page_size", Nrf51NVMCState, page_size, 0x400),
+    DEFINE_PROP_UINT32("code_size", Nrf51NVMCState, code_size, 0x100),
+    DEFINE_PROP_LINK("memory", Nrf51NVMCState, mr, TYPE_MEMORY_REGION,
+                     MemoryRegion *),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void nrf51_nvmc_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->props = nrf51_nvmc_properties;
+    dc->realize = nrf51_nvmc_realize;
+    dc->unrealize = nrf51_nvmc_unrealize;
+}
+
+static const TypeInfo nrf51_nvmc_info = {
+    .name = TYPE_NRF51_NVMC,
+    .parent = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(Nrf51NVMCState),
+    .instance_init = nrf51_nvmc_init,
+    .class_init = nrf51_nvmc_class_init
+};
+
+static void nrf51_nvmc_register_types(void)
+{
+    type_register_static(&nrf51_nvmc_info);
+}
+
+type_init(nrf51_nvmc_register_types)
diff --git a/include/hw/nvram/nrf51_nvmc.h b/include/hw/nvram/nrf51_nvmc.h
new file mode 100644
index 0000000000..3a63b7e5ad
--- /dev/null
+++ b/include/hw/nvram/nrf51_nvmc.h
@@ -0,0 +1,51 @@
+/*
+ * nrf51_nvmc.h
+ *
+ * Copyright 2018 Steffen Görtz <contrib@steffen-goertz.de>
+ *
+ * This code is licensed under the GPL version 2 or later.  See
+ * the COPYING file in the top-level directory.
+ *
+ * See Nrf51 reference manual 6 Non-Volatile Memory Controller (NVMC)
+ * See Nrf51 product sheet 8.22 NVMC specifications
+ *
+ * QEMU interface:
+ * + sysbus MMIO regions 0: Memory Region with registers
+ *   to be mapped to the peripherals instance address by the SOC.
+ * + page_size property to set the page size in bytes.
+ * + code_size property to set the code size in number of pages.
+ *
+ * Accuracy of the peripheral model:
+ * + The NVMC is always ready, all requested erase operations succeed
+ *   immediately.
+ * + CONFIG.WEN and CONFIG.EEN flags can be written and read back
+ *   but are not evaluated to check whether a requested write/erase operation
+ *   is legal.
+ * + Code regions (MPU configuration) are disregarded.
+ */
+#ifndef NRF51_NVMC_H
+#define NRF51_NVMC_H
+
+#include "hw/sysbus.h"
+#define TYPE_NRF51_NVMC "nrf51_soc.nvmc"
+#define NRF51_NVMC(obj) OBJECT_CHECK(Nrf51NVMCState, (obj), TYPE_NRF51_NVMC)
+
+typedef struct Nrf51NVMCState {
+    SysBusDevice parent_obj;
+
+    MemoryRegion mmio;
+
+    uint32_t code_size;
+    uint16_t page_size;
+    uint8_t *empty_page;
+    MemoryRegion *mr;
+    AddressSpace as;
+
+    struct {
+        uint32_t config:2;
+    } state;
+
+} Nrf51NVMCState;
+
+
+#endif
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [Qemu-devel] [RFC 8/8] arm: Instantiate NVMC in NRF51.
  2018-06-27  7:33 [Qemu-devel] [RFC 0/8] arm: Changes to Microbit Board and NRF51 SOC Steffen Görtz
                   ` (6 preceding siblings ...)
  2018-06-27  7:33 ` [Qemu-devel] [RFC 7/8] arm: Add NRF51 SOC non-volatile memory controller Steffen Görtz
@ 2018-06-27  7:33 ` Steffen Görtz
  2018-06-27  9:46 ` [Qemu-devel] [RFC 0/8] arm: Changes to Microbit Board and NRF51 SOC Stefan Hajnoczi
  8 siblings, 0 replies; 14+ messages in thread
From: Steffen Görtz @ 2018-06-27  7:33 UTC (permalink / raw)
  To: qemu-devel
  Cc: Stefan Hajnoczi, Joel Stanley, Jim Mussared, Julia Suvorova,
	Steffen Görtz, Peter Maydell, open list:ARM

Signed-off-by: Steffen Görtz <contrib@steffen-goertz.de>
---
 hw/arm/nrf51_soc.c         | 50 +++++++++++++++++++++++---------------
 include/hw/arm/nrf51_soc.h |  3 ++-
 2 files changed, 32 insertions(+), 21 deletions(-)

diff --git a/hw/arm/nrf51_soc.c b/hw/arm/nrf51_soc.c
index 82e4c2d833..9ff622b792 100644
--- a/hw/arm/nrf51_soc.c
+++ b/hw/arm/nrf51_soc.c
@@ -40,6 +40,9 @@
 #define UART_SIZE       0x1000
 #define UART_INT        2
 
+#define NVMC_BASE       0x4001E000
+#define NVMC_SIZE       0x1000
+
 #define RNG_BASE        0x4000D000
 
 #define PAGE_SIZE       1024
@@ -182,23 +185,6 @@ static const MemoryRegionOps clock_ops = {
     .write = clock_write
 };
 
-static uint64_t nvmc_read(void *opaque, hwaddr addr, unsigned int size)
-{
-    qemu_log_mask(LOG_TRACE, "%s: 0x%" HWADDR_PRIx " [%u]\n", __func__, addr, size);
-    return 1;
-}
-
-static void nvmc_write(void *opaque, hwaddr addr, uint64_t data, unsigned int size)
-{
-    qemu_log_mask(LOG_TRACE, "%s: 0x%" HWADDR_PRIx " <- 0x%" PRIx64 " [%u]\n", __func__, addr, data, size);
-}
-
-
-static const MemoryRegionOps nvmc_ops = {
-    .read = nvmc_read,
-    .write = nvmc_write
-};
-
 static void nrf51_soc_init(Object *obj)
 {
     NRF51State *s = NRF51_SOC(obj);
@@ -223,6 +209,10 @@ static void nrf51_soc_init(Object *obj)
     object_property_add_child(obj, "uart", OBJECT(&s->uart), &error_abort);
     qdev_set_parent_bus(DEVICE(&s->uart), sysbus_get_default());
 
+    object_initialize(&s->nvmc, sizeof(s->nvmc), TYPE_NRF51_NVMC);
+    object_property_add_child(obj, "nvmc", OBJECT(&s->nvmc), &error_abort);
+    qdev_set_parent_bus(DEVICE(&s->nvmc), sysbus_get_default());
+
     object_initialize(&s->rng, sizeof(s->rng), TYPE_NRF51_RNG);
     object_property_add_child(obj, "rng", OBJECT(&s->rng), &error_abort);
     qdev_set_parent_bus(DEVICE(&s->rng), sysbus_get_default());
@@ -309,6 +299,29 @@ static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp)
     qdev_connect_gpio_out_named(DEVICE(&s->uart), "irq", 0,
             qdev_get_gpio_in(DEVICE(&s->armv7m), BASE_TO_IRQ(UART_BASE)));
 
+    /* NVMC */
+    object_property_set_link(OBJECT(&s->nvmc), OBJECT(&s->container),
+                                         "memory", &err);
+    if (err) {
+        error_propagate(errp, err);
+        return;
+    }
+    object_property_set_uint(OBJECT(&s->nvmc),
+            NRF51VariantAttributes[s->part_variant].flash_size, "code_size",
+            &err);
+    if (err) {
+        error_propagate(errp, err);
+        return;
+    }
+    object_property_set_bool(OBJECT(&s->nvmc), true, "realized", &err);
+    if (err) {
+        error_propagate(errp, err);
+        return;
+    }
+
+    mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->nvmc), 0);
+    memory_region_add_subregion_overlap(&s->container, NVMC_BASE, mr, 0);
+
     /* RNG */
     object_property_set_bool(OBJECT(&s->rng), true, "realized", &err);
     if (err) {
@@ -324,9 +337,6 @@ static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp)
     /* 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);
-
-    memory_region_init_io(&s->nvmc, NULL, &nvmc_ops, NULL, "nrf51_soc.nvmc", 0x1000);
-    memory_region_add_subregion_overlap(&s->container, 0x4001E000, &s->nvmc, -1);
 }
 
 static Property nrf51_soc_properties[] = {
diff --git a/include/hw/arm/nrf51_soc.h b/include/hw/arm/nrf51_soc.h
index 35dd71c3db..70d9f5863c 100644
--- a/include/hw/arm/nrf51_soc.h
+++ b/include/hw/arm/nrf51_soc.h
@@ -15,6 +15,7 @@
 #include "hw/arm/armv7m.h"
 #include "hw/misc/unimp.h"
 #include "hw/char/nrf51_uart.h"
+#include "hw/nvram/nrf51_nvmc.h"
 #include "hw/misc/nrf51_rng.h"
 
 
@@ -32,6 +33,7 @@ typedef struct NRF51State {
 
     UnimplementedDeviceState mmio;
     Nrf51UART uart;
+    Nrf51NVMCState nvmc;
     Nrf51RNGState rng;
 
     MemoryRegion container;
@@ -40,7 +42,6 @@ typedef struct NRF51State {
     MemoryRegion ficr;
     MemoryRegion uicr;
     MemoryRegion clock;
-    MemoryRegion nvmc;
 
     /* Properties */
     int32_t part_variant;
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [Qemu-devel] [RFC 0/8] arm: Changes to Microbit Board and NRF51 SOC
  2018-06-27  7:33 [Qemu-devel] [RFC 0/8] arm: Changes to Microbit Board and NRF51 SOC Steffen Görtz
                   ` (7 preceding siblings ...)
  2018-06-27  7:33 ` [Qemu-devel] [RFC 8/8] arm: Instantiate NVMC in NRF51 Steffen Görtz
@ 2018-06-27  9:46 ` Stefan Hajnoczi
  8 siblings, 0 replies; 14+ messages in thread
From: Stefan Hajnoczi @ 2018-06-27  9:46 UTC (permalink / raw)
  To: Steffen Görtz; +Cc: qemu-devel, Joel Stanley, Jim Mussared, Julia Suvorova

[-- Attachment #1: Type: text/plain, Size: 634 bytes --]

On Wed, Jun 27, 2018 at 09:33:43AM +0200, Steffen Görtz wrote:
> This is a series of changes to the NRF51 SOC and the microbit board.
> The changes can not be posted as patches as the nrf51 is not mergable
> yet due to missing cortex-m0/armv6 support.
> 
> "arm: Add NRF51 random number generator peripheral" was already
> posted to devel and is being discussed in <20180626104943.2756-1-contrib@steffen-goertz.de>
> 
> "arm: Add NRF51 SOC non-volatile memory controller" was already 
> posted to devel and is being discussed in
> <20180626093204.27612-1-contrib@steffen-goertz.de>

Which tree does this series apply to?

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 455 bytes --]

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [Qemu-devel] [RFC 1/8] arm: NRF51/Microbit Memory container and SOC variants
  2018-06-27  7:33 ` [Qemu-devel] [RFC 1/8] arm: NRF51/Microbit Memory container and SOC variants Steffen Görtz
@ 2018-06-27  9:53   ` Stefan Hajnoczi
  0 siblings, 0 replies; 14+ messages in thread
From: Stefan Hajnoczi @ 2018-06-27  9:53 UTC (permalink / raw)
  To: Steffen Görtz
  Cc: qemu-devel, Joel Stanley, Jim Mussared, Julia Suvorova,
	Peter Maydell, open list:ARM

[-- Attachment #1: Type: text/plain, Size: 9647 bytes --]

On Wed, Jun 27, 2018 at 09:33:44AM +0200, Steffen Görtz wrote:

This looks like code that can be squashed into to Joel's 'microbit'
machine type series.  Please agree with Joel how to include this in his
upcoming v2 patch series.

There are several things going on here and the patch could be split into
several commits with commit descriptions that explain the rationale,
making it easier to review.  But if Joel is happy to work this into his
code as-is then there's no need to worry about structuring this patch
right now.

> Signed-off-by: Steffen Görtz <contrib@steffen-goertz.de>
> ---
>  hw/arm/microbit.c          |  8 ++--
>  hw/arm/nrf51_soc.c         | 98 +++++++++++++++++++++++++++-----------
>  include/hw/arm/nrf51_soc.h | 24 ++++++++--
>  3 files changed, 95 insertions(+), 35 deletions(-)
> 
> diff --git a/hw/arm/microbit.c b/hw/arm/microbit.c
> index b61d0747fe..9deb1a36ca 100644
> --- a/hw/arm/microbit.c
> +++ b/hw/arm/microbit.c
> @@ -10,6 +10,7 @@
>  #include "qemu/osdep.h"
>  #include "qapi/error.h"
>  #include "hw/boards.h"
> +#include "hw/arm/arm.h"
>  
>  #include "hw/arm/nrf51_soc.h"
>  
> @@ -18,10 +19,11 @@ static void microbit_init(MachineState *machine)
>      DeviceState *dev;
>  
>      dev = qdev_create(NULL, TYPE_NRF51_SOC);
> -    if (machine->kernel_filename) {
> -        qdev_prop_set_string(dev, "kernel-filename", machine->kernel_filename);
> -    }
> +    qdev_prop_set_uint32(DEVICE(dev), "VARIANT", NRF51_VARIANT_AA);
>      object_property_set_bool(OBJECT(dev), true, "realized", &error_fatal);
> +
> +    armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename,
> +            0x00000000);
>  }
>  
>  static void microbit_machine_init(MachineClass *mc)
> diff --git a/hw/arm/nrf51_soc.c b/hw/arm/nrf51_soc.c
> index b9f309aa6b..1f7c159edf 100644
> --- a/hw/arm/nrf51_soc.c
> +++ b/hw/arm/nrf51_soc.c
> @@ -22,23 +22,33 @@
>  #include "crypto/random.h"
>  
>  #include "hw/arm/nrf51_soc.h"
> -#include "hw/char/nrf51_uart.h"
>  
>  #define IOMEM_BASE      0x40000000
>  #define IOMEM_SIZE      0x20000000
>  
>  #define FLASH_BASE      0x00000000
> -#define FLASH_SIZE      (256 * 1024)
>  
>  #define FICR_BASE       0x10000000
>  #define FICR_SIZE       0x100
>  
>  #define SRAM_BASE       0x20000000
> -#define SRAM_SIZE       (16 * 1024)
>  
>  #define UART_BASE       0x40002000
>  #define UART_SIZE       0x1000
>  
> +#define PAGE_SIZE       0x0400
> +
> +
> +struct {
> +  hwaddr ram_size;
> +  hwaddr flash_size;
> +} NRF51VariantAttributes[] = {
> +        {.ram_size = 16, .flash_size = 256 },
> +        {.ram_size = 16, .flash_size = 128 },
> +        {.ram_size = 32, .flash_size = 256 },
> +};
> +
> +
>  static uint64_t clock_read(void *opaque, hwaddr addr, unsigned int size)
>  {
>      qemu_log_mask(LOG_UNIMP, "%s: 0x%" HWADDR_PRIx " [%u]\n", __func__, addr, size);
> @@ -101,62 +111,93 @@ static const MemoryRegionOps rng_ops = {
>      .write = rng_write
>  };
>  
> +static void nrf51_soc_init(Object *obj)
> +{
> +    NRF51State *s = NRF51_SOC(obj);
> +
> +    memory_region_init(&s->container, obj, "microbit-container",
> +            UINT64_MAX);
> +
> +    /* TODO: Change to armv6m when cortex-m0 core is available */
> +    object_initialize(&s->armv7m, sizeof(s->armv7m), TYPE_ARMV7M);
> +    object_property_add_child(obj, "armv7m", OBJECT(&s->armv7m), &error_abort);
> +    qdev_set_parent_bus(DEVICE(&s->armv7m), sysbus_get_default());
> +    qdev_prop_set_string(DEVICE(&s->armv7m), "cpu-type",
> +                         ARM_CPU_TYPE_NAME("cortex-m3"));
> +
> +    object_initialize(&s->uart, sizeof(s->uart), TYPE_NRF51_UART);
> +    object_property_add_child(obj, "uart", OBJECT(&s->uart), &error_abort);
> +    qdev_set_parent_bus(DEVICE(&s->uart), sysbus_get_default());
> +}
> +
>  
>  static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp)
>  {
>      NRF51State *s = NRF51_SOC(dev_soc);
>      Error *err = NULL;
>  
> -    /* IO space */
> -    create_unimplemented_device("nrf51_soc.io", IOMEM_BASE, IOMEM_SIZE);
> -
> -    /* FICR */
> -    create_unimplemented_device("nrf51_soc.ficr", FICR_BASE, FICR_SIZE);
> +    if (!(s->part_variant > NRF51_VARIANT_INVALID
> +            && s->part_variant < NRF51_VARIANT_MAX)) {
> +        error_setg(errp, "VARIANT not set or invalid");
> +        return;
> +    }
>  
> -    MemoryRegion *system_memory = get_system_memory();
> -    MemoryRegion *sram = g_new(MemoryRegion, 1);
> -    MemoryRegion *flash = g_new(MemoryRegion, 1);
> +    memory_region_init_ram(&s->sram, NULL, "nrf51_soc.sram",
> +            NRF51VariantAttributes[s->part_variant].ram_size * PAGE_SIZE, &err);
> +    if (err) {
> +        error_propagate(errp, err);
> +        return;
> +    }
> +    memory_region_add_subregion(&s->container, SRAM_BASE, &s->sram);
>  
> -    memory_region_init_ram_nomigrate(flash, NULL, "nrf51.flash", FLASH_SIZE,
> +    memory_region_init_ram(&s->flash, NULL, "nrf51_soc.flash",
> +            NRF51VariantAttributes[s->part_variant].flash_size * PAGE_SIZE,
>              &err);
>      if (err) {
>          error_propagate(errp, err);
>          return;
>      }
> +    memory_region_add_subregion(&s->container, FLASH_BASE, &s->flash);
>  
> -    vmstate_register_ram_global(flash);
> -    memory_region_set_readonly(flash, true);
> +    qdev_prop_set_uint32(DEVICE(&s->armv7m), "num-irq", 60);
> +    object_property_set_link(OBJECT(&s->armv7m), OBJECT(&s->container),
> +                                         "memory", &err);
> +    if (err) {
> +        error_propagate(errp, err);
> +        return;
> +    }
>  
> -    memory_region_add_subregion(system_memory, FLASH_BASE, flash);
>  
> -    memory_region_init_ram_nomigrate(sram, NULL, "nrf51.sram", SRAM_SIZE,
> -            &err);
> +    object_property_set_bool(OBJECT(&s->armv7m), true, "realized", &err);
>      if (err) {
>          error_propagate(errp, err);
>          return;
>      }
> -    vmstate_register_ram_global(sram);
> -    memory_region_add_subregion(system_memory, SRAM_BASE, sram);
>  
> -    /* TODO: implement a cortex m0 and update this */
> -    s->nvic = armv7m_init(get_system_memory(), FLASH_SIZE, 96,
> -               s->kernel_filename, ARM_CPU_TYPE_NAME("cortex-m3"));
> +    /* IO space */
> +    create_unimplemented_device("nrf51_soc.io", IOMEM_BASE, IOMEM_SIZE);
> +
> +    /* FICR */
> +    create_unimplemented_device("nrf51_soc.ficr", FICR_BASE, FICR_SIZE);
>  
> -    s->uart = nrf51_uart_create(UART_BASE, qdev_get_gpio_in(s->nvic, 2),
> -                                serial_hd(0));
> +    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)); */
>  
>      memory_region_init_io(&s->clock, NULL, &clock_ops, NULL, "nrf51_soc.clock", 0x1000);
> -    memory_region_add_subregion_overlap(get_system_memory(), IOMEM_BASE, &s->clock, -1);
> +    memory_region_add_subregion_overlap(&s->container, IOMEM_BASE, &s->clock, -1);
>  
>      memory_region_init_io(&s->nvmc, NULL, &nvmc_ops, NULL, "nrf51_soc.nvmc", 0x1000);
> -    memory_region_add_subregion_overlap(get_system_memory(), 0x4001E000, &s->nvmc, -1);
> +    memory_region_add_subregion_overlap(&s->container, 0x4001E000, &s->nvmc, -1);
>  
>      memory_region_init_io(&s->rng, NULL, &rng_ops, NULL, "nrf51_soc.rng", 0x1000);
> -    memory_region_add_subregion_overlap(get_system_memory(), 0x4000D000, &s->rng, -1);
> +    memory_region_add_subregion_overlap(&s->container, 0x4000D000, &s->rng, -1);
>  }
>  
>  static Property nrf51_soc_properties[] = {
> -    DEFINE_PROP_STRING("kernel-filename", NRF51State, kernel_filename),
> +    DEFINE_PROP_INT32("VARIANT", NRF51State, part_variant,
> +            NRF51_VARIANT_INVALID),
>      DEFINE_PROP_END_OF_LIST(),
>  };
>  
> @@ -172,6 +213,7 @@ static const TypeInfo nrf51_soc_info = {
>      .name          = TYPE_NRF51_SOC,
>      .parent        = TYPE_SYS_BUS_DEVICE,
>      .instance_size = sizeof(NRF51State),
> +    .instance_init = nrf51_soc_init,
>      .class_init    = nrf51_soc_class_init,
>  };
>  
> diff --git a/include/hw/arm/nrf51_soc.h b/include/hw/arm/nrf51_soc.h
> index f81cbbe3ce..c9af9659e9 100644
> --- a/include/hw/arm/nrf51_soc.h
> +++ b/include/hw/arm/nrf51_soc.h
> @@ -12,6 +12,8 @@
>  
>  #include "qemu/osdep.h"
>  #include "hw/sysbus.h"
> +#include "hw/arm/armv7m.h"
> +#include "hw/char/nrf51_uart.h"
>  
>  #define TYPE_NRF51_SOC "nrf51-soc"
>  #define NRF51_SOC(obj) \
> @@ -22,16 +24,30 @@ typedef struct NRF51State {
>      SysBusDevice parent_obj;
>  
>      /*< public >*/
> -    char *kernel_filename;
> -    DeviceState *nvic;
> -    DeviceState *uart;
> +    /* TODO: Change to armv6m when cortex-m0 core is available */
> +    ARMv7MState armv7m;
>  
> -    MemoryRegion iomem;
> +    Nrf51UART uart;
>  
> +    MemoryRegion container;
> +    MemoryRegion sram;
> +    MemoryRegion flash;
> +    MemoryRegion iomem;
>      MemoryRegion clock;
>      MemoryRegion nvmc;
>      MemoryRegion rng;
> +
> +    /* Properties */
> +    int32_t part_variant;
>  } NRF51State;
>  
> +typedef enum {
> +    NRF51_VARIANT_INVALID = -1,
> +    NRF51_VARIANT_AA = 0,
> +    NRF51_VARIANT_AB = 1,
> +    NRF51_VARIANT_AC = 2,
> +    NRF51_VARIANT_MAX = 3
> +} NRF51Variants;
> +
>  #endif
>  
> -- 
> 2.17.1
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 455 bytes --]

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [Qemu-devel] [RFC 6/8] arm: Add UICR/FICR handling to NRF51 SOC
  2018-06-27  7:33 ` [Qemu-devel] [RFC 6/8] arm: Add UICR/FICR handling to NRF51 SOC Steffen Görtz
@ 2018-06-27  9:57   ` Stefan Hajnoczi
  0 siblings, 0 replies; 14+ messages in thread
From: Stefan Hajnoczi @ 2018-06-27  9:57 UTC (permalink / raw)
  To: Steffen Görtz
  Cc: qemu-devel, Joel Stanley, Jim Mussared, Julia Suvorova,
	Peter Maydell, open list:ARM

[-- Attachment #1: Type: text/plain, Size: 1057 bytes --]

On Wed, Jun 27, 2018 at 09:33:49AM +0200, Steffen Görtz wrote:
> This patch maps preallocated user/factory information
> configuration registers to the NRF51 SOC.
> See NRF51 reference manual section 7 and 8.
> 
> Signed-off-by: Steffen Görtz <contrib@steffen-goertz.de>
> ---
>  hw/arm/nrf51_soc.c         | 174 ++++++++++++++++++++++++++++++-------
>  include/hw/arm/nrf51_soc.h |   5 +-
>  2 files changed, 145 insertions(+), 34 deletions(-)
> 
> diff --git a/hw/arm/nrf51_soc.c b/hw/arm/nrf51_soc.c
> index e93699a4b0..82e4c2d833 100644
> --- a/hw/arm/nrf51_soc.c
> +++ b/hw/arm/nrf51_soc.c
> @@ -19,7 +19,6 @@
>  #include "sysemu/sysemu.h"
>  #include "qemu/log.h"
>  #include "cpu.h"
> -#include "crypto/random.h"
>  
>  #include "hw/arm/nrf51_soc.h"
>  
> @@ -29,6 +28,9 @@
>  #define FICR_BASE       0x10000000
>  #define FICR_SIZE       0x100
>  
> +#define UICR_BASE       0x10001000
> +#define UICR_SIZE       0x100

This definition is duplicated in your NVMC patch.  Please put it in the
nrf51_soc.h header file.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 455 bytes --]

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [Qemu-devel] [RFC 5/8] arm: Add NRF51 random number generator peripheral
  2018-06-27  7:33 ` [Qemu-devel] [RFC 5/8] arm: Add NRF51 random number generator peripheral Steffen Görtz
@ 2018-07-05 16:51   ` Peter Maydell
  2018-07-05 17:19     ` Steffen Görtz
  0 siblings, 1 reply; 14+ messages in thread
From: Peter Maydell @ 2018-07-05 16:51 UTC (permalink / raw)
  To: Steffen Görtz
  Cc: QEMU Developers, Stefan Hajnoczi, Jim Mussared, Julia Suvorova,
	Joel Stanley

On 27 June 2018 at 08:33, Steffen Görtz <contrib@steffen-goertz.de> wrote:
> Add a model of the NRF51 random number generator peripheral.
>
> Changes since v2:
>   - Add missing 'qapi/error.h' for error_abort
>
> Changes since v1:
>   - Add implementation access size hints to MemoryRegionOps
>   - Fail on error if qcrypto_random_bytes fails
>   - Add references to Nrf51 datasheets
>
> Signed-off-by: Steffen Görtz <contrib@steffen-goertz.de>
> ---

Hi -- a couple of general notes about device modelling
which might apply to other devices in this series as well:

> +static void nrf51_rng_class_init(ObjectClass *klass, void *data)
> +{
> +    DeviceClass *dc = DEVICE_CLASS(klass);
> +
> +    dc->props = nrf51_rng_properties;

In general, every device that has any modifiable state needs:
 * a reset function
 * a vmstate struct that defines its state for migration

These get set up in the class init function by setting
dc->vmsd and dc->reset.

For devices that don't have any modifiable state, a comment
in the init function to say so helps to reassure readers
that the issue has been considered :-)

> +}


> +    struct {
> +        uint32_t active:1;
> +        uint32_t event_valrdy:1;
> +        uint32_t shortcut_stop_on_valrdy:1;
> +        uint32_t interrupt_enabled:1;
> +        uint32_t filter_enabled:1;
> +    } state;

Prefer to avoid bitfields.

thanks
-- PMM

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [Qemu-devel] [RFC 5/8] arm: Add NRF51 random number generator peripheral
  2018-07-05 16:51   ` Peter Maydell
@ 2018-07-05 17:19     ` Steffen Görtz
  0 siblings, 0 replies; 14+ messages in thread
From: Steffen Görtz @ 2018-07-05 17:19 UTC (permalink / raw)
  To: Peter Maydell
  Cc: QEMU Developers, Stefan Hajnoczi, Jim Mussared, Julia Suvorova,
	Joel Stanley

Hi Peter,

> Hi -- a couple of general notes about device modelling
> which might apply to other devices in this series as well:
> 
>> +static void nrf51_rng_class_init(ObjectClass *klass, void *data)
>> +{
>> +    DeviceClass *dc = DEVICE_CLASS(klass);
>> +
>> +    dc->props = nrf51_rng_properties;
> 
> In general, every device that has any modifiable state needs:
>  * a reset function
>  * a vmstate struct that defines its state for migration
> 
> These get set up in the class init function by setting
> dc->vmsd and dc->reset.
> 
> For devices that don't have any modifiable state, a comment
> in the init function to say so helps to reassure readers
> that the issue has been considered :-)

Thank you for your remarks!
I will add the missing handler/structure. I will have to revise the
other devices i have pending for comments as well!

> 
>> +}
> 
> 
>> +    struct {
>> +        uint32_t active:1;
>> +        uint32_t event_valrdy:1;
>> +        uint32_t shortcut_stop_on_valrdy:1;
>> +        uint32_t interrupt_enabled:1;
>> +        uint32_t filter_enabled:1;
>> +    } state;
> 
> Prefer to avoid bitfields.

Will do!

Steffen

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2018-07-05 17:19 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-06-27  7:33 [Qemu-devel] [RFC 0/8] arm: Changes to Microbit Board and NRF51 SOC Steffen Görtz
2018-06-27  7:33 ` [Qemu-devel] [RFC 1/8] arm: NRF51/Microbit Memory container and SOC variants Steffen Görtz
2018-06-27  9:53   ` Stefan Hajnoczi
2018-06-27  7:33 ` [Qemu-devel] [RFC 2/8] arm: NRF51 Add unimplemented device for MMIO Steffen Görtz
2018-06-27  7:33 ` [Qemu-devel] [RFC 3/8] arm: NRF51 create UART in-place, error handling Steffen Görtz
2018-06-27  7:33 ` [Qemu-devel] [RFC 4/8] arm: NRF51 Calculate peripheral id from base address Steffen Görtz
2018-06-27  7:33 ` [Qemu-devel] [RFC 5/8] arm: Add NRF51 random number generator peripheral Steffen Görtz
2018-07-05 16:51   ` Peter Maydell
2018-07-05 17:19     ` Steffen Görtz
2018-06-27  7:33 ` [Qemu-devel] [RFC 6/8] arm: Add UICR/FICR handling to NRF51 SOC Steffen Görtz
2018-06-27  9:57   ` Stefan Hajnoczi
2018-06-27  7:33 ` [Qemu-devel] [RFC 7/8] arm: Add NRF51 SOC non-volatile memory controller Steffen Görtz
2018-06-27  7:33 ` [Qemu-devel] [RFC 8/8] arm: Instantiate NVMC in NRF51 Steffen Görtz
2018-06-27  9:46 ` [Qemu-devel] [RFC 0/8] arm: Changes to Microbit Board and NRF51 SOC Stefan Hajnoczi

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.