All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 00/11] arm: Core nRF51 Devices and Microbit Support
@ 2019-01-03  9:11 Stefan Hajnoczi
  2019-01-03  9:11 ` [Qemu-devel] [PATCH 01/11] qtest: Add set_irq_in command to set IRQ/GPIO level Stefan Hajnoczi
                   ` (11 more replies)
  0 siblings, 12 replies; 15+ messages in thread
From: Stefan Hajnoczi @ 2019-01-03  9:11 UTC (permalink / raw)
  To: qemu-devel
  Cc: Thomas Huth, qemu-arm, Joel Stanley, Julia Suvorova,
	Paolo Bonzini, Jim Mussared, Steffen Görtz, Peter Maydell,
	Laurent Vivier, Stefan Hajnoczi

Steffen has been busy so I picked up "[PATCH v5 00/14] arm: nRF51 Devices and
Microbit Support".  This series includes the core devices needed to boot basic
guest software on the "microbit" board.

This series includes Steffen's random number generator, GPIO, timer, and a
stubbed clock.  Also, this series adds the tests/microbit-test.c qtest.

Changes from Steffen's series:
 * Made timer tickless [Peter]
 * Dropped non-volatile memory controller.  More work is needed there and I
   don't want to hold back other devices in this series that are ready for
   merge.
 * Rebased and re-tested with make check and real micro:bit programs
   (requires out-of-tree -kernel and stub TWI device patches)

Steffen Görtz (11):
  qtest: Add set_irq_in command to set IRQ/GPIO level
  arm: Add header to host common definition for nRF51 SOC peripherals
  hw/misc/nrf51_rng: Add NRF51 random number generator peripheral
  arm: Instantiate NRF51 random number generator
  hw/gpio/nrf51_gpio: Add nRF51 GPIO peripheral
  arm: Instantiate NRF51 general purpose I/O
  tests/microbit-test: Add Tests for nRF51 GPIO
  hw/timer/nrf51_timer: Add nRF51 Timer peripheral
  arm: Instantiate NRF51 Timers
  tests/microbit-test: Add Tests for nRF51 Timer
  arm: Add Clock peripheral stub to NRF51 SOC

 Makefile.objs                  |   1 +
 hw/gpio/Makefile.objs          |   1 +
 hw/misc/Makefile.objs          |   1 +
 hw/timer/Makefile.objs         |   1 +
 tests/Makefile.include         |   2 +
 include/hw/arm/nrf51.h         |  45 ++++
 include/hw/arm/nrf51_soc.h     |   9 +
 include/hw/char/nrf51_uart.h   |   1 -
 include/hw/gpio/nrf51_gpio.h   |  69 ++++++
 include/hw/misc/nrf51_rng.h    |  83 +++++++
 include/hw/timer/nrf51_timer.h |  80 +++++++
 tests/libqtest.h               |  13 ++
 hw/arm/nrf51_soc.c             | 117 ++++++++--
 hw/gpio/nrf51_gpio.c           | 300 +++++++++++++++++++++++++
 hw/misc/nrf51_rng.c            | 262 ++++++++++++++++++++++
 hw/timer/nrf51_timer.c         | 393 +++++++++++++++++++++++++++++++++
 qtest.c                        |  43 ++++
 tests/libqtest.c               |  10 +
 tests/microbit-test.c          | 255 +++++++++++++++++++++
 hw/gpio/trace-events           |   7 +
 hw/timer/trace-events          |   5 +
 21 files changed, 1676 insertions(+), 22 deletions(-)
 create mode 100644 include/hw/arm/nrf51.h
 create mode 100644 include/hw/gpio/nrf51_gpio.h
 create mode 100644 include/hw/misc/nrf51_rng.h
 create mode 100644 include/hw/timer/nrf51_timer.h
 create mode 100644 hw/gpio/nrf51_gpio.c
 create mode 100644 hw/misc/nrf51_rng.c
 create mode 100644 hw/timer/nrf51_timer.c
 create mode 100644 tests/microbit-test.c
 create mode 100644 hw/gpio/trace-events

-- 
2.19.2

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

* [Qemu-devel] [PATCH 01/11] qtest: Add set_irq_in command to set IRQ/GPIO level
  2019-01-03  9:11 [Qemu-devel] [PATCH 00/11] arm: Core nRF51 Devices and Microbit Support Stefan Hajnoczi
@ 2019-01-03  9:11 ` Stefan Hajnoczi
  2019-01-03  9:11 ` [Qemu-devel] [PATCH 02/11] arm: Add header to host common definition for nRF51 SOC peripherals Stefan Hajnoczi
                   ` (10 subsequent siblings)
  11 siblings, 0 replies; 15+ messages in thread
From: Stefan Hajnoczi @ 2019-01-03  9:11 UTC (permalink / raw)
  To: qemu-devel
  Cc: Thomas Huth, qemu-arm, Joel Stanley, Julia Suvorova,
	Paolo Bonzini, Jim Mussared, Steffen Görtz, Peter Maydell,
	Laurent Vivier, Stefan Hajnoczi

From: Steffen Görtz <contrib@steffen-goertz.de>

Adds a new qtest command "set_irq_in" which allows
to set qemu gpio lines to a given level.

Based on https://lists.gnu.org/archive/html/qemu-devel/2012-12/msg02363.html
which never got merged.

Signed-off-by: Steffen Görtz <contrib@steffen-goertz.de>
Originally-by: Matthew Ogilvie <mmogilvi_qemu@miniinfo.net>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Reviewed-by: Laurent Vivier <lvivier@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
 tests/libqtest.h | 13 +++++++++++++
 qtest.c          | 43 +++++++++++++++++++++++++++++++++++++++++++
 tests/libqtest.c | 10 ++++++++++
 3 files changed, 66 insertions(+)

diff --git a/tests/libqtest.h b/tests/libqtest.h
index 9758c51be6..7ea94139b0 100644
--- a/tests/libqtest.h
+++ b/tests/libqtest.h
@@ -230,6 +230,19 @@ void qtest_irq_intercept_in(QTestState *s, const char *string);
  */
 void qtest_irq_intercept_out(QTestState *s, const char *string);
 
+/**
+ * qtest_set_irq_in:
+ * @s: QTestState instance to operate on.
+ * @string: QOM path of a device
+ * @name: IRQ name
+ * @irq: IRQ number
+ * @level: IRQ level
+ *
+ * Force given device/irq GPIO-in pin to the given level.
+ */
+void qtest_set_irq_in(QTestState *s, const char *string, const char *name,
+                      int irq, int level);
+
 /**
  * qtest_outb:
  * @s: #QTestState instance to operate on.
diff --git a/qtest.c b/qtest.c
index 69b9e9962b..451696b5da 100644
--- a/qtest.c
+++ b/qtest.c
@@ -164,6 +164,17 @@ static bool qtest_opened;
  * where NUM is an IRQ number.  For the PC, interrupts can be intercepted
  * simply with "irq_intercept_in ioapic" (note that IRQ0 comes out with
  * NUM=0 even though it is remapped to GSI 2).
+ *
+ * Setting interrupt level:
+ *
+ *  > set_irq_in QOM-PATH NAME NUM LEVEL
+ *  < OK
+ *
+ *  where NAME is the name of the irq/gpio list, NUM is an IRQ number and
+ *  LEVEL is an signed integer IRQ level.
+ *
+ * Forcibly set the given interrupt pin to the given level.
+ *
  */
 
 static int hex2nib(char ch)
@@ -326,7 +337,39 @@ static void qtest_process_command(CharBackend *chr, gchar **words)
         irq_intercept_dev = dev;
         qtest_send_prefix(chr);
         qtest_send(chr, "OK\n");
+    } else if (strcmp(words[0], "set_irq_in") == 0) {
+        DeviceState *dev;
+        qemu_irq irq;
+        char *name;
+        int ret;
+        int num;
+        int level;
 
+        g_assert(words[1] && words[2] && words[3] && words[4]);
+
+        dev = DEVICE(object_resolve_path(words[1], NULL));
+        if (!dev) {
+            qtest_send_prefix(chr);
+            qtest_send(chr, "FAIL Unknown device\n");
+            return;
+        }
+
+        if (strcmp(words[2], "unnamed-gpio-in") == 0) {
+            name = NULL;
+        } else {
+            name = words[2];
+        }
+
+        ret = qemu_strtoi(words[3], NULL, 0, &num);
+        g_assert(!ret);
+        ret = qemu_strtoi(words[4], NULL, 0, &level);
+        g_assert(!ret);
+
+        irq = qdev_get_gpio_in_named(dev, name, num);
+
+        qemu_set_irq(irq, level);
+        qtest_send_prefix(chr);
+        qtest_send(chr, "OK\n");
     } else if (strcmp(words[0], "outb") == 0 ||
                strcmp(words[0], "outw") == 0 ||
                strcmp(words[0], "outl") == 0) {
diff --git a/tests/libqtest.c b/tests/libqtest.c
index 1d75d3c936..55750dd68d 100644
--- a/tests/libqtest.c
+++ b/tests/libqtest.c
@@ -753,6 +753,16 @@ void qtest_irq_intercept_in(QTestState *s, const char *qom_path)
     qtest_rsp(s, 0);
 }
 
+void qtest_set_irq_in(QTestState *s, const char *qom_path, const char *name,
+                      int num, int level)
+{
+    if (!name) {
+        name = "unnamed-gpio-in";
+    }
+    qtest_sendf(s, "set_irq_in %s %s %d %d\n", qom_path, name, num, level);
+    qtest_rsp(s, 0);
+}
+
 static void qtest_out(QTestState *s, const char *cmd, uint16_t addr, uint32_t value)
 {
     qtest_sendf(s, "%s 0x%x 0x%x\n", cmd, addr, value);
-- 
2.19.2

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

* [Qemu-devel] [PATCH 02/11] arm: Add header to host common definition for nRF51 SOC peripherals
  2019-01-03  9:11 [Qemu-devel] [PATCH 00/11] arm: Core nRF51 Devices and Microbit Support Stefan Hajnoczi
  2019-01-03  9:11 ` [Qemu-devel] [PATCH 01/11] qtest: Add set_irq_in command to set IRQ/GPIO level Stefan Hajnoczi
@ 2019-01-03  9:11 ` Stefan Hajnoczi
  2019-01-03 10:40   ` Philippe Mathieu-Daudé
  2019-01-03  9:11 ` [Qemu-devel] [PATCH 03/11] hw/misc/nrf51_rng: Add NRF51 random number generator peripheral Stefan Hajnoczi
                   ` (9 subsequent siblings)
  11 siblings, 1 reply; 15+ messages in thread
From: Stefan Hajnoczi @ 2019-01-03  9:11 UTC (permalink / raw)
  To: qemu-devel
  Cc: Thomas Huth, qemu-arm, Joel Stanley, Julia Suvorova,
	Paolo Bonzini, Jim Mussared, Steffen Görtz, Peter Maydell,
	Laurent Vivier, Stefan Hajnoczi

From: Steffen Görtz <contrib@steffen-goertz.de>

Adds a header that provides definitions that are used
across nRF51 peripherals

Signed-off-by: Steffen Görtz <contrib@steffen-goertz.de>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
 include/hw/arm/nrf51.h       | 45 ++++++++++++++++++++++++++++++++++++
 include/hw/char/nrf51_uart.h |  1 -
 hw/arm/nrf51_soc.c           | 33 ++++++++++----------------
 3 files changed, 57 insertions(+), 22 deletions(-)
 create mode 100644 include/hw/arm/nrf51.h

diff --git a/include/hw/arm/nrf51.h b/include/hw/arm/nrf51.h
new file mode 100644
index 0000000000..175bb6c301
--- /dev/null
+++ b/include/hw/arm/nrf51.h
@@ -0,0 +1,45 @@
+/*
+ * Nordic Semiconductor nRF51 Series SOC Common Defines
+ *
+ * This file hosts generic defines used in various nRF51 peripheral devices.
+ *
+ * Reference Manual: http://infocenter.nordicsemi.com/pdf/nRF51_RM_v3.0.pdf
+ * Product Spec: http://infocenter.nordicsemi.com/pdf/nRF51822_PS_v3.1.pdf
+ *
+ * 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.
+ */
+
+#ifndef NRF51_H
+#define NRF51_H
+
+#define NRF51_FLASH_BASE      0x00000000
+#define NRF51_FICR_BASE       0x10000000
+#define NRF51_FICR_SIZE       0x00000100
+#define NRF51_UICR_BASE       0x10001000
+#define NRF51_SRAM_BASE       0x20000000
+
+#define NRF51_IOMEM_BASE      0x40000000
+#define NRF51_IOMEM_SIZE      0x20000000
+
+#define NRF51_UART_BASE       0x40002000
+#define NRF51_TIMER_BASE      0x40008000
+#define NRF51_TIMER_SIZE      0x00001000
+#define NRF51_RNG_BASE        0x4000D000
+#define NRF51_NVMC_BASE       0x4001E000
+#define NRF51_GPIO_BASE       0x50000000
+
+#define NRF51_PRIVATE_BASE    0xF0000000
+#define NRF51_PRIVATE_SIZE    0x10000000
+
+#define NRF51_PAGE_SIZE       1024
+
+/* Trigger */
+#define NRF51_TRIGGER_TASK 0x01
+
+/* Events */
+#define NRF51_EVENT_CLEAR  0x00
+
+#endif
diff --git a/include/hw/char/nrf51_uart.h b/include/hw/char/nrf51_uart.h
index e3ecb7c81c..eb1c15b490 100644
--- a/include/hw/char/nrf51_uart.h
+++ b/include/hw/char/nrf51_uart.h
@@ -16,7 +16,6 @@
 #include "hw/registerfields.h"
 
 #define UART_FIFO_LENGTH 6
-#define UART_BASE 0x40002000
 #define UART_SIZE 0x1000
 
 #define TYPE_NRF51_UART "nrf51_soc.uart"
diff --git a/hw/arm/nrf51_soc.c b/hw/arm/nrf51_soc.c
index b89c1bdea0..55f8eaafcb 100644
--- a/hw/arm/nrf51_soc.c
+++ b/hw/arm/nrf51_soc.c
@@ -21,27 +21,16 @@
 #include "qemu/log.h"
 #include "cpu.h"
 
+#include "hw/arm/nrf51.h"
 #include "hw/arm/nrf51_soc.h"
 
-#define IOMEM_BASE      0x40000000
-#define IOMEM_SIZE      0x20000000
-
-#define FICR_BASE       0x10000000
-#define FICR_SIZE       0x000000fc
-
-#define FLASH_BASE      0x00000000
-#define SRAM_BASE       0x20000000
-
-#define PRIVATE_BASE    0xF0000000
-#define PRIVATE_SIZE    0x10000000
-
 /*
  * The size and base is for the NRF51822 part. If other parts
  * are supported in the future, add a sub-class of NRF51SoC for
  * the specific variants
  */
-#define NRF51822_FLASH_SIZE     (256 * 1024)
-#define NRF51822_SRAM_SIZE      (16 * 1024)
+#define NRF51822_FLASH_SIZE     (256 * NRF51_PAGE_SIZE)
+#define NRF51822_SRAM_SIZE      (16 * NRF51_PAGE_SIZE)
 
 #define BASE_TO_IRQ(base) ((base >> 12) & 0x1F)
 
@@ -76,14 +65,14 @@ static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp)
         error_propagate(errp, err);
         return;
     }
-    memory_region_add_subregion(&s->container, FLASH_BASE, &s->flash);
+    memory_region_add_subregion(&s->container, NRF51_FLASH_BASE, &s->flash);
 
     memory_region_init_ram(&s->sram, NULL, "nrf51.sram", s->sram_size, &err);
     if (err) {
         error_propagate(errp, err);
         return;
     }
-    memory_region_add_subregion(&s->container, SRAM_BASE, &s->sram);
+    memory_region_add_subregion(&s->container, NRF51_SRAM_BASE, &s->sram);
 
     /* UART */
     object_property_set_bool(OBJECT(&s->uart), true, "realized", &err);
@@ -92,15 +81,17 @@ static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp)
         return;
     }
     mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->uart), 0);
-    memory_region_add_subregion_overlap(&s->container, UART_BASE, mr, 0);
+    memory_region_add_subregion_overlap(&s->container, NRF51_UART_BASE, mr, 0);
     sysbus_connect_irq(SYS_BUS_DEVICE(&s->uart), 0,
                        qdev_get_gpio_in(DEVICE(&s->cpu),
-                       BASE_TO_IRQ(UART_BASE)));
+                       BASE_TO_IRQ(NRF51_UART_BASE)));
 
-    create_unimplemented_device("nrf51_soc.io", IOMEM_BASE, IOMEM_SIZE);
-    create_unimplemented_device("nrf51_soc.ficr", FICR_BASE, FICR_SIZE);
+    create_unimplemented_device("nrf51_soc.io", NRF51_IOMEM_BASE,
+                                NRF51_IOMEM_SIZE);
+    create_unimplemented_device("nrf51_soc.ficr", NRF51_FICR_BASE,
+                                NRF51_FICR_SIZE);
     create_unimplemented_device("nrf51_soc.private",
-                                PRIVATE_BASE, PRIVATE_SIZE);
+                                NRF51_PRIVATE_BASE, NRF51_PRIVATE_SIZE);
 }
 
 static void nrf51_soc_init(Object *obj)
-- 
2.19.2

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

* [Qemu-devel] [PATCH 03/11] hw/misc/nrf51_rng: Add NRF51 random number generator peripheral
  2019-01-03  9:11 [Qemu-devel] [PATCH 00/11] arm: Core nRF51 Devices and Microbit Support Stefan Hajnoczi
  2019-01-03  9:11 ` [Qemu-devel] [PATCH 01/11] qtest: Add set_irq_in command to set IRQ/GPIO level Stefan Hajnoczi
  2019-01-03  9:11 ` [Qemu-devel] [PATCH 02/11] arm: Add header to host common definition for nRF51 SOC peripherals Stefan Hajnoczi
@ 2019-01-03  9:11 ` Stefan Hajnoczi
  2019-01-03  9:11 ` [Qemu-devel] [PATCH 04/11] arm: Instantiate NRF51 random number generator Stefan Hajnoczi
                   ` (8 subsequent siblings)
  11 siblings, 0 replies; 15+ messages in thread
From: Stefan Hajnoczi @ 2019-01-03  9:11 UTC (permalink / raw)
  To: qemu-devel
  Cc: Thomas Huth, qemu-arm, Joel Stanley, Julia Suvorova,
	Paolo Bonzini, Jim Mussared, Steffen Görtz, Peter Maydell,
	Laurent Vivier, Stefan Hajnoczi

From: Steffen Görtz <contrib@steffen-goertz.de>

Add a model of the NRF51 random number generator peripheral.
This is a simple random generator that continuously generates
new random values after startup.

Reference Manual: http://infocenter.nordicsemi.com/pdf/nRF51_RM_v3.0.pdf

Signed-off-by: Steffen Görtz <contrib@steffen-goertz.de>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
 hw/misc/Makefile.objs       |   1 +
 include/hw/misc/nrf51_rng.h |  83 ++++++++++++
 hw/misc/nrf51_rng.c         | 262 ++++++++++++++++++++++++++++++++++++
 3 files changed, 346 insertions(+)
 create mode 100644 include/hw/misc/nrf51_rng.h
 create mode 100644 hw/misc/nrf51_rng.c

diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
index 680350b3c3..04f3bfa516 100644
--- a/hw/misc/Makefile.objs
+++ b/hw/misc/Makefile.objs
@@ -74,3 +74,4 @@ obj-$(CONFIG_PVPANIC) += pvpanic.o
 obj-$(CONFIG_AUX) += auxbus.o
 obj-$(CONFIG_ASPEED_SOC) += aspeed_scu.o aspeed_sdmc.o
 obj-$(CONFIG_MSF2) += msf2-sysreg.o
+obj-$(CONFIG_NRF51_SOC) += nrf51_rng.o
diff --git a/include/hw/misc/nrf51_rng.h b/include/hw/misc/nrf51_rng.h
new file mode 100644
index 0000000000..3d6bf79997
--- /dev/null
+++ b/include/hw/misc/nrf51_rng.h
@@ -0,0 +1,83 @@
+/*
+ * nRF51 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.
+ *
+ * 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.
+ *
+ */
+#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)
+
+#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
+
+typedef struct {
+    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;
+
+    uint32_t active;
+    uint32_t event_valrdy;
+    uint32_t shortcut_stop_on_valrdy;
+    uint32_t interrupt_enabled;
+    uint32_t filter_enabled;
+
+} NRF51RNGState;
+
+
+#endif /* NRF51_RNG_H_ */
diff --git a/hw/misc/nrf51_rng.c b/hw/misc/nrf51_rng.c
new file mode 100644
index 0000000000..d188f044f4
--- /dev/null
+++ b/hw/misc/nrf51_rng.c
@@ -0,0 +1,262 @@
+/*
+ * nRF51 Random Number Generator
+ *
+ * Reference Manual: http://infocenter.nordicsemi.com/pdf/nRF51_RM_v3.0.1.pdf
+ *
+ * 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/arm/nrf51.h"
+#include "hw/misc/nrf51_rng.h"
+#include "crypto/random.h"
+
+static void update_irq(NRF51RNGState *s)
+{
+    bool irq = s->interrupt_enabled && s->event_valrdy;
+    qemu_set_irq(s->irq, irq);
+}
+
+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->event_valrdy;
+        break;
+    case NRF51_RNG_REG_SHORTS:
+        r = s->shortcut_stop_on_valrdy;
+        break;
+    case NRF51_RNG_REG_INTEN:
+    case NRF51_RNG_REG_INTENSET:
+    case NRF51_RNG_REG_INTENCLR:
+        r = s->interrupt_enabled;
+        break;
+    case NRF51_RNG_REG_CONFIG:
+        r = s->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->filter_enabled) {
+        timeout += s->period_filtered_us;
+    } else {
+        timeout += s->period_unfiltered_us;
+    }
+
+    return timeout;
+}
+
+
+static void rng_update_timer(NRF51RNGState *s)
+{
+    if (s->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->active = 1;
+            rng_update_timer(s);
+        }
+        break;
+    case NRF51_RNG_TASK_STOP:
+        if (value == NRF51_TRIGGER_TASK) {
+            s->active = 0;
+            rng_update_timer(s);
+        }
+        break;
+    case NRF51_RNG_EVENT_VALRDY:
+        if (value == NRF51_EVENT_CLEAR) {
+            s->event_valrdy = 0;
+        }
+        break;
+    case NRF51_RNG_REG_SHORTS:
+        s->shortcut_stop_on_valrdy =
+                (value & BIT_MASK(NRF51_RNG_REG_SHORTS_VALRDY_STOP)) ? 1 : 0;
+        break;
+    case NRF51_RNG_REG_INTEN:
+        s->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->interrupt_enabled = 1;
+        }
+        break;
+    case NRF51_RNG_REG_INTENCLR:
+        if (value & BIT_MASK(NRF51_RNG_REG_INTEN_VALRDY)) {
+            s->interrupt_enabled = 0;
+        }
+        break;
+    case NRF51_RNG_REG_CONFIG:
+        s->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);
+    }
+
+    update_irq(s);
+}
+
+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->event_valrdy = 1;
+    qemu_set_irq(s->eep_valrdy, 1);
+
+    if (s->shortcut_stop_on_valrdy) {
+        s->active = 0;
+    }
+
+    rng_update_timer(s);
+    update_irq(s);
+}
+
+static void nrf51_rng_tep_start(void *opaque, int n, int level)
+{
+    NRF51RNGState *s = NRF51_RNG(opaque);
+
+    if (level) {
+        s->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->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);
+
+    sysbus_init_irq(sbd, &s->irq);
+
+    /* 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 void nrf51_rng_reset(DeviceState *dev)
+{
+    NRF51RNGState *s = NRF51_RNG(dev);
+
+    s->value = 0;
+    s->active = 0;
+    s->event_valrdy = 0;
+    s->shortcut_stop_on_valrdy = 0;
+    s->interrupt_enabled = 0;
+    s->filter_enabled = 0;
+
+    rng_update_timer(s);
+}
+
+
+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 const VMStateDescription vmstate_rng = {
+    .name = "nrf51_soc.rng",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32(active, NRF51RNGState),
+        VMSTATE_UINT32(event_valrdy, NRF51RNGState),
+        VMSTATE_UINT32(shortcut_stop_on_valrdy, NRF51RNGState),
+        VMSTATE_UINT32(interrupt_enabled, NRF51RNGState),
+        VMSTATE_UINT32(filter_enabled, NRF51RNGState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void nrf51_rng_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->props = nrf51_rng_properties;
+    dc->vmsd = &vmstate_rng;
+    dc->reset = nrf51_rng_reset;
+}
+
+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)
-- 
2.19.2

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

* [Qemu-devel] [PATCH 04/11] arm: Instantiate NRF51 random number generator
  2019-01-03  9:11 [Qemu-devel] [PATCH 00/11] arm: Core nRF51 Devices and Microbit Support Stefan Hajnoczi
                   ` (2 preceding siblings ...)
  2019-01-03  9:11 ` [Qemu-devel] [PATCH 03/11] hw/misc/nrf51_rng: Add NRF51 random number generator peripheral Stefan Hajnoczi
@ 2019-01-03  9:11 ` Stefan Hajnoczi
  2019-01-03  9:11 ` [Qemu-devel] [PATCH 05/11] hw/gpio/nrf51_gpio: Add nRF51 GPIO peripheral Stefan Hajnoczi
                   ` (7 subsequent siblings)
  11 siblings, 0 replies; 15+ messages in thread
From: Stefan Hajnoczi @ 2019-01-03  9:11 UTC (permalink / raw)
  To: qemu-devel
  Cc: Thomas Huth, qemu-arm, Joel Stanley, Julia Suvorova,
	Paolo Bonzini, Jim Mussared, Steffen Görtz, Peter Maydell,
	Laurent Vivier, Stefan Hajnoczi

From: Steffen Görtz <contrib@steffen-goertz.de>

Use RNG in SOC.

Signed-off-by: Steffen Görtz <contrib@steffen-goertz.de>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
 include/hw/arm/nrf51_soc.h |  2 ++
 hw/arm/nrf51_soc.c         | 16 ++++++++++++++++
 2 files changed, 18 insertions(+)

diff --git a/include/hw/arm/nrf51_soc.h b/include/hw/arm/nrf51_soc.h
index 73fc92e9a8..9e3ba916bd 100644
--- a/include/hw/arm/nrf51_soc.h
+++ b/include/hw/arm/nrf51_soc.h
@@ -13,6 +13,7 @@
 #include "hw/sysbus.h"
 #include "hw/arm/armv7m.h"
 #include "hw/char/nrf51_uart.h"
+#include "hw/misc/nrf51_rng.h"
 
 #define TYPE_NRF51_SOC "nrf51-soc"
 #define NRF51_SOC(obj) \
@@ -26,6 +27,7 @@ typedef struct NRF51State {
     ARMv7MState cpu;
 
     NRF51UARTState uart;
+    NRF51RNGState rng;
 
     MemoryRegion iomem;
     MemoryRegion sram;
diff --git a/hw/arm/nrf51_soc.c b/hw/arm/nrf51_soc.c
index 55f8eaafcb..d2a19b8ead 100644
--- a/hw/arm/nrf51_soc.c
+++ b/hw/arm/nrf51_soc.c
@@ -86,6 +86,19 @@ static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp)
                        qdev_get_gpio_in(DEVICE(&s->cpu),
                        BASE_TO_IRQ(NRF51_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, NRF51_RNG_BASE, mr, 0);
+    sysbus_connect_irq(SYS_BUS_DEVICE(&s->rng), 0,
+                       qdev_get_gpio_in(DEVICE(&s->cpu),
+                       BASE_TO_IRQ(NRF51_RNG_BASE)));
+
     create_unimplemented_device("nrf51_soc.io", NRF51_IOMEM_BASE,
                                 NRF51_IOMEM_SIZE);
     create_unimplemented_device("nrf51_soc.ficr", NRF51_FICR_BASE,
@@ -110,6 +123,9 @@ static void nrf51_soc_init(Object *obj)
                            TYPE_NRF51_UART);
     object_property_add_alias(obj, "serial0", OBJECT(&s->uart), "chardev",
                               &error_abort);
+
+    sysbus_init_child_obj(obj, "rng", &s->rng, sizeof(s->rng),
+                           TYPE_NRF51_RNG);
 }
 
 static Property nrf51_soc_properties[] = {
-- 
2.19.2

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

* [Qemu-devel] [PATCH 05/11] hw/gpio/nrf51_gpio: Add nRF51 GPIO peripheral
  2019-01-03  9:11 [Qemu-devel] [PATCH 00/11] arm: Core nRF51 Devices and Microbit Support Stefan Hajnoczi
                   ` (3 preceding siblings ...)
  2019-01-03  9:11 ` [Qemu-devel] [PATCH 04/11] arm: Instantiate NRF51 random number generator Stefan Hajnoczi
@ 2019-01-03  9:11 ` Stefan Hajnoczi
  2019-01-03  9:11 ` [Qemu-devel] [PATCH 06/11] arm: Instantiate NRF51 general purpose I/O Stefan Hajnoczi
                   ` (6 subsequent siblings)
  11 siblings, 0 replies; 15+ messages in thread
From: Stefan Hajnoczi @ 2019-01-03  9:11 UTC (permalink / raw)
  To: qemu-devel
  Cc: Thomas Huth, qemu-arm, Joel Stanley, Julia Suvorova,
	Paolo Bonzini, Jim Mussared, Steffen Görtz, Peter Maydell,
	Laurent Vivier, Stefan Hajnoczi

From: Steffen Görtz <contrib@steffen-goertz.de>

This adds a model of the nRF51 GPIO peripheral.

Reference Manual: http://infocenter.nordicsemi.com/pdf/nRF51_RM_v3.0.pdf

The nRF51 series microcontrollers support up to 32 GPIO pins in various configurations.
The pins can be used as input pins with pull-ups or pull-down.
Furthermore, three different output driver modes per level are
available (disconnected, standard, high-current).

The GPIO-Peripheral has a mechanism for detecting level changes which is
not featured in this model.

Signed-off-by: Steffen Görtz <contrib@steffen-goertz.de>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
 Makefile.objs                |   1 +
 hw/gpio/Makefile.objs        |   1 +
 include/hw/gpio/nrf51_gpio.h |  69 ++++++++
 hw/gpio/nrf51_gpio.c         | 300 +++++++++++++++++++++++++++++++++++
 hw/gpio/trace-events         |   7 +
 5 files changed, 378 insertions(+)
 create mode 100644 include/hw/gpio/nrf51_gpio.h
 create mode 100644 hw/gpio/nrf51_gpio.c
 create mode 100644 hw/gpio/trace-events

diff --git a/Makefile.objs b/Makefile.objs
index bc5b8a8442..456115992a 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -184,6 +184,7 @@ trace-events-subdirs += hw/vfio
 trace-events-subdirs += hw/virtio
 trace-events-subdirs += hw/watchdog
 trace-events-subdirs += hw/xen
+trace-events-subdirs += hw/gpio
 trace-events-subdirs += io
 trace-events-subdirs += linux-user
 trace-events-subdirs += migration
diff --git a/hw/gpio/Makefile.objs b/hw/gpio/Makefile.objs
index fa0a72e6d0..e5da0cb54f 100644
--- a/hw/gpio/Makefile.objs
+++ b/hw/gpio/Makefile.objs
@@ -8,3 +8,4 @@ common-obj-$(CONFIG_GPIO_KEY) += gpio_key.o
 obj-$(CONFIG_OMAP) += omap_gpio.o
 obj-$(CONFIG_IMX) += imx_gpio.o
 obj-$(CONFIG_RASPI) += bcm2835_gpio.o
+obj-$(CONFIG_NRF51_SOC) += nrf51_gpio.o
diff --git a/include/hw/gpio/nrf51_gpio.h b/include/hw/gpio/nrf51_gpio.h
new file mode 100644
index 0000000000..337ee534bb
--- /dev/null
+++ b/include/hw/gpio/nrf51_gpio.h
@@ -0,0 +1,69 @@
+/*
+ * nRF51 System-on-Chip general purpose input/output register definition
+ *
+ * QEMU interface:
+ * + sysbus MMIO regions 0: GPIO registers
+ * + Unnamed GPIO inputs 0-31: Set tri-state input level for GPIO pin.
+ *   Level -1: Externally Disconnected/Floating; Pull-up/down will be regarded
+ *   Level 0: Input externally driven LOW
+ *   Level 1: Input externally driven HIGH
+ * + Unnamed GPIO outputs 0-31:
+ *   Level -1: Disconnected/Floating
+ *   Level 0: Driven LOW
+ *   Level 1: Driven HIGH
+ *
+ * Accuracy of the peripheral model:
+ * + The nRF51 GPIO output driver supports two modes, standard and high-current
+ *   mode. These different drive modes are not modeled and handled the same.
+ * + Pin SENSEing is not modeled/implemented.
+ *
+ * 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.
+ *
+ */
+#ifndef NRF51_GPIO_H
+#define NRF51_GPIO_H
+
+#include "hw/sysbus.h"
+#define TYPE_NRF51_GPIO "nrf51_soc.gpio"
+#define NRF51_GPIO(obj) OBJECT_CHECK(NRF51GPIOState, (obj), TYPE_NRF51_GPIO)
+
+#define NRF51_GPIO_PINS 32
+
+#define NRF51_GPIO_SIZE 0x1000
+
+#define NRF51_GPIO_REG_OUT          0x504
+#define NRF51_GPIO_REG_OUTSET       0x508
+#define NRF51_GPIO_REG_OUTCLR       0x50C
+#define NRF51_GPIO_REG_IN           0x510
+#define NRF51_GPIO_REG_DIR          0x514
+#define NRF51_GPIO_REG_DIRSET       0x518
+#define NRF51_GPIO_REG_DIRCLR       0x51C
+#define NRF51_GPIO_REG_CNF_START    0x700
+#define NRF51_GPIO_REG_CNF_END      0x77F
+
+#define NRF51_GPIO_PULLDOWN 1
+#define NRF51_GPIO_PULLUP 3
+
+typedef struct NRF51GPIOState {
+    SysBusDevice parent_obj;
+
+    MemoryRegion mmio;
+    qemu_irq irq;
+
+    uint32_t out;
+    uint32_t in;
+    uint32_t in_mask;
+    uint32_t dir;
+    uint32_t cnf[NRF51_GPIO_PINS];
+
+    uint32_t old_out;
+    uint32_t old_out_connected;
+
+    qemu_irq output[NRF51_GPIO_PINS];
+} NRF51GPIOState;
+
+
+#endif
diff --git a/hw/gpio/nrf51_gpio.c b/hw/gpio/nrf51_gpio.c
new file mode 100644
index 0000000000..86e047d649
--- /dev/null
+++ b/hw/gpio/nrf51_gpio.c
@@ -0,0 +1,300 @@
+/*
+ * nRF51 System-on-Chip general purpose input/output register definition
+ *
+ * Reference Manual: http://infocenter.nordicsemi.com/pdf/nRF51_RM_v3.0.pdf
+ * Product Spec: http://infocenter.nordicsemi.com/pdf/nRF51822_PS_v3.1.pdf
+ *
+ * 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 "hw/gpio/nrf51_gpio.h"
+#include "trace.h"
+
+/*
+ * Check if the output driver is connected to the direction switch
+ * given the current configuration and logic level.
+ * It is not differentiated between standard and "high"(-power) drive modes.
+ */
+static bool is_connected(uint32_t config, uint32_t level)
+{
+    bool state;
+    uint32_t drive_config = extract32(config, 8, 3);
+
+    switch (drive_config) {
+    case 0 ... 3:
+        state = true;
+        break;
+    case 4 ... 5:
+        state = level != 0;
+        break;
+    case 6 ... 7:
+        state = level == 0;
+        break;
+    default:
+        g_assert_not_reached();
+        break;
+    }
+
+    return state;
+}
+
+static void update_output_irq(NRF51GPIOState *s, size_t i,
+                              bool connected, bool level)
+{
+    int64_t irq_level = connected ? level : -1;
+    bool old_connected = extract32(s->old_out_connected, i, 1);
+    bool old_level = extract32(s->old_out, i, 1);
+
+    if ((old_connected != connected) || (old_level != level)) {
+        qemu_set_irq(s->output[i], irq_level);
+        trace_nrf51_gpio_update_output_irq(i, irq_level);
+    }
+
+    s->old_out = deposit32(s->old_out, i, 1, level);
+    s->old_out_connected = deposit32(s->old_out_connected, i, 1, connected);
+}
+
+static void update_state(NRF51GPIOState *s)
+{
+    uint32_t pull;
+    size_t i;
+    bool connected_out, dir, connected_in, out, input;
+
+    for (i = 0; i < NRF51_GPIO_PINS; i++) {
+        pull = extract32(s->cnf[i], 2, 2);
+        dir = extract32(s->cnf[i], 0, 1);
+        connected_in = extract32(s->in_mask, i, 1);
+        out = extract32(s->out, i, 1);
+        input = !extract32(s->cnf[i], 1, 1);
+        connected_out = is_connected(s->cnf[i], out) && dir;
+
+        update_output_irq(s, i, connected_out, out);
+
+        /* Pin both driven externally and internally */
+        if (connected_out && connected_in) {
+            qemu_log_mask(LOG_GUEST_ERROR, "GPIO pin %zu short circuited\n", i);
+        }
+
+        /*
+         * Input buffer disconnected from internal/external drives, so
+         * pull-up/pull-down becomes relevant
+         */
+        if (!input || (input && !connected_in && !connected_out)) {
+            if (pull == NRF51_GPIO_PULLDOWN) {
+                s->in = deposit32(s->in, i, 1, 0);
+            } else if (pull == NRF51_GPIO_PULLUP) {
+                s->in = deposit32(s->in, i, 1, 1);
+            }
+        }
+
+        /* Self stimulation through internal output driver */
+        if (connected_out && !connected_in && input) {
+            s->in = deposit32(s->in, i, 1, out);
+        }
+    }
+
+}
+
+/*
+ * Direction is exposed in both the DIR register and the DIR bit
+ * of each PINs CNF configuration register. Reflect bits for pins in DIR
+ * to individual pin configuration registers.
+ */
+static void reflect_dir_bit_in_cnf(NRF51GPIOState *s)
+{
+    size_t i;
+
+    uint32_t value = s->dir;
+
+    for (i = 0; i < NRF51_GPIO_PINS; i++) {
+        s->cnf[i] = (s->cnf[i] & ~(1UL)) | ((value >> i) & 0x01);
+    }
+}
+
+static uint64_t nrf51_gpio_read(void *opaque, hwaddr offset, unsigned int size)
+{
+    NRF51GPIOState *s = NRF51_GPIO(opaque);
+    uint64_t r = 0;
+    size_t idx;
+
+    switch (offset) {
+    case NRF51_GPIO_REG_OUT ... NRF51_GPIO_REG_OUTCLR:
+        r = s->out;
+        break;
+
+    case NRF51_GPIO_REG_IN:
+        r = s->in;
+        break;
+
+    case NRF51_GPIO_REG_DIR ... NRF51_GPIO_REG_DIRCLR:
+        r = s->dir;
+        break;
+
+    case NRF51_GPIO_REG_CNF_START ... NRF51_GPIO_REG_CNF_END:
+        idx = (offset - NRF51_GPIO_REG_CNF_START) / 4;
+        r = s->cnf[idx];
+        break;
+
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR,
+                "%s: bad read offset 0x%" HWADDR_PRIx "\n",
+                      __func__, offset);
+    }
+
+    trace_nrf51_gpio_read(offset, r);
+
+    return r;
+}
+
+static void nrf51_gpio_write(void *opaque, hwaddr offset,
+                       uint64_t value, unsigned int size)
+{
+    NRF51GPIOState *s = NRF51_GPIO(opaque);
+    size_t idx;
+
+    trace_nrf51_gpio_write(offset, value);
+
+    switch (offset) {
+    case NRF51_GPIO_REG_OUT:
+        s->out = value;
+        break;
+
+    case NRF51_GPIO_REG_OUTSET:
+        s->out |= value;
+        break;
+
+    case NRF51_GPIO_REG_OUTCLR:
+        s->out &= ~value;
+        break;
+
+    case NRF51_GPIO_REG_DIR:
+        s->dir = value;
+        reflect_dir_bit_in_cnf(s);
+        break;
+
+    case NRF51_GPIO_REG_DIRSET:
+        s->dir |= value;
+        reflect_dir_bit_in_cnf(s);
+        break;
+
+    case NRF51_GPIO_REG_DIRCLR:
+        s->dir &= ~value;
+        reflect_dir_bit_in_cnf(s);
+        break;
+
+    case NRF51_GPIO_REG_CNF_START ... NRF51_GPIO_REG_CNF_END:
+        idx = (offset - NRF51_GPIO_REG_CNF_START) / 4;
+        s->cnf[idx] = value;
+        /*
+         * direction is exposed in both the DIR register and the DIR bit
+         * of each PINs CNF configuration register.
+         */
+        s->dir = (s->dir & ~(1UL << idx)) | ((value & 0x01) << idx);
+        break;
+
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "%s: bad write offset 0x%" HWADDR_PRIx "\n",
+                      __func__, offset);
+    }
+
+    update_state(s);
+}
+
+static const MemoryRegionOps gpio_ops = {
+    .read =  nrf51_gpio_read,
+    .write = nrf51_gpio_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .impl.min_access_size = 4,
+    .impl.max_access_size = 4,
+};
+
+static void nrf51_gpio_set(void *opaque, int line, int value)
+{
+    NRF51GPIOState *s = NRF51_GPIO(opaque);
+
+    trace_nrf51_gpio_set(line, value);
+
+    assert(line >= 0 && line < NRF51_GPIO_PINS);
+
+    s->in_mask = deposit32(s->in_mask, line, 1, value >= 0);
+    if (value >= 0) {
+        s->in = deposit32(s->in, line, 1, value != 0);
+    }
+
+    update_state(s);
+}
+
+static void nrf51_gpio_reset(DeviceState *dev)
+{
+    NRF51GPIOState *s = NRF51_GPIO(dev);
+    size_t i;
+
+    s->out = 0;
+    s->old_out = 0;
+    s->old_out_connected = 0;
+    s->in = 0;
+    s->in_mask = 0;
+    s->dir = 0;
+
+    for (i = 0; i < NRF51_GPIO_PINS; i++) {
+        s->cnf[i] = 0x00000002;
+    }
+}
+
+static const VMStateDescription vmstate_nrf51_gpio = {
+    .name = TYPE_NRF51_GPIO,
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32(out, NRF51GPIOState),
+        VMSTATE_UINT32(in, NRF51GPIOState),
+        VMSTATE_UINT32(in_mask, NRF51GPIOState),
+        VMSTATE_UINT32(dir, NRF51GPIOState),
+        VMSTATE_UINT32_ARRAY(cnf, NRF51GPIOState, NRF51_GPIO_PINS),
+        VMSTATE_UINT32(old_out, NRF51GPIOState),
+        VMSTATE_UINT32(old_out_connected, NRF51GPIOState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void nrf51_gpio_init(Object *obj)
+{
+    NRF51GPIOState *s = NRF51_GPIO(obj);
+
+    memory_region_init_io(&s->mmio, obj, &gpio_ops, s,
+            TYPE_NRF51_GPIO, NRF51_GPIO_SIZE);
+    sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
+
+    qdev_init_gpio_in(DEVICE(s), nrf51_gpio_set, NRF51_GPIO_PINS);
+    qdev_init_gpio_out(DEVICE(s), s->output, NRF51_GPIO_PINS);
+}
+
+static void nrf51_gpio_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->vmsd = &vmstate_nrf51_gpio;
+    dc->reset = nrf51_gpio_reset;
+    dc->desc = "nRF51 GPIO";
+}
+
+static const TypeInfo nrf51_gpio_info = {
+    .name = TYPE_NRF51_GPIO,
+    .parent = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(NRF51GPIOState),
+    .instance_init = nrf51_gpio_init,
+    .class_init = nrf51_gpio_class_init
+};
+
+static void nrf51_gpio_register_types(void)
+{
+    type_register_static(&nrf51_gpio_info);
+}
+
+type_init(nrf51_gpio_register_types)
diff --git a/hw/gpio/trace-events b/hw/gpio/trace-events
new file mode 100644
index 0000000000..cb41a89756
--- /dev/null
+++ b/hw/gpio/trace-events
@@ -0,0 +1,7 @@
+# See docs/devel/tracing.txt for syntax documentation.
+
+# hw/gpio/nrf51_gpio.c
+nrf51_gpio_read(uint64_t offset, uint64_t r) "offset 0x%" PRIx64 " value 0x%" PRIx64
+nrf51_gpio_write(uint64_t offset, uint64_t value) "offset 0x%" PRIx64 " value 0x%" PRIx64
+nrf51_gpio_set(int64_t line, int64_t value) "line %" PRIi64 " value %" PRIi64
+nrf51_gpio_update_output_irq(int64_t line, int64_t value) "line %" PRIi64 " value %" PRIi64
\ No newline at end of file
-- 
2.19.2

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

* [Qemu-devel] [PATCH 06/11] arm: Instantiate NRF51 general purpose I/O
  2019-01-03  9:11 [Qemu-devel] [PATCH 00/11] arm: Core nRF51 Devices and Microbit Support Stefan Hajnoczi
                   ` (4 preceding siblings ...)
  2019-01-03  9:11 ` [Qemu-devel] [PATCH 05/11] hw/gpio/nrf51_gpio: Add nRF51 GPIO peripheral Stefan Hajnoczi
@ 2019-01-03  9:11 ` Stefan Hajnoczi
  2019-01-03  9:11 ` [Qemu-devel] [PATCH 07/11] tests/microbit-test: Add Tests for nRF51 GPIO Stefan Hajnoczi
                   ` (5 subsequent siblings)
  11 siblings, 0 replies; 15+ messages in thread
From: Stefan Hajnoczi @ 2019-01-03  9:11 UTC (permalink / raw)
  To: qemu-devel
  Cc: Thomas Huth, qemu-arm, Joel Stanley, Julia Suvorova,
	Paolo Bonzini, Jim Mussared, Steffen Görtz, Peter Maydell,
	Laurent Vivier, Stefan Hajnoczi

From: Steffen Görtz <contrib@steffen-goertz.de>

Instantiates GPIO peripheral model

Signed-off-by: Steffen Görtz <contrib@steffen-goertz.de>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
 include/hw/arm/nrf51_soc.h |  2 ++
 hw/arm/nrf51_soc.c         | 16 ++++++++++++++++
 2 files changed, 18 insertions(+)

diff --git a/include/hw/arm/nrf51_soc.h b/include/hw/arm/nrf51_soc.h
index 9e3ba916bd..84e0278881 100644
--- a/include/hw/arm/nrf51_soc.h
+++ b/include/hw/arm/nrf51_soc.h
@@ -14,6 +14,7 @@
 #include "hw/arm/armv7m.h"
 #include "hw/char/nrf51_uart.h"
 #include "hw/misc/nrf51_rng.h"
+#include "hw/gpio/nrf51_gpio.h"
 
 #define TYPE_NRF51_SOC "nrf51-soc"
 #define NRF51_SOC(obj) \
@@ -28,6 +29,7 @@ typedef struct NRF51State {
 
     NRF51UARTState uart;
     NRF51RNGState rng;
+    NRF51GPIOState gpio;
 
     MemoryRegion iomem;
     MemoryRegion sram;
diff --git a/hw/arm/nrf51_soc.c b/hw/arm/nrf51_soc.c
index d2a19b8ead..db817fe506 100644
--- a/hw/arm/nrf51_soc.c
+++ b/hw/arm/nrf51_soc.c
@@ -99,6 +99,19 @@ static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp)
                        qdev_get_gpio_in(DEVICE(&s->cpu),
                        BASE_TO_IRQ(NRF51_RNG_BASE)));
 
+    /* GPIO */
+    object_property_set_bool(OBJECT(&s->gpio), true, "realized", &err);
+    if (err) {
+        error_propagate(errp, err);
+        return;
+    }
+
+    mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->gpio), 0);
+    memory_region_add_subregion_overlap(&s->container, NRF51_GPIO_BASE, mr, 0);
+
+    /* Pass all GPIOs to the SOC layer so they are available to the board */
+    qdev_pass_gpios(DEVICE(&s->gpio), dev_soc, NULL);
+
     create_unimplemented_device("nrf51_soc.io", NRF51_IOMEM_BASE,
                                 NRF51_IOMEM_SIZE);
     create_unimplemented_device("nrf51_soc.ficr", NRF51_FICR_BASE,
@@ -126,6 +139,9 @@ static void nrf51_soc_init(Object *obj)
 
     sysbus_init_child_obj(obj, "rng", &s->rng, sizeof(s->rng),
                            TYPE_NRF51_RNG);
+
+    sysbus_init_child_obj(obj, "gpio", &s->gpio, sizeof(s->gpio),
+                          TYPE_NRF51_GPIO);
 }
 
 static Property nrf51_soc_properties[] = {
-- 
2.19.2

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

* [Qemu-devel] [PATCH 07/11] tests/microbit-test: Add Tests for nRF51 GPIO
  2019-01-03  9:11 [Qemu-devel] [PATCH 00/11] arm: Core nRF51 Devices and Microbit Support Stefan Hajnoczi
                   ` (5 preceding siblings ...)
  2019-01-03  9:11 ` [Qemu-devel] [PATCH 06/11] arm: Instantiate NRF51 general purpose I/O Stefan Hajnoczi
@ 2019-01-03  9:11 ` Stefan Hajnoczi
  2019-01-03  9:11 ` [Qemu-devel] [PATCH 08/11] hw/timer/nrf51_timer: Add nRF51 Timer peripheral Stefan Hajnoczi
                   ` (4 subsequent siblings)
  11 siblings, 0 replies; 15+ messages in thread
From: Stefan Hajnoczi @ 2019-01-03  9:11 UTC (permalink / raw)
  To: qemu-devel
  Cc: Thomas Huth, qemu-arm, Joel Stanley, Julia Suvorova,
	Paolo Bonzini, Jim Mussared, Steffen Görtz, Peter Maydell,
	Laurent Vivier, Stefan Hajnoczi

From: Steffen Görtz <contrib@steffen-goertz.de>

The test suite for the nRF51 GPIO peripheral for now
only tests initial state. Additionally a set of
tests testing an implementation detail of the model
are included.

Signed-off-by: Steffen Görtz <contrib@steffen-goertz.de>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
 tests/Makefile.include |   2 +
 tests/microbit-test.c  | 160 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 162 insertions(+)
 create mode 100644 tests/microbit-test.c

diff --git a/tests/Makefile.include b/tests/Makefile.include
index 3f5a1d0c30..9c84bbd829 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -277,6 +277,7 @@ check-qtest-sparc64-y += tests/boot-serial-test$(EXESUF)
 check-qtest-arm-y += tests/tmp105-test$(EXESUF)
 check-qtest-arm-y += tests/pca9552-test$(EXESUF)
 check-qtest-arm-y += tests/ds1338-test$(EXESUF)
+check-qtest-arm-y += tests/microbit-test$(EXESUF)
 check-qtest-arm-y += tests/m25p80-test$(EXESUF)
 check-qtest-arm-y += tests/virtio-blk-test$(EXESUF)
 check-qtest-arm-y += tests/test-arm-mptimer$(EXESUF)
@@ -708,6 +709,7 @@ tests/pxe-test$(EXESUF): tests/pxe-test.o tests/boot-sector.o $(libqos-obj-y)
 tests/tmp105-test$(EXESUF): tests/tmp105-test.o $(libqos-omap-obj-y)
 tests/pca9552-test$(EXESUF): tests/pca9552-test.o $(libqos-omap-obj-y)
 tests/ds1338-test$(EXESUF): tests/ds1338-test.o $(libqos-imx-obj-y)
+tests/microbit-test$(EXESUF): tests/microbit-test.o
 tests/m25p80-test$(EXESUF): tests/m25p80-test.o
 tests/i440fx-test$(EXESUF): tests/i440fx-test.o $(libqos-pc-obj-y)
 tests/q35-test$(EXESUF): tests/q35-test.o $(libqos-pc-obj-y)
diff --git a/tests/microbit-test.c b/tests/microbit-test.c
new file mode 100644
index 0000000000..535714797a
--- /dev/null
+++ b/tests/microbit-test.c
@@ -0,0 +1,160 @@
+ /*
+ * QTest testcase for Microbit board using the Nordic Semiconductor nRF51 SoC.
+ *
+ * nRF51:
+ * Reference Manual: http://infocenter.nordicsemi.com/pdf/nRF51_RM_v3.0.pdf
+ * Product Spec: http://infocenter.nordicsemi.com/pdf/nRF51822_PS_v3.1.pdf
+ *
+ * Microbit Board: http://microbit.org/
+ *
+ * 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 "exec/hwaddr.h"
+#include "libqtest.h"
+
+#include "hw/arm/nrf51.h"
+#include "hw/gpio/nrf51_gpio.h"
+
+static void test_nrf51_gpio(void)
+{
+    size_t i;
+    uint32_t actual, expected;
+
+    struct {
+        hwaddr addr;
+        uint32_t expected;
+    } const reset_state[] = {
+        {NRF51_GPIO_REG_OUT, 0x00000000}, {NRF51_GPIO_REG_OUTSET, 0x00000000},
+        {NRF51_GPIO_REG_OUTCLR, 0x00000000}, {NRF51_GPIO_REG_IN, 0x00000000},
+        {NRF51_GPIO_REG_DIR, 0x00000000}, {NRF51_GPIO_REG_DIRSET, 0x00000000},
+        {NRF51_GPIO_REG_DIRCLR, 0x00000000}
+    };
+
+    /* Check reset state */
+    for (i = 0; i < ARRAY_SIZE(reset_state); i++) {
+        expected = reset_state[i].expected;
+        actual = readl(NRF51_GPIO_BASE + reset_state[i].addr);
+        g_assert_cmpuint(actual, ==, expected);
+    }
+
+    for (i = 0; i < NRF51_GPIO_PINS; i++) {
+        expected = 0x00000002;
+        actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START + i * 4);
+        g_assert_cmpuint(actual, ==, expected);
+    }
+
+    /* Check dir bit consistency between dir and cnf */
+    /* Check set via DIRSET */
+    expected = 0x80000001;
+    writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_DIRSET, expected);
+    actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_DIR);
+    g_assert_cmpuint(actual, ==, expected);
+    actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START) & 0x01;
+    g_assert_cmpuint(actual, ==, 0x01);
+    actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_END) & 0x01;
+    g_assert_cmpuint(actual, ==, 0x01);
+
+    /* Check clear via DIRCLR */
+    writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_DIRCLR, 0x80000001);
+    actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_DIR);
+    g_assert_cmpuint(actual, ==, 0x00000000);
+    actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START) & 0x01;
+    g_assert_cmpuint(actual, ==, 0x00);
+    actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_END) & 0x01;
+    g_assert_cmpuint(actual, ==, 0x00);
+
+    /* Check set via DIR */
+    expected = 0x80000001;
+    writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_DIR, expected);
+    actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_DIR);
+    g_assert_cmpuint(actual, ==, expected);
+    actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START) & 0x01;
+    g_assert_cmpuint(actual, ==, 0x01);
+    actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_END) & 0x01;
+    g_assert_cmpuint(actual, ==, 0x01);
+
+    /* Reset DIR */
+    writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_DIR, 0x00000000);
+
+    /* Check Input propagates */
+    writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0x00);
+    qtest_set_irq_in(global_qtest, "/machine/nrf51", "unnamed-gpio-in", 0, 0);
+    actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_IN) & 0x01;
+    g_assert_cmpuint(actual, ==, 0x00);
+    qtest_set_irq_in(global_qtest, "/machine/nrf51", "unnamed-gpio-in", 0, 1);
+    actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_IN) & 0x01;
+    g_assert_cmpuint(actual, ==, 0x01);
+    qtest_set_irq_in(global_qtest, "/machine/nrf51", "unnamed-gpio-in", 0, -1);
+    actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_IN) & 0x01;
+    g_assert_cmpuint(actual, ==, 0x01);
+    writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0x02);
+
+    /* Check pull-up working */
+    qtest_set_irq_in(global_qtest, "/machine/nrf51", "unnamed-gpio-in", 0, 0);
+    writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0b0000);
+    actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_IN) & 0x01;
+    g_assert_cmpuint(actual, ==, 0x00);
+    writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0b1110);
+    actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_IN) & 0x01;
+    g_assert_cmpuint(actual, ==, 0x01);
+    writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0x02);
+
+    /* Check pull-down working */
+    qtest_set_irq_in(global_qtest, "/machine/nrf51", "unnamed-gpio-in", 0, 1);
+    writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0b0000);
+    actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_IN) & 0x01;
+    g_assert_cmpuint(actual, ==, 0x01);
+    writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0b0110);
+    actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_IN) & 0x01;
+    g_assert_cmpuint(actual, ==, 0x00);
+    writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0x02);
+    qtest_set_irq_in(global_qtest, "/machine/nrf51", "unnamed-gpio-in", 0, -1);
+
+    /* Check Output propagates */
+    irq_intercept_out("/machine/nrf51");
+    writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0b0011);
+    writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_OUTSET, 0x01);
+    g_assert_true(get_irq(0));
+    writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_OUTCLR, 0x01);
+    g_assert_false(get_irq(0));
+
+    /* Check self-stimulation */
+    writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0b01);
+    writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_OUTSET, 0x01);
+    actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_IN) & 0x01;
+    g_assert_cmpuint(actual, ==, 0x01);
+
+    writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_OUTCLR, 0x01);
+    actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_IN) & 0x01;
+    g_assert_cmpuint(actual, ==, 0x00);
+
+    /*
+     * Check short-circuit - generates an guest_error which must be checked
+     * manually as long as qtest can not scan qemu_log messages
+     */
+    writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0b01);
+    writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_OUTSET, 0x01);
+    qtest_set_irq_in(global_qtest, "/machine/nrf51", "unnamed-gpio-in", 0, 0);
+}
+
+int main(int argc, char **argv)
+{
+    int ret;
+
+    g_test_init(&argc, &argv, NULL);
+
+    global_qtest = qtest_initf("-machine microbit");
+
+    qtest_add_func("/microbit/nrf51/gpio", test_nrf51_gpio);
+
+    ret = g_test_run();
+
+    qtest_quit(global_qtest);
+    return ret;
+}
-- 
2.19.2

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

* [Qemu-devel] [PATCH 08/11] hw/timer/nrf51_timer: Add nRF51 Timer peripheral
  2019-01-03  9:11 [Qemu-devel] [PATCH 00/11] arm: Core nRF51 Devices and Microbit Support Stefan Hajnoczi
                   ` (6 preceding siblings ...)
  2019-01-03  9:11 ` [Qemu-devel] [PATCH 07/11] tests/microbit-test: Add Tests for nRF51 GPIO Stefan Hajnoczi
@ 2019-01-03  9:11 ` Stefan Hajnoczi
  2019-01-03  9:11 ` [Qemu-devel] [PATCH 09/11] arm: Instantiate NRF51 Timers Stefan Hajnoczi
                   ` (3 subsequent siblings)
  11 siblings, 0 replies; 15+ messages in thread
From: Stefan Hajnoczi @ 2019-01-03  9:11 UTC (permalink / raw)
  To: qemu-devel
  Cc: Thomas Huth, qemu-arm, Joel Stanley, Julia Suvorova,
	Paolo Bonzini, Jim Mussared, Steffen Görtz, Peter Maydell,
	Laurent Vivier, Stefan Hajnoczi

From: Steffen Görtz <contrib@steffen-goertz.de>

This patch adds the model for the nRF51 timer peripheral.
Currently, only the TIMER mode is implemented.

Signed-off-by: Steffen Görtz <contrib@steffen-goertz.de>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
 hw/timer/Makefile.objs         |   1 +
 include/hw/timer/nrf51_timer.h |  80 +++++++
 hw/timer/nrf51_timer.c         | 393 +++++++++++++++++++++++++++++++++
 hw/timer/trace-events          |   5 +
 4 files changed, 479 insertions(+)
 create mode 100644 include/hw/timer/nrf51_timer.h
 create mode 100644 hw/timer/nrf51_timer.c

diff --git a/hw/timer/Makefile.objs b/hw/timer/Makefile.objs
index b32194d153..0e9a4530f8 100644
--- a/hw/timer/Makefile.objs
+++ b/hw/timer/Makefile.objs
@@ -23,6 +23,7 @@ common-obj-$(CONFIG_IMX) += imx_gpt.o
 common-obj-$(CONFIG_LM32) += lm32_timer.o
 common-obj-$(CONFIG_MILKYMIST) += milkymist-sysctl.o
 common-obj-$(CONFIG_XLNX_ZYNQMP) += xlnx-zynqmp-rtc.o
+common-obj-$(CONFIG_NRF51_SOC) += nrf51_timer.o
 
 obj-$(CONFIG_ALTERA_TIMER) += altera_timer.o
 obj-$(CONFIG_EXYNOS4) += exynos4210_mct.o
diff --git a/include/hw/timer/nrf51_timer.h b/include/hw/timer/nrf51_timer.h
new file mode 100644
index 0000000000..85cad2300d
--- /dev/null
+++ b/include/hw/timer/nrf51_timer.h
@@ -0,0 +1,80 @@
+/*
+ * nRF51 System-on-Chip Timer peripheral
+ *
+ * QEMU interface:
+ * + sysbus MMIO regions 0: GPIO registers
+ * + sysbus irq
+ *
+ * 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.
+ */
+#ifndef NRF51_TIMER_H
+#define NRF51_TIMER_H
+
+#include "hw/sysbus.h"
+#include "qemu/timer.h"
+#define TYPE_NRF51_TIMER "nrf51_soc.timer"
+#define NRF51_TIMER(obj) OBJECT_CHECK(NRF51TimerState, (obj), TYPE_NRF51_TIMER)
+
+#define NRF51_TIMER_REG_COUNT 4
+
+#define NRF51_TIMER_TASK_START 0x000
+#define NRF51_TIMER_TASK_STOP 0x004
+#define NRF51_TIMER_TASK_COUNT 0x008
+#define NRF51_TIMER_TASK_CLEAR 0x00C
+#define NRF51_TIMER_TASK_SHUTDOWN 0x010
+#define NRF51_TIMER_TASK_CAPTURE_0 0x040
+#define NRF51_TIMER_TASK_CAPTURE_3 0x04C
+
+#define NRF51_TIMER_EVENT_COMPARE_0 0x140
+#define NRF51_TIMER_EVENT_COMPARE_1 0x144
+#define NRF51_TIMER_EVENT_COMPARE_2 0x148
+#define NRF51_TIMER_EVENT_COMPARE_3 0x14C
+
+#define NRF51_TIMER_REG_SHORTS 0x200
+#define NRF51_TIMER_REG_SHORTS_MASK 0xf0f
+#define NRF51_TIMER_REG_INTENSET 0x304
+#define NRF51_TIMER_REG_INTENCLR 0x308
+#define NRF51_TIMER_REG_INTEN_MASK 0xf0000
+#define NRF51_TIMER_REG_MODE 0x504
+#define NRF51_TIMER_REG_MODE_MASK 0x01
+#define NRF51_TIMER_TIMER 0
+#define NRF51_TIMER_COUNTER 1
+#define NRF51_TIMER_REG_BITMODE 0x508
+#define NRF51_TIMER_REG_BITMODE_MASK 0x03
+#define NRF51_TIMER_WIDTH_16 0
+#define NRF51_TIMER_WIDTH_8 1
+#define NRF51_TIMER_WIDTH_24 2
+#define NRF51_TIMER_WIDTH_32 3
+#define NRF51_TIMER_REG_PRESCALER 0x510
+#define NRF51_TIMER_REG_PRESCALER_MASK 0x0F
+#define NRF51_TIMER_REG_CC0 0x540
+#define NRF51_TIMER_REG_CC3 0x54C
+
+typedef struct NRF51TimerState {
+    SysBusDevice parent_obj;
+
+    MemoryRegion iomem;
+    qemu_irq irq;
+
+    QEMUTimer timer;
+    int64_t timer_start_ns;
+    int64_t update_counter_ns;
+    uint32_t counter;
+
+    bool running;
+
+    uint8_t events_compare[NRF51_TIMER_REG_COUNT];
+    uint32_t cc[NRF51_TIMER_REG_COUNT];
+    uint32_t shorts;
+    uint32_t inten;
+    uint32_t mode;
+    uint32_t bitmode;
+    uint32_t prescaler;
+
+} NRF51TimerState;
+
+
+#endif
diff --git a/hw/timer/nrf51_timer.c b/hw/timer/nrf51_timer.c
new file mode 100644
index 0000000000..0c90662896
--- /dev/null
+++ b/hw/timer/nrf51_timer.c
@@ -0,0 +1,393 @@
+/*
+ * nRF51 System-on-Chip Timer peripheral
+ *
+ * Reference Manual: http://infocenter.nordicsemi.com/pdf/nRF51_RM_v3.0.pdf
+ * Product Spec: http://infocenter.nordicsemi.com/pdf/nRF51822_PS_v3.1.pdf
+ *
+ * Copyright 2018 Steffen Görtz <contrib@steffen-goertz.de>
+ * Copyright (c) 2019 Red Hat, Inc.
+ *
+ * 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 "hw/arm/nrf51.h"
+#include "hw/timer/nrf51_timer.h"
+#include "trace.h"
+
+#define TIMER_CLK_FREQ 16000000UL
+
+static uint32_t const bitwidths[] = {16, 8, 24, 32};
+
+static uint32_t ns_to_ticks(NRF51TimerState *s, int64_t ns)
+{
+    uint32_t freq = TIMER_CLK_FREQ >> s->prescaler;
+
+    return muldiv64(ns, freq, NANOSECONDS_PER_SECOND);
+}
+
+static int64_t ticks_to_ns(NRF51TimerState *s, uint32_t ticks)
+{
+    uint32_t freq = TIMER_CLK_FREQ >> s->prescaler;
+
+    return muldiv64(ticks, NANOSECONDS_PER_SECOND, freq);
+}
+
+/* Returns number of ticks since last call */
+static uint32_t update_counter(NRF51TimerState *s, int64_t now)
+{
+    uint32_t ticks = ns_to_ticks(s, now - s->update_counter_ns);
+
+    s->counter = (s->counter + ticks) % BIT(bitwidths[s->bitmode]);
+    s->update_counter_ns = now;
+    return ticks;
+}
+
+/* Assumes s->counter is up-to-date */
+static void rearm_timer(NRF51TimerState *s, int64_t now)
+{
+    int64_t min_ns = INT64_MAX;
+    size_t i;
+
+    for (i = 0; i < NRF51_TIMER_REG_COUNT; i++) {
+        int64_t delta_ns;
+
+        if (s->events_compare[i]) {
+            continue; /* already expired, ignore it for now */
+        }
+
+        if (s->cc[i] <= s->counter) {
+            delta_ns = ticks_to_ns(s, BIT(bitwidths[s->bitmode]) -
+                                      s->counter + s->cc[i]);
+        } else {
+            delta_ns = ticks_to_ns(s, s->cc[i] - s->counter);
+        }
+
+        if (delta_ns < min_ns) {
+            min_ns = delta_ns;
+        }
+    }
+
+    if (min_ns != INT64_MAX) {
+        timer_mod_ns(&s->timer, now + min_ns);
+    }
+}
+
+static void update_irq(NRF51TimerState *s)
+{
+    bool flag = false;
+    size_t i;
+
+    for (i = 0; i < NRF51_TIMER_REG_COUNT; i++) {
+        flag |= s->events_compare[i] && extract32(s->inten, 16 + i, 1);
+    }
+    qemu_set_irq(s->irq, flag);
+}
+
+static void timer_expire(void *opaque)
+{
+    NRF51TimerState *s = NRF51_TIMER(opaque);
+    int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+    uint32_t cc_remaining[NRF51_TIMER_REG_COUNT];
+    bool should_stop = false;
+    uint32_t ticks;
+    size_t i;
+
+    for (i = 0; i < NRF51_TIMER_REG_COUNT; i++) {
+        if (s->cc[i] > s->counter) {
+            cc_remaining[i] = s->cc[i] - s->counter;
+        } else {
+            cc_remaining[i] = BIT(bitwidths[s->bitmode]) -
+                              s->counter + s->cc[i];
+        }
+    }
+
+    ticks = update_counter(s, now);
+
+    for (i = 0; i < NRF51_TIMER_REG_COUNT; i++) {
+        if (cc_remaining[i] <= ticks) {
+            s->events_compare[i] = 1;
+
+            if (s->shorts & BIT(i)) {
+                s->timer_start_ns = now;
+                s->update_counter_ns = s->timer_start_ns;
+                s->counter = 0;
+            }
+
+            should_stop |= s->shorts & BIT(i + 8);
+        }
+    }
+
+    update_irq(s);
+
+    if (should_stop) {
+        s->running = false;
+        timer_del(&s->timer);
+    } else {
+        rearm_timer(s, now);
+    }
+}
+
+static void counter_compare(NRF51TimerState *s)
+{
+    uint32_t counter = s->counter;
+    size_t i;
+
+    for (i = 0; i < NRF51_TIMER_REG_COUNT; i++) {
+        if (counter == s->cc[i]) {
+            s->events_compare[i] = 1;
+
+            if (s->shorts & BIT(i)) {
+                s->counter = 0;
+            }
+        }
+    }
+}
+
+static uint64_t nrf51_timer_read(void *opaque, hwaddr offset, unsigned int size)
+{
+    NRF51TimerState *s = NRF51_TIMER(opaque);
+    uint64_t r = 0;
+
+    switch (offset) {
+    case NRF51_TIMER_EVENT_COMPARE_0 ... NRF51_TIMER_EVENT_COMPARE_3:
+        r = s->events_compare[(offset - NRF51_TIMER_EVENT_COMPARE_0) / 4];
+        break;
+    case NRF51_TIMER_REG_SHORTS:
+        r = s->shorts;
+        break;
+    case NRF51_TIMER_REG_INTENSET:
+        r = s->inten;
+        break;
+    case NRF51_TIMER_REG_INTENCLR:
+        r = s->inten;
+        break;
+    case NRF51_TIMER_REG_MODE:
+        r = s->mode;
+        break;
+    case NRF51_TIMER_REG_BITMODE:
+        r = s->bitmode;
+        break;
+    case NRF51_TIMER_REG_PRESCALER:
+        r = s->prescaler;
+        break;
+    case NRF51_TIMER_REG_CC0 ... NRF51_TIMER_REG_CC3:
+        r = s->cc[(offset - NRF51_TIMER_REG_CC0) / 4];
+        break;
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR,
+                "%s: bad read offset 0x%" HWADDR_PRIx "\n",
+                      __func__, offset);
+    }
+
+    trace_nrf51_timer_read(offset, r, size);
+
+    return r;
+}
+
+static void nrf51_timer_write(void *opaque, hwaddr offset,
+                       uint64_t value, unsigned int size)
+{
+    NRF51TimerState *s = NRF51_TIMER(opaque);
+    uint64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+    size_t idx;
+
+    trace_nrf51_timer_write(offset, value, size);
+
+    switch (offset) {
+    case NRF51_TIMER_TASK_START:
+        if (value == NRF51_TRIGGER_TASK && s->mode == NRF51_TIMER_TIMER) {
+            s->running = true;
+            s->timer_start_ns = now - ticks_to_ns(s, s->counter);
+            s->update_counter_ns = s->timer_start_ns;
+            rearm_timer(s, now);
+        }
+        break;
+    case NRF51_TIMER_TASK_STOP:
+    case NRF51_TIMER_TASK_SHUTDOWN:
+        if (value == NRF51_TRIGGER_TASK) {
+            s->running = false;
+            timer_del(&s->timer);
+        }
+        break;
+    case NRF51_TIMER_TASK_COUNT:
+        if (value == NRF51_TRIGGER_TASK && s->mode == NRF51_TIMER_COUNTER) {
+            s->counter = (s->counter + 1) % BIT(bitwidths[s->bitmode]);
+            counter_compare(s);
+        }
+        break;
+    case NRF51_TIMER_TASK_CLEAR:
+        if (value == NRF51_TRIGGER_TASK) {
+            s->timer_start_ns = now;
+            s->update_counter_ns = s->timer_start_ns;
+            s->counter = 0;
+            if (s->running) {
+                rearm_timer(s, now);
+            }
+        }
+        break;
+    case NRF51_TIMER_TASK_CAPTURE_0 ... NRF51_TIMER_TASK_CAPTURE_3:
+        if (value == NRF51_TRIGGER_TASK) {
+            if (s->running) {
+                timer_expire(s); /* update counter and all state */
+            }
+
+            idx = (offset - NRF51_TIMER_TASK_CAPTURE_0) / 4;
+            s->cc[idx] = s->counter;
+        }
+        break;
+    case NRF51_TIMER_EVENT_COMPARE_0 ... NRF51_TIMER_EVENT_COMPARE_3:
+        if (value == NRF51_EVENT_CLEAR) {
+            s->events_compare[(offset - NRF51_TIMER_EVENT_COMPARE_0) / 4] = 0;
+
+            if (s->running) {
+                timer_expire(s); /* update counter and all state */
+            }
+        }
+        break;
+    case NRF51_TIMER_REG_SHORTS:
+        s->shorts = value & NRF51_TIMER_REG_SHORTS_MASK;
+        break;
+    case NRF51_TIMER_REG_INTENSET:
+        s->inten |= value & NRF51_TIMER_REG_INTEN_MASK;
+        break;
+    case NRF51_TIMER_REG_INTENCLR:
+        s->inten &= ~(value & NRF51_TIMER_REG_INTEN_MASK);
+        break;
+    case NRF51_TIMER_REG_MODE:
+        s->mode = value;
+        break;
+    case NRF51_TIMER_REG_BITMODE:
+        if (s->mode == NRF51_TIMER_TIMER && s->running) {
+            qemu_log_mask(LOG_GUEST_ERROR,
+                    "%s: erroneous change of BITMODE while timer is running\n",
+                    __func__);
+        }
+        s->bitmode = value & NRF51_TIMER_REG_BITMODE_MASK;
+        break;
+    case NRF51_TIMER_REG_PRESCALER:
+        if (s->mode == NRF51_TIMER_TIMER && s->running) {
+            qemu_log_mask(LOG_GUEST_ERROR,
+                "%s: erroneous change of PRESCALER while timer is running\n",
+                __func__);
+        }
+        s->prescaler = value & NRF51_TIMER_REG_PRESCALER_MASK;
+        break;
+    case NRF51_TIMER_REG_CC0 ... NRF51_TIMER_REG_CC3:
+        if (s->running) {
+            timer_expire(s); /* update counter */
+        }
+
+        idx = (offset - NRF51_TIMER_REG_CC0) / 4;
+        s->cc[idx] = value % BIT(bitwidths[s->bitmode]);
+
+        if (s->running) {
+            rearm_timer(s, now);
+        }
+        break;
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "%s: bad write offset 0x%" HWADDR_PRIx "\n",
+                      __func__, offset);
+    }
+
+    update_irq(s);
+}
+
+static const MemoryRegionOps rng_ops = {
+    .read =  nrf51_timer_read,
+    .write = nrf51_timer_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .impl.min_access_size = 4,
+    .impl.max_access_size = 4,
+};
+
+static void nrf51_timer_init(Object *obj)
+{
+    NRF51TimerState *s = NRF51_TIMER(obj);
+    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+
+    memory_region_init_io(&s->iomem, obj, &rng_ops, s,
+            TYPE_NRF51_TIMER, NRF51_TIMER_SIZE);
+    sysbus_init_mmio(sbd, &s->iomem);
+    sysbus_init_irq(sbd, &s->irq);
+
+    timer_init_ns(&s->timer, QEMU_CLOCK_VIRTUAL, timer_expire, s);
+}
+
+static void nrf51_timer_reset(DeviceState *dev)
+{
+    NRF51TimerState *s = NRF51_TIMER(dev);
+
+    timer_del(&s->timer);
+    s->timer_start_ns = 0x00;
+    s->update_counter_ns = 0x00;
+    s->counter = 0x00;
+    s->running = false;
+
+    memset(s->events_compare, 0x00, sizeof(s->events_compare));
+    memset(s->cc, 0x00, sizeof(s->cc));
+
+    s->shorts = 0x00;
+    s->inten = 0x00;
+    s->mode = 0x00;
+    s->bitmode = 0x00;
+    s->prescaler = 0x00;
+}
+
+static int nrf51_timer_post_load(void *opaque, int version_id)
+{
+    NRF51TimerState *s = NRF51_TIMER(opaque);
+
+    if (s->running && s->mode == NRF51_TIMER_TIMER) {
+        timer_expire(s);
+    }
+    return 0;
+}
+
+static const VMStateDescription vmstate_nrf51_timer = {
+    .name = TYPE_NRF51_TIMER,
+    .version_id = 1,
+    .post_load = nrf51_timer_post_load,
+    .fields = (VMStateField[]) {
+        VMSTATE_TIMER(timer, NRF51TimerState),
+        VMSTATE_INT64(timer_start_ns, NRF51TimerState),
+        VMSTATE_INT64(update_counter_ns, NRF51TimerState),
+        VMSTATE_UINT32(counter, NRF51TimerState),
+        VMSTATE_BOOL(running, NRF51TimerState),
+        VMSTATE_UINT8_ARRAY(events_compare, NRF51TimerState,
+                            NRF51_TIMER_REG_COUNT),
+        VMSTATE_UINT32_ARRAY(cc, NRF51TimerState, NRF51_TIMER_REG_COUNT),
+        VMSTATE_UINT32(shorts, NRF51TimerState),
+        VMSTATE_UINT32(inten, NRF51TimerState),
+        VMSTATE_UINT32(mode, NRF51TimerState),
+        VMSTATE_UINT32(bitmode, NRF51TimerState),
+        VMSTATE_UINT32(prescaler, NRF51TimerState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void nrf51_timer_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->reset = nrf51_timer_reset;
+    dc->vmsd = &vmstate_nrf51_timer;
+}
+
+static const TypeInfo nrf51_timer_info = {
+    .name = TYPE_NRF51_TIMER,
+    .parent = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(NRF51TimerState),
+    .instance_init = nrf51_timer_init,
+    .class_init = nrf51_timer_class_init
+};
+
+static void nrf51_timer_register_types(void)
+{
+    type_register_static(&nrf51_timer_info);
+}
+
+type_init(nrf51_timer_register_types)
diff --git a/hw/timer/trace-events b/hw/timer/trace-events
index 75bd3b1042..0144a68951 100644
--- a/hw/timer/trace-events
+++ b/hw/timer/trace-events
@@ -72,3 +72,8 @@ sun4v_rtc_write(uint64_t addr, uint64_t value) "write: addr 0x%" PRIx64 " value
 
 # hw/timer/xlnx-zynqmp-rtc.c
 xlnx_zynqmp_rtc_gettime(int year, int month, int day, int hour, int min, int sec) "Get time from host: %d-%d-%d %2d:%02d:%02d"
+
+# hw/timer/nrf51_timer.c
+nrf51_timer_read(uint64_t addr, uint32_t value, unsigned size) "read addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u"
+nrf51_timer_write(uint64_t addr, uint32_t value, unsigned size) "write addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u"
+
-- 
2.19.2

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

* [Qemu-devel] [PATCH 09/11] arm: Instantiate NRF51 Timers
  2019-01-03  9:11 [Qemu-devel] [PATCH 00/11] arm: Core nRF51 Devices and Microbit Support Stefan Hajnoczi
                   ` (7 preceding siblings ...)
  2019-01-03  9:11 ` [Qemu-devel] [PATCH 08/11] hw/timer/nrf51_timer: Add nRF51 Timer peripheral Stefan Hajnoczi
@ 2019-01-03  9:11 ` Stefan Hajnoczi
  2019-01-03  9:11 ` [Qemu-devel] [PATCH 10/11] tests/microbit-test: Add Tests for nRF51 Timer Stefan Hajnoczi
                   ` (2 subsequent siblings)
  11 siblings, 0 replies; 15+ messages in thread
From: Stefan Hajnoczi @ 2019-01-03  9:11 UTC (permalink / raw)
  To: qemu-devel
  Cc: Thomas Huth, qemu-arm, Joel Stanley, Julia Suvorova,
	Paolo Bonzini, Jim Mussared, Steffen Görtz, Peter Maydell,
	Laurent Vivier, Stefan Hajnoczi

From: Steffen Görtz <contrib@steffen-goertz.de>

Instantiates TIMER0 - TIMER2

Signed-off-by: Steffen Görtz <contrib@steffen-goertz.de>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
 include/hw/arm/nrf51_soc.h |  4 ++++
 hw/arm/nrf51_soc.c         | 26 ++++++++++++++++++++++++++
 2 files changed, 30 insertions(+)

diff --git a/include/hw/arm/nrf51_soc.h b/include/hw/arm/nrf51_soc.h
index 84e0278881..39e613e1c9 100644
--- a/include/hw/arm/nrf51_soc.h
+++ b/include/hw/arm/nrf51_soc.h
@@ -15,11 +15,14 @@
 #include "hw/char/nrf51_uart.h"
 #include "hw/misc/nrf51_rng.h"
 #include "hw/gpio/nrf51_gpio.h"
+#include "hw/timer/nrf51_timer.h"
 
 #define TYPE_NRF51_SOC "nrf51-soc"
 #define NRF51_SOC(obj) \
     OBJECT_CHECK(NRF51State, (obj), TYPE_NRF51_SOC)
 
+#define NRF51_NUM_TIMERS 3
+
 typedef struct NRF51State {
     /*< private >*/
     SysBusDevice parent_obj;
@@ -30,6 +33,7 @@ typedef struct NRF51State {
     NRF51UARTState uart;
     NRF51RNGState rng;
     NRF51GPIOState gpio;
+    NRF51TimerState timer[NRF51_NUM_TIMERS];
 
     MemoryRegion iomem;
     MemoryRegion sram;
diff --git a/hw/arm/nrf51_soc.c b/hw/arm/nrf51_soc.c
index db817fe506..ef70bd62fa 100644
--- a/hw/arm/nrf51_soc.c
+++ b/hw/arm/nrf51_soc.c
@@ -39,6 +39,8 @@ static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp)
     NRF51State *s = NRF51_SOC(dev_soc);
     MemoryRegion *mr;
     Error *err = NULL;
+    uint8_t i = 0;
+    hwaddr base_addr = 0;
 
     if (!s->board_memory) {
         error_setg(errp, "memory property was not set");
@@ -112,6 +114,22 @@ static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp)
     /* Pass all GPIOs to the SOC layer so they are available to the board */
     qdev_pass_gpios(DEVICE(&s->gpio), dev_soc, NULL);
 
+    /* TIMER */
+    for (i = 0; i < NRF51_NUM_TIMERS; i++) {
+        object_property_set_bool(OBJECT(&s->timer[i]), true, "realized", &err);
+        if (err) {
+            error_propagate(errp, err);
+            return;
+        }
+
+        base_addr = NRF51_TIMER_BASE + i * NRF51_TIMER_SIZE;
+
+        sysbus_mmio_map(SYS_BUS_DEVICE(&s->timer[i]), 0, base_addr);
+        sysbus_connect_irq(SYS_BUS_DEVICE(&s->timer[i]), 0,
+                           qdev_get_gpio_in(DEVICE(&s->cpu),
+                                            BASE_TO_IRQ(base_addr)));
+    }
+
     create_unimplemented_device("nrf51_soc.io", NRF51_IOMEM_BASE,
                                 NRF51_IOMEM_SIZE);
     create_unimplemented_device("nrf51_soc.ficr", NRF51_FICR_BASE,
@@ -122,6 +140,8 @@ static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp)
 
 static void nrf51_soc_init(Object *obj)
 {
+    uint8_t i = 0;
+
     NRF51State *s = NRF51_SOC(obj);
 
     memory_region_init(&s->container, obj, "nrf51-container", UINT64_MAX);
@@ -142,6 +162,12 @@ static void nrf51_soc_init(Object *obj)
 
     sysbus_init_child_obj(obj, "gpio", &s->gpio, sizeof(s->gpio),
                           TYPE_NRF51_GPIO);
+
+    for (i = 0; i < NRF51_NUM_TIMERS; i++) {
+        sysbus_init_child_obj(obj, "timer[*]", &s->timer[i],
+                              sizeof(s->timer[i]), TYPE_NRF51_TIMER);
+
+    }
 }
 
 static Property nrf51_soc_properties[] = {
-- 
2.19.2

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

* [Qemu-devel] [PATCH 10/11] tests/microbit-test: Add Tests for nRF51 Timer
  2019-01-03  9:11 [Qemu-devel] [PATCH 00/11] arm: Core nRF51 Devices and Microbit Support Stefan Hajnoczi
                   ` (8 preceding siblings ...)
  2019-01-03  9:11 ` [Qemu-devel] [PATCH 09/11] arm: Instantiate NRF51 Timers Stefan Hajnoczi
@ 2019-01-03  9:11 ` Stefan Hajnoczi
  2019-01-03  9:11 ` [Qemu-devel] [PATCH 11/11] arm: Add Clock peripheral stub to NRF51 SOC Stefan Hajnoczi
  2019-01-07 15:19 ` [Qemu-devel] [PATCH 00/11] arm: Core nRF51 Devices and Microbit Support Peter Maydell
  11 siblings, 0 replies; 15+ messages in thread
From: Stefan Hajnoczi @ 2019-01-03  9:11 UTC (permalink / raw)
  To: qemu-devel
  Cc: Thomas Huth, qemu-arm, Joel Stanley, Julia Suvorova,
	Paolo Bonzini, Jim Mussared, Steffen Görtz, Peter Maydell,
	Laurent Vivier, Stefan Hajnoczi

From: Steffen Görtz <contrib@steffen-goertz.de>

Basic tests for nRF51 Timer Peripheral.

Signed-off-by: Steffen Görtz <contrib@steffen-goertz.de>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
 tests/microbit-test.c | 95 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 95 insertions(+)

diff --git a/tests/microbit-test.c b/tests/microbit-test.c
index 535714797a..16dffb1396 100644
--- a/tests/microbit-test.c
+++ b/tests/microbit-test.c
@@ -20,6 +20,7 @@
 
 #include "hw/arm/nrf51.h"
 #include "hw/gpio/nrf51_gpio.h"
+#include "hw/timer/nrf51_timer.h"
 
 static void test_nrf51_gpio(void)
 {
@@ -143,6 +144,99 @@ static void test_nrf51_gpio(void)
     qtest_set_irq_in(global_qtest, "/machine/nrf51", "unnamed-gpio-in", 0, 0);
 }
 
+static void timer_task(hwaddr task)
+{
+    writel(NRF51_TIMER_BASE + task, NRF51_TRIGGER_TASK);
+}
+
+static void timer_clear_event(hwaddr event)
+{
+    writel(NRF51_TIMER_BASE + event, NRF51_EVENT_CLEAR);
+}
+
+static void timer_set_bitmode(uint8_t mode)
+{
+    writel(NRF51_TIMER_BASE + NRF51_TIMER_REG_BITMODE, mode);
+}
+
+static void timer_set_prescaler(uint8_t prescaler)
+{
+    writel(NRF51_TIMER_BASE + NRF51_TIMER_REG_PRESCALER, prescaler);
+}
+
+static void timer_set_cc(size_t idx, uint32_t value)
+{
+    writel(NRF51_TIMER_BASE + NRF51_TIMER_REG_CC0 + idx * 4, value);
+}
+
+static void timer_assert_events(uint32_t ev0, uint32_t ev1, uint32_t ev2,
+                                uint32_t ev3)
+{
+    g_assert(readl(NRF51_TIMER_BASE + NRF51_TIMER_EVENT_COMPARE_0) == ev0);
+    g_assert(readl(NRF51_TIMER_BASE + NRF51_TIMER_EVENT_COMPARE_1) == ev1);
+    g_assert(readl(NRF51_TIMER_BASE + NRF51_TIMER_EVENT_COMPARE_2) == ev2);
+    g_assert(readl(NRF51_TIMER_BASE + NRF51_TIMER_EVENT_COMPARE_3) == ev3);
+}
+
+static void test_nrf51_timer(void)
+{
+    uint32_t steps_to_overflow = 408;
+
+    /* Compare Match */
+    timer_task(NRF51_TIMER_TASK_STOP);
+    timer_task(NRF51_TIMER_TASK_CLEAR);
+
+    timer_clear_event(NRF51_TIMER_EVENT_COMPARE_0);
+    timer_clear_event(NRF51_TIMER_EVENT_COMPARE_1);
+    timer_clear_event(NRF51_TIMER_EVENT_COMPARE_2);
+    timer_clear_event(NRF51_TIMER_EVENT_COMPARE_3);
+
+    timer_set_bitmode(NRF51_TIMER_WIDTH_16); /* 16 MHz Timer */
+    timer_set_prescaler(0);
+    /* Swept over in first step */
+    timer_set_cc(0, 2);
+    /* Barely miss on first step */
+    timer_set_cc(1, 162);
+    /* Spot on on third step */
+    timer_set_cc(2, 480);
+
+    timer_assert_events(0, 0, 0, 0);
+
+    timer_task(NRF51_TIMER_TASK_START);
+    clock_step(10000);
+    timer_assert_events(1, 0, 0, 0);
+
+    /* Swept over on first overflow */
+    timer_set_cc(3, 114);
+
+    clock_step(10000);
+    timer_assert_events(1, 1, 0, 0);
+
+    clock_step(10000);
+    timer_assert_events(1, 1, 1, 0);
+
+    /* Wrap time until internal counter overflows */
+    while (steps_to_overflow--) {
+        timer_assert_events(1, 1, 1, 0);
+        clock_step(10000);
+    }
+
+    timer_assert_events(1, 1, 1, 1);
+
+    timer_clear_event(NRF51_TIMER_EVENT_COMPARE_0);
+    timer_clear_event(NRF51_TIMER_EVENT_COMPARE_1);
+    timer_clear_event(NRF51_TIMER_EVENT_COMPARE_2);
+    timer_clear_event(NRF51_TIMER_EVENT_COMPARE_3);
+    timer_assert_events(0, 0, 0, 0);
+
+    timer_task(NRF51_TIMER_TASK_STOP);
+
+    /* Test Proposal: Stop/Shutdown */
+    /* Test Proposal: Shortcut Compare -> Clear */
+    /* Test Proposal: Shortcut Compare -> Stop */
+    /* Test Proposal: Counter Mode */
+}
+
 int main(int argc, char **argv)
 {
     int ret;
@@ -152,6 +246,7 @@ int main(int argc, char **argv)
     global_qtest = qtest_initf("-machine microbit");
 
     qtest_add_func("/microbit/nrf51/gpio", test_nrf51_gpio);
+    qtest_add_func("/microbit/nrf51/timer", test_nrf51_timer);
 
     ret = g_test_run();
 
-- 
2.19.2

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

* [Qemu-devel] [PATCH 11/11] arm: Add Clock peripheral stub to NRF51 SOC
  2019-01-03  9:11 [Qemu-devel] [PATCH 00/11] arm: Core nRF51 Devices and Microbit Support Stefan Hajnoczi
                   ` (9 preceding siblings ...)
  2019-01-03  9:11 ` [Qemu-devel] [PATCH 10/11] tests/microbit-test: Add Tests for nRF51 Timer Stefan Hajnoczi
@ 2019-01-03  9:11 ` Stefan Hajnoczi
  2019-01-07 15:19 ` [Qemu-devel] [PATCH 00/11] arm: Core nRF51 Devices and Microbit Support Peter Maydell
  11 siblings, 0 replies; 15+ messages in thread
From: Stefan Hajnoczi @ 2019-01-03  9:11 UTC (permalink / raw)
  To: qemu-devel
  Cc: Thomas Huth, qemu-arm, Joel Stanley, Julia Suvorova,
	Paolo Bonzini, Jim Mussared, Steffen Görtz, Peter Maydell,
	Laurent Vivier, Stefan Hajnoczi

From: Steffen Görtz <contrib@steffen-goertz.de>

This stubs enables the microbit-micropython firmware to run
on the microbit machine.

Signed-off-by: Steffen Görtz <contrib@steffen-goertz.de>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
 include/hw/arm/nrf51_soc.h |  1 +
 hw/arm/nrf51_soc.c         | 26 ++++++++++++++++++++++++++
 2 files changed, 27 insertions(+)

diff --git a/include/hw/arm/nrf51_soc.h b/include/hw/arm/nrf51_soc.h
index 39e613e1c9..e06f0304b4 100644
--- a/include/hw/arm/nrf51_soc.h
+++ b/include/hw/arm/nrf51_soc.h
@@ -38,6 +38,7 @@ typedef struct NRF51State {
     MemoryRegion iomem;
     MemoryRegion sram;
     MemoryRegion flash;
+    MemoryRegion clock;
 
     uint32_t sram_size;
     uint32_t flash_size;
diff --git a/hw/arm/nrf51_soc.c b/hw/arm/nrf51_soc.c
index ef70bd62fa..1630c27594 100644
--- a/hw/arm/nrf51_soc.c
+++ b/hw/arm/nrf51_soc.c
@@ -34,6 +34,26 @@
 
 #define BASE_TO_IRQ(base) ((base >> 12) & 0x1F)
 
+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);
+    return 1;
+}
+
+static void clock_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 clock_ops = {
+    .read = clock_read,
+    .write = clock_write
+};
+
+
 static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp)
 {
     NRF51State *s = NRF51_SOC(dev_soc);
@@ -130,6 +150,12 @@ static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp)
                                             BASE_TO_IRQ(base_addr)));
     }
 
+    /* STUB Peripherals */
+    memory_region_init_io(&s->clock, NULL, &clock_ops, NULL,
+                          "nrf51_soc.clock", 0x1000);
+    memory_region_add_subregion_overlap(&s->container,
+                                        NRF51_IOMEM_BASE, &s->clock, -1);
+
     create_unimplemented_device("nrf51_soc.io", NRF51_IOMEM_BASE,
                                 NRF51_IOMEM_SIZE);
     create_unimplemented_device("nrf51_soc.ficr", NRF51_FICR_BASE,
-- 
2.19.2

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

* Re: [Qemu-devel] [PATCH 02/11] arm: Add header to host common definition for nRF51 SOC peripherals
  2019-01-03  9:11 ` [Qemu-devel] [PATCH 02/11] arm: Add header to host common definition for nRF51 SOC peripherals Stefan Hajnoczi
@ 2019-01-03 10:40   ` Philippe Mathieu-Daudé
  2019-01-04  9:51     ` Stefan Hajnoczi
  0 siblings, 1 reply; 15+ messages in thread
From: Philippe Mathieu-Daudé @ 2019-01-03 10:40 UTC (permalink / raw)
  To: Stefan Hajnoczi, qemu-devel
  Cc: Laurent Vivier, Peter Maydell, Thomas Huth, Steffen Görtz,
	Jim Mussared, qemu-arm, Joel Stanley, Paolo Bonzini,
	Julia Suvorova

On 1/3/19 10:11 AM, Stefan Hajnoczi wrote:
> From: Steffen Görtz <contrib@steffen-goertz.de>
> 
> Adds a header that provides definitions that are used
> across nRF51 peripherals
> 
> Signed-off-by: Steffen Görtz <contrib@steffen-goertz.de>
> Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
> Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
> Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
> ---
>  include/hw/arm/nrf51.h       | 45 ++++++++++++++++++++++++++++++++++++
>  include/hw/char/nrf51_uart.h |  1 -
>  hw/arm/nrf51_soc.c           | 33 ++++++++++----------------
>  3 files changed, 57 insertions(+), 22 deletions(-)
>  create mode 100644 include/hw/arm/nrf51.h
> 
> diff --git a/include/hw/arm/nrf51.h b/include/hw/arm/nrf51.h
> new file mode 100644
> index 0000000000..175bb6c301
> --- /dev/null
> +++ b/include/hw/arm/nrf51.h
> @@ -0,0 +1,45 @@
> +/*
> + * Nordic Semiconductor nRF51 Series SOC Common Defines
> + *
> + * This file hosts generic defines used in various nRF51 peripheral devices.
> + *
> + * Reference Manual: http://infocenter.nordicsemi.com/pdf/nRF51_RM_v3.0.pdf
> + * Product Spec: http://infocenter.nordicsemi.com/pdf/nRF51822_PS_v3.1.pdf
> + *
> + * 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.
> + */
> +
> +#ifndef NRF51_H
> +#define NRF51_H
> +
> +#define NRF51_FLASH_BASE      0x00000000
> +#define NRF51_FICR_BASE       0x10000000
> +#define NRF51_FICR_SIZE       0x00000100
> +#define NRF51_UICR_BASE       0x10001000
> +#define NRF51_SRAM_BASE       0x20000000
> +
> +#define NRF51_IOMEM_BASE      0x40000000
> +#define NRF51_IOMEM_SIZE      0x20000000
> +
> +#define NRF51_UART_BASE       0x40002000
> +#define NRF51_TIMER_BASE      0x40008000
> +#define NRF51_TIMER_SIZE      0x00001000
> +#define NRF51_RNG_BASE        0x4000D000
> +#define NRF51_NVMC_BASE       0x4001E000
> +#define NRF51_GPIO_BASE       0x50000000
> +
> +#define NRF51_PRIVATE_BASE    0xF0000000
> +#define NRF51_PRIVATE_SIZE    0x10000000
> +
> +#define NRF51_PAGE_SIZE       1024

I'd keep this file in hw/arm (not include/...).

> +
> +/* Trigger */
> +#define NRF51_TRIGGER_TASK 0x01
> +
> +/* Events */
> +#define NRF51_EVENT_CLEAR  0x00

These definitions might be the only one used out of hw/arm/.

> +
> +#endif
> diff --git a/include/hw/char/nrf51_uart.h b/include/hw/char/nrf51_uart.h
> index e3ecb7c81c..eb1c15b490 100644
> --- a/include/hw/char/nrf51_uart.h
> +++ b/include/hw/char/nrf51_uart.h
> @@ -16,7 +16,6 @@
>  #include "hw/registerfields.h"
>  
>  #define UART_FIFO_LENGTH 6
> -#define UART_BASE 0x40002000
>  #define UART_SIZE 0x1000
>  
>  #define TYPE_NRF51_UART "nrf51_soc.uart"
> diff --git a/hw/arm/nrf51_soc.c b/hw/arm/nrf51_soc.c
> index b89c1bdea0..55f8eaafcb 100644
> --- a/hw/arm/nrf51_soc.c
> +++ b/hw/arm/nrf51_soc.c
> @@ -21,27 +21,16 @@
>  #include "qemu/log.h"
>  #include "cpu.h"
>  
> +#include "hw/arm/nrf51.h"
>  #include "hw/arm/nrf51_soc.h"
>  
> -#define IOMEM_BASE      0x40000000
> -#define IOMEM_SIZE      0x20000000
> -
> -#define FICR_BASE       0x10000000
> -#define FICR_SIZE       0x000000fc
> -
> -#define FLASH_BASE      0x00000000
> -#define SRAM_BASE       0x20000000
> -
> -#define PRIVATE_BASE    0xF0000000
> -#define PRIVATE_SIZE    0x10000000
> -
>  /*
>   * The size and base is for the NRF51822 part. If other parts
>   * are supported in the future, add a sub-class of NRF51SoC for
>   * the specific variants
>   */
> -#define NRF51822_FLASH_SIZE     (256 * 1024)
> -#define NRF51822_SRAM_SIZE      (16 * 1024)
> +#define NRF51822_FLASH_SIZE     (256 * NRF51_PAGE_SIZE)
> +#define NRF51822_SRAM_SIZE      (16 * NRF51_PAGE_SIZE)
>  
>  #define BASE_TO_IRQ(base) ((base >> 12) & 0x1F)
>  
> @@ -76,14 +65,14 @@ static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp)
>          error_propagate(errp, err);
>          return;
>      }
> -    memory_region_add_subregion(&s->container, FLASH_BASE, &s->flash);
> +    memory_region_add_subregion(&s->container, NRF51_FLASH_BASE, &s->flash);
>  
>      memory_region_init_ram(&s->sram, NULL, "nrf51.sram", s->sram_size, &err);
>      if (err) {
>          error_propagate(errp, err);
>          return;
>      }
> -    memory_region_add_subregion(&s->container, SRAM_BASE, &s->sram);
> +    memory_region_add_subregion(&s->container, NRF51_SRAM_BASE, &s->sram);
>  
>      /* UART */
>      object_property_set_bool(OBJECT(&s->uart), true, "realized", &err);
> @@ -92,15 +81,17 @@ static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp)
>          return;
>      }
>      mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->uart), 0);
> -    memory_region_add_subregion_overlap(&s->container, UART_BASE, mr, 0);
> +    memory_region_add_subregion_overlap(&s->container, NRF51_UART_BASE, mr, 0);
>      sysbus_connect_irq(SYS_BUS_DEVICE(&s->uart), 0,
>                         qdev_get_gpio_in(DEVICE(&s->cpu),
> -                       BASE_TO_IRQ(UART_BASE)));
> +                       BASE_TO_IRQ(NRF51_UART_BASE)));
>  
> -    create_unimplemented_device("nrf51_soc.io", IOMEM_BASE, IOMEM_SIZE);
> -    create_unimplemented_device("nrf51_soc.ficr", FICR_BASE, FICR_SIZE);
> +    create_unimplemented_device("nrf51_soc.io", NRF51_IOMEM_BASE,
> +                                NRF51_IOMEM_SIZE);
> +    create_unimplemented_device("nrf51_soc.ficr", NRF51_FICR_BASE,
> +                                NRF51_FICR_SIZE);
>      create_unimplemented_device("nrf51_soc.private",
> -                                PRIVATE_BASE, PRIVATE_SIZE);
> +                                NRF51_PRIVATE_BASE, NRF51_PRIVATE_SIZE);
>  }
>  
>  static void nrf51_soc_init(Object *obj)
> 

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

* Re: [Qemu-devel] [PATCH 02/11] arm: Add header to host common definition for nRF51 SOC peripherals
  2019-01-03 10:40   ` Philippe Mathieu-Daudé
@ 2019-01-04  9:51     ` Stefan Hajnoczi
  0 siblings, 0 replies; 15+ messages in thread
From: Stefan Hajnoczi @ 2019-01-04  9:51 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé
  Cc: qemu-devel, Laurent Vivier, Peter Maydell, Thomas Huth,
	Steffen Görtz, Jim Mussared, qemu-arm, Joel Stanley,
	Paolo Bonzini, Julia Suvorova

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

On Thu, Jan 03, 2019 at 11:40:30AM +0100, Philippe Mathieu-Daudé wrote:
> On 1/3/19 10:11 AM, Stefan Hajnoczi wrote:
> > From: Steffen Görtz <contrib@steffen-goertz.de>
> > 
> > Adds a header that provides definitions that are used
> > across nRF51 peripherals
> > 
> > Signed-off-by: Steffen Görtz <contrib@steffen-goertz.de>
> > Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
> > Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
> > Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
> > ---
> >  include/hw/arm/nrf51.h       | 45 ++++++++++++++++++++++++++++++++++++
> >  include/hw/char/nrf51_uart.h |  1 -
> >  hw/arm/nrf51_soc.c           | 33 ++++++++++----------------
> >  3 files changed, 57 insertions(+), 22 deletions(-)
> >  create mode 100644 include/hw/arm/nrf51.h
> > 
> > diff --git a/include/hw/arm/nrf51.h b/include/hw/arm/nrf51.h
> > new file mode 100644
> > index 0000000000..175bb6c301
> > --- /dev/null
> > +++ b/include/hw/arm/nrf51.h
> > @@ -0,0 +1,45 @@
> > +/*
> > + * Nordic Semiconductor nRF51 Series SOC Common Defines
> > + *
> > + * This file hosts generic defines used in various nRF51 peripheral devices.
> > + *
> > + * Reference Manual: http://infocenter.nordicsemi.com/pdf/nRF51_RM_v3.0.pdf
> > + * Product Spec: http://infocenter.nordicsemi.com/pdf/nRF51822_PS_v3.1.pdf
> > + *
> > + * 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.
> > + */
> > +
> > +#ifndef NRF51_H
> > +#define NRF51_H
> > +
> > +#define NRF51_FLASH_BASE      0x00000000
> > +#define NRF51_FICR_BASE       0x10000000
> > +#define NRF51_FICR_SIZE       0x00000100
> > +#define NRF51_UICR_BASE       0x10001000
> > +#define NRF51_SRAM_BASE       0x20000000
> > +
> > +#define NRF51_IOMEM_BASE      0x40000000
> > +#define NRF51_IOMEM_SIZE      0x20000000
> > +
> > +#define NRF51_UART_BASE       0x40002000
> > +#define NRF51_TIMER_BASE      0x40008000
> > +#define NRF51_TIMER_SIZE      0x00001000
> > +#define NRF51_RNG_BASE        0x4000D000
> > +#define NRF51_NVMC_BASE       0x4001E000
> > +#define NRF51_GPIO_BASE       0x50000000
> > +
> > +#define NRF51_PRIVATE_BASE    0xF0000000
> > +#define NRF51_PRIVATE_SIZE    0x10000000
> > +
> > +#define NRF51_PAGE_SIZE       1024
> 
> I'd keep this file in hw/arm (not include/...).

This header file avoids duplicating definitions in
tests/microbit-test.c.

How would you structure it differently?

Stefan

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

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

* Re: [Qemu-devel] [PATCH 00/11] arm: Core nRF51 Devices and Microbit Support
  2019-01-03  9:11 [Qemu-devel] [PATCH 00/11] arm: Core nRF51 Devices and Microbit Support Stefan Hajnoczi
                   ` (10 preceding siblings ...)
  2019-01-03  9:11 ` [Qemu-devel] [PATCH 11/11] arm: Add Clock peripheral stub to NRF51 SOC Stefan Hajnoczi
@ 2019-01-07 15:19 ` Peter Maydell
  11 siblings, 0 replies; 15+ messages in thread
From: Peter Maydell @ 2019-01-07 15:19 UTC (permalink / raw)
  To: Stefan Hajnoczi
  Cc: QEMU Developers, Thomas Huth, qemu-arm, Joel Stanley,
	Julia Suvorova, Paolo Bonzini, Jim Mussared, Steffen Görtz,
	Laurent Vivier

On Thu, 3 Jan 2019 at 09:12, Stefan Hajnoczi <stefanha@redhat.com> wrote:
>
> Steffen has been busy so I picked up "[PATCH v5 00/14] arm: nRF51 Devices and
> Microbit Support".  This series includes the core devices needed to boot basic
> guest software on the "microbit" board.
>
> This series includes Steffen's random number generator, GPIO, timer, and a
> stubbed clock.  Also, this series adds the tests/microbit-test.c qtest.
>
> Changes from Steffen's series:
>  * Made timer tickless [Peter]
>  * Dropped non-volatile memory controller.  More work is needed there and I
>    don't want to hold back other devices in this series that are ready for
>    merge.
>  * Rebased and re-tested with make check and real micro:bit programs
>    (requires out-of-tree -kernel and stub TWI device patches)

Applied to target-arm.next, thanks.

-- PMM

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

end of thread, other threads:[~2019-01-07 15:20 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-01-03  9:11 [Qemu-devel] [PATCH 00/11] arm: Core nRF51 Devices and Microbit Support Stefan Hajnoczi
2019-01-03  9:11 ` [Qemu-devel] [PATCH 01/11] qtest: Add set_irq_in command to set IRQ/GPIO level Stefan Hajnoczi
2019-01-03  9:11 ` [Qemu-devel] [PATCH 02/11] arm: Add header to host common definition for nRF51 SOC peripherals Stefan Hajnoczi
2019-01-03 10:40   ` Philippe Mathieu-Daudé
2019-01-04  9:51     ` Stefan Hajnoczi
2019-01-03  9:11 ` [Qemu-devel] [PATCH 03/11] hw/misc/nrf51_rng: Add NRF51 random number generator peripheral Stefan Hajnoczi
2019-01-03  9:11 ` [Qemu-devel] [PATCH 04/11] arm: Instantiate NRF51 random number generator Stefan Hajnoczi
2019-01-03  9:11 ` [Qemu-devel] [PATCH 05/11] hw/gpio/nrf51_gpio: Add nRF51 GPIO peripheral Stefan Hajnoczi
2019-01-03  9:11 ` [Qemu-devel] [PATCH 06/11] arm: Instantiate NRF51 general purpose I/O Stefan Hajnoczi
2019-01-03  9:11 ` [Qemu-devel] [PATCH 07/11] tests/microbit-test: Add Tests for nRF51 GPIO Stefan Hajnoczi
2019-01-03  9:11 ` [Qemu-devel] [PATCH 08/11] hw/timer/nrf51_timer: Add nRF51 Timer peripheral Stefan Hajnoczi
2019-01-03  9:11 ` [Qemu-devel] [PATCH 09/11] arm: Instantiate NRF51 Timers Stefan Hajnoczi
2019-01-03  9:11 ` [Qemu-devel] [PATCH 10/11] tests/microbit-test: Add Tests for nRF51 Timer Stefan Hajnoczi
2019-01-03  9:11 ` [Qemu-devel] [PATCH 11/11] arm: Add Clock peripheral stub to NRF51 SOC Stefan Hajnoczi
2019-01-07 15:19 ` [Qemu-devel] [PATCH 00/11] arm: Core nRF51 Devices and Microbit Support Peter Maydell

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.