From aea268819c02d5dff6523a57e35e2534999c828e Mon Sep 17 00:00:00 2001
From: Davids Paskevics <davip00@mi.fu-berlin.de>
Date: Tue, 23 May 2023 15:03:51 +0200
Subject: [PATCH] Register dummy I/O memory for some ESP32-C3 peripherals

---
 hw/riscv/esp32_c3.c         | 42 ++++++++++++++++++++++++++++++++++++-
 include/hw/riscv/esp32_c3.h |  4 ++++
 2 files changed, 45 insertions(+), 1 deletion(-)

diff --git a/hw/riscv/esp32_c3.c b/hw/riscv/esp32_c3.c
index 78da9c67848..47f7c00a78a 100644
--- a/hw/riscv/esp32_c3.c
+++ b/hw/riscv/esp32_c3.c
@@ -16,6 +16,7 @@
  */
 
 #include "qemu/osdep.h"
+#include "qemu/log.h"
 #include "hw/boards.h"
 #include "hw/riscv/esp32_c3.h"
 #include "qapi/error.h"
@@ -26,6 +27,8 @@
 #include "hw/qdev-properties.h"
 #include "exec/address-spaces.h"
 #include "hw/riscv/boot.h"
+#include "hw/misc/unimp.h"
+#include "hw/qdev-core.h"
 
 
 static const struct MemmapEntry {
@@ -40,8 +43,33 @@ static const struct MemmapEntry {
     [ESP32_C3_DM]     =  {  0x20000000,  0x7FFFFFF }
 };
 
-// Reset vector according to technical manual page 217
+/* Reset vector according to technical manual page 217 */
 static const hwaddr esp32_c3_entry = 0x40000400;
+/* System I/O memory (TRM p. 91) */
+static const hwaddr esp32_c3_sysregs = 0x600C0000;
+static const hwaddr esp32_c3_sysregs_size = 4096;
+/* Clock control/configuration register */
+static const hwaddr esp32_c3_clkcfg = esp32_c3_sysregs + 0x0000;
+
+// Stub implementation for the clock peripheral
+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 esp32_c3_setup_reset_vec(void) {
     // TODO: Implement
@@ -154,6 +182,18 @@ static void esp32_c3_soc_state_realize(DeviceState *dev, Error **errp)
                                 &sss->dram);
 
     // TODO: Do we need to register dummy RAM here?
+
+    /* register dummy peripherals */
+    /*
+    Top-level instance owning all I/O memory.
+    Not sure if we need this, but NRF51/microbit does it this way.
+    */
+    memory_region_init(&sss->container,NULL, "riscv.esp32.c.container", UINT64_MAX);
+    memory_region_init_io(&sss->clock, NULL, &clock_ops, NULL,
+                          "riscv.esp32.c.clock", 0x0058);
+    memory_region_add_subregion_overlap(&sss->container,
+                                        esp32_c3_clkcfg, &sss->clock, -1);
+    create_unimplemented_device("riscv.esp32.c.sysregs", esp32_c3_sysregs, esp32_c3_sysregs_size);
 }
 
 static void esp32_c3_soc_class_init(ObjectClass *klass, void *data)
diff --git a/include/hw/riscv/esp32_c3.h b/include/hw/riscv/esp32_c3.h
index fb79fbc1bb5..cb799764f56 100644
--- a/include/hw/riscv/esp32_c3.h
+++ b/include/hw/riscv/esp32_c3.h
@@ -39,11 +39,15 @@ typedef struct Esp32C3SoCState {
     /*< public >*/
     RISCVHartArrayState cpus;
     DeviceState *plic;
+    /* RAM / ROM */
     MemoryRegion dummy;
     MemoryRegion irom;
     MemoryRegion drom;
     MemoryRegion iram;
     MemoryRegion dram;
+    /* Memory mapped I/O devices */
+    MemoryRegion container;
+    MemoryRegion clock;
 
 } Esp32C3SoCState;
 
-- 
GitLab