* [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.