From nobody Mon Apr 29 04:37:18 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1530085156100790.585121772631; Wed, 27 Jun 2018 00:39:16 -0700 (PDT) Received: from localhost ([::1]:57171 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fY52p-0002zK-9k for importer@patchew.org; Wed, 27 Jun 2018 03:39:15 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:52108) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fY4y2-0007ht-DP for qemu-devel@nongnu.org; Wed, 27 Jun 2018 03:34:20 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fY4xz-0005oJ-Gt for qemu-devel@nongnu.org; Wed, 27 Jun 2018 03:34:18 -0400 Received: from steffen-goertz.de ([88.198.119.201]:51434) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fY4xu-0005fU-U4; Wed, 27 Jun 2018 03:34:11 -0400 Received: from localhost.localdomain (tmo-096-88.customers.d1-online.com [80.187.96.88]) by steffen-goertz.de (Postfix) with ESMTPSA id 1582949237; Wed, 27 Jun 2018 09:32:41 +0200 (CEST) From: =?UTF-8?q?Steffen=20G=C3=B6rtz?= To: qemu-devel@nongnu.org Date: Wed, 27 Jun 2018 09:33:44 +0200 Message-Id: <20180627073351.856-2-contrib@steffen-goertz.de> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180627073351.856-1-contrib@steffen-goertz.de> References: <20180627073351.856-1-contrib@steffen-goertz.de> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 88.198.119.201 Subject: [Qemu-devel] [RFC 1/8] arm: NRF51/Microbit Memory container and SOC variants X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Peter Maydell , Jim Mussared , Stefan Hajnoczi , =?UTF-8?q?Steffen=20G=C3=B6rtz?= , "open list:ARM" , Joel Stanley , Julia Suvorova Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" Signed-off-by: Steffen G=C3=B6rtz --- hw/arm/microbit.c | 8 ++-- hw/arm/nrf51_soc.c | 98 +++++++++++++++++++++++++++----------- include/hw/arm/nrf51_soc.h | 24 ++++++++-- 3 files changed, 95 insertions(+), 35 deletions(-) diff --git a/hw/arm/microbit.c b/hw/arm/microbit.c index b61d0747fe..9deb1a36ca 100644 --- a/hw/arm/microbit.c +++ b/hw/arm/microbit.c @@ -10,6 +10,7 @@ #include "qemu/osdep.h" #include "qapi/error.h" #include "hw/boards.h" +#include "hw/arm/arm.h" =20 #include "hw/arm/nrf51_soc.h" =20 @@ -18,10 +19,11 @@ static void microbit_init(MachineState *machine) DeviceState *dev; =20 dev =3D qdev_create(NULL, TYPE_NRF51_SOC); - if (machine->kernel_filename) { - qdev_prop_set_string(dev, "kernel-filename", machine->kernel_filen= ame); - } + qdev_prop_set_uint32(DEVICE(dev), "VARIANT", NRF51_VARIANT_AA); object_property_set_bool(OBJECT(dev), true, "realized", &error_fatal); + + armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, + 0x00000000); } =20 static void microbit_machine_init(MachineClass *mc) diff --git a/hw/arm/nrf51_soc.c b/hw/arm/nrf51_soc.c index b9f309aa6b..1f7c159edf 100644 --- a/hw/arm/nrf51_soc.c +++ b/hw/arm/nrf51_soc.c @@ -22,23 +22,33 @@ #include "crypto/random.h" =20 #include "hw/arm/nrf51_soc.h" -#include "hw/char/nrf51_uart.h" =20 #define IOMEM_BASE 0x40000000 #define IOMEM_SIZE 0x20000000 =20 #define FLASH_BASE 0x00000000 -#define FLASH_SIZE (256 * 1024) =20 #define FICR_BASE 0x10000000 #define FICR_SIZE 0x100 =20 #define SRAM_BASE 0x20000000 -#define SRAM_SIZE (16 * 1024) =20 #define UART_BASE 0x40002000 #define UART_SIZE 0x1000 =20 +#define PAGE_SIZE 0x0400 + + +struct { + hwaddr ram_size; + hwaddr flash_size; +} NRF51VariantAttributes[] =3D { + {.ram_size =3D 16, .flash_size =3D 256 }, + {.ram_size =3D 16, .flash_size =3D 128 }, + {.ram_size =3D 32, .flash_size =3D 256 }, +}; + + static uint64_t clock_read(void *opaque, hwaddr addr, unsigned int size) { qemu_log_mask(LOG_UNIMP, "%s: 0x%" HWADDR_PRIx " [%u]\n", __func__, ad= dr, size); @@ -101,62 +111,93 @@ static const MemoryRegionOps rng_ops =3D { .write =3D rng_write }; =20 +static void nrf51_soc_init(Object *obj) +{ + NRF51State *s =3D NRF51_SOC(obj); + + memory_region_init(&s->container, obj, "microbit-container", + UINT64_MAX); + + /* TODO: Change to armv6m when cortex-m0 core is available */ + object_initialize(&s->armv7m, sizeof(s->armv7m), TYPE_ARMV7M); + object_property_add_child(obj, "armv7m", OBJECT(&s->armv7m), &error_ab= ort); + qdev_set_parent_bus(DEVICE(&s->armv7m), sysbus_get_default()); + qdev_prop_set_string(DEVICE(&s->armv7m), "cpu-type", + ARM_CPU_TYPE_NAME("cortex-m3")); + + object_initialize(&s->uart, sizeof(s->uart), TYPE_NRF51_UART); + object_property_add_child(obj, "uart", OBJECT(&s->uart), &error_abort); + qdev_set_parent_bus(DEVICE(&s->uart), sysbus_get_default()); +} + =20 static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp) { NRF51State *s =3D NRF51_SOC(dev_soc); Error *err =3D NULL; =20 - /* IO space */ - create_unimplemented_device("nrf51_soc.io", IOMEM_BASE, IOMEM_SIZE); - - /* FICR */ - create_unimplemented_device("nrf51_soc.ficr", FICR_BASE, FICR_SIZE); + if (!(s->part_variant > NRF51_VARIANT_INVALID + && s->part_variant < NRF51_VARIANT_MAX)) { + error_setg(errp, "VARIANT not set or invalid"); + return; + } =20 - MemoryRegion *system_memory =3D get_system_memory(); - MemoryRegion *sram =3D g_new(MemoryRegion, 1); - MemoryRegion *flash =3D g_new(MemoryRegion, 1); + memory_region_init_ram(&s->sram, NULL, "nrf51_soc.sram", + NRF51VariantAttributes[s->part_variant].ram_size * PAGE_SIZE, = &err); + if (err) { + error_propagate(errp, err); + return; + } + memory_region_add_subregion(&s->container, SRAM_BASE, &s->sram); =20 - memory_region_init_ram_nomigrate(flash, NULL, "nrf51.flash", FLASH_SIZ= E, + memory_region_init_ram(&s->flash, NULL, "nrf51_soc.flash", + NRF51VariantAttributes[s->part_variant].flash_size * PAGE_SIZE, &err); if (err) { error_propagate(errp, err); return; } + memory_region_add_subregion(&s->container, FLASH_BASE, &s->flash); =20 - vmstate_register_ram_global(flash); - memory_region_set_readonly(flash, true); + qdev_prop_set_uint32(DEVICE(&s->armv7m), "num-irq", 60); + object_property_set_link(OBJECT(&s->armv7m), OBJECT(&s->container), + "memory", &err); + if (err) { + error_propagate(errp, err); + return; + } =20 - memory_region_add_subregion(system_memory, FLASH_BASE, flash); =20 - memory_region_init_ram_nomigrate(sram, NULL, "nrf51.sram", SRAM_SIZE, - &err); + object_property_set_bool(OBJECT(&s->armv7m), true, "realized", &err); if (err) { error_propagate(errp, err); return; } - vmstate_register_ram_global(sram); - memory_region_add_subregion(system_memory, SRAM_BASE, sram); =20 - /* TODO: implement a cortex m0 and update this */ - s->nvic =3D armv7m_init(get_system_memory(), FLASH_SIZE, 96, - s->kernel_filename, ARM_CPU_TYPE_NAME("cortex-m3")); + /* IO space */ + create_unimplemented_device("nrf51_soc.io", IOMEM_BASE, IOMEM_SIZE); + + /* FICR */ + create_unimplemented_device("nrf51_soc.ficr", FICR_BASE, FICR_SIZE); =20 - s->uart =3D nrf51_uart_create(UART_BASE, qdev_get_gpio_in(s->nvic, 2), - serial_hd(0)); + qdev_prop_set_chr(DEVICE(&s->uart), "chardev", serial_hd(0)); + qdev_init_nofail(DEVICE(&s->uart)); +/* sysbus_mmio_map(s, 0, UART_BASE); + sysbus_connect_irq(s, 0, qdev_get_gpio_in(s->nvic, 2)); */ =20 memory_region_init_io(&s->clock, NULL, &clock_ops, NULL, "nrf51_soc.cl= ock", 0x1000); - memory_region_add_subregion_overlap(get_system_memory(), IOMEM_BASE, &= s->clock, -1); + memory_region_add_subregion_overlap(&s->container, IOMEM_BASE, &s->clo= ck, -1); =20 memory_region_init_io(&s->nvmc, NULL, &nvmc_ops, NULL, "nrf51_soc.nvmc= ", 0x1000); - memory_region_add_subregion_overlap(get_system_memory(), 0x4001E000, &= s->nvmc, -1); + memory_region_add_subregion_overlap(&s->container, 0x4001E000, &s->nvm= c, -1); =20 memory_region_init_io(&s->rng, NULL, &rng_ops, NULL, "nrf51_soc.rng", = 0x1000); - memory_region_add_subregion_overlap(get_system_memory(), 0x4000D000, &= s->rng, -1); + memory_region_add_subregion_overlap(&s->container, 0x4000D000, &s->rng= , -1); } =20 static Property nrf51_soc_properties[] =3D { - DEFINE_PROP_STRING("kernel-filename", NRF51State, kernel_filename), + DEFINE_PROP_INT32("VARIANT", NRF51State, part_variant, + NRF51_VARIANT_INVALID), DEFINE_PROP_END_OF_LIST(), }; =20 @@ -172,6 +213,7 @@ static const TypeInfo nrf51_soc_info =3D { .name =3D TYPE_NRF51_SOC, .parent =3D TYPE_SYS_BUS_DEVICE, .instance_size =3D sizeof(NRF51State), + .instance_init =3D nrf51_soc_init, .class_init =3D nrf51_soc_class_init, }; =20 diff --git a/include/hw/arm/nrf51_soc.h b/include/hw/arm/nrf51_soc.h index f81cbbe3ce..c9af9659e9 100644 --- a/include/hw/arm/nrf51_soc.h +++ b/include/hw/arm/nrf51_soc.h @@ -12,6 +12,8 @@ =20 #include "qemu/osdep.h" #include "hw/sysbus.h" +#include "hw/arm/armv7m.h" +#include "hw/char/nrf51_uart.h" =20 #define TYPE_NRF51_SOC "nrf51-soc" #define NRF51_SOC(obj) \ @@ -22,16 +24,30 @@ typedef struct NRF51State { SysBusDevice parent_obj; =20 /*< public >*/ - char *kernel_filename; - DeviceState *nvic; - DeviceState *uart; + /* TODO: Change to armv6m when cortex-m0 core is available */ + ARMv7MState armv7m; =20 - MemoryRegion iomem; + Nrf51UART uart; =20 + MemoryRegion container; + MemoryRegion sram; + MemoryRegion flash; + MemoryRegion iomem; MemoryRegion clock; MemoryRegion nvmc; MemoryRegion rng; + + /* Properties */ + int32_t part_variant; } NRF51State; =20 +typedef enum { + NRF51_VARIANT_INVALID =3D -1, + NRF51_VARIANT_AA =3D 0, + NRF51_VARIANT_AB =3D 1, + NRF51_VARIANT_AC =3D 2, + NRF51_VARIANT_MAX =3D 3 +} NRF51Variants; + #endif =20 --=20 2.17.1 From nobody Mon Apr 29 04:37:18 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 153008498939019.82943967221331; Wed, 27 Jun 2018 00:36:29 -0700 (PDT) Received: from localhost ([::1]:57156 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fY508-0000hq-Iz for importer@patchew.org; Wed, 27 Jun 2018 03:36:28 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:52109) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fY4y2-0007hx-Du for qemu-devel@nongnu.org; Wed, 27 Jun 2018 03:34:19 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fY4xz-0005o6-78 for qemu-devel@nongnu.org; Wed, 27 Jun 2018 03:34:18 -0400 Received: from steffen-goertz.de ([88.198.119.201]:51448) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fY4xw-0005iO-30; Wed, 27 Jun 2018 03:34:12 -0400 Received: from localhost.localdomain (tmo-096-88.customers.d1-online.com [80.187.96.88]) by steffen-goertz.de (Postfix) with ESMTPSA id D3DD549364; Wed, 27 Jun 2018 09:32:43 +0200 (CEST) From: =?UTF-8?q?Steffen=20G=C3=B6rtz?= To: qemu-devel@nongnu.org Date: Wed, 27 Jun 2018 09:33:45 +0200 Message-Id: <20180627073351.856-3-contrib@steffen-goertz.de> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180627073351.856-1-contrib@steffen-goertz.de> References: <20180627073351.856-1-contrib@steffen-goertz.de> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 88.198.119.201 Subject: [Qemu-devel] [RFC 2/8] arm: NRF51 Add unimplemented device for MMIO X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Peter Maydell , Jim Mussared , Stefan Hajnoczi , =?UTF-8?q?Steffen=20G=C3=B6rtz?= , "open list:ARM" , Joel Stanley , Julia Suvorova Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" Signed-off-by: Steffen G=C3=B6rtz --- hw/arm/nrf51_soc.c | 18 +++++++++++++----- include/hw/arm/nrf51_soc.h | 4 +++- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/hw/arm/nrf51_soc.c b/hw/arm/nrf51_soc.c index 1f7c159edf..175a009e65 100644 --- a/hw/arm/nrf51_soc.c +++ b/hw/arm/nrf51_soc.c @@ -48,7 +48,6 @@ struct { {.ram_size =3D 32, .flash_size =3D 256 }, }; =20 - static uint64_t clock_read(void *opaque, hwaddr addr, unsigned int size) { qemu_log_mask(LOG_UNIMP, "%s: 0x%" HWADDR_PRIx " [%u]\n", __func__, ad= dr, size); @@ -125,6 +124,12 @@ static void nrf51_soc_init(Object *obj) qdev_prop_set_string(DEVICE(&s->armv7m), "cpu-type", ARM_CPU_TYPE_NAME("cortex-m3")); =20 + object_initialize(&s->mmio, sizeof(s->mmio), TYPE_UNIMPLEMENTED_DEVICE= ); + object_property_add_child(obj, "iomem", OBJECT(&s->mmio), &error_abort= ); + qdev_set_parent_bus(DEVICE(&s->mmio), sysbus_get_default()); + qdev_prop_set_string(DEVICE(&s->mmio), "name", "nrf51.iomem"); + qdev_prop_set_uint64(DEVICE(&s->mmio), "size", IOMEM_SIZE); + object_initialize(&s->uart, sizeof(s->uart), TYPE_NRF51_UART); object_property_add_child(obj, "uart", OBJECT(&s->uart), &error_abort); qdev_set_parent_bus(DEVICE(&s->uart), sysbus_get_default()); @@ -135,6 +140,7 @@ static void nrf51_soc_realize(DeviceState *dev_soc, Err= or **errp) { NRF51State *s =3D NRF51_SOC(dev_soc); Error *err =3D NULL; + MemoryRegion *mr =3D NULL; =20 if (!(s->part_variant > NRF51_VARIANT_INVALID && s->part_variant < NRF51_VARIANT_MAX)) { @@ -142,6 +148,7 @@ static void nrf51_soc_realize(DeviceState *dev_soc, Err= or **errp) return; } =20 + /** SRAM **/ memory_region_init_ram(&s->sram, NULL, "nrf51_soc.sram", NRF51VariantAttributes[s->part_variant].ram_size * PAGE_SIZE, = &err); if (err) { @@ -150,6 +157,7 @@ static void nrf51_soc_realize(DeviceState *dev_soc, Err= or **errp) } memory_region_add_subregion(&s->container, SRAM_BASE, &s->sram); =20 + /** FLASH **/ memory_region_init_ram(&s->flash, NULL, "nrf51_soc.flash", NRF51VariantAttributes[s->part_variant].flash_size * PAGE_SIZE, &err); @@ -159,6 +167,7 @@ static void nrf51_soc_realize(DeviceState *dev_soc, Err= or **errp) } memory_region_add_subregion(&s->container, FLASH_BASE, &s->flash); =20 + /** MCU **/ qdev_prop_set_uint32(DEVICE(&s->armv7m), "num-irq", 60); object_property_set_link(OBJECT(&s->armv7m), OBJECT(&s->container), "memory", &err); @@ -175,10 +184,9 @@ static void nrf51_soc_realize(DeviceState *dev_soc, Er= ror **errp) } =20 /* IO space */ - create_unimplemented_device("nrf51_soc.io", IOMEM_BASE, IOMEM_SIZE); - - /* FICR */ - create_unimplemented_device("nrf51_soc.ficr", FICR_BASE, FICR_SIZE); + object_property_set_bool(OBJECT(&s->mmio), true, "realized", &error_fa= tal); + mr =3D sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->mmio), 0); + memory_region_add_subregion_overlap(&s->container, IOMEM_BASE, mr, -15= 00); =20 qdev_prop_set_chr(DEVICE(&s->uart), "chardev", serial_hd(0)); qdev_init_nofail(DEVICE(&s->uart)); diff --git a/include/hw/arm/nrf51_soc.h b/include/hw/arm/nrf51_soc.h index c9af9659e9..86bc304b57 100644 --- a/include/hw/arm/nrf51_soc.h +++ b/include/hw/arm/nrf51_soc.h @@ -13,8 +13,10 @@ #include "qemu/osdep.h" #include "hw/sysbus.h" #include "hw/arm/armv7m.h" +#include "hw/misc/unimp.h" #include "hw/char/nrf51_uart.h" =20 + #define TYPE_NRF51_SOC "nrf51-soc" #define NRF51_SOC(obj) \ OBJECT_CHECK(NRF51State, (obj), TYPE_NRF51_SOC) @@ -27,12 +29,12 @@ typedef struct NRF51State { /* TODO: Change to armv6m when cortex-m0 core is available */ ARMv7MState armv7m; =20 + UnimplementedDeviceState mmio; Nrf51UART uart; =20 MemoryRegion container; MemoryRegion sram; MemoryRegion flash; - MemoryRegion iomem; MemoryRegion clock; MemoryRegion nvmc; MemoryRegion rng; --=20 2.17.1 From nobody Mon Apr 29 04:37:18 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1530085180697979.6980613514055; Wed, 27 Jun 2018 00:39:40 -0700 (PDT) Received: from localhost ([::1]:57173 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fY53C-0003Lx-Ua for importer@patchew.org; Wed, 27 Jun 2018 03:39:39 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:52155) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fY4y4-0007jk-6k for qemu-devel@nongnu.org; Wed, 27 Jun 2018 03:34:21 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fY4y2-0005rj-M4 for qemu-devel@nongnu.org; Wed, 27 Jun 2018 03:34:20 -0400 Received: from steffen-goertz.de ([88.198.119.201]:51450) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fY4xx-0005lE-IG; Wed, 27 Jun 2018 03:34:13 -0400 Received: from localhost.localdomain (tmo-096-88.customers.d1-online.com [80.187.96.88]) by steffen-goertz.de (Postfix) with ESMTPSA id 06D4049369; Wed, 27 Jun 2018 09:32:44 +0200 (CEST) From: =?UTF-8?q?Steffen=20G=C3=B6rtz?= To: qemu-devel@nongnu.org Date: Wed, 27 Jun 2018 09:33:46 +0200 Message-Id: <20180627073351.856-4-contrib@steffen-goertz.de> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180627073351.856-1-contrib@steffen-goertz.de> References: <20180627073351.856-1-contrib@steffen-goertz.de> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 88.198.119.201 Subject: [Qemu-devel] [RFC 3/8] arm: NRF51 create UART in-place, error handling X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Peter Maydell , Jim Mussared , Stefan Hajnoczi , =?UTF-8?q?Steffen=20G=C3=B6rtz?= , "open list:ARM" , Joel Stanley , Paolo Bonzini , Julia Suvorova Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" Signed-off-by: Steffen G=C3=B6rtz --- hw/arm/nrf51_soc.c | 30 ++++++++++++++++++++++-------- hw/char/nrf51_uart.c | 10 ++++++---- include/hw/char/nrf51_uart.h | 26 ++++++++------------------ 3 files changed, 36 insertions(+), 30 deletions(-) diff --git a/hw/arm/nrf51_soc.c b/hw/arm/nrf51_soc.c index 175a009e65..bfcacdf447 100644 --- a/hw/arm/nrf51_soc.c +++ b/hw/arm/nrf51_soc.c @@ -35,8 +35,9 @@ =20 #define UART_BASE 0x40002000 #define UART_SIZE 0x1000 +#define UART_INT 2 =20 -#define PAGE_SIZE 0x0400 +#define PAGE_SIZE 1024 =20 =20 struct { @@ -148,7 +149,7 @@ static void nrf51_soc_realize(DeviceState *dev_soc, Err= or **errp) return; } =20 - /** SRAM **/ + /* SRAM */ memory_region_init_ram(&s->sram, NULL, "nrf51_soc.sram", NRF51VariantAttributes[s->part_variant].ram_size * PAGE_SIZE, = &err); if (err) { @@ -157,7 +158,7 @@ static void nrf51_soc_realize(DeviceState *dev_soc, Err= or **errp) } memory_region_add_subregion(&s->container, SRAM_BASE, &s->sram); =20 - /** FLASH **/ + /* FLASH */ memory_region_init_ram(&s->flash, NULL, "nrf51_soc.flash", NRF51VariantAttributes[s->part_variant].flash_size * PAGE_SIZE, &err); @@ -167,7 +168,7 @@ static void nrf51_soc_realize(DeviceState *dev_soc, Err= or **errp) } memory_region_add_subregion(&s->container, FLASH_BASE, &s->flash); =20 - /** MCU **/ + /* MCU */ qdev_prop_set_uint32(DEVICE(&s->armv7m), "num-irq", 60); object_property_set_link(OBJECT(&s->armv7m), OBJECT(&s->container), "memory", &err); @@ -184,15 +185,28 @@ static void nrf51_soc_realize(DeviceState *dev_soc, E= rror **errp) } =20 /* IO space */ - object_property_set_bool(OBJECT(&s->mmio), true, "realized", &error_fa= tal); + object_property_set_bool(OBJECT(&s->mmio), true, "realized", &err); + if (err) { + error_propagate(errp, err); + return; + } mr =3D sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->mmio), 0); memory_region_add_subregion_overlap(&s->container, IOMEM_BASE, mr, -15= 00); =20 + /* UART */ qdev_prop_set_chr(DEVICE(&s->uart), "chardev", serial_hd(0)); - qdev_init_nofail(DEVICE(&s->uart)); -/* sysbus_mmio_map(s, 0, UART_BASE); - sysbus_connect_irq(s, 0, qdev_get_gpio_in(s->nvic, 2)); */ + object_property_set_bool(OBJECT(&s->uart), true, "realized", &err); + if (err) { + error_propagate(errp, err); + return; + } + + mr =3D sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->uart), 0); + memory_region_add_subregion_overlap(&s->container, UART_BASE, mr, 0); + qdev_connect_gpio_out_named(DEVICE(&s->uart), "irq", 0, + qdev_get_gpio_in(DEVICE(&s->armv7m), UART_INT)); =20 + /* STUB Peripherals */ memory_region_init_io(&s->clock, NULL, &clock_ops, NULL, "nrf51_soc.cl= ock", 0x1000); memory_region_add_subregion_overlap(&s->container, IOMEM_BASE, &s->clo= ck, -1); =20 diff --git a/hw/char/nrf51_uart.c b/hw/char/nrf51_uart.c index 2da97aa0c4..9c9f4a9c3f 100644 --- a/hw/char/nrf51_uart.c +++ b/hw/char/nrf51_uart.c @@ -13,6 +13,8 @@ #include "hw/registerfields.h" #include "hw/char/nrf51_uart.h" =20 +#define NRF51_UART_SIZE 0x1000 + REG32(STARTRX, 0x000) REG32(STOPRX, 0x004) REG32(STARTTX, 0x008) @@ -196,10 +198,10 @@ static void nrf51_uart_init(Object *obj) Nrf51UART *s =3D NRF51_UART(obj); SysBusDevice *sbd =3D SYS_BUS_DEVICE(obj); =20 - memory_region_init_io(&s->mmio, obj, &uart_ops, s, - "nrf51_soc.uart", 0x1000); - sysbus_init_mmio(sbd, &s->mmio); - sysbus_init_irq(sbd, &s->irq); + memory_region_init_io(&s->iomem, obj, &uart_ops, s, + "nrf51_soc.uart", NRF51_UART_SIZE); + sysbus_init_mmio(sbd, &s->iomem); + qdev_init_gpio_out_named(DEVICE(s), &s->irq, "irq", 1); } =20 static Property nrf51_uart_properties[] =3D { diff --git a/include/hw/char/nrf51_uart.h b/include/hw/char/nrf51_uart.h index 758203f1c3..e0769b90fb 100644 --- a/include/hw/char/nrf51_uart.h +++ b/include/hw/char/nrf51_uart.h @@ -6,6 +6,13 @@ * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 or * (at your option) any later version. + * + * QEMU interface: + * + sysbus MMIO regions 0: Memory Region with tasks, events and registers + * to be mapped to the peripherals instance address by the SOC. + * + Named GPIO output "irq": Interrupt line of the peripheral. Must be + * connected to the respective peripheral interrupt line of the NVIC. + * */ =20 #ifndef NRF51_UART_H @@ -21,8 +28,8 @@ =20 typedef struct Nrf51UART { SysBusDevice parent_obj; + MemoryRegion iomem; =20 - MemoryRegion mmio; CharBackend chr; qemu_irq irq; guint watch_tag; @@ -34,21 +41,4 @@ typedef struct Nrf51UART { uint32_t reg[0x1000]; } Nrf51UART; =20 -static inline DeviceState *nrf51_uart_create(hwaddr addr, - qemu_irq irq, - Chardev *chr) -{ - DeviceState *dev; - SysBusDevice *s; - - dev =3D qdev_create(NULL, "nrf51_soc.uart"); - s =3D SYS_BUS_DEVICE(dev); - qdev_prop_set_chr(dev, "chardev", chr); - qdev_init_nofail(dev); - sysbus_mmio_map(s, 0, addr); - sysbus_connect_irq(s, 0, irq); - - return dev; -} - #endif --=20 2.17.1 From nobody Mon Apr 29 04:37:18 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1530085026714343.9595852100298; Wed, 27 Jun 2018 00:37:06 -0700 (PDT) Received: from localhost ([::1]:57158 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fY50j-0001Hg-TV for importer@patchew.org; Wed, 27 Jun 2018 03:37:05 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:52132) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fY4y3-0007iq-Ei for qemu-devel@nongnu.org; Wed, 27 Jun 2018 03:34:20 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fY4y2-0005rX-Jk for qemu-devel@nongnu.org; Wed, 27 Jun 2018 03:34:19 -0400 Received: from steffen-goertz.de ([88.198.119.201]:51464) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fY4xy-0005n2-IZ; Wed, 27 Jun 2018 03:34:14 -0400 Received: from localhost.localdomain (tmo-096-88.customers.d1-online.com [80.187.96.88]) by steffen-goertz.de (Postfix) with ESMTPSA id 611DC49364; Wed, 27 Jun 2018 09:32:46 +0200 (CEST) From: =?UTF-8?q?Steffen=20G=C3=B6rtz?= To: qemu-devel@nongnu.org Date: Wed, 27 Jun 2018 09:33:47 +0200 Message-Id: <20180627073351.856-5-contrib@steffen-goertz.de> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180627073351.856-1-contrib@steffen-goertz.de> References: <20180627073351.856-1-contrib@steffen-goertz.de> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 88.198.119.201 Subject: [Qemu-devel] [RFC 4/8] arm: NRF51 Calculate peripheral id from base address X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Peter Maydell , Jim Mussared , Stefan Hajnoczi , =?UTF-8?q?Steffen=20G=C3=B6rtz?= , "open list:ARM" , Joel Stanley , Julia Suvorova Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" The base address determines a peripherals id, which identifies its interrupt line, see NRF51 reference manual section 10 peripheral interface. This little gem calculates the peripheral id based on its base address. Signed-off-by: Steffen G=C3=B6rtz --- hw/arm/nrf51_soc.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/hw/arm/nrf51_soc.c b/hw/arm/nrf51_soc.c index bfcacdf447..e93699a4b0 100644 --- a/hw/arm/nrf51_soc.c +++ b/hw/arm/nrf51_soc.c @@ -23,8 +23,6 @@ =20 #include "hw/arm/nrf51_soc.h" =20 -#define IOMEM_BASE 0x40000000 -#define IOMEM_SIZE 0x20000000 =20 #define FLASH_BASE 0x00000000 =20 @@ -33,12 +31,19 @@ =20 #define SRAM_BASE 0x20000000 =20 +#define IOMEM_BASE 0x40000000 +#define IOMEM_SIZE 0x20000000 + #define UART_BASE 0x40002000 #define UART_SIZE 0x1000 #define UART_INT 2 =20 +#define RNG_BASE 0x4000D000 + #define PAGE_SIZE 1024 =20 +#define BASE_TO_IRQ(base) ((base >> 12) & 0x1F) + =20 struct { hwaddr ram_size; @@ -177,7 +182,6 @@ static void nrf51_soc_realize(DeviceState *dev_soc, Err= or **errp) return; } =20 - object_property_set_bool(OBJECT(&s->armv7m), true, "realized", &err); if (err) { error_propagate(errp, err); @@ -204,7 +208,7 @@ static void nrf51_soc_realize(DeviceState *dev_soc, Err= or **errp) mr =3D sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->uart), 0); memory_region_add_subregion_overlap(&s->container, UART_BASE, mr, 0); qdev_connect_gpio_out_named(DEVICE(&s->uart), "irq", 0, - qdev_get_gpio_in(DEVICE(&s->armv7m), UART_INT)); + qdev_get_gpio_in(DEVICE(&s->armv7m), BASE_TO_IRQ(UART_BASE))); =20 /* STUB Peripherals */ memory_region_init_io(&s->clock, NULL, &clock_ops, NULL, "nrf51_soc.cl= ock", 0x1000); --=20 2.17.1 From nobody Mon Apr 29 04:37:18 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1530085196375603.9717809290769; Wed, 27 Jun 2018 00:39:56 -0700 (PDT) Received: from localhost ([::1]:57174 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fY53T-0003YZ-Ga for importer@patchew.org; Wed, 27 Jun 2018 03:39:55 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:52111) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fY4y2-0007i2-Eg for qemu-devel@nongnu.org; Wed, 27 Jun 2018 03:34:20 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fY4xz-0005oZ-RR for qemu-devel@nongnu.org; Wed, 27 Jun 2018 03:34:18 -0400 Received: from steffen-goertz.de ([88.198.119.201]:51480) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fY4xz-0005o2-Eq for qemu-devel@nongnu.org; Wed, 27 Jun 2018 03:34:15 -0400 Received: from localhost.localdomain (tmo-096-88.customers.d1-online.com [80.187.96.88]) by steffen-goertz.de (Postfix) with ESMTPSA id 6B1DD4936C; Wed, 27 Jun 2018 09:32:47 +0200 (CEST) From: =?UTF-8?q?Steffen=20G=C3=B6rtz?= To: qemu-devel@nongnu.org Date: Wed, 27 Jun 2018 09:33:48 +0200 Message-Id: <20180627073351.856-6-contrib@steffen-goertz.de> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180627073351.856-1-contrib@steffen-goertz.de> References: <20180627073351.856-1-contrib@steffen-goertz.de> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 88.198.119.201 Subject: [Qemu-devel] [RFC 5/8] arm: Add NRF51 random number generator peripheral X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Stefan Hajnoczi , Jim Mussared , Julia Suvorova , Joel Stanley , =?UTF-8?q?Steffen=20G=C3=B6rtz?= Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" Add a model of the NRF51 random number generator peripheral. Changes since v2: - Add missing 'qapi/error.h' for error_abort Changes since v1: - Add implementation access size hints to MemoryRegionOps - Fail on error if qcrypto_random_bytes fails - Add references to Nrf51 datasheets Signed-off-by: Steffen G=C3=B6rtz --- hw/misc/Makefile.objs | 1 + hw/misc/nrf51_rng.c | 243 ++++++++++++++++++++++++++++++++++++ include/hw/misc/nrf51_rng.h | 73 +++++++++++ 3 files changed, 317 insertions(+) create mode 100644 hw/misc/nrf51_rng.c create mode 100644 include/hw/misc/nrf51_rng.h diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs index 00e834d0f0..fd8cc97249 100644 --- a/hw/misc/Makefile.objs +++ b/hw/misc/Makefile.objs @@ -70,3 +70,4 @@ obj-$(CONFIG_AUX) +=3D auxbus.o obj-$(CONFIG_ASPEED_SOC) +=3D aspeed_scu.o aspeed_sdmc.o obj-y +=3D mmio_interface.o obj-$(CONFIG_MSF2) +=3D msf2-sysreg.o +obj-$(CONFIG_NRF51_SOC) +=3D nrf51_rng.o diff --git a/hw/misc/nrf51_rng.c b/hw/misc/nrf51_rng.c new file mode 100644 index 0000000000..46bdb21850 --- /dev/null +++ b/hw/misc/nrf51_rng.c @@ -0,0 +1,243 @@ +/* + * nrf51_rng.c + * + * Copyright 2018 Steffen G=C3=B6rtz + * + * This code is licensed under the GPL version 2 or later. See + * the COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "qapi/error.h" +#include "hw/misc/nrf51_rng.h" +#include "crypto/random.h" + +#define NRF51_RNG_SIZE 0x1000 + +#define NRF51_RNG_TASK_START 0x000 +#define NRF51_RNG_TASK_STOP 0x004 +#define NRF51_RNG_EVENT_VALRDY 0x100 +#define NRF51_RNG_REG_SHORTS 0x200 +#define NRF51_RNG_REG_SHORTS_VALRDY_STOP 0 +#define NRF51_RNG_REG_INTEN 0x300 +#define NRF51_RNG_REG_INTEN_VALRDY 0 +#define NRF51_RNG_REG_INTENSET 0x304 +#define NRF51_RNG_REG_INTENCLR 0x308 +#define NRF51_RNG_REG_CONFIG 0x504 +#define NRF51_RNG_REG_CONFIG_DECEN 0 +#define NRF51_RNG_REG_VALUE 0x508 + +#define NRF51_TRIGGER_TASK 0x01 +#define NRF51_EVENT_CLEAR 0x00 + + +static uint64_t rng_read(void *opaque, hwaddr offset, unsigned int size) +{ + Nrf51RNGState *s =3D NRF51_RNG(opaque); + uint64_t r =3D 0; + + switch (offset) { + case NRF51_RNG_EVENT_VALRDY: + r =3D s->state.event_valrdy; + break; + case NRF51_RNG_REG_SHORTS: + r =3D s->state.shortcut_stop_on_valrdy; + break; + case NRF51_RNG_REG_INTEN: + case NRF51_RNG_REG_INTENSET: + case NRF51_RNG_REG_INTENCLR: + r =3D s->state.interrupt_enabled; + break; + case NRF51_RNG_REG_CONFIG: + r =3D s->state.filter_enabled; + break; + case NRF51_RNG_REG_VALUE: + r =3D 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 =3D qemu_clock_get_us(QEMU_CLOCK_VIRTUAL); + if (s->state.filter_enabled) { + timeout +=3D s->period_filtered_us; + } else { + timeout +=3D s->period_unfiltered_us; + } + + return timeout; +} + + +static void rng_update_timer(Nrf51RNGState *s) +{ + if (s->state.active) { + timer_mod(&s->timer, calc_next_timeout(s)); + } else { + timer_del(&s->timer); + } +} + + +static void rng_write(void *opaque, hwaddr offset, + uint64_t value, unsigned int size) +{ + Nrf51RNGState *s =3D NRF51_RNG(opaque); + + switch (offset) { + case NRF51_RNG_TASK_START: + if (value =3D=3D NRF51_TRIGGER_TASK) { + s->state.active =3D 1; + rng_update_timer(s); + } + break; + case NRF51_RNG_TASK_STOP: + if (value =3D=3D NRF51_TRIGGER_TASK) { + s->state.active =3D 0; + rng_update_timer(s); + } + break; + case NRF51_RNG_EVENT_VALRDY: + if (value =3D=3D NRF51_EVENT_CLEAR) { + s->state.event_valrdy =3D 0; + qemu_set_irq(s->eep_valrdy, 0); + } + break; + case NRF51_RNG_REG_SHORTS: + s->state.shortcut_stop_on_valrdy =3D + (value & BIT_MASK(NRF51_RNG_REG_SHORTS_VALRDY_STOP)) ? 1 := 0; + break; + case NRF51_RNG_REG_INTEN: + s->state.interrupt_enabled =3D + (value & BIT_MASK(NRF51_RNG_REG_INTEN_VALRDY)) ? 1 : 0; + break; + case NRF51_RNG_REG_INTENSET: + if (value & BIT_MASK(NRF51_RNG_REG_INTEN_VALRDY)) { + s->state.interrupt_enabled =3D 1; + } + break; + case NRF51_RNG_REG_INTENCLR: + if (value & BIT_MASK(NRF51_RNG_REG_INTEN_VALRDY)) { + s->state.interrupt_enabled =3D 0; + } + break; + case NRF51_RNG_REG_CONFIG: + s->state.filter_enabled =3D + (value & BIT_MASK(NRF51_RNG_REG_CONFIG_DECEN)) ? 1 := 0; + break; + + default: + qemu_log_mask(LOG_GUEST_ERROR, + "%s: bad write offset 0x%" HWADDR_PRIx "\n", + __func__, offset); + } +} + +static const MemoryRegionOps rng_ops =3D { + .read =3D rng_read, + .write =3D rng_write, + .endianness =3D DEVICE_LITTLE_ENDIAN, + .impl.min_access_size =3D 4, + .impl.max_access_size =3D 4 +}; + +static void nrf51_rng_timer_expire(void *opaque) +{ + Nrf51RNGState *s =3D NRF51_RNG(opaque); + + qcrypto_random_bytes(&s->value, 1, &error_abort); + + s->state.event_valrdy =3D 1; + qemu_set_irq(s->eep_valrdy, 1); + + if (s->state.interrupt_enabled) { + qemu_irq_pulse(s->irq); + } + + if (s->state.shortcut_stop_on_valrdy) { + s->state.active =3D 0; + } + + rng_update_timer(s); +} + +static void nrf51_rng_tep_start(void *opaque, int n, int level) +{ + Nrf51RNGState *s =3D NRF51_RNG(opaque); + + if (level) { + s->state.active =3D 1; + rng_update_timer(s); + } +} + +static void nrf51_rng_tep_stop(void *opaque, int n, int level) +{ + Nrf51RNGState *s =3D NRF51_RNG(opaque); + + if (level) { + s->state.active =3D 0; + rng_update_timer(s); + } +} + + +static void nrf51_rng_init(Object *obj) +{ + Nrf51RNGState *s =3D NRF51_RNG(obj); + SysBusDevice *sbd =3D SYS_BUS_DEVICE(obj); + + memory_region_init_io(&s->mmio, obj, &rng_ops, s, + TYPE_NRF51_RNG, NRF51_RNG_SIZE); + sysbus_init_mmio(sbd, &s->mmio); + + timer_init_us(&s->timer, QEMU_CLOCK_VIRTUAL, nrf51_rng_timer_expire, s= ); + + qdev_init_gpio_out_named(DEVICE(s), &s->irq, "irq", 1); + + /* Tasks */ + qdev_init_gpio_in_named(DEVICE(s), nrf51_rng_tep_start, "tep_start", 1= ); + qdev_init_gpio_in_named(DEVICE(s), nrf51_rng_tep_stop, "tep_stop", 1); + + /* Events */ + qdev_init_gpio_out_named(DEVICE(s), &s->eep_valrdy, "eep_valrdy", 1); +} + +static Property nrf51_rng_properties[] =3D { + DEFINE_PROP_UINT16("period_unfiltered_us", Nrf51RNGState, + period_unfiltered_us, 167), + DEFINE_PROP_UINT16("period_filtered_us", Nrf51RNGState, + period_filtered_us, 660), + DEFINE_PROP_END_OF_LIST(), +}; + +static void nrf51_rng_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(klass); + + dc->props =3D nrf51_rng_properties; +} + +static const TypeInfo nrf51_rng_info =3D { + .name =3D TYPE_NRF51_RNG, + .parent =3D TYPE_SYS_BUS_DEVICE, + .instance_size =3D sizeof(Nrf51RNGState), + .instance_init =3D nrf51_rng_init, + .class_init =3D nrf51_rng_class_init +}; + +static void nrf51_rng_register_types(void) +{ + type_register_static(&nrf51_rng_info); +} + +type_init(nrf51_rng_register_types) diff --git a/include/hw/misc/nrf51_rng.h b/include/hw/misc/nrf51_rng.h new file mode 100644 index 0000000000..a8f0630a98 --- /dev/null +++ b/include/hw/misc/nrf51_rng.h @@ -0,0 +1,73 @@ +/* + * nrf51_rng.h + * + * Copyright 2018 Steffen G=C3=B6rtz + * + * This code is licensed under the GPL version 2 or later. See + * the COPYING file in the top-level directory. + * + * See NRF51 reference manual section 21 Random Number Generator + * See NRF51 product specification section 8.16 Random Number Generator + * + * QEMU interface: + * + Property "period_unfiltered_us": Time between two biased values in + * microseconds. + * + Property "period_filtered_us": Time between two unbiased values in + * microseconds. + * + sysbus MMIO regions 0: Memory Region with tasks, events and registers + * to be mapped to the peripherals instance address by the SOC. + * + Named GPIO output "irq": Interrupt line of the peripheral. Must be + * connected to the associated peripheral interrupt line of the NVIC. + * + Named GPIO output "eep_valrdy": Event set when new random value is re= ady + * to be read. + * + Named GPIO input "tep_start": Task that triggers start of continuous + * generation of random values. + * + Named GPIO input "tep_stop": Task that ends continuous generation of + * random values. + * + * Accuracy of the peripheral model: + * + Stochastic properties of different configurations of the random source + * are not modeled. + * + Generation of unfiltered and filtered random values take at least the + * average generation time stated in the production specification; + * non-deterministic generation times are not modeled. + * + */ +#ifndef NRF51_RNG_H +#define NRF51_RNG_H + +#include "hw/sysbus.h" +#include "qemu/timer.h" +#define TYPE_NRF51_RNG "nrf51_soc.rng" +#define NRF51_RNG(obj) OBJECT_CHECK(Nrf51RNGState, (obj), TYPE_NRF51_RNG) + +typedef struct Nrf51RNGState { + SysBusDevice parent_obj; + + MemoryRegion mmio; + qemu_irq irq; + + /* Event End Points */ + qemu_irq eep_valrdy; + + QEMUTimer timer; + + /* Time between generation of successive unfiltered values in us */ + uint16_t period_unfiltered_us; + /* Time between generation of successive filtered values in us */ + uint16_t period_filtered_us; + + uint8_t value; + + struct { + uint32_t active:1; + uint32_t event_valrdy:1; + uint32_t shortcut_stop_on_valrdy:1; + uint32_t interrupt_enabled:1; + uint32_t filter_enabled:1; + } state; + +} Nrf51RNGState; + + +#endif /* NRF51_RNG_H_ */ --=20 2.17.1 From nobody Mon Apr 29 04:37:18 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1530085422869588.7508922004761; Wed, 27 Jun 2018 00:43:42 -0700 (PDT) Received: from localhost ([::1]:57200 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fY578-0006uP-71 for importer@patchew.org; Wed, 27 Jun 2018 03:43:42 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:52210) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fY4y6-0007mE-Jo for qemu-devel@nongnu.org; Wed, 27 Jun 2018 03:34:24 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fY4y5-0005tS-0Z for qemu-devel@nongnu.org; Wed, 27 Jun 2018 03:34:22 -0400 Received: from steffen-goertz.de ([88.198.119.201]:51490) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fY4y0-0005pD-MB; Wed, 27 Jun 2018 03:34:16 -0400 Received: from localhost.localdomain (tmo-096-88.customers.d1-online.com [80.187.96.88]) by steffen-goertz.de (Postfix) with ESMTPSA id 54E8649364; Wed, 27 Jun 2018 09:32:48 +0200 (CEST) From: =?UTF-8?q?Steffen=20G=C3=B6rtz?= To: qemu-devel@nongnu.org Date: Wed, 27 Jun 2018 09:33:49 +0200 Message-Id: <20180627073351.856-7-contrib@steffen-goertz.de> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180627073351.856-1-contrib@steffen-goertz.de> References: <20180627073351.856-1-contrib@steffen-goertz.de> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 88.198.119.201 Subject: [Qemu-devel] [RFC 6/8] arm: Add UICR/FICR handling to NRF51 SOC X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Peter Maydell , Jim Mussared , Stefan Hajnoczi , =?UTF-8?q?Steffen=20G=C3=B6rtz?= , "open list:ARM" , Joel Stanley , Julia Suvorova Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" This patch maps preallocated user/factory information configuration registers to the NRF51 SOC. See NRF51 reference manual section 7 and 8. Signed-off-by: Steffen G=C3=B6rtz --- hw/arm/nrf51_soc.c | 174 ++++++++++++++++++++++++++++++------- include/hw/arm/nrf51_soc.h | 5 +- 2 files changed, 145 insertions(+), 34 deletions(-) diff --git a/hw/arm/nrf51_soc.c b/hw/arm/nrf51_soc.c index e93699a4b0..82e4c2d833 100644 --- a/hw/arm/nrf51_soc.c +++ b/hw/arm/nrf51_soc.c @@ -19,7 +19,6 @@ #include "sysemu/sysemu.h" #include "qemu/log.h" #include "cpu.h" -#include "crypto/random.h" =20 #include "hw/arm/nrf51_soc.h" =20 @@ -29,6 +28,9 @@ #define FICR_BASE 0x10000000 #define FICR_SIZE 0x100 =20 +#define UICR_BASE 0x10001000 +#define UICR_SIZE 0x100 + #define SRAM_BASE 0x20000000 =20 #define IOMEM_BASE 0x40000000 @@ -54,9 +56,118 @@ struct { {.ram_size =3D 32, .flash_size =3D 256 }, }; =20 +/* +FICR Registers Assignments +CODEPAGESIZE 0x010 [4, +CODESIZE 0x014 5, +CLENR0 0x028 10, +PPFC 0x02C 11, +NUMRAMBLOCK 0x034 13, +SIZERAMBLOCKS 0x038 14, +SIZERAMBLOCK[0] 0x038 14, +SIZERAMBLOCK[1] 0x03C 15, +SIZERAMBLOCK[2] 0x040 16, +SIZERAMBLOCK[3] 0x044 17, +CONFIGID 0x05C 23, +DEVICEID[0] 0x060 24, +DEVICEID[1] 0x064 25, +ER[0] 0x080 32, +ER[1] 0x084 33, +ER[2] 0x088 34, +ER[3] 0x08C 35, +IR[0] 0x090 36, +IR[1] 0x094 37, +IR[2] 0x098 38, +IR[3] 0x09C 39, +DEVICEADDRTYPE 0x0A0 40, +DEVICEADDR[0] 0x0A4 41, +DEVICEADDR[1] 0x0A8 42, +OVERRIDEEN 0x0AC 43, +NRF_1MBIT[0] 0x0B0 44, +NRF_1MBIT[1] 0x0B4 45, +NRF_1MBIT[2] 0x0B8 46, +NRF_1MBIT[3] 0x0BC 47, +NRF_1MBIT[4] 0x0C0 48, +BLE_1MBIT[0] 0x0EC 59, +BLE_1MBIT[1] 0x0F0 60, +BLE_1MBIT[2] 0x0F4 61, +BLE_1MBIT[3] 0x0F8 62, +BLE_1MBIT[4] 0x0FC 63] +*/ + +static const uint32_t ficr_content[64] =3D { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFF= FFFFF, + 0xFFFFFFFF, 0x00000400, 0x00000100, 0xFFFFFFFF, 0xFFFFFFFF, 0x0000= 0002, + 0x00002000, 0x00002000, 0x00002000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFF= FFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFF= FFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000003, 0x12345678, 0x9ABC= DEF1, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFF= FFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFF= FFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFF= FFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFF= FFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFF= FFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFF= FFFF, + 0xFFFFFFFF, }; + +static uint64_t ficr_read(void *opaque, hwaddr offset, unsigned int size) +{ + qemu_log_mask(LOG_TRACE, "%s: 0x%" HWADDR_PRIx " [%u]\n", + __func__, offset, size); + + if (offset > (ARRAY_SIZE(ficr_content) - size)) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: bad read offset 0x%" HWADDR_PRIx "\n", __func__, offs= et); + return 0; + } + + return ficr_content[offset >> 2]; +} + +static const MemoryRegionOps ficr_ops =3D { + .read =3D ficr_read, + .impl.min_access_size =3D 4, + .impl.max_access_size =3D 4, + .impl.unaligned =3D false, +}; + +static const uint32_t uicr_content[64] =3D { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFF= FFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFF= FFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFF= FFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFF= FFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFF= FFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFF= FFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFF= FFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFF= FFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFF= FFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFF= FFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFF= FFFF, + 0xFFFFFFFF, }; + +static uint64_t uicr_read(void *opaque, hwaddr offset, unsigned int size) +{ + qemu_log_mask(LOG_TRACE, "%s: 0x%" HWADDR_PRIx " [%u]\n", + __func__, offset, size); + + if (offset > (ARRAY_SIZE(uicr_content) - size)) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: bad read offset 0x%" HWADDR_PRIx "\n", __func__, offs= et); + return 0; + } + + return uicr_content[offset >> 2]; +} + +static const MemoryRegionOps uicr_ops =3D { + .read =3D uicr_read, + .impl.min_access_size =3D 4, + .impl.max_access_size =3D 4, + .impl.unaligned =3D false, +}; + + static uint64_t clock_read(void *opaque, hwaddr addr, unsigned int size) { - qemu_log_mask(LOG_UNIMP, "%s: 0x%" HWADDR_PRIx " [%u]\n", __func__, ad= dr, size); + qemu_log_mask(LOG_UNIMP, "%s: 0x%" HWADDR_PRIx " [%u]\n", + __func__, addr, size); return 1; } =20 @@ -88,34 +199,6 @@ static const MemoryRegionOps nvmc_ops =3D { .write =3D nvmc_write }; =20 -static uint64_t rng_read(void *opaque, hwaddr addr, unsigned int size) -{ - uint64_t r =3D 0; - - qemu_log_mask(LOG_UNIMP, "%s: 0x%" HWADDR_PRIx " [%u]\n", __func__, ad= dr, size); - - switch (addr) { - case 0x508: - qcrypto_random_bytes((uint8_t *)&r, 1, NULL); - break; - default: - r =3D 1; - break; - } - return r; -} - -static void rng_write(void *opaque, hwaddr addr, uint64_t data, unsigned i= nt size) -{ - qemu_log_mask(LOG_UNIMP, "%s: 0x%" HWADDR_PRIx " <- 0x%" PRIx64 " [%u]= \n", __func__, addr, data, size); -} - - -static const MemoryRegionOps rng_ops =3D { - .read =3D rng_read, - .write =3D rng_write -}; - static void nrf51_soc_init(Object *obj) { NRF51State *s =3D NRF51_SOC(obj); @@ -139,6 +222,10 @@ static void nrf51_soc_init(Object *obj) object_initialize(&s->uart, sizeof(s->uart), TYPE_NRF51_UART); object_property_add_child(obj, "uart", OBJECT(&s->uart), &error_abort); qdev_set_parent_bus(DEVICE(&s->uart), sysbus_get_default()); + + object_initialize(&s->rng, sizeof(s->rng), TYPE_NRF51_RNG); + object_property_add_child(obj, "rng", OBJECT(&s->rng), &error_abort); + qdev_set_parent_bus(DEVICE(&s->rng), sysbus_get_default()); } =20 =20 @@ -197,6 +284,18 @@ static void nrf51_soc_realize(DeviceState *dev_soc, Er= ror **errp) mr =3D sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->mmio), 0); memory_region_add_subregion_overlap(&s->container, IOMEM_BASE, mr, -15= 00); =20 + /* FICR */ + memory_region_init_io(&s->ficr, NULL, &ficr_ops, NULL, "nrf51_soc.ficr= ", + FICR_SIZE); + memory_region_set_readonly(&s->ficr, true); + memory_region_add_subregion_overlap(&s->container, FICR_BASE, &s->ficr= , 0); + + /* UICR */ + memory_region_init_io(&s->uicr, NULL, &uicr_ops, NULL, "nrf51_soc.uicr= ", + UICR_SIZE); + memory_region_set_readonly(&s->uicr, true); + memory_region_add_subregion_overlap(&s->container, UICR_BASE, &s->uicr= , 0); + /* UART */ qdev_prop_set_chr(DEVICE(&s->uart), "chardev", serial_hd(0)); object_property_set_bool(OBJECT(&s->uart), true, "realized", &err); @@ -210,15 +309,24 @@ static void nrf51_soc_realize(DeviceState *dev_soc, E= rror **errp) qdev_connect_gpio_out_named(DEVICE(&s->uart), "irq", 0, qdev_get_gpio_in(DEVICE(&s->armv7m), BASE_TO_IRQ(UART_BASE))); =20 + /* RNG */ + object_property_set_bool(OBJECT(&s->rng), true, "realized", &err); + if (err) { + error_propagate(errp, err); + return; + } + + mr =3D sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->rng), 0); + memory_region_add_subregion_overlap(&s->container, RNG_BASE, mr, 0); + qdev_connect_gpio_out_named(DEVICE(&s->rng), "irq", 0, + qdev_get_gpio_in(DEVICE(&s->armv7m), BASE_TO_IRQ(RNG_BASE))); + /* STUB Peripherals */ memory_region_init_io(&s->clock, NULL, &clock_ops, NULL, "nrf51_soc.cl= ock", 0x1000); memory_region_add_subregion_overlap(&s->container, IOMEM_BASE, &s->clo= ck, -1); =20 memory_region_init_io(&s->nvmc, NULL, &nvmc_ops, NULL, "nrf51_soc.nvmc= ", 0x1000); memory_region_add_subregion_overlap(&s->container, 0x4001E000, &s->nvm= c, -1); - - memory_region_init_io(&s->rng, NULL, &rng_ops, NULL, "nrf51_soc.rng", = 0x1000); - memory_region_add_subregion_overlap(&s->container, 0x4000D000, &s->rng= , -1); } =20 static Property nrf51_soc_properties[] =3D { diff --git a/include/hw/arm/nrf51_soc.h b/include/hw/arm/nrf51_soc.h index 86bc304b57..35dd71c3db 100644 --- a/include/hw/arm/nrf51_soc.h +++ b/include/hw/arm/nrf51_soc.h @@ -15,6 +15,7 @@ #include "hw/arm/armv7m.h" #include "hw/misc/unimp.h" #include "hw/char/nrf51_uart.h" +#include "hw/misc/nrf51_rng.h" =20 =20 #define TYPE_NRF51_SOC "nrf51-soc" @@ -31,13 +32,15 @@ typedef struct NRF51State { =20 UnimplementedDeviceState mmio; Nrf51UART uart; + Nrf51RNGState rng; =20 MemoryRegion container; MemoryRegion sram; MemoryRegion flash; + MemoryRegion ficr; + MemoryRegion uicr; MemoryRegion clock; MemoryRegion nvmc; - MemoryRegion rng; =20 /* Properties */ int32_t part_variant; --=20 2.17.1 From nobody Mon Apr 29 04:37:18 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 153008517421894.72197437809302; Wed, 27 Jun 2018 00:39:34 -0700 (PDT) Received: from localhost ([::1]:57172 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fY537-0003GH-FP for importer@patchew.org; Wed, 27 Jun 2018 03:39:33 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:52154) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fY4y4-0007ji-6K for qemu-devel@nongnu.org; Wed, 27 Jun 2018 03:34:21 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fY4y2-0005qy-88 for qemu-devel@nongnu.org; Wed, 27 Jun 2018 03:34:20 -0400 Received: from steffen-goertz.de ([88.198.119.201]:51500) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fY4y1-0005qU-O1 for qemu-devel@nongnu.org; Wed, 27 Jun 2018 03:34:18 -0400 Received: from localhost.localdomain (tmo-096-88.customers.d1-online.com [80.187.96.88]) by steffen-goertz.de (Postfix) with ESMTPSA id 7995F49370; Wed, 27 Jun 2018 09:32:49 +0200 (CEST) From: =?UTF-8?q?Steffen=20G=C3=B6rtz?= To: qemu-devel@nongnu.org Date: Wed, 27 Jun 2018 09:33:50 +0200 Message-Id: <20180627073351.856-8-contrib@steffen-goertz.de> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180627073351.856-1-contrib@steffen-goertz.de> References: <20180627073351.856-1-contrib@steffen-goertz.de> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 88.198.119.201 Subject: [Qemu-devel] [RFC 7/8] arm: Add NRF51 SOC non-volatile memory controller X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Stefan Hajnoczi , Jim Mussared , Julia Suvorova , Joel Stanley , =?UTF-8?q?Steffen=20G=C3=B6rtz?= Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" Changes since V1: - Code style changes Signed-off-by: Steffen G=C3=B6rtz --- hw/nvram/Makefile.objs | 1 + hw/nvram/nrf51_nvmc.c | 168 ++++++++++++++++++++++++++++++++++ include/hw/nvram/nrf51_nvmc.h | 51 +++++++++++ 3 files changed, 220 insertions(+) create mode 100644 hw/nvram/nrf51_nvmc.c create mode 100644 include/hw/nvram/nrf51_nvmc.h diff --git a/hw/nvram/Makefile.objs b/hw/nvram/Makefile.objs index a912d25391..9edd61e8af 100644 --- a/hw/nvram/Makefile.objs +++ b/hw/nvram/Makefile.objs @@ -5,3 +5,4 @@ common-obj-y +=3D fw_cfg.o common-obj-y +=3D chrp_nvram.o common-obj-$(CONFIG_MAC_NVRAM) +=3D mac_nvram.o obj-$(CONFIG_PSERIES) +=3D spapr_nvram.o +obj-$(CONFIG_NRF51_SOC) +=3D nrf51_nvmc.o diff --git a/hw/nvram/nrf51_nvmc.c b/hw/nvram/nrf51_nvmc.c new file mode 100644 index 0000000000..5dde3088a8 --- /dev/null +++ b/hw/nvram/nrf51_nvmc.c @@ -0,0 +1,168 @@ +/* + * nrf51_nvmc.c + * + * Copyright 2018 Steffen G=C3=B6rtz + * + * This code is licensed under the GPL version 2 or later. See + * the COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "qemu/log.h" +#include "hw/nvram/nrf51_nvmc.h" +#include "exec/address-spaces.h" + +#define NRF51_NVMC_SIZE 0x1000 + +#define NRF51_NVMC_READY 0x400 +#define NRF51_NVMC_READY_READY 0x01 +#define NRF51_NVMC_CONFIG 0x504 +#define NRF51_NVMC_CONFIG_MASK 0x03 +#define NRF51_NVMC_CONFIG_WEN 0x01 +#define NRF51_NVMC_CONFIG_EEN 0x02 +#define NRF51_NVMC_ERASEPCR1 0x508 +#define NRF51_NVMC_ERASEPCR0 0x510 +#define NRF51_NVMC_ERASEALL 0x50C +#define NRF51_NVMC_ERASEUICR 0x512 +#define NRF51_NVMC_ERASE 0x01 + +#define NRF51_UICR_OFFSET 0x10001000UL +#define NRF51_UICR_SIZE 0x100 + +static uint64_t io_read(void *opaque, hwaddr offset, unsigned int size) +{ + Nrf51NVMCState *s =3D NRF51_NVMC(opaque); + uint64_t r =3D 0; + + switch (offset) { + case NRF51_NVMC_READY: + r =3D NRF51_NVMC_READY_READY; + break; + case NRF51_NVMC_CONFIG: + r =3D s->state.config; + break; + default: + qemu_log_mask(LOG_GUEST_ERROR, + "%s: bad read offset 0x%" HWADDR_PRIx "\n", __func__, offs= et); + } + + return r; +} + +static void io_write(void *opaque, hwaddr offset, uint64_t value, + unsigned int size) +{ + Nrf51NVMCState *s =3D NRF51_NVMC(opaque); + + switch (offset) { + case NRF51_NVMC_CONFIG: + s->state.config =3D value & NRF51_NVMC_CONFIG_MASK; + break; + case NRF51_NVMC_ERASEPCR0: + case NRF51_NVMC_ERASEPCR1: + value &=3D ~(s->page_size - 1); + if (value < (s->code_size * s->page_size)) { + address_space_write(&s->as, value, MEMTXATTRS_UNSPECIFIED, + s->empty_page, s->page_size); + } + break; + case NRF51_NVMC_ERASEALL: + if (value =3D=3D NRF51_NVMC_ERASE) { + for (uint32_t i =3D 0; i < s->code_size; i++) { + address_space_write(&s->as, i * s->page_size, + MEMTXATTRS_UNSPECIFIED, s->empty_page, s->page_size); + } + address_space_write(&s->as, NRF51_UICR_OFFSET, + MEMTXATTRS_UNSPECIFIED, s->empty_page, NRF51_UICR_SIZE); + } + break; + case NRF51_NVMC_ERASEUICR: + if (value =3D=3D NRF51_NVMC_ERASE) { + address_space_write(&s->as, NRF51_UICR_OFFSET, + MEMTXATTRS_UNSPECIFIED, s->empty_page, NRF51_UICR_SIZE); + } + break; + + default: + qemu_log_mask(LOG_GUEST_ERROR, + "%s: bad write offset 0x%" HWADDR_PRIx "\n", __func__, off= set); + } +} + +static const MemoryRegionOps io_ops =3D { + .read =3D io_read, + .write =3D io_write, + .endianness =3D DEVICE_LITTLE_ENDIAN, +}; + +static void nrf51_nvmc_init(Object *obj) +{ + Nrf51NVMCState *s =3D NRF51_NVMC(obj); + SysBusDevice *sbd =3D SYS_BUS_DEVICE(obj); + + memory_region_init_io(&s->mmio, obj, &io_ops, s, + TYPE_NRF51_NVMC, NRF51_NVMC_SIZE); + sysbus_init_mmio(sbd, &s->mmio); +} + +static void nrf51_nvmc_realize(DeviceState *dev, Error **errp) +{ + Nrf51NVMCState *s =3D NRF51_NVMC(dev); + + if (!s->mr) { + error_setg(errp, "memory property was not set"); + return; + } + + if (s->page_size < NRF51_UICR_SIZE) { + error_setg(errp, "page size too small"); + return; + } + + s->empty_page =3D g_malloc(s->page_size); + memset(s->empty_page, 0xFF, s->page_size); + + address_space_init(&s->as, s->mr, "system-memory"); +} + +static void nrf51_nvmc_unrealize(DeviceState *dev, Error **errp) +{ + Nrf51NVMCState *s =3D NRF51_NVMC(dev); + + g_free(s->empty_page); + s->empty_page =3D NULL; + +} + +static Property nrf51_nvmc_properties[] =3D { + DEFINE_PROP_UINT16("page_size", Nrf51NVMCState, page_size, 0x400), + DEFINE_PROP_UINT32("code_size", Nrf51NVMCState, code_size, 0x100), + DEFINE_PROP_LINK("memory", Nrf51NVMCState, mr, TYPE_MEMORY_REGION, + MemoryRegion *), + DEFINE_PROP_END_OF_LIST(), +}; + +static void nrf51_nvmc_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(klass); + + dc->props =3D nrf51_nvmc_properties; + dc->realize =3D nrf51_nvmc_realize; + dc->unrealize =3D nrf51_nvmc_unrealize; +} + +static const TypeInfo nrf51_nvmc_info =3D { + .name =3D TYPE_NRF51_NVMC, + .parent =3D TYPE_SYS_BUS_DEVICE, + .instance_size =3D sizeof(Nrf51NVMCState), + .instance_init =3D nrf51_nvmc_init, + .class_init =3D nrf51_nvmc_class_init +}; + +static void nrf51_nvmc_register_types(void) +{ + type_register_static(&nrf51_nvmc_info); +} + +type_init(nrf51_nvmc_register_types) diff --git a/include/hw/nvram/nrf51_nvmc.h b/include/hw/nvram/nrf51_nvmc.h new file mode 100644 index 0000000000..3a63b7e5ad --- /dev/null +++ b/include/hw/nvram/nrf51_nvmc.h @@ -0,0 +1,51 @@ +/* + * nrf51_nvmc.h + * + * Copyright 2018 Steffen G=C3=B6rtz + * + * This code is licensed under the GPL version 2 or later. See + * the COPYING file in the top-level directory. + * + * See Nrf51 reference manual 6 Non-Volatile Memory Controller (NVMC) + * See Nrf51 product sheet 8.22 NVMC specifications + * + * QEMU interface: + * + sysbus MMIO regions 0: Memory Region with registers + * to be mapped to the peripherals instance address by the SOC. + * + page_size property to set the page size in bytes. + * + code_size property to set the code size in number of pages. + * + * Accuracy of the peripheral model: + * + The NVMC is always ready, all requested erase operations succeed + * immediately. + * + CONFIG.WEN and CONFIG.EEN flags can be written and read back + * but are not evaluated to check whether a requested write/erase operat= ion + * is legal. + * + Code regions (MPU configuration) are disregarded. + */ +#ifndef NRF51_NVMC_H +#define NRF51_NVMC_H + +#include "hw/sysbus.h" +#define TYPE_NRF51_NVMC "nrf51_soc.nvmc" +#define NRF51_NVMC(obj) OBJECT_CHECK(Nrf51NVMCState, (obj), TYPE_NRF51_NVM= C) + +typedef struct Nrf51NVMCState { + SysBusDevice parent_obj; + + MemoryRegion mmio; + + uint32_t code_size; + uint16_t page_size; + uint8_t *empty_page; + MemoryRegion *mr; + AddressSpace as; + + struct { + uint32_t config:2; + } state; + +} Nrf51NVMCState; + + +#endif --=20 2.17.1 From nobody Mon Apr 29 04:37:18 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1530085334711779.0653049399937; Wed, 27 Jun 2018 00:42:14 -0700 (PDT) Received: from localhost ([::1]:57193 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fY55f-0005r1-8t for importer@patchew.org; Wed, 27 Jun 2018 03:42:11 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:52211) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fY4y6-0007mH-Jp for qemu-devel@nongnu.org; Wed, 27 Jun 2018 03:34:23 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fY4y5-0005tf-M3 for qemu-devel@nongnu.org; Wed, 27 Jun 2018 03:34:22 -0400 Received: from steffen-goertz.de ([88.198.119.201]:51510) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fY4y2-0005r7-IE; Wed, 27 Jun 2018 03:34:18 -0400 Received: from localhost.localdomain (tmo-096-88.customers.d1-online.com [80.187.96.88]) by steffen-goertz.de (Postfix) with ESMTPSA id 7BF8A4936F; Wed, 27 Jun 2018 09:32:50 +0200 (CEST) From: =?UTF-8?q?Steffen=20G=C3=B6rtz?= To: qemu-devel@nongnu.org Date: Wed, 27 Jun 2018 09:33:51 +0200 Message-Id: <20180627073351.856-9-contrib@steffen-goertz.de> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180627073351.856-1-contrib@steffen-goertz.de> References: <20180627073351.856-1-contrib@steffen-goertz.de> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 88.198.119.201 Subject: [Qemu-devel] [RFC 8/8] arm: Instantiate NVMC in NRF51. X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Peter Maydell , Jim Mussared , Stefan Hajnoczi , =?UTF-8?q?Steffen=20G=C3=B6rtz?= , "open list:ARM" , Joel Stanley , Julia Suvorova Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" Signed-off-by: Steffen G=C3=B6rtz --- hw/arm/nrf51_soc.c | 50 +++++++++++++++++++++++--------------- include/hw/arm/nrf51_soc.h | 3 ++- 2 files changed, 32 insertions(+), 21 deletions(-) diff --git a/hw/arm/nrf51_soc.c b/hw/arm/nrf51_soc.c index 82e4c2d833..9ff622b792 100644 --- a/hw/arm/nrf51_soc.c +++ b/hw/arm/nrf51_soc.c @@ -40,6 +40,9 @@ #define UART_SIZE 0x1000 #define UART_INT 2 =20 +#define NVMC_BASE 0x4001E000 +#define NVMC_SIZE 0x1000 + #define RNG_BASE 0x4000D000 =20 #define PAGE_SIZE 1024 @@ -182,23 +185,6 @@ static const MemoryRegionOps clock_ops =3D { .write =3D clock_write }; =20 -static uint64_t nvmc_read(void *opaque, hwaddr addr, unsigned int size) -{ - qemu_log_mask(LOG_TRACE, "%s: 0x%" HWADDR_PRIx " [%u]\n", __func__, ad= dr, size); - return 1; -} - -static void nvmc_write(void *opaque, hwaddr addr, uint64_t data, unsigned = int size) -{ - qemu_log_mask(LOG_TRACE, "%s: 0x%" HWADDR_PRIx " <- 0x%" PRIx64 " [%u]= \n", __func__, addr, data, size); -} - - -static const MemoryRegionOps nvmc_ops =3D { - .read =3D nvmc_read, - .write =3D nvmc_write -}; - static void nrf51_soc_init(Object *obj) { NRF51State *s =3D NRF51_SOC(obj); @@ -223,6 +209,10 @@ static void nrf51_soc_init(Object *obj) object_property_add_child(obj, "uart", OBJECT(&s->uart), &error_abort); qdev_set_parent_bus(DEVICE(&s->uart), sysbus_get_default()); =20 + object_initialize(&s->nvmc, sizeof(s->nvmc), TYPE_NRF51_NVMC); + object_property_add_child(obj, "nvmc", OBJECT(&s->nvmc), &error_abort); + qdev_set_parent_bus(DEVICE(&s->nvmc), sysbus_get_default()); + object_initialize(&s->rng, sizeof(s->rng), TYPE_NRF51_RNG); object_property_add_child(obj, "rng", OBJECT(&s->rng), &error_abort); qdev_set_parent_bus(DEVICE(&s->rng), sysbus_get_default()); @@ -309,6 +299,29 @@ static void nrf51_soc_realize(DeviceState *dev_soc, Er= ror **errp) qdev_connect_gpio_out_named(DEVICE(&s->uart), "irq", 0, qdev_get_gpio_in(DEVICE(&s->armv7m), BASE_TO_IRQ(UART_BASE))); =20 + /* NVMC */ + object_property_set_link(OBJECT(&s->nvmc), OBJECT(&s->container), + "memory", &err); + if (err) { + error_propagate(errp, err); + return; + } + object_property_set_uint(OBJECT(&s->nvmc), + NRF51VariantAttributes[s->part_variant].flash_size, "code_size= ", + &err); + if (err) { + error_propagate(errp, err); + return; + } + object_property_set_bool(OBJECT(&s->nvmc), true, "realized", &err); + if (err) { + error_propagate(errp, err); + return; + } + + mr =3D sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->nvmc), 0); + memory_region_add_subregion_overlap(&s->container, NVMC_BASE, mr, 0); + /* RNG */ object_property_set_bool(OBJECT(&s->rng), true, "realized", &err); if (err) { @@ -324,9 +337,6 @@ static void nrf51_soc_realize(DeviceState *dev_soc, Err= or **errp) /* STUB Peripherals */ memory_region_init_io(&s->clock, NULL, &clock_ops, NULL, "nrf51_soc.cl= ock", 0x1000); memory_region_add_subregion_overlap(&s->container, IOMEM_BASE, &s->clo= ck, -1); - - memory_region_init_io(&s->nvmc, NULL, &nvmc_ops, NULL, "nrf51_soc.nvmc= ", 0x1000); - memory_region_add_subregion_overlap(&s->container, 0x4001E000, &s->nvm= c, -1); } =20 static Property nrf51_soc_properties[] =3D { diff --git a/include/hw/arm/nrf51_soc.h b/include/hw/arm/nrf51_soc.h index 35dd71c3db..70d9f5863c 100644 --- a/include/hw/arm/nrf51_soc.h +++ b/include/hw/arm/nrf51_soc.h @@ -15,6 +15,7 @@ #include "hw/arm/armv7m.h" #include "hw/misc/unimp.h" #include "hw/char/nrf51_uart.h" +#include "hw/nvram/nrf51_nvmc.h" #include "hw/misc/nrf51_rng.h" =20 =20 @@ -32,6 +33,7 @@ typedef struct NRF51State { =20 UnimplementedDeviceState mmio; Nrf51UART uart; + Nrf51NVMCState nvmc; Nrf51RNGState rng; =20 MemoryRegion container; @@ -40,7 +42,6 @@ typedef struct NRF51State { MemoryRegion ficr; MemoryRegion uicr; MemoryRegion clock; - MemoryRegion nvmc; =20 /* Properties */ int32_t part_variant; --=20 2.17.1