From nobody Sat Sep 28 22:38:03 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1548700912800160.89012153330088; Mon, 28 Jan 2019 10:41:52 -0800 (PST) Received: from localhost ([127.0.0.1]:36822 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1goBqu-0002XS-Hz for importer@patchew.org; Mon, 28 Jan 2019 13:41:48 -0500 Received: from eggs.gnu.org ([209.51.188.92]:40951) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1goBN9-0002fk-Uj for qemu-devel@nongnu.org; Mon, 28 Jan 2019 13:11:05 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1goBN7-0008Me-NN for qemu-devel@nongnu.org; Mon, 28 Jan 2019 13:11:03 -0500 Received: from mail-wm1-x343.google.com ([2a00:1450:4864:20::343]:34154) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1goBN6-0008EN-A6 for qemu-devel@nongnu.org; Mon, 28 Jan 2019 13:11:01 -0500 Received: by mail-wm1-x343.google.com with SMTP id y185so11062339wmd.1 for ; Mon, 28 Jan 2019 10:10:56 -0800 (PST) Received: from orth.archaic.org.uk (orth.archaic.org.uk. [81.2.115.148]) by smtp.gmail.com with ESMTPSA id b18sm97910681wrw.83.2019.01.28.10.10.53 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 28 Jan 2019 10:10:54 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:subject:date:message-id:in-reply-to:references:mime-version :content-transfer-encoding; bh=5SVy/G+rudPF28WchmM63tosFhBQDHRZR1pK9+PXPTA=; b=MJ00YpRUkLxVWvTR41lbjs3o8qPaeP026KflJIyRPh6iOkjBNLZpu27PoWSX9D2EOh K6jv4Oq2NeFaFe+zipDxepsAN4aGu77A7rQ+NltxhM2dIk8MTAdzipAeeYEHf5nCkPMn VD2QSXt6kEguvBQDzzkcBBKebGs1YjN2TNnB0= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=5SVy/G+rudPF28WchmM63tosFhBQDHRZR1pK9+PXPTA=; b=lxUS4WflUL37slx7dillKnytxMh3nG6omX/PjH4UbOcPr1pNZaIbun3ekbW+ek+KE4 loRYkWR47eTd/uVA1lR71+s4ndC6WAbFfLy010B1x5d/VP3bxDqRYD2ONQDJaTHE70vw oB52kSEz/iD3y8CIdJ8HBY8HO4hennQCcrNZiiABMrYOHGHwk/2R28S237c+0wJ0WCDx 1P5sF2Heg/ya3ouo5FwYrZ/r83J1G3v1RAlbwyYL5zMfaAXp8rLmpWo+2baGjA79BnEq de9gWr0Bi7JmrfgfTG6gl+O1yOX0LDKqkuoEJ7YQ5InMC2K2gvgBCrMuLMRwK5b5afbp bnlg== X-Gm-Message-State: AJcUukeRnql5x8by8i35ourNrepHFWKy4nIpw50lUUf1wsyj4zwKy+WW fN57/QC43FuBFsvqWdf9fUAQWs10t0LXYw== X-Google-Smtp-Source: ALg8bN4fsWuQGKxQP3Xerh9X0P9n+RFa0H3jIoY4YlUwhw03+g9qWcZ16XT+WLT7KEttjbS+BOUYAQ== X-Received: by 2002:a1c:bbd6:: with SMTP id l205mr16997971wmf.97.1548699055064; Mon, 28 Jan 2019 10:10:55 -0800 (PST) From: Peter Maydell To: qemu-devel@nongnu.org Date: Mon, 28 Jan 2019 18:10:25 +0000 Message-Id: <20190128181047.20781-5-peter.maydell@linaro.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190128181047.20781-1-peter.maydell@linaro.org> References: <20190128181047.20781-1-peter.maydell@linaro.org> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2a00:1450:4864:20::343 Subject: [Qemu-devel] [PULL 04/26] arm: Stub out NRF51 TWI magnetometer/accelerometer detection 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: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) From: Steffen G=C3=B6rtz Recent microbit firmwares panic if the TWI magnetometer/accelerometer devices are not detected during startup. We don't implement TWI (I2C) so let's stub out these devices just to let the firmware boot. Signed-off by: Steffen G=C3=B6rtz Signed-off-by: Stefan Hajnoczi Message-id: 20190110094020.18354-2-stefanha@redhat.com Reviewed-by: Peter Maydell [PMM: fixed comment style] Signed-off-by: Peter Maydell --- hw/i2c/Makefile.objs | 1 + include/hw/arm/nrf51.h | 2 + include/hw/arm/nrf51_soc.h | 1 + include/hw/i2c/microbit_i2c.h | 42 +++++++++++ hw/arm/microbit.c | 16 +++++ hw/i2c/microbit_i2c.c | 127 ++++++++++++++++++++++++++++++++++ 6 files changed, 189 insertions(+) create mode 100644 include/hw/i2c/microbit_i2c.h create mode 100644 hw/i2c/microbit_i2c.c diff --git a/hw/i2c/Makefile.objs b/hw/i2c/Makefile.objs index 37cacde9788..82e747e1cd1 100644 --- a/hw/i2c/Makefile.objs +++ b/hw/i2c/Makefile.objs @@ -7,5 +7,6 @@ common-obj-$(CONFIG_BITBANG_I2C) +=3D bitbang_i2c.o common-obj-$(CONFIG_EXYNOS4) +=3D exynos4210_i2c.o common-obj-$(CONFIG_IMX_I2C) +=3D imx_i2c.o common-obj-$(CONFIG_ASPEED_SOC) +=3D aspeed_i2c.o +common-obj-$(CONFIG_NRF51_SOC) +=3D microbit_i2c.o obj-$(CONFIG_OMAP) +=3D omap_i2c.o obj-$(CONFIG_PPC4XX) +=3D ppc4xx_i2c.o diff --git a/include/hw/arm/nrf51.h b/include/hw/arm/nrf51.h index 175bb6c301e..1008fee6c93 100644 --- a/include/hw/arm/nrf51.h +++ b/include/hw/arm/nrf51.h @@ -25,6 +25,8 @@ #define NRF51_IOMEM_SIZE 0x20000000 =20 #define NRF51_UART_BASE 0x40002000 +#define NRF51_TWI_BASE 0x40003000 +#define NRF51_TWI_SIZE 0x00001000 #define NRF51_TIMER_BASE 0x40008000 #define NRF51_TIMER_SIZE 0x00001000 #define NRF51_RNG_BASE 0x4000D000 diff --git a/include/hw/arm/nrf51_soc.h b/include/hw/arm/nrf51_soc.h index e06f0304b48..fbdefc07e4d 100644 --- a/include/hw/arm/nrf51_soc.h +++ b/include/hw/arm/nrf51_soc.h @@ -39,6 +39,7 @@ typedef struct NRF51State { MemoryRegion sram; MemoryRegion flash; MemoryRegion clock; + MemoryRegion twi; =20 uint32_t sram_size; uint32_t flash_size; diff --git a/include/hw/i2c/microbit_i2c.h b/include/hw/i2c/microbit_i2c.h new file mode 100644 index 00000000000..aad636127ea --- /dev/null +++ b/include/hw/i2c/microbit_i2c.h @@ -0,0 +1,42 @@ +/* + * Microbit stub for Nordic Semiconductor nRF51 SoC Two-Wire Interface + * http://infocenter.nordicsemi.com/pdf/nRF51_RM_v3.0.1.pdf + * + * Copyright 2019 Red Hat, Inc. + * + * This code is licensed under the GPL version 2 or later. See + * the COPYING file in the top-level directory. + */ + +#ifndef MICROBIT_I2C_H +#define MICROBIT_I2C_H + +#include "hw/sysbus.h" +#include "hw/arm/nrf51.h" + +#define NRF51_TWI_TASK_STARTRX 0x000 +#define NRF51_TWI_TASK_STARTTX 0x008 +#define NRF51_TWI_TASK_STOP 0x014 +#define NRF51_TWI_EVENT_STOPPED 0x104 +#define NRF51_TWI_EVENT_RXDREADY 0x108 +#define NRF51_TWI_EVENT_TXDSENT 0x11c +#define NRF51_TWI_REG_ENABLE 0x500 +#define NRF51_TWI_REG_RXD 0x518 +#define NRF51_TWI_REG_TXD 0x51c +#define NRF51_TWI_REG_ADDRESS 0x588 + +#define TYPE_MICROBIT_I2C "microbit.i2c" +#define MICROBIT_I2C(obj) \ + OBJECT_CHECK(MicrobitI2CState, (obj), TYPE_MICROBIT_I2C) + +#define MICROBIT_I2C_NREGS (NRF51_TWI_SIZE / sizeof(uint32_t)) + +typedef struct { + SysBusDevice parent_obj; + + MemoryRegion iomem; + uint32_t regs[MICROBIT_I2C_NREGS]; + uint32_t read_idx; +} MicrobitI2CState; + +#endif /* MICROBIT_I2C_H */ diff --git a/hw/arm/microbit.c b/hw/arm/microbit.c index a734e7f650e..da67bf6d9d1 100644 --- a/hw/arm/microbit.c +++ b/hw/arm/microbit.c @@ -16,11 +16,13 @@ #include "exec/address-spaces.h" =20 #include "hw/arm/nrf51_soc.h" +#include "hw/i2c/microbit_i2c.h" =20 typedef struct { MachineState parent; =20 NRF51State nrf51; + MicrobitI2CState i2c; } MicrobitMachineState; =20 #define TYPE_MICROBIT_MACHINE MACHINE_TYPE_NAME("microbit") @@ -32,7 +34,9 @@ static void microbit_init(MachineState *machine) { MicrobitMachineState *s =3D MICROBIT_MACHINE(machine); MemoryRegion *system_memory =3D get_system_memory(); + MemoryRegion *mr; Object *soc =3D OBJECT(&s->nrf51); + Object *i2c =3D OBJECT(&s->i2c); =20 sysbus_init_child_obj(OBJECT(machine), "nrf51", soc, sizeof(s->nrf51), TYPE_NRF51_SOC); @@ -41,6 +45,18 @@ static void microbit_init(MachineState *machine) &error_fatal); object_property_set_bool(soc, true, "realized", &error_fatal); =20 + /* + * Overlap the TWI stub device into the SoC. This is a microbit-speci= fic + * hack until we implement the nRF51 TWI controller properly and the + * magnetometer/accelerometer devices. + */ + sysbus_init_child_obj(OBJECT(machine), "microbit.twi", i2c, + sizeof(s->i2c), TYPE_MICROBIT_I2C); + object_property_set_bool(i2c, true, "realized", &error_fatal); + mr =3D sysbus_mmio_get_region(SYS_BUS_DEVICE(i2c), 0); + memory_region_add_subregion_overlap(&s->nrf51.container, NRF51_TWI_BAS= E, + mr, -1); + armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, NRF51_SOC(soc)->flash_size); } diff --git a/hw/i2c/microbit_i2c.c b/hw/i2c/microbit_i2c.c new file mode 100644 index 00000000000..793f1b0f8ba --- /dev/null +++ b/hw/i2c/microbit_i2c.c @@ -0,0 +1,127 @@ +/* + * Microbit stub for Nordic Semiconductor nRF51 SoC Two-Wire Interface + * http://infocenter.nordicsemi.com/pdf/nRF51_RM_v3.0.1.pdf + * + * This is a microbit-specific stub for the TWI controller on the nRF51 So= C. + * We don't emulate I2C devices but the firmware probes the + * accelerometer/magnetometer on startup and panics if they are not found. + * Therefore we stub out the probing. + * + * In the future this file could evolve into a full nRF51 TWI controller + * device. + * + * Copyright 2018 Steffen G=C3=B6rtz + * Copyright 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/i2c/microbit_i2c.h" + +static const uint32_t twi_read_sequence[] =3D {0x5A, 0x5A, 0x40}; + +static uint64_t microbit_i2c_read(void *opaque, hwaddr addr, unsigned int = size) +{ + MicrobitI2CState *s =3D opaque; + uint64_t data =3D 0x00; + + switch (addr) { + case NRF51_TWI_EVENT_STOPPED: + data =3D 0x01; + break; + case NRF51_TWI_EVENT_RXDREADY: + data =3D 0x01; + break; + case NRF51_TWI_EVENT_TXDSENT: + data =3D 0x01; + break; + case NRF51_TWI_REG_RXD: + data =3D twi_read_sequence[s->read_idx]; + if (s->read_idx < G_N_ELEMENTS(twi_read_sequence)) { + s->read_idx++; + } + break; + default: + data =3D s->regs[addr / sizeof(s->regs[0])]; + break; + } + + qemu_log_mask(LOG_UNIMP, "%s: 0x%" HWADDR_PRIx " [%u] =3D %" PRIx32 "\= n", + __func__, addr, size, (uint32_t)data); + + + return data; +} + +static void microbit_i2c_write(void *opaque, hwaddr addr, uint64_t data, + unsigned int size) +{ + MicrobitI2CState *s =3D opaque; + + qemu_log_mask(LOG_UNIMP, "%s: 0x%" HWADDR_PRIx " <- 0x%" PRIx64 " [%u]= \n", + __func__, addr, data, size); + s->regs[addr / sizeof(s->regs[0])] =3D data; +} + +static const MemoryRegionOps microbit_i2c_ops =3D { + .read =3D microbit_i2c_read, + .write =3D microbit_i2c_write, + .endianness =3D DEVICE_LITTLE_ENDIAN, + .impl.min_access_size =3D 4, + .impl.max_access_size =3D 4, +}; + +static const VMStateDescription microbit_i2c_vmstate =3D { + .name =3D TYPE_MICROBIT_I2C, + .version_id =3D 1, + .minimum_version_id =3D 1, + .fields =3D (VMStateField[]) { + VMSTATE_UINT32_ARRAY(regs, MicrobitI2CState, MICROBIT_I2C_NREGS), + VMSTATE_UINT32(read_idx, MicrobitI2CState), + }, +}; + +static void microbit_i2c_reset(DeviceState *dev) +{ + MicrobitI2CState *s =3D MICROBIT_I2C(dev); + + memset(s->regs, 0, sizeof(s->regs)); + s->read_idx =3D 0; +} + +static void microbit_i2c_realize(DeviceState *dev, Error **errp) +{ + SysBusDevice *sbd =3D SYS_BUS_DEVICE(dev); + MicrobitI2CState *s =3D MICROBIT_I2C(dev); + + memory_region_init_io(&s->iomem, OBJECT(s), µbit_i2c_ops, s, + "microbit.twi", NRF51_TWI_SIZE); + sysbus_init_mmio(sbd, &s->iomem); +} + +static void microbit_i2c_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(klass); + + dc->vmsd =3D µbit_i2c_vmstate; + dc->reset =3D microbit_i2c_reset; + dc->realize =3D microbit_i2c_realize; + dc->desc =3D "Microbit I2C controller"; +} + +static const TypeInfo microbit_i2c_info =3D { + .name =3D TYPE_MICROBIT_I2C, + .parent =3D TYPE_SYS_BUS_DEVICE, + .instance_size =3D sizeof(MicrobitI2CState), + .class_init =3D microbit_i2c_class_init, +}; + +static void microbit_i2c_register_types(void) +{ + type_register_static(µbit_i2c_info); +} + +type_init(microbit_i2c_register_types) --=20 2.20.1