From patchwork Fri Jul 14 10:51:19 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 107772 Delivered-To: patches@linaro.org Received: by 10.140.101.44 with SMTP id t41csp729950qge; Fri, 14 Jul 2017 03:51:36 -0700 (PDT) X-Received: by 10.98.15.71 with SMTP id x68mr4613168pfi.176.1500029496678; Fri, 14 Jul 2017 03:51:36 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1500029496; cv=none; d=google.com; s=arc-20160816; b=K4qwsW1sTOCweTQRghHqBiga0EGIChGrWZltLWMEWHkaGeoQefJ6DilnP4PMRTtKEm G0GrtacGdYP9INBwdg70q+EeyqRu4x4GuW7I4Vr9ftbgXSvZA5dJ2sSlr6WTgIucGnCs dD5VIpUcGCiabFjbNyx17hWj/Q2P0CMGv7M4Ih+mlk3MDE6sRMMXzqV/DKBAA/h4sysw TDRxs/l+Fu2rux8EIdwKvUP+rzJgsuDCDEn4LSJBy4O4pOHe2f9NoAzMoBEbYpNiyQdq e251f1iCLYgoUV2pCoCXd1SzNpZD1OfUlKPuc+z6Gzbalt+281ovEmJWqX1txRD3Ziuy rwxQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=references:in-reply-to:message-id:date:subject:cc:to:from :arc-authentication-results; bh=TAKTGte9taKbmuvCEoaxbt4yqz1lkfYcZxxHYg+MH+o=; b=OV0KLwcSh+HuKQzoCbNTb3b9j5K0k8onAPRlGCpElJAQo6bJz6/in1GyjSb2/l+SOo zgNCkEs2/zCn9nDhD45MfGSo4vegrDgs5FLmh4N3eR4aAbfNVvvUvikzyyorq3atxxps /N4flddv+xatoXLzd98NWUApz2QfhSp71FNcuD1oXRcC3AsjgI2FYsooc+6ZDLffrMtS Nd8ILbytZC/L19+oW+Kl3m93iRXRQJE3lhxCWdUaHZxddt9Tl6dUn1OCG2k+Q49/LT2+ yFVNotr8fH/s7ACl3BtvqvlRcacveUv9HdhxM2yGRismNM+0JGz6QjNrrV/3VBUZUicz Y4/g== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of pm215@archaic.org.uk designates 2001:8b0:1d0::2 as permitted sender) smtp.mailfrom=pm215@archaic.org.uk; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from orth.archaic.org.uk (orth.archaic.org.uk. [2001:8b0:1d0::2]) by mx.google.com with ESMTPS id b5si6576008plk.410.2017.07.14.03.51.35 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 14 Jul 2017 03:51:36 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of pm215@archaic.org.uk designates 2001:8b0:1d0::2 as permitted sender) client-ip=2001:8b0:1d0::2; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of pm215@archaic.org.uk designates 2001:8b0:1d0::2 as permitted sender) smtp.mailfrom=pm215@archaic.org.uk; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from pm215 by orth.archaic.org.uk with local (Exim 4.84_2) (envelope-from ) id 1dVyBz-0007jc-UQ; Fri, 14 Jul 2017 11:51:27 +0100 From: Peter Maydell To: qemu-arm@nongnu.org, qemu-devel@nongnu.org Cc: patches@linaro.org, =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= , Alistair Francis Subject: [PATCH v2 1/9] hw/arm/mps2: Implement skeleton mps2-an385 and mps2-an511 board models Date: Fri, 14 Jul 2017 11:51:19 +0100 Message-Id: <1500029487-14822-2-git-send-email-peter.maydell@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1500029487-14822-1-git-send-email-peter.maydell@linaro.org> References: <1500029487-14822-1-git-send-email-peter.maydell@linaro.org> Model the ARM MPS2/MPS2+ FPGA based development board. The MPS2 and MPS2+ dev boards are FPGA based (the 2+ has a bigger FPGA but is otherwise the same as the 2). Since the CPU itself and most of the devices are in the FPGA, the details of the board as seen by the guest depend significantly on the FPGA image. We model the following FPGA images: "mps2_an385" -- Cortex-M3 as documented in ARM Application Note AN385 "mps2_an511" -- Cortex-M3 'DesignStart' as documented in AN511 They are fairly similar but differ in the details for some peripherals. Signed-off-by: Peter Maydell --- hw/arm/Makefile.objs | 1 + hw/arm/mps2.c | 271 ++++++++++++++++++++++++++++++++++++++++ default-configs/arm-softmmu.mak | 1 + 3 files changed, 273 insertions(+) create mode 100644 hw/arm/mps2.c -- 2.7.4 Reviewed-by: Alex Bennée diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs index 4c5c4ee..a2e56ec 100644 --- a/hw/arm/Makefile.objs +++ b/hw/arm/Makefile.objs @@ -18,3 +18,4 @@ obj-$(CONFIG_FSL_IMX25) += fsl-imx25.o imx25_pdk.o obj-$(CONFIG_FSL_IMX31) += fsl-imx31.o kzm.o obj-$(CONFIG_FSL_IMX6) += fsl-imx6.o sabrelite.o obj-$(CONFIG_ASPEED_SOC) += aspeed_soc.o aspeed.o +obj-$(CONFIG_MPS2) += mps2.o diff --git a/hw/arm/mps2.c b/hw/arm/mps2.c new file mode 100644 index 0000000..3dad02d --- /dev/null +++ b/hw/arm/mps2.c @@ -0,0 +1,271 @@ +/* + * ARM V2M MPS2 board emulation. + * + * Copyright (c) 2017 Linaro Limited + * Written by Peter Maydell + * + * 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. + */ + +/* The MPS2 and MPS2+ dev boards are FPGA based (the 2+ has a bigger + * FPGA but is otherwise the same as the 2). Since the CPU itself + * and most of the devices are in the FPGA, the details of the board + * as seen by the guest depend significantly on the FPGA image. + * We model the following FPGA images: + * "mps2-an385" -- Cortex-M3 as documented in ARM Application Note AN385 + * "mps2-an511" -- Cortex-M3 'DesignStart' as documented in AN511 + * + * Links to the TRM for the board itself and to the various Application + * Notes which document the FPGA images can be found here: + * https://developer.arm.com/products/system-design/development-boards/cortex-m-prototyping-system + */ + +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "qemu/error-report.h" +#include "hw/arm/arm.h" +#include "hw/arm/armv7m.h" +#include "hw/boards.h" +#include "exec/address-spaces.h" +#include "hw/misc/unimp.h" + +typedef enum MPS2FPGAType { + FPGA_AN385, + FPGA_AN511, +} MPS2FPGAType; + +typedef struct { + MachineClass parent; + MPS2FPGAType fpga_type; + const char *cpu_model; +} MPS2MachineClass; + +typedef struct { + MachineState parent; + + ARMv7MState armv7m; + MemoryRegion psram; + MemoryRegion ssram1; + MemoryRegion ssram1_m; + MemoryRegion ssram23; + MemoryRegion ssram23_m; + MemoryRegion blockram; + MemoryRegion blockram_m1; + MemoryRegion blockram_m2; + MemoryRegion blockram_m3; + MemoryRegion sram; +} MPS2MachineState; + +#define TYPE_MPS2_MACHINE "mps2" +#define TYPE_MPS2_AN385_MACHINE MACHINE_TYPE_NAME("mps2-an385") +#define TYPE_MPS2_AN511_MACHINE MACHINE_TYPE_NAME("mps2-an511") + +#define MPS2_MACHINE(obj) \ + OBJECT_CHECK(MPS2MachineState, obj, TYPE_MPS2_MACHINE) +#define MPS2_MACHINE_GET_CLASS(obj) \ + OBJECT_GET_CLASS(MPS2MachineClass, obj, TYPE_MPS2_MACHINE) +#define MPS2_MACHINE_CLASS(klass) \ + OBJECT_CLASS_CHECK(MPS2MachineClass, klass, TYPE_MPS2_MACHINE) + +/* Main SYSCLK frequency in Hz */ +#define SYSCLK_FRQ 25000000 + +/* Initialize the auxiliary RAM region @mr and map it into + * the memory map at @base. + */ +static void make_ram(MemoryRegion *mr, const char *name, + hwaddr base, hwaddr size) +{ + memory_region_init_ram(mr, NULL, name, size, &error_fatal); + vmstate_register_ram_global(mr); + memory_region_add_subregion(get_system_memory(), base, mr); +} + +/* Create an alias of an entire original MemoryRegion @orig + * located at @base in the memory map. + */ +static void make_ram_alias(MemoryRegion *mr, const char *name, + MemoryRegion *orig, hwaddr base) +{ + memory_region_init_alias(mr, NULL, name, orig, 0, + memory_region_size(orig)); + memory_region_add_subregion(get_system_memory(), base, mr); +} + +static void mps2_common_init(MachineState *machine) +{ + MPS2MachineState *mms = MPS2_MACHINE(machine); + MPS2MachineClass *mmc = MPS2_MACHINE_GET_CLASS(machine); + MemoryRegion *system_memory = get_system_memory(); + DeviceState *armv7m; + + if (!machine->cpu_model) { + machine->cpu_model = mmc->cpu_model; + } + + if (strcmp(machine->cpu_model, mmc->cpu_model) != 0) { + error_report("This board can only be used with CPU %s", mmc->cpu_model); + exit(1); + } + + /* The FPGA images have an odd combination of different RAMs, + * because in hardware they are different implementations and + * connected to different buses, giving varying performance/size + * tradeoffs. For QEMU they're all just RAM, though. We arbitrarily + * call the 16MB our "system memory", as it's the largest lump. + * + * Common to both boards: + * 0x21000000..0x21ffffff : PSRAM (16MB) + * AN385 only: + * 0x00000000 .. 0x003fffff : ZBT SSRAM1 + * 0x00400000 .. 0x007fffff : mirror of ZBT SSRAM1 + * 0x20000000 .. 0x203fffff : ZBT SSRAM 2&3 + * 0x20400000 .. 0x207fffff : mirror of ZBT SSRAM 2&3 + * 0x01000000 .. 0x01003fff : block RAM (16K) + * 0x01004000 .. 0x01007fff : mirror of above + * 0x01008000 .. 0x0100bfff : mirror of above + * 0x0100c000 .. 0x0100ffff : mirror of above + * AN511 only: + * 0x00000000 .. 0x0003ffff : FPGA block RAM + * 0x00400000 .. 0x007fffff : ZBT SSRAM1 + * 0x20000000 .. 0x2001ffff : SRAM + * 0x20400000 .. 0x207fffff : ZBT SSRAM 2&3 + * + * The AN385 has a feature where the lowest 16K can be mapped + * either to the bottom of the ZBT SSRAM1 or to the block RAM. + * This is of no use for QEMU so we don't implement it (as if + * zbt_boot_ctrl is always zero). + */ + memory_region_allocate_system_memory(&mms->psram, + NULL, "mps.ram", 0x1000000); + memory_region_add_subregion(system_memory, 0x21000000, &mms->psram); + + switch (mmc->fpga_type) { + case FPGA_AN385: + make_ram(&mms->ssram1, "mps.ssram1", 0x0, 0x400000); + make_ram_alias(&mms->ssram1_m, "mps.ssram1_m", &mms->ssram1, 0x400000); + make_ram(&mms->ssram23, "mps.ssram23", 0x20000000, 0x400000); + make_ram_alias(&mms->ssram23_m, "mps.ssram23_m", + &mms->ssram23, 0x20400000); + make_ram(&mms->blockram, "mps.blockram", 0x01000000, 0x4000); + make_ram_alias(&mms->blockram_m1, "mps.blockram_m1", + &mms->blockram, 0x01004000); + make_ram_alias(&mms->blockram_m2, "mps.blockram_m2", + &mms->blockram, 0x01008000); + make_ram_alias(&mms->blockram_m3, "mps.blockram_m3", + &mms->blockram, 0x0100c000); + break; + case FPGA_AN511: + make_ram(&mms->blockram, "mps.blockram", 0x0, 0x40000); + make_ram(&mms->ssram1, "mps.ssram1", 0x00400000, 0x00800000); + make_ram(&mms->sram, "mps.sram", 0x20000000, 0x20000); + make_ram(&mms->ssram23, "mps.ssram23", 0x20400000, 0x400000); + break; + default: + g_assert_not_reached(); + } + + object_initialize(&mms->armv7m, sizeof(mms->armv7m), TYPE_ARMV7M); + armv7m = DEVICE(&mms->armv7m); + qdev_set_parent_bus(armv7m, sysbus_get_default()); + switch (mmc->fpga_type) { + case FPGA_AN385: + qdev_prop_set_uint32(armv7m, "num-irq", 32); + break; + case FPGA_AN511: + qdev_prop_set_uint32(armv7m, "num-irq", 64); + break; + default: + g_assert_not_reached(); + } + qdev_prop_set_string(armv7m, "cpu-model", machine->cpu_model); + object_property_set_link(OBJECT(&mms->armv7m), OBJECT(system_memory), + "memory", &error_abort); + object_property_set_bool(OBJECT(&mms->armv7m), true, "realized", + &error_fatal); + + create_unimplemented_device("zbtsmram mirror", 0x00400000, 0x00400000); + create_unimplemented_device("RESERVED 1", 0x00800000, 0x00800000); + create_unimplemented_device("Block RAM", 0x01000000, 0x00010000); + create_unimplemented_device("RESERVED 2", 0x01010000, 0x1EFF0000); + create_unimplemented_device("RESERVED 3", 0x20800000, 0x00800000); + create_unimplemented_device("PSRAM", 0x21000000, 0x01000000); + /* These three ranges all cover multiple devices; we may implement + * some of them below (in which case the real device takes precedence + * over the unimplemented-region mapping). + */ + create_unimplemented_device("CMSDK APB peripheral region @0x40000000", + 0x40000000, 0x00010000); + create_unimplemented_device("CMSDK peripheral region @0x40010000", + 0x40010000, 0x00010000); + create_unimplemented_device("Extra peripheral region @0x40020000", + 0x40020000, 0x00010000); + create_unimplemented_device("RESERVED 4", 0x40030000, 0x001D0000); + create_unimplemented_device("Ethernet", 0x40200000, 0x00100000); + create_unimplemented_device("VGA", 0x41000000, 0x0200000); + + system_clock_scale = NANOSECONDS_PER_SECOND / SYSCLK_FRQ; + + armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, + 0x400000); +} + +static void mps2_class_init(ObjectClass *oc, void *data) +{ + MachineClass *mc = MACHINE_CLASS(oc); + + mc->init = mps2_common_init; + mc->max_cpus = 1; +} + +static void mps2_an385_class_init(ObjectClass *oc, void *data) +{ + MachineClass *mc = MACHINE_CLASS(oc); + MPS2MachineClass *mmc = MPS2_MACHINE_CLASS(oc); + + mc->desc = "ARM MPS2 with AN385 FPGA image for Cortex-M3"; + mmc->fpga_type = FPGA_AN385; + mmc->cpu_model = "cortex-m3"; +} + +static void mps2_an511_class_init(ObjectClass *oc, void *data) +{ + MachineClass *mc = MACHINE_CLASS(oc); + MPS2MachineClass *mmc = MPS2_MACHINE_CLASS(oc); + + mc->desc = "ARM MPS2 with AN511 DesignStart FPGA image for Cortex-M3"; + mmc->fpga_type = FPGA_AN511; + mmc->cpu_model = "cortex-m3"; +} + +static const TypeInfo mps2_info = { + .name = TYPE_MPS2_MACHINE, + .parent = TYPE_MACHINE, + .abstract = true, + .instance_size = sizeof(MPS2MachineState), + .class_size = sizeof(MPS2MachineClass), + .class_init = mps2_class_init, +}; + +static const TypeInfo mps2_an385_info = { + .name = TYPE_MPS2_AN385_MACHINE, + .parent = TYPE_MPS2_MACHINE, + .class_init = mps2_an385_class_init, +}; + +static const TypeInfo mps2_an511_info = { + .name = TYPE_MPS2_AN511_MACHINE, + .parent = TYPE_MPS2_MACHINE, + .class_init = mps2_an511_class_init, +}; + +static void mps2_machine_init(void) +{ + type_register_static(&mps2_info); + type_register_static(&mps2_an385_info); + type_register_static(&mps2_an511_info); +} + +type_init(mps2_machine_init); diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak index 93e995d..bfd2a88 100644 --- a/default-configs/arm-softmmu.mak +++ b/default-configs/arm-softmmu.mak @@ -83,6 +83,7 @@ CONFIG_ONENAND=y CONFIG_TUSB6010=y CONFIG_IMX=y CONFIG_MAINSTONE=y +CONFIG_MPS2=y CONFIG_NSERIES=y CONFIG_RASPI=y CONFIG_REALVIEW=y From patchwork Fri Jul 14 10:51:20 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 107766 Delivered-To: patches@linaro.org Received: by 10.140.101.44 with SMTP id t41csp729848qge; Fri, 14 Jul 2017 03:51:31 -0700 (PDT) X-Received: by 10.25.145.82 with SMTP id y18mr2940121lfj.158.1500029491184; Fri, 14 Jul 2017 03:51:31 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1500029491; cv=none; d=google.com; s=arc-20160816; b=TqBOvj4DzFaYmLcNIEw0PMD6tO6PV3H0aXkVUU0Puk6EV/aXSn4RUvUJ7McVaGhe2G GrtUEoaDUrAmK3iYDCcy+EzET6O4arsj0oTEGEAORxh3byuIMDu56enKs2jQ3ZIp6VZL tiSXHhIGsHc1gQea864Bwoj9BhTtCnv4M0H9C+wElvAd8SkeMYUSts0iU5MJqtpG8MSo WxbqCENQ3a+T/TQnN5MkrCH8oKztl0DFnrRjYxPkFpzAIgh8o4x6D+eCLCyr84iH/2VA 933SIPGlNxX8p8Ek8BVtZ5sTwcKTO1zxO5+EC0ZhJJeJY41gOxDly3etv7CRH8KeIWEC 0Gpw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=references:in-reply-to:message-id:date:subject:cc:to:from :arc-authentication-results; bh=d5ZpoJrU5RVoVqAlHmHw1zXekfunG1ND8m8LSxqVVEE=; b=zBDzIyr+hv7AectTlDFGAYVHN+SUJCla59+OJOq2cwRTiMVFPG0Jxz7qQJ5HfQRZcA nx1q39cK3J0ld1MWp5xekqD7hBZIHGAfWm1rR5GfiL5GdsWwKQ4WKqcY//fEMafefBX/ 0DO6Oz0/BUIZSqWMixPWF8bYQzXOoU1p/dJppi1qXiOHvpEcVBGN4r+iudpNxtklHVJK WeYaEbUpTZuDJX55+EMVDi+5JxFLucP/PQtYcovUS4kRYFARz1K/wq3Aks4vlvfm4Cml Wp/IdGVy441NHyO8M47Jd1iQBFMnA2ZUmAll6iyYMLmt9wpXP/zVN/tmlxp5rtpHFspZ apXA== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of pm215@archaic.org.uk designates 2001:8b0:1d0::2 as permitted sender) smtp.mailfrom=pm215@archaic.org.uk; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from orth.archaic.org.uk (orth.archaic.org.uk. [2001:8b0:1d0::2]) by mx.google.com with ESMTPS id h93si4482397ljh.100.2017.07.14.03.51.30 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 14 Jul 2017 03:51:30 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of pm215@archaic.org.uk designates 2001:8b0:1d0::2 as permitted sender) client-ip=2001:8b0:1d0::2; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of pm215@archaic.org.uk designates 2001:8b0:1d0::2 as permitted sender) smtp.mailfrom=pm215@archaic.org.uk; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from pm215 by orth.archaic.org.uk with local (Exim 4.84_2) (envelope-from ) id 1dVyC0-0007jt-Cm; Fri, 14 Jul 2017 11:51:28 +0100 From: Peter Maydell To: qemu-arm@nongnu.org, qemu-devel@nongnu.org Cc: patches@linaro.org, =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= , Alistair Francis Subject: [PATCH v2 2/9] hw/char/cmsdk-apb-uart.c: Implement CMSDK APB UART Date: Fri, 14 Jul 2017 11:51:20 +0100 Message-Id: <1500029487-14822-3-git-send-email-peter.maydell@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1500029487-14822-1-git-send-email-peter.maydell@linaro.org> References: <1500029487-14822-1-git-send-email-peter.maydell@linaro.org> Implement a model of the simple "APB UART" provided in the Cortex-M System Design Kit (CMSDK). Signed-off-by: Peter Maydell --- hw/char/Makefile.objs | 1 + include/hw/char/cmsdk-apb-uart.h | 78 ++++++++ hw/char/cmsdk-apb-uart.c | 402 +++++++++++++++++++++++++++++++++++++++ default-configs/arm-softmmu.mak | 2 + hw/char/trace-events | 9 + 5 files changed, 492 insertions(+) create mode 100644 include/hw/char/cmsdk-apb-uart.h create mode 100644 hw/char/cmsdk-apb-uart.c -- 2.7.4 Reviewed-by: Alex Bennée diff --git a/hw/char/Makefile.objs b/hw/char/Makefile.objs index 55fcb68..1bcd37e 100644 --- a/hw/char/Makefile.objs +++ b/hw/char/Makefile.objs @@ -19,6 +19,7 @@ obj-$(CONFIG_DIGIC) += digic-uart.o obj-$(CONFIG_STM32F2XX_USART) += stm32f2xx_usart.o obj-$(CONFIG_RASPI) += bcm2835_aux.o +common-obj-$(CONFIG_CMSDK_APB_UART) += cmsdk-apb-uart.o common-obj-$(CONFIG_ETRAXFS) += etraxfs_ser.o common-obj-$(CONFIG_ISA_DEBUG) += debugcon.o common-obj-$(CONFIG_GRLIB) += grlib_apbuart.o diff --git a/include/hw/char/cmsdk-apb-uart.h b/include/hw/char/cmsdk-apb-uart.h new file mode 100644 index 0000000..c41fba9 --- /dev/null +++ b/include/hw/char/cmsdk-apb-uart.h @@ -0,0 +1,78 @@ +/* + * ARM CMSDK APB UART emulation + * + * Copyright (c) 2017 Linaro Limited + * Written by Peter Maydell + * + * 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. + */ + +#ifndef CMSDK_APB_UART_H +#define CMSDK_APB_UART_H + +#include "hw/sysbus.h" +#include "chardev/char-fe.h" + +#define TYPE_CMSDK_APB_UART "cmsdk-apb-uart" +#define CMSDK_APB_UART(obj) OBJECT_CHECK(CMSDKAPBUART, (obj), \ + TYPE_CMSDK_APB_UART) + +typedef struct { + /*< private >*/ + SysBusDevice parent_obj; + + /*< public >*/ + MemoryRegion iomem; + CharBackend chr; + qemu_irq txint; + qemu_irq rxint; + qemu_irq txovrint; + qemu_irq rxovrint; + qemu_irq uartint; + guint watch_tag; + uint32_t pclk_frq; + + uint32_t state; + uint32_t ctrl; + uint32_t intstatus; + uint32_t bauddiv; + /* This UART has no FIFO, only a 1-character buffer for each of Tx and Rx */ + uint8_t txbuf; + uint8_t rxbuf; +} CMSDKAPBUART; + +/** + * cmsdk_apb_uart_create - convenience function to create TYPE_CMSDK_APB_UART + * @addr: location in system memory to map registers + * @chr: Chardev backend to connect UART to, or NULL if no backend + * @pclk_frq: frequency in Hz of the PCLK clock (used for calculating baud rate) + */ +static inline DeviceState *cmsdk_apb_uart_create(hwaddr addr, + qemu_irq txint, + qemu_irq rxint, + qemu_irq txovrint, + qemu_irq rxovrint, + qemu_irq uartint, + Chardev *chr, + uint32_t pclk_frq) +{ + DeviceState *dev; + SysBusDevice *s; + + dev = qdev_create(NULL, TYPE_CMSDK_APB_UART); + s = SYS_BUS_DEVICE(dev); + qdev_prop_set_chr(dev, "chardev", chr); + qdev_prop_set_uint32(dev, "pclk-frq", pclk_frq); + qdev_init_nofail(dev); + sysbus_mmio_map(s, 0, addr); + sysbus_connect_irq(s, 0, txint); + sysbus_connect_irq(s, 1, rxint); + sysbus_connect_irq(s, 2, txovrint); + sysbus_connect_irq(s, 3, rxovrint); + sysbus_connect_irq(s, 4, uartint); + return dev; +} + +#endif diff --git a/hw/char/cmsdk-apb-uart.c b/hw/char/cmsdk-apb-uart.c new file mode 100644 index 0000000..82d2bea --- /dev/null +++ b/hw/char/cmsdk-apb-uart.c @@ -0,0 +1,402 @@ +/* + * ARM CMSDK APB UART emulation + * + * Copyright (c) 2017 Linaro Limited + * Written by Peter Maydell + * + * 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. + */ + +/* This is a model of the "APB UART" which is part of the Cortex-M + * System Design Kit (CMSDK) and documented in the Cortex-M System + * Design Kit Technical Reference Manual (ARM DDI0479C): + * https://developer.arm.com/products/system-design/system-design-kits/cortex-m-system-design-kit + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "qapi/error.h" +#include "trace.h" +#include "hw/sysbus.h" +#include "hw/registerfields.h" +#include "chardev/char-fe.h" +#include "chardev/char-serial.h" +#include "hw/char/cmsdk-apb-uart.h" + +REG32(DATA, 0) +REG32(STATE, 4) + FIELD(STATE, TXFULL, 0, 1) + FIELD(STATE, RXFULL, 1, 1) + FIELD(STATE, TXOVERRUN, 2, 1) + FIELD(STATE, RXOVERRUN, 3, 1) +REG32(CTRL, 8) + FIELD(CTRL, TX_EN, 0, 1) + FIELD(CTRL, RX_EN, 1, 1) + FIELD(CTRL, TX_INTEN, 2, 1) + FIELD(CTRL, RX_INTEN, 3, 1) + FIELD(CTRL, TXO_INTEN, 4, 1) + FIELD(CTRL, RXO_INTEN, 5, 1) + FIELD(CTRL, HSTEST, 6, 1) +REG32(INTSTATUS, 0xc) + FIELD(INTSTATUS, TX, 0, 1) + FIELD(INTSTATUS, RX, 1, 1) + FIELD(INTSTATUS, TXO, 2, 1) + FIELD(INTSTATUS, RXO, 3, 1) +REG32(BAUDDIV, 0x10) +REG32(PID4, 0xFD0) +REG32(PID5, 0xFD4) +REG32(PID6, 0xFD8) +REG32(PID7, 0xFDC) +REG32(PID0, 0xFE0) +REG32(PID1, 0xFE4) +REG32(PID2, 0xFE8) +REG32(PID3, 0xFEC) +REG32(CID0, 0xFF0) +REG32(CID1, 0xFF4) +REG32(CID2, 0xFF8) +REG32(CID3, 0xFFC) + +/* PID/CID values */ +static const int uart_id[] = { + 0x04, 0x00, 0x00, 0x00, /* PID4..PID7 */ + 0x21, 0xb8, 0x1b, 0x00, /* PID0..PID3 */ + 0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */ +}; + +static bool uart_baudrate_ok(CMSDKAPBUART *s) +{ + /* The minimum permitted bauddiv setting is 16, so we just ignore + * settings below that (usually this means the device has just + * been reset and not yet programmed). + */ + return s->bauddiv >= 16 && s->bauddiv <= s->pclk_frq; +} + +static void uart_update_parameters(CMSDKAPBUART *s) +{ + QEMUSerialSetParams ssp; + + /* This UART is always 8N1 but the baud rate is programmable. */ + if (!uart_baudrate_ok(s)) { + return; + } + + ssp.data_bits = 8; + ssp.parity = 'N'; + ssp.stop_bits = 1; + ssp.speed = s->pclk_frq / s->bauddiv; + qemu_chr_fe_ioctl(&s->chr, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp); + trace_cmsdk_apb_uart_set_params(ssp.speed); +} + +static void cmsdk_apb_uart_update(CMSDKAPBUART *s) +{ + /* update outbound irqs, including handling the way the rxo and txo + * interrupt status bits are just logical AND of the overrun bit in + * STATE and the overrun interrupt enable bit in CTRL. + */ + uint32_t omask = (R_INTSTATUS_RXO_MASK | R_INTSTATUS_TXO_MASK); + s->intstatus &= ~omask; + s->intstatus |= (s->state & (s->ctrl >> 2) & omask); + + qemu_set_irq(s->txint, !!(s->intstatus & R_INTSTATUS_TX_MASK)); + qemu_set_irq(s->rxint, !!(s->intstatus & R_INTSTATUS_RX_MASK)); + qemu_set_irq(s->txovrint, !!(s->intstatus & R_INTSTATUS_TXO_MASK)); + qemu_set_irq(s->rxovrint, !!(s->intstatus & R_INTSTATUS_RXO_MASK)); + qemu_set_irq(s->uartint, !!(s->intstatus)); +} + +static int uart_can_receive(void *opaque) +{ + CMSDKAPBUART *s = CMSDK_APB_UART(opaque); + + /* We can take a char if RX is enabled and the buffer is empty */ + if (s->ctrl & R_CTRL_RX_EN_MASK && !(s->state & R_STATE_RXFULL_MASK)) { + return 1; + } + return 0; +} + +static void uart_receive(void *opaque, const uint8_t *buf, int size) +{ + CMSDKAPBUART *s = CMSDK_APB_UART(opaque); + + trace_cmsdk_apb_uart_receive(*buf); + + /* In fact uart_can_receive() ensures that we can't be + * called unless RX is enabled and the buffer is empty, + * but we include this logic as documentation of what the + * hardware does if a character arrives in these circumstances. + */ + if (!(s->ctrl & R_CTRL_RX_EN_MASK)) { + /* Just drop the character on the floor */ + return; + } + + if (s->state & R_STATE_RXFULL_MASK) { + s->state |= R_STATE_RXOVERRUN_MASK; + } + + s->rxbuf = *buf; + s->state |= R_STATE_RXFULL_MASK; + if (s->ctrl & R_CTRL_RX_INTEN_MASK) { + s->intstatus |= R_INTSTATUS_RX_MASK; + } + cmsdk_apb_uart_update(s); +} + +static uint64_t uart_read(void *opaque, hwaddr offset, unsigned size) +{ + CMSDKAPBUART *s = CMSDK_APB_UART(opaque); + uint64_t r; + + switch (offset) { + case A_DATA: + r = s->rxbuf; + s->state &= ~R_STATE_RXFULL_MASK; + cmsdk_apb_uart_update(s); + break; + case A_STATE: + r = s->state; + break; + case A_CTRL: + r = s->ctrl; + break; + case A_INTSTATUS: + r = s->intstatus; + break; + case A_BAUDDIV: + r = s->bauddiv; + break; + case A_PID4 ... A_CID3: + r = uart_id[(offset - A_PID4) / 4]; + break; + default: + qemu_log_mask(LOG_GUEST_ERROR, + "CMSDK APB UART read: bad offset %x\n", (int) offset); + r = 0; + break; + } + trace_cmsdk_apb_uart_read(offset, r, size); + return r; +} + +/* Try to send tx data, and arrange to be called back later if + * we can't (ie the char backend is busy/blocking). + */ +static gboolean uart_transmit(GIOChannel *chan, GIOCondition cond, void *opaque) +{ + CMSDKAPBUART *s = CMSDK_APB_UART(opaque); + int ret; + + s->watch_tag = 0; + + if (!(s->ctrl & R_CTRL_TX_EN_MASK) || !(s->state & R_STATE_TXFULL_MASK)) { + return FALSE; + } + + ret = qemu_chr_fe_write(&s->chr, &s->txbuf, 1); + if (ret <= 0) { + s->watch_tag = qemu_chr_fe_add_watch(&s->chr, G_IO_OUT | G_IO_HUP, + uart_transmit, s); + if (!s->watch_tag) { + /* Most common reason to be here is "no chardev backend": + * just insta-drain the buffer, so the serial output + * goes into a void, rather than blocking the guest. + */ + goto buffer_drained; + } + /* Transmit pending */ + trace_cmsdk_apb_uart_tx_pending(); + return FALSE; + } + +buffer_drained: + /* Character successfully sent */ + trace_cmsdk_apb_uart_tx(s->txbuf); + s->state &= ~R_STATE_TXFULL_MASK; + /* Going from TXFULL set to clear triggers the tx interrupt */ + if (s->ctrl & R_CTRL_TX_INTEN_MASK) { + s->intstatus |= R_INTSTATUS_TX_MASK; + } + cmsdk_apb_uart_update(s); + return FALSE; +} + +static void uart_cancel_transmit(CMSDKAPBUART *s) +{ + if (s->watch_tag) { + g_source_remove(s->watch_tag); + s->watch_tag = 0; + } +} + +static void uart_write(void *opaque, hwaddr offset, uint64_t value, + unsigned size) +{ + CMSDKAPBUART *s = CMSDK_APB_UART(opaque); + + trace_cmsdk_apb_uart_write(offset, value, size); + + switch (offset) { + case A_DATA: + s->txbuf = value; + if (s->state & R_STATE_TXFULL_MASK) { + /* Buffer already full -- note the overrun and let the + * existing pending transmit callback handle the new char. + */ + s->state |= R_STATE_TXOVERRUN_MASK; + cmsdk_apb_uart_update(s); + } else { + s->state |= R_STATE_TXFULL_MASK; + uart_transmit(NULL, G_IO_OUT, s); + } + break; + case A_STATE: + /* Bits 0 and 1 are read only; bits 2 and 3 are W1C */ + s->state &= ~(value & 0xc); + cmsdk_apb_uart_update(s); + break; + case A_CTRL: + s->ctrl = value & 0x7f; + if ((s->ctrl & R_CTRL_TX_EN_MASK) && !uart_baudrate_ok(s)) { + qemu_log_mask(LOG_GUEST_ERROR, + "CMSDK APB UART: Tx enabled with invalid baudrate\n"); + } + cmsdk_apb_uart_update(s); + break; + case A_INTSTATUS: + /* All bits are W1C. Clearing the overrun interrupt bits really + * clears the overrun status bits in the STATE register (which + * is then reflected into the intstatus value by the update function). + */ + s->state &= ~(value & 0xc); + cmsdk_apb_uart_update(s); + break; + case A_BAUDDIV: + s->bauddiv = value & 0xFFFFF; + uart_update_parameters(s); + break; + case A_PID4 ... A_CID3: + qemu_log_mask(LOG_GUEST_ERROR, + "CMSDK APB UART write: write to RO offset 0x%x\n", + (int)offset); + break; + default: + qemu_log_mask(LOG_GUEST_ERROR, + "CMSDK APB UART write: bad offset 0x%x\n", (int) offset); + break; + } +} + +static const MemoryRegionOps uart_ops = { + .read = uart_read, + .write = uart_write, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +static void cmsdk_apb_uart_reset(DeviceState *dev) +{ + CMSDKAPBUART *s = CMSDK_APB_UART(dev); + + trace_cmsdk_apb_uart_reset(); + uart_cancel_transmit(s); + s->state = 0; + s->ctrl = 0; + s->intstatus = 0; + s->bauddiv = 0; + s->txbuf = 0; + s->rxbuf = 0; +} + +static void cmsdk_apb_uart_init(Object *obj) +{ + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + CMSDKAPBUART *s = CMSDK_APB_UART(obj); + + memory_region_init_io(&s->iomem, obj, &uart_ops, s, "uart", 0x1000); + sysbus_init_mmio(sbd, &s->iomem); + sysbus_init_irq(sbd, &s->txint); + sysbus_init_irq(sbd, &s->rxint); + sysbus_init_irq(sbd, &s->txovrint); + sysbus_init_irq(sbd, &s->rxovrint); + sysbus_init_irq(sbd, &s->uartint); +} + +static void cmsdk_apb_uart_realize(DeviceState *dev, Error **errp) +{ + CMSDKAPBUART *s = CMSDK_APB_UART(dev); + + if (s->pclk_frq == 0) { + error_setg(errp, "CMSDK APB UART: pclk-frq property must be set"); + return; + } + + /* This UART has no flow control, so we do not need to register + * an event handler to deal with CHR_EVENT_BREAK. + */ + qemu_chr_fe_set_handlers(&s->chr, uart_can_receive, uart_receive, + NULL, s, NULL, true); +} + +static int cmsdk_apb_uart_post_load(void *opaque, int version_id) +{ + CMSDKAPBUART *s = CMSDK_APB_UART(opaque); + + /* If we have a pending character, arrange to resend it. */ + if (s->state & R_STATE_TXFULL_MASK) { + s->watch_tag = qemu_chr_fe_add_watch(&s->chr, G_IO_OUT | G_IO_HUP, + uart_transmit, s); + } + uart_update_parameters(s); + return 0; +} + +static const VMStateDescription cmsdk_apb_uart_vmstate = { + .name = "cmsdk-apb-uart", + .version_id = 1, + .minimum_version_id = 1, + .post_load = cmsdk_apb_uart_post_load, + .fields = (VMStateField[]) { + VMSTATE_UINT32(state, CMSDKAPBUART), + VMSTATE_UINT32(ctrl, CMSDKAPBUART), + VMSTATE_UINT32(intstatus, CMSDKAPBUART), + VMSTATE_UINT32(bauddiv, CMSDKAPBUART), + VMSTATE_UINT8(txbuf, CMSDKAPBUART), + VMSTATE_UINT8(rxbuf, CMSDKAPBUART), + VMSTATE_END_OF_LIST() + } +}; + +static Property cmsdk_apb_uart_properties[] = { + DEFINE_PROP_CHR("chardev", CMSDKAPBUART, chr), + DEFINE_PROP_UINT32("pclk-frq", CMSDKAPBUART, pclk_frq, 0), + DEFINE_PROP_END_OF_LIST(), +}; + +static void cmsdk_apb_uart_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->realize = cmsdk_apb_uart_realize; + dc->vmsd = &cmsdk_apb_uart_vmstate; + dc->reset = cmsdk_apb_uart_reset; + dc->props = cmsdk_apb_uart_properties; +} + +static const TypeInfo cmsdk_apb_uart_info = { + .name = TYPE_CMSDK_APB_UART, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(CMSDKAPBUART), + .instance_init = cmsdk_apb_uart_init, + .class_init = cmsdk_apb_uart_class_init, +}; + +static void cmsdk_apb_uart_register_types(void) +{ + type_register_static(&cmsdk_apb_uart_info); +} + +type_init(cmsdk_apb_uart_register_types); diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak index bfd2a88..d128e9d 100644 --- a/default-configs/arm-softmmu.mak +++ b/default-configs/arm-softmmu.mak @@ -96,6 +96,8 @@ CONFIG_STM32F2XX_ADC=y CONFIG_STM32F2XX_SPI=y CONFIG_STM32F205_SOC=y +CONFIG_CMSDK_APB_UART=y + CONFIG_VERSATILE_PCI=y CONFIG_VERSATILE_I2C=y diff --git a/hw/char/trace-events b/hw/char/trace-events index 7fd48bb..daf4ee4 100644 --- a/hw/char/trace-events +++ b/hw/char/trace-events @@ -56,3 +56,12 @@ pl011_write(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x" pl011_can_receive(uint32_t lcr, int read_count, int r) "LCR %08x read_count %d returning %d" pl011_put_fifo(uint32_t c, int read_count) "new char 0x%x read_count now %d" pl011_put_fifo_full(void) "FIFO now full, RXFF set" + +# hw/char/cmsdk_apb_uart.c +cmsdk_apb_uart_read(uint64_t offset, uint64_t data, unsigned size) "CMSDK APB UART read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u" +cmsdk_apb_uart_write(uint64_t offset, uint64_t data, unsigned size) "CMSDK APB UART write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u" +cmsdk_apb_uart_reset(void) "CMSDK APB UART: reset" +cmsdk_apb_uart_receive(uint8_t c) "CMSDK APB UART: got character 0x%x from backend" +cmsdk_apb_uart_tx_pending(void) "CMSDK APB UART: character send to backend pending" +cmsdk_apb_uart_tx(uint8_t c) "CMSDK APB UART: character 0x%x sent to backend" +cmsdk_apb_uart_set_params(int speed) "CMSDK APB UART: params set to %d 8N1" From patchwork Fri Jul 14 10:51:21 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 107765 Delivered-To: patches@linaro.org Received: by 10.140.101.44 with SMTP id t41csp729855qge; Fri, 14 Jul 2017 03:51:31 -0700 (PDT) X-Received: by 10.28.109.26 with SMTP id i26mr2486823wmc.64.1500029491439; Fri, 14 Jul 2017 03:51:31 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1500029491; cv=none; d=google.com; s=arc-20160816; b=dusXVVb3ZX0IZ2EmQjJCSY7LxQ3Lcj/s7H6Sr22DKieTX8gsD3zxPyi+QxVA4fB2VH VBZ1++18W/S5RCgOaFyohQHKs62nlxrmD6iZ1CjFSUhRuNkpq98CdcvaDqJW2nE2tCvX 76K0arKsgB68VHZON/OeQWxvnt5VZxK9yYQZuSbohE2VdT9szfRxUmcfO+RRDGFqvTlC 0mT7OUqwEC+11BtA7Lx/c1Ujdwam2NlqnwoYIfX5bjNF6+7mPO1ysSTjbA2CvZruWjnE p0IOfkrSoYVRRJ64Org+HD08R89RrVoX0Tfih++Ea9hKbyjAWu/aOIhuUMiDguZ0e+IA lyCg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=references:in-reply-to:message-id:date:subject:cc:to:from :arc-authentication-results; bh=z4/fTT/pmsnXzSM0zFLnDUTgAAkWScl5TL+n/1hgCjQ=; b=mHWUr7fM8aNh6puxP1VdegNW93n7OJsDANul8CNsM/TxnKAf7qg8vGMD3OXashdn9/ HS1Fm8B2VNnGYfwBSiACPT3nCbiG1VI+8o530LtOpnUmTFEcgKLMmWh0u+sgRKZAOSgc zvQJCzKDVSNiPq2wjOh0b3aEL01aseN4iBk45wIcs4votDBMjzEtuOzjzAxrn/w6pgW+ UeDQHTWw2Wfq1Nl8ENIq5gJLInxQyXAaZfEEwU414lNZiIwJO/hwUMybxfhCi+vwHXvk LOG24bUBlXf5sH2i+223ns8DUMgnsDj6Iwn4dILa1epi1jfODHh72lQtcn56cuzJKyuV 1sMQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of pm215@archaic.org.uk designates 2001:8b0:1d0::2 as permitted sender) smtp.mailfrom=pm215@archaic.org.uk; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from orth.archaic.org.uk (orth.archaic.org.uk. [2001:8b0:1d0::2]) by mx.google.com with ESMTPS id n16si6269991wrn.214.2017.07.14.03.51.30 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 14 Jul 2017 03:51:30 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of pm215@archaic.org.uk designates 2001:8b0:1d0::2 as permitted sender) client-ip=2001:8b0:1d0::2; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of pm215@archaic.org.uk designates 2001:8b0:1d0::2 as permitted sender) smtp.mailfrom=pm215@archaic.org.uk; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from pm215 by orth.archaic.org.uk with local (Exim 4.84_2) (envelope-from ) id 1dVyC0-0007kA-Sl; Fri, 14 Jul 2017 11:51:28 +0100 From: Peter Maydell To: qemu-arm@nongnu.org, qemu-devel@nongnu.org Cc: patches@linaro.org, =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= , Alistair Francis Subject: [PATCH v2 3/9] hw/arm/mps2: Add UARTs Date: Fri, 14 Jul 2017 11:51:21 +0100 Message-Id: <1500029487-14822-4-git-send-email-peter.maydell@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1500029487-14822-1-git-send-email-peter.maydell@linaro.org> References: <1500029487-14822-1-git-send-email-peter.maydell@linaro.org> Add the UARTs to the MPS2 board models. Unfortunately the details of the wiring of the interrupts through various OR gates differ between AN511 and AN385 so this can't be purely a data-driven difference. Signed-off-by: Peter Maydell Reviewed-by: Alistair Francis --- hw/arm/mps2.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) -- 2.7.4 diff --git a/hw/arm/mps2.c b/hw/arm/mps2.c index 3dad02d..180c5d2 100644 --- a/hw/arm/mps2.c +++ b/hw/arm/mps2.c @@ -27,9 +27,12 @@ #include "qemu/error-report.h" #include "hw/arm/arm.h" #include "hw/arm/armv7m.h" +#include "hw/or-irq.h" #include "hw/boards.h" #include "exec/address-spaces.h" +#include "sysemu/sysemu.h" #include "hw/misc/unimp.h" +#include "hw/char/cmsdk-apb-uart.h" typedef enum MPS2FPGAType { FPGA_AN385, @@ -206,6 +209,89 @@ static void mps2_common_init(MachineState *machine) create_unimplemented_device("Ethernet", 0x40200000, 0x00100000); create_unimplemented_device("VGA", 0x41000000, 0x0200000); + switch (mmc->fpga_type) { + case FPGA_AN385: + { + /* The overflow IRQs for UARTs 0, 1 and 2 are ORed together. + * Overflow for UARTs 4 and 5 doesn't trigger any interrupt. + */ + Object *orgate; + DeviceState *orgate_dev; + int i; + + orgate = object_new(TYPE_OR_IRQ); + object_property_set_int(orgate, 6, "num-lines", &error_fatal); + object_property_set_bool(orgate, true, "realized", &error_fatal); + orgate_dev = DEVICE(orgate); + qdev_connect_gpio_out(orgate_dev, 0, qdev_get_gpio_in(armv7m, 12)); + + for (i = 0; i < 5; i++) { + hwaddr uartbase[] = {0x40004000, 0x40005000, 0x40006000, + 0x40007000, 0x40009000}; + Chardev *uartchr = i < MAX_SERIAL_PORTS ? serial_hds[i] : NULL; + /* RX irq number; TX irq is always one greater */ + int uartirq[] = {0, 2, 4, 18, 20}; + qemu_irq txovrint = NULL, rxovrint = NULL; + + if (i < 3) { + txovrint = qdev_get_gpio_in(orgate_dev, i * 2); + rxovrint = qdev_get_gpio_in(orgate_dev, i * 2 + 1); + } + + cmsdk_apb_uart_create(uartbase[i], + qdev_get_gpio_in(armv7m, uartirq[i] + 1), + qdev_get_gpio_in(armv7m, uartirq[i]), + txovrint, rxovrint, + NULL, + uartchr, SYSCLK_FRQ); + } + break; + } + case FPGA_AN511: + { + /* The overflow IRQs for all UARTs are ORed together. + * Tx and Rx IRQs for each UART are ORed together. + */ + Object *orgate; + DeviceState *orgate_dev; + int i; + + orgate = object_new(TYPE_OR_IRQ); + object_property_set_int(orgate, 10, "num-lines", &error_fatal); + object_property_set_bool(orgate, true, "realized", &error_fatal); + orgate_dev = DEVICE(orgate); + qdev_connect_gpio_out(orgate_dev, 0, qdev_get_gpio_in(armv7m, 12)); + + for (i = 0; i < 5; i++) { + /* system irq numbers for the combined tx/rx for each UART */ + const int uart_txrx_irqno[] = {0, 2, 45, 46, 56}; + hwaddr uartbase[] = {0x40004000, 0x40005000, 0x4002c000, + 0x4002d000, 0x4002e000}; + Chardev *uartchr = i < MAX_SERIAL_PORTS ? serial_hds[i] : NULL; + Object *txrx_orgate; + DeviceState *txrx_orgate_dev; + + txrx_orgate = object_new(TYPE_OR_IRQ); + object_property_set_int(txrx_orgate, 2, "num-lines", &error_fatal); + object_property_set_bool(txrx_orgate, true, "realized", + &error_fatal); + txrx_orgate_dev = DEVICE(txrx_orgate); + qdev_connect_gpio_out(txrx_orgate_dev, 0, + qdev_get_gpio_in(armv7m, uart_txrx_irqno[i])); + cmsdk_apb_uart_create(uartbase[i], + qdev_get_gpio_in(txrx_orgate_dev, 0), + qdev_get_gpio_in(txrx_orgate_dev, 1), + qdev_get_gpio_in(orgate_dev, 0), + qdev_get_gpio_in(orgate_dev, 1), + NULL, + uartchr, SYSCLK_FRQ); + } + break; + } + default: + g_assert_not_reached(); + } + system_clock_scale = NANOSECONDS_PER_SECOND / SYSCLK_FRQ; armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, From patchwork Fri Jul 14 10:51:22 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 107773 Delivered-To: patches@linaro.org Received: by 10.140.101.44 with SMTP id t41csp729879qge; Fri, 14 Jul 2017 03:51:32 -0700 (PDT) X-Received: by 10.101.73.197 with SMTP id t5mr14228398pgs.160.1500029492707; Fri, 14 Jul 2017 03:51:32 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1500029492; cv=none; d=google.com; s=arc-20160816; b=OMOVNLnXgAgj+VddngIxpl/pUPCXaaF1LFIdFMd3xS67AyJfj0YQ+NxKaZPuPXGJg4 Q+LDyCgUV0ZO690SDeqflJ1QwkaPUCZ1lDyBoIWjpBrucPd//+NY6jWw8hvEAcNbjg2+ upFO0S3/eTLhBscYTQTfs2ED/czm9tJJogML7S99TP9d/B69c7vDduqv/Nh3lIDaNlo8 xVm2KcJwqddnicQmfJGRysRONaMCv2ZxLiF5bp01Cb8lr4ZgjK++UqeebXL9LVpGO3Tt KFPSgk0GOGfyYrRca2bibm/0fD2PDZHJQdvtQk9dJLQnXaCrXnBqrb/psPycuQ9+HkTi 9m1g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:arc-authentication-results; bh=yHeCpQBduc+vXqFGhsq6+e9qt12urpRFb/sgxn6BrNk=; b=A/+J7GAkwqvLLMi9pgfHEn4ZYImKEAA5Bmlf46vPHjxPO6jXD9FXjzmlYl4yo6YLLG F6xNkRGS5F7DUEb2n3eccSzlxEhLF/OH9PPEYEWl+e2YENg5Wxof5OXXBbKG5LxtSRnr AIHQTM54+n3Anmm2dCBiJnA6tfp989QP+/wavMMHVsCaLppKMWEO6QWsItg7nlhhCie5 LbCtuKaz57kuMC/pLE8WcoC3lEKRwMrqc0WbwDAStUN8/cqQ5Nqk/pp7IDRc6X5ATkb/ UyaSZpSetryVUbCsg77y/uNkBzBoVxJBZ2Kc0cV6VZ+d/jtI4NFMDPHGQer95Yh1zbEK o6yQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of pm215@archaic.org.uk designates 2001:8b0:1d0::2 as permitted sender) smtp.mailfrom=pm215@archaic.org.uk; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from orth.archaic.org.uk (orth.archaic.org.uk. [2001:8b0:1d0::2]) by mx.google.com with ESMTPS id k4si6235068pgp.279.2017.07.14.03.51.32 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 14 Jul 2017 03:51:32 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of pm215@archaic.org.uk designates 2001:8b0:1d0::2 as permitted sender) client-ip=2001:8b0:1d0::2; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of pm215@archaic.org.uk designates 2001:8b0:1d0::2 as permitted sender) smtp.mailfrom=pm215@archaic.org.uk; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from pm215 by orth.archaic.org.uk with local (Exim 4.84_2) (envelope-from ) id 1dVyC1-0007kP-Gb; Fri, 14 Jul 2017 11:51:29 +0100 From: Peter Maydell To: qemu-arm@nongnu.org, qemu-devel@nongnu.org Cc: patches@linaro.org, =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= , Alistair Francis Subject: [PATCH v2 4/9] hw/char/cmsdk-apb-timer: Implement CMSDK APB timer device Date: Fri, 14 Jul 2017 11:51:22 +0100 Message-Id: <1500029487-14822-5-git-send-email-peter.maydell@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1500029487-14822-1-git-send-email-peter.maydell@linaro.org> References: <1500029487-14822-1-git-send-email-peter.maydell@linaro.org> MIME-Version: 1.0 Implement a model of the simple timer device found in the CMSDK. Signed-off-by: Peter Maydell Reviewed-by: Philippe Mathieu-Daudé --- hw/timer/Makefile.objs | 1 + include/hw/timer/cmsdk-apb-timer.h | 59 +++++++++ hw/timer/cmsdk-apb-timer.c | 253 +++++++++++++++++++++++++++++++++++++ default-configs/arm-softmmu.mak | 1 + hw/timer/trace-events | 5 + 5 files changed, 319 insertions(+) create mode 100644 include/hw/timer/cmsdk-apb-timer.h create mode 100644 hw/timer/cmsdk-apb-timer.c -- 2.7.4 diff --git a/hw/timer/Makefile.objs b/hw/timer/Makefile.objs index dd6f27e..15cce1c 100644 --- a/hw/timer/Makefile.objs +++ b/hw/timer/Makefile.objs @@ -41,3 +41,4 @@ common-obj-$(CONFIG_STM32F2XX_TIMER) += stm32f2xx_timer.o common-obj-$(CONFIG_ASPEED_SOC) += aspeed_timer.o common-obj-$(CONFIG_SUN4V_RTC) += sun4v-rtc.o +common-obj-$(CONFIG_CMSDK_APB_TIMER) += cmsdk-apb-timer.o diff --git a/include/hw/timer/cmsdk-apb-timer.h b/include/hw/timer/cmsdk-apb-timer.h new file mode 100644 index 0000000..f21686d --- /dev/null +++ b/include/hw/timer/cmsdk-apb-timer.h @@ -0,0 +1,59 @@ +/* + * ARM CMSDK APB timer emulation + * + * Copyright (c) 2017 Linaro Limited + * Written by Peter Maydell + * + * 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. + */ + +#ifndef CMSDK_APB_TIMER_H +#define CMSDK_APB_TIMER_H + +#include "hw/sysbus.h" +#include "hw/ptimer.h" + +#define TYPE_CMSDK_APB_TIMER "cmsdk-apb-timer" +#define CMSDK_APB_TIMER(obj) OBJECT_CHECK(CMSDKAPBTIMER, (obj), \ + TYPE_CMSDK_APB_TIMER) + +typedef struct { + /*< private >*/ + SysBusDevice parent_obj; + + /*< public >*/ + MemoryRegion iomem; + qemu_irq timerint; + uint32_t pclk_frq; + struct ptimer_state *timer; + + uint32_t ctrl; + uint32_t value; + uint32_t reload; + uint32_t intstatus; +} CMSDKAPBTIMER; + +/** + * cmsdk_apb_timer_create - convenience function to create TYPE_CMSDK_APB_TIMER + * @addr: location in system memory to map registers + * @pclk_frq: frequency in Hz of the PCLK clock (used for calculating baud rate) + */ +static inline DeviceState *cmsdk_apb_timer_create(hwaddr addr, + qemu_irq timerint, + uint32_t pclk_frq) +{ + DeviceState *dev; + SysBusDevice *s; + + dev = qdev_create(NULL, TYPE_CMSDK_APB_TIMER); + s = SYS_BUS_DEVICE(dev); + qdev_prop_set_uint32(dev, "pclk-frq", pclk_frq); + qdev_init_nofail(dev); + sysbus_mmio_map(s, 0, addr); + sysbus_connect_irq(s, 0, timerint); + return dev; +} + +#endif diff --git a/hw/timer/cmsdk-apb-timer.c b/hw/timer/cmsdk-apb-timer.c new file mode 100644 index 0000000..9878746 --- /dev/null +++ b/hw/timer/cmsdk-apb-timer.c @@ -0,0 +1,253 @@ +/* + * ARM CMSDK APB timer emulation + * + * Copyright (c) 2017 Linaro Limited + * Written by Peter Maydell + * + * 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. + */ + +/* This is a model of the "APB timer" which is part of the Cortex-M + * System Design Kit (CMSDK) and documented in the Cortex-M System + * Design Kit Technical Reference Manual (ARM DDI0479C): + * https://developer.arm.com/products/system-design/system-design-kits/cortex-m-system-design-kit + * + * The hardware has an EXTIN input wire, which can be configured + * by the guest to act either as a 'timer enable' (timer does not run + * when EXTIN is low), or as a 'timer clock' (timer runs at frequency + * of EXTIN clock, not PCLK frequency). We don't model this. + * + * The documentation is not very clear about the exact behaviour; + * we choose to implement that the interrupt is triggered when + * the counter goes from 1 to 0, that the counter then holds at 0 + * for one clock cycle before reloading from the RELOAD register, + * and that if the RELOAD register is 0 this does not cause an + * interrupt (as there is no further 1->0 transition). + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "qemu/main-loop.h" +#include "qapi/error.h" +#include "trace.h" +#include "hw/sysbus.h" +#include "hw/registerfields.h" +#include "hw/timer/cmsdk-apb-timer.h" + +REG32(CTRL, 0) + FIELD(CTRL, EN, 0, 1) + FIELD(CTRL, SELEXTEN, 1, 1) + FIELD(CTRL, SELEXTCLK, 2, 1) + FIELD(CTRL, IRQEN, 3, 1) +REG32(VALUE, 4) +REG32(RELOAD, 8) +REG32(INTSTATUS, 0xc) + FIELD(INTSTATUS, IRQ, 0, 1) +REG32(PID4, 0xFD0) +REG32(PID5, 0xFD4) +REG32(PID6, 0xFD8) +REG32(PID7, 0xFDC) +REG32(PID0, 0xFE0) +REG32(PID1, 0xFE4) +REG32(PID2, 0xFE8) +REG32(PID3, 0xFEC) +REG32(CID0, 0xFF0) +REG32(CID1, 0xFF4) +REG32(CID2, 0xFF8) +REG32(CID3, 0xFFC) + +/* PID/CID values */ +static const int timer_id[] = { + 0x04, 0x00, 0x00, 0x00, /* PID4..PID7 */ + 0x22, 0xb8, 0x1b, 0x00, /* PID0..PID3 */ + 0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */ +}; + +static void cmsdk_apb_timer_update(CMSDKAPBTIMER *s) +{ + qemu_set_irq(s->timerint, !!(s->intstatus & R_INTSTATUS_IRQ_MASK)); +} + +static uint64_t cmsdk_apb_timer_read(void *opaque, hwaddr offset, unsigned size) +{ + CMSDKAPBTIMER *s = CMSDK_APB_TIMER(opaque); + uint64_t r; + + switch (offset) { + case A_CTRL: + r = s->ctrl; + break; + case A_VALUE: + r = ptimer_get_count(s->timer); + break; + case A_RELOAD: + r = ptimer_get_limit(s->timer); + break; + case A_INTSTATUS: + r = s->intstatus; + break; + case A_PID4 ... A_CID3: + r = timer_id[(offset - A_PID4) / 4]; + break; + default: + qemu_log_mask(LOG_GUEST_ERROR, + "CMSDK APB timer read: bad offset %x\n", (int) offset); + r = 0; + break; + } + trace_cmsdk_apb_timer_read(offset, r, size); + return r; +} + +static void cmsdk_apb_timer_write(void *opaque, hwaddr offset, uint64_t value, + unsigned size) +{ + CMSDKAPBTIMER *s = CMSDK_APB_TIMER(opaque); + + trace_cmsdk_apb_timer_write(offset, value, size); + + switch (offset) { + case A_CTRL: + if (value & 6) { + /* Bits [1] and [2] enable using EXTIN as either clock or + * an enable line. We don't model this. + */ + qemu_log_mask(LOG_UNIMP, + "CMSDK APB timer: EXTIN input not supported\n"); + } + s->ctrl = value & 0xf; + if (s->ctrl & R_CTRL_EN_MASK) { + ptimer_run(s->timer, 0); + } else { + ptimer_stop(s->timer); + } + break; + case A_RELOAD: + /* Writing to reload also sets the current timer value */ + ptimer_set_limit(s->timer, value, 1); + break; + case A_VALUE: + ptimer_set_count(s->timer, value); + break; + case A_INTSTATUS: + /* Just one bit, which is W1C. */ + value &= 1; + s->intstatus &= ~value; + cmsdk_apb_timer_update(s); + break; + case A_PID4 ... A_CID3: + qemu_log_mask(LOG_GUEST_ERROR, + "CMSDK APB timer write: write to RO offset 0x%x\n", + (int)offset); + break; + default: + qemu_log_mask(LOG_GUEST_ERROR, + "CMSDK APB timer write: bad offset 0x%x\n", (int) offset); + break; + } +} + +static const MemoryRegionOps cmsdk_apb_timer_ops = { + .read = cmsdk_apb_timer_read, + .write = cmsdk_apb_timer_write, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +static void cmsdk_apb_timer_tick(void *opaque) +{ + CMSDKAPBTIMER *s = CMSDK_APB_TIMER(opaque); + + if (s->ctrl & R_CTRL_IRQEN_MASK) { + s->intstatus |= R_INTSTATUS_IRQ_MASK; + cmsdk_apb_timer_update(s); + } +} + +static void cmsdk_apb_timer_reset(DeviceState *dev) +{ + CMSDKAPBTIMER *s = CMSDK_APB_TIMER(dev); + + trace_cmsdk_apb_timer_reset(); + s->ctrl = 0; + s->intstatus = 0; + ptimer_stop(s->timer); + /* Set the limit and the count */ + ptimer_set_limit(s->timer, 0, 1); +} + +static void cmsdk_apb_timer_init(Object *obj) +{ + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + CMSDKAPBTIMER *s = CMSDK_APB_TIMER(obj); + + memory_region_init_io(&s->iomem, obj, &cmsdk_apb_timer_ops, + s, "cmsdk-apb-timer", 0x1000); + sysbus_init_mmio(sbd, &s->iomem); + sysbus_init_irq(sbd, &s->timerint); +} + +static void cmsdk_apb_timer_realize(DeviceState *dev, Error **errp) +{ + CMSDKAPBTIMER *s = CMSDK_APB_TIMER(dev); + QEMUBH *bh; + + if (s->pclk_frq == 0) { + error_setg(errp, "CMSDK APB timer: pclk-frq property must be set"); + return; + } + + bh = qemu_bh_new(cmsdk_apb_timer_tick, s); + s->timer = ptimer_init(bh, + PTIMER_POLICY_WRAP_AFTER_ONE_PERIOD | + PTIMER_POLICY_NO_IMMEDIATE_TRIGGER | + PTIMER_POLICY_NO_IMMEDIATE_RELOAD | + PTIMER_POLICY_NO_COUNTER_ROUND_DOWN); + + ptimer_set_freq(s->timer, s->pclk_frq); +} + +static const VMStateDescription cmsdk_apb_timer_vmstate = { + .name = "cmsdk-apb-timer", + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_PTIMER(timer, CMSDKAPBTIMER), + VMSTATE_UINT32(ctrl, CMSDKAPBTIMER), + VMSTATE_UINT32(value, CMSDKAPBTIMER), + VMSTATE_UINT32(reload, CMSDKAPBTIMER), + VMSTATE_UINT32(intstatus, CMSDKAPBTIMER), + VMSTATE_END_OF_LIST() + } +}; + +static Property cmsdk_apb_timer_properties[] = { + DEFINE_PROP_UINT32("pclk-frq", CMSDKAPBTIMER, pclk_frq, 0), + DEFINE_PROP_END_OF_LIST(), +}; + +static void cmsdk_apb_timer_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->realize = cmsdk_apb_timer_realize; + dc->vmsd = &cmsdk_apb_timer_vmstate; + dc->reset = cmsdk_apb_timer_reset; + dc->props = cmsdk_apb_timer_properties; +} + +static const TypeInfo cmsdk_apb_timer_info = { + .name = TYPE_CMSDK_APB_TIMER, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(CMSDKAPBTIMER), + .instance_init = cmsdk_apb_timer_init, + .class_init = cmsdk_apb_timer_class_init, +}; + +static void cmsdk_apb_timer_register_types(void) +{ + type_register_static(&cmsdk_apb_timer_info); +} + +type_init(cmsdk_apb_timer_register_types); diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak index d128e9d..c75f52c 100644 --- a/default-configs/arm-softmmu.mak +++ b/default-configs/arm-softmmu.mak @@ -96,6 +96,7 @@ CONFIG_STM32F2XX_ADC=y CONFIG_STM32F2XX_SPI=y CONFIG_STM32F205_SOC=y +CONFIG_CMSDK_APB_TIMER=y CONFIG_CMSDK_APB_UART=y CONFIG_VERSATILE_PCI=y diff --git a/hw/timer/trace-events b/hw/timer/trace-events index d17cfe6..fd8196b 100644 --- a/hw/timer/trace-events +++ b/hw/timer/trace-events @@ -55,3 +55,8 @@ systick_reload(void) "systick reload" systick_timer_tick(void) "systick reload" systick_read(uint64_t addr, uint32_t value, unsigned size) "systick read addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u" systick_write(uint64_t addr, uint32_t value, unsigned size) "systick write addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u" + +# hw/char/cmsdk_apb_timer.c +cmsdk_apb_timer_read(uint64_t offset, uint64_t data, unsigned size) "CMSDK APB timer read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u" +cmsdk_apb_timer_write(uint64_t offset, uint64_t data, unsigned size) "CMSDK APB timer write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u" +cmsdk_apb_timer_reset(void) "CMSDK APB timer: reset" From patchwork Fri Jul 14 10:51:23 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 107771 Delivered-To: patches@linaro.org Received: by 10.140.101.44 with SMTP id t41csp729949qge; Fri, 14 Jul 2017 03:51:36 -0700 (PDT) X-Received: by 10.101.70.70 with SMTP id k6mr13879221pgr.39.1500029496672; Fri, 14 Jul 2017 03:51:36 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1500029496; cv=none; d=google.com; s=arc-20160816; b=Oa12UHJYe8CYB0Ymvfec+h732qPKVVCd4MWD7O5zroU/40d9U4c8rSnb0v24GMgVHG dbXIx9cI1/pDOwvjvO9QuXMc6mA8g+h/ueUvrZoXGzN8RUs0LEQbtL8v6vgynfzTWNFT Q3Ti/rZwM+o+i3QYAzfc4G9Xv3kMbTAIfh3FZxHT1xWXnvFdvpN6SJ5OXninP3bltjYn ZyJTKFa4FK2sgknBsbWQgeUg2y+hzkPKcYJVnPg414Zp6mAZNHMUo6aAGxc6t3pbf28V YSy8ugsaepuZIS75uaq5Axlk4WjGyYhcbJI7s5EdTqChxzacROeV18oFRJYjyWa5vthm bCGw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:arc-authentication-results; bh=O1SAgLx5uNlMOSh/O6XsR79qugWF9NoI6M7p+ObqtgQ=; b=p/8gbUyDH1SWA+Vj1lTqYM6LX1GSzbQ4jVU3zXmdNL+oD8dwMMwCEJdZ39qH/GwYsc j5NrlqvVCNnW4b1Czah/91/a2rBRkuLs/x39BMxXaJOd1k/L5DaEWFluf5cEBbcZuLtr osjp/yrQ/QckxSyxyRK5KNtAdMw5MNVrn7f8Csu6DoDaBbMgdW1vuHKJ+UzoBAomnNUl pnnW5g8+2/7IqQhKJ3dJt8M1/dsq9VF1CLFIcQXySHtmsoAgX9D1arKE98WNd5sLrP78 OkSNW6+X0J+OZ5TrkgXePW8VbtemVhEThMEgpxc/NOm2+x3YH0rsH+0SfSbrCXtGhhAz WFzg== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of pm215@archaic.org.uk designates 2001:8b0:1d0::2 as permitted sender) smtp.mailfrom=pm215@archaic.org.uk; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from orth.archaic.org.uk (orth.archaic.org.uk. [2001:8b0:1d0::2]) by mx.google.com with ESMTPS id 33si6748177plh.532.2017.07.14.03.51.35 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 14 Jul 2017 03:51:36 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of pm215@archaic.org.uk designates 2001:8b0:1d0::2 as permitted sender) client-ip=2001:8b0:1d0::2; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of pm215@archaic.org.uk designates 2001:8b0:1d0::2 as permitted sender) smtp.mailfrom=pm215@archaic.org.uk; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from pm215 by orth.archaic.org.uk with local (Exim 4.84_2) (envelope-from ) id 1dVyC2-0007ke-2q; Fri, 14 Jul 2017 11:51:30 +0100 From: Peter Maydell To: qemu-arm@nongnu.org, qemu-devel@nongnu.org Cc: patches@linaro.org, =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= , Alistair Francis Subject: [PATCH v2 5/9] hw/arm/mps2: Add timers Date: Fri, 14 Jul 2017 11:51:23 +0100 Message-Id: <1500029487-14822-6-git-send-email-peter.maydell@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1500029487-14822-1-git-send-email-peter.maydell@linaro.org> References: <1500029487-14822-1-git-send-email-peter.maydell@linaro.org> MIME-Version: 1.0 Add the CMSDK APB timers to the MPS2 board. Signed-off-by: Peter Maydell Reviewed-by: Philippe Mathieu-Daudé --- hw/arm/mps2.c | 4 ++++ 1 file changed, 4 insertions(+) -- 2.7.4 diff --git a/hw/arm/mps2.c b/hw/arm/mps2.c index 180c5d2..0de0ffcb 100644 --- a/hw/arm/mps2.c +++ b/hw/arm/mps2.c @@ -33,6 +33,7 @@ #include "sysemu/sysemu.h" #include "hw/misc/unimp.h" #include "hw/char/cmsdk-apb-uart.h" +#include "hw/timer/cmsdk-apb-timer.h" typedef enum MPS2FPGAType { FPGA_AN385, @@ -292,6 +293,9 @@ static void mps2_common_init(MachineState *machine) g_assert_not_reached(); } + cmsdk_apb_timer_create(0x40000000, qdev_get_gpio_in(armv7m, 8), SYSCLK_FRQ); + cmsdk_apb_timer_create(0x40001000, qdev_get_gpio_in(armv7m, 9), SYSCLK_FRQ); + system_clock_scale = NANOSECONDS_PER_SECOND / SYSCLK_FRQ; armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, From patchwork Fri Jul 14 10:51:24 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 107770 Delivered-To: patches@linaro.org Received: by 10.140.101.44 with SMTP id t41csp729908qge; Fri, 14 Jul 2017 03:51:34 -0700 (PDT) X-Received: by 10.101.70.137 with SMTP id h9mr14366237pgr.50.1500029494348; Fri, 14 Jul 2017 03:51:34 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1500029494; cv=none; d=google.com; s=arc-20160816; b=h6X+dYwxeI6QRoZoIQjDpyQNsZ3aVRU6zWcYM8vNAdpVfv7fNXO2wtl1CyOuji61FM C2UuTwi3tpc/fALo1SiNOfG/sMxlsxIruZloo/092imkPikrlBsLdQjCfT/WKasI+RHV fpmEUG6tS1tcJ/MH5VWrW+l6e9D0G36zh0xJfI9Rljx3+e2wVMu/VOsgmMZ6A30YlVdQ SNMMtzazNAF/k7u3vzUIUPHjbqhUSWfHnB+pS18zbMWZIXYMFVFAk/BeQ4zfo/7i+D9y VcnIUJYLEiI6m11gKI4JNld6CuUN/9+cmkZBr3GaDsVe+NTVHhmfHvjVXrDwZm/u91zR uixg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:arc-authentication-results; bh=M6bNHQCaJK9v0RCNPPSM4r2HURkUNWXGEhdmqi8Z5zs=; b=WDOw/FjOvJ54cAOvsJO7hSDaG6KwvLgAd4/dSfHiIE4BUeRti7zx22ADYWhB7w3Gvx yUW3fG5C2Zh36LwpTAKsNcLU6z5Zn4CuB9i/H8E4bbrCvs+K3uD8AWvYWew6HHSqwAqa /g04HJRQyHxQ4N06t0Ho5eyrf37Kghd3tb6ZXATE8TU5V2avca+65lnFidZlJ7CrS+En iVA0nZDc9LS7+asTS+aLXTPioamNDURCllFu6hjQ50oHoBZZiwrE765JjsQ4qBNZfiV2 c9fgwR0ZQ/cA0AhWbJ3i9O89bjvMlEc7jdlNrZ7PszMjErDXINSpVRN81NDjawKwX7Pa xtCg== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of pm215@archaic.org.uk designates 2001:8b0:1d0::2 as permitted sender) smtp.mailfrom=pm215@archaic.org.uk; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from orth.archaic.org.uk (orth.archaic.org.uk. [2001:8b0:1d0::2]) by mx.google.com with ESMTPS id d18si6204295pfm.71.2017.07.14.03.51.33 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 14 Jul 2017 03:51:34 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of pm215@archaic.org.uk designates 2001:8b0:1d0::2 as permitted sender) client-ip=2001:8b0:1d0::2; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of pm215@archaic.org.uk designates 2001:8b0:1d0::2 as permitted sender) smtp.mailfrom=pm215@archaic.org.uk; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from pm215 by orth.archaic.org.uk with local (Exim 4.84_2) (envelope-from ) id 1dVyC2-0007kt-Hp; Fri, 14 Jul 2017 11:51:30 +0100 From: Peter Maydell To: qemu-arm@nongnu.org, qemu-devel@nongnu.org Cc: patches@linaro.org, =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= , Alistair Francis Subject: [PATCH v2 6/9] hw/misc/mps2_scc: Implement MPS2 Serial Communication Controller Date: Fri, 14 Jul 2017 11:51:24 +0100 Message-Id: <1500029487-14822-7-git-send-email-peter.maydell@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1500029487-14822-1-git-send-email-peter.maydell@linaro.org> References: <1500029487-14822-1-git-send-email-peter.maydell@linaro.org> MIME-Version: 1.0 Implement a model of the Serial Communication Controller (SCC) found in MPS2 FPGA images. The primary purpose of this device is to communicate with the Motherboard Configuration Controller (MCC) which is located on the MPS board itself, outside the FPGA image. This is used for programming the MPS clock generators. The SCC also has some basic ID registers and an output for the board LEDs. Signed-off-by: Peter Maydell Reviewed-by: Philippe Mathieu-Daudé --- hw/misc/Makefile.objs | 1 + include/hw/misc/mps2-scc.h | 43 ++++++ hw/misc/mps2-scc.c | 310 ++++++++++++++++++++++++++++++++++++++++ default-configs/arm-softmmu.mak | 2 + hw/misc/trace-events | 8 ++ 5 files changed, 364 insertions(+) create mode 100644 include/hw/misc/mps2-scc.h create mode 100644 hw/misc/mps2-scc.c -- 2.7.4 diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs index 7e373db..3b91d32 100644 --- a/hw/misc/Makefile.objs +++ b/hw/misc/Makefile.objs @@ -52,6 +52,7 @@ obj-$(CONFIG_STM32F2XX_SYSCFG) += stm32f2xx_syscfg.o obj-$(CONFIG_MIPS_CPS) += mips_cmgcr.o obj-$(CONFIG_MIPS_CPS) += mips_cpc.o obj-$(CONFIG_MIPS_ITU) += mips_itu.o +obj-$(CONFIG_MPS2_SCC) += mps2-scc.o obj-$(CONFIG_PVPANIC) += pvpanic.o obj-$(CONFIG_HYPERV_TESTDEV) += hyperv_testdev.o diff --git a/include/hw/misc/mps2-scc.h b/include/hw/misc/mps2-scc.h new file mode 100644 index 0000000..7045473 --- /dev/null +++ b/include/hw/misc/mps2-scc.h @@ -0,0 +1,43 @@ +/* + * ARM MPS2 SCC emulation + * + * Copyright (c) 2017 Linaro Limited + * Written by Peter Maydell + * + * 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. + */ + +#ifndef MPS2_SCC_H +#define MPS2_SCC_H + +#include "hw/sysbus.h" + +#define TYPE_MPS2_SCC "mps2-scc" +#define MPS2_SCC(obj) OBJECT_CHECK(MPS2SCC, (obj), TYPE_MPS2_SCC) + +#define NUM_OSCCLK 3 + +typedef struct { + /*< private >*/ + SysBusDevice parent_obj; + + /*< public >*/ + MemoryRegion iomem; + + uint32_t cfg0; + uint32_t cfg1; + uint32_t cfg4; + uint32_t cfgdata_rtn; + uint32_t cfgdata_out; + uint32_t cfgctrl; + uint32_t cfgstat; + uint32_t dll; + uint32_t aid; + uint32_t id; + uint32_t oscclk[NUM_OSCCLK]; + uint32_t oscclk_reset[NUM_OSCCLK]; +} MPS2SCC; + +#endif diff --git a/hw/misc/mps2-scc.c b/hw/misc/mps2-scc.c new file mode 100644 index 0000000..cc58d26 --- /dev/null +++ b/hw/misc/mps2-scc.c @@ -0,0 +1,310 @@ +/* + * ARM MPS2 SCC emulation + * + * Copyright (c) 2017 Linaro Limited + * Written by Peter Maydell + * + * 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. + */ + +/* This is a model of the SCC (Serial Communication Controller) + * found in the FPGA images of MPS2 development boards. + * + * Documentation of it can be found in the MPS2 TRM: + * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.100112_0100_03_en/index.html + * and also in the Application Notes documenting individual FPGA images. + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "qapi/error.h" +#include "trace.h" +#include "hw/sysbus.h" +#include "hw/registerfields.h" +#include "hw/misc/mps2-scc.h" + +REG32(CFG0, 0) +REG32(CFG1, 4) +REG32(CFG3, 0xc) +REG32(CFG4, 0x10) +REG32(CFGDATA_RTN, 0xa0) +REG32(CFGDATA_OUT, 0xa4) +REG32(CFGCTRL, 0xa8) + FIELD(CFGCTRL, DEVICE, 0, 12) + FIELD(CFGCTRL, RES1, 12, 8) + FIELD(CFGCTRL, FUNCTION, 20, 6) + FIELD(CFGCTRL, RES2, 26, 4) + FIELD(CFGCTRL, WRITE, 30, 1) + FIELD(CFGCTRL, START, 31, 1) +REG32(CFGSTAT, 0xac) + FIELD(CFGSTAT, DONE, 0, 1) + FIELD(CFGSTAT, ERROR, 1, 1) +REG32(DLL, 0x100) +REG32(AID, 0xFF8) +REG32(ID, 0xFFC) + +/* Handle a write via the SYS_CFG channel to the specified function/device. + * Return false on error (reported to guest via SYS_CFGCTRL ERROR bit). + */ +static bool scc_cfg_write(MPS2SCC *s, unsigned function, + unsigned device, uint32_t value) +{ + trace_mps2_scc_cfg_write(function, device, value); + + if (function != 1 || device >= NUM_OSCCLK) { + qemu_log_mask(LOG_GUEST_ERROR, + "MPS2 SCC config write: bad function %d device %d\n", + function, device); + return false; + } + + s->oscclk[device] = value; + return true; +} + +/* Handle a read via the SYS_CFG channel to the specified function/device. + * Return false on error (reported to guest via SYS_CFGCTRL ERROR bit), + * or set *value on success. + */ +static bool scc_cfg_read(MPS2SCC *s, unsigned function, + unsigned device, uint32_t *value) +{ + if (function != 1 || device >= NUM_OSCCLK) { + qemu_log_mask(LOG_GUEST_ERROR, + "MPS2 SCC config read: bad function %d device %d\n", + function, device); + return false; + } + + *value = s->oscclk[device]; + + trace_mps2_scc_cfg_read(function, device, *value); + return true; +} + +static uint64_t mps2_scc_read(void *opaque, hwaddr offset, unsigned size) +{ + MPS2SCC *s = MPS2_SCC(opaque); + uint64_t r; + + switch (offset) { + case A_CFG0: + r = s->cfg0; + break; + case A_CFG1: + r = s->cfg1; + break; + case A_CFG3: + /* These are user-settable DIP switches on the board. We don't + * model that, so just return zeroes. + */ + r = 0; + break; + case A_CFG4: + r = s->cfg4; + break; + case A_CFGDATA_RTN: + r = s->cfgdata_rtn; + break; + case A_CFGDATA_OUT: + r = s->cfgdata_out; + break; + case A_CFGCTRL: + r = s->cfgctrl; + break; + case A_CFGSTAT: + r = s->cfgstat; + break; + case A_DLL: + r = s->dll; + break; + case A_AID: + r = s->aid; + break; + case A_ID: + r = s->id; + break; + default: + qemu_log_mask(LOG_GUEST_ERROR, + "MPS2 SCC read: bad offset %x\n", (int) offset); + r = 0; + break; + } + + trace_mps2_scc_read(offset, r, size); + return r; +} + +static void mps2_scc_write(void *opaque, hwaddr offset, uint64_t value, + unsigned size) +{ + MPS2SCC *s = MPS2_SCC(opaque); + + trace_mps2_scc_write(offset, value, size); + + switch (offset) { + case A_CFG0: + /* TODO on some boards bit 0 controls RAM remapping */ + s->cfg0 = value; + break; + case A_CFG1: + /* CFG1 bits [7:0] control the board LEDs. We don't currently have + * a mechanism for displaying this graphically, so use a trace event. + */ + trace_mps2_scc_leds(value & 0x80 ? '*' : '.', + value & 0x40 ? '*' : '.', + value & 0x20 ? '*' : '.', + value & 0x10 ? '*' : '.', + value & 0x08 ? '*' : '.', + value & 0x04 ? '*' : '.', + value & 0x02 ? '*' : '.', + value & 0x01 ? '*' : '.'); + s->cfg1 = value; + break; + case A_CFGDATA_OUT: + s->cfgdata_out = value; + break; + case A_CFGCTRL: + /* Writing to CFGCTRL clears SYS_CFGSTAT */ + s->cfgstat = 0; + s->cfgctrl = value & ~(R_CFGCTRL_RES1_MASK | + R_CFGCTRL_RES2_MASK | + R_CFGCTRL_START_MASK); + + if (value & R_CFGCTRL_START_MASK) { + /* Start bit set -- do a read or write (instantaneously) */ + int device = extract32(s->cfgctrl, R_CFGCTRL_DEVICE_SHIFT, + R_CFGCTRL_DEVICE_LENGTH); + int function = extract32(s->cfgctrl, R_CFGCTRL_FUNCTION_SHIFT, + R_CFGCTRL_FUNCTION_LENGTH); + + s->cfgstat = R_CFGSTAT_DONE_MASK; + if (s->cfgctrl & R_CFGCTRL_WRITE_MASK) { + if (!scc_cfg_write(s, function, device, s->cfgdata_out)) { + s->cfgstat |= R_CFGSTAT_ERROR_MASK; + } + } else { + uint32_t result; + if (!scc_cfg_read(s, function, device, &result)) { + s->cfgstat |= R_CFGSTAT_ERROR_MASK; + } else { + s->cfgdata_rtn = result; + } + } + } + break; + case A_DLL: + /* DLL stands for Digital Locked Loop. + * Bits [31:24] (DLL_LOCK_MASK) are writable, and indicate a + * mask of which of the DLL_LOCKED bits [16:23] should be ORed + * together to determine the ALL_UNMASKED_DLLS_LOCKED bit [0]. + * For QEMU, our DLLs are always locked, so we can leave bit 0 + * as 1 always and don't need to recalculate it. + */ + s->dll = deposit32(s->dll, 24, 8, extract32(value, 24, 8)); + break; + default: + qemu_log_mask(LOG_GUEST_ERROR, + "MPS2 SCC write: bad offset 0x%x\n", (int) offset); + break; + } +} + +static const MemoryRegionOps mps2_scc_ops = { + .read = mps2_scc_read, + .write = mps2_scc_write, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +static void mps2_scc_reset(DeviceState *dev) +{ + MPS2SCC *s = MPS2_SCC(dev); + int i; + + trace_mps2_scc_reset(); + s->cfg0 = 0; + s->cfg1 = 0; + s->cfgdata_rtn = 0; + s->cfgdata_out = 0; + s->cfgctrl = 0x100000; + s->cfgstat = 0; + s->dll = 0xffff0001; + for (i = 0; i < NUM_OSCCLK; i++) { + s->oscclk[i] = s->oscclk_reset[i]; + } +} + +static void mps2_scc_init(Object *obj) +{ + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + MPS2SCC *s = MPS2_SCC(obj); + + memory_region_init_io(&s->iomem, obj, &mps2_scc_ops, s, "mps2-scc", 0x1000); + sysbus_init_mmio(sbd, &s->iomem); +} + +static void mps2_scc_realize(DeviceState *dev, Error **errp) +{ +} + +static const VMStateDescription mps2_scc_vmstate = { + .name = "mps2-scc", + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT32(cfg0, MPS2SCC), + VMSTATE_UINT32(cfg1, MPS2SCC), + VMSTATE_UINT32(cfgdata_rtn, MPS2SCC), + VMSTATE_UINT32(cfgdata_out, MPS2SCC), + VMSTATE_UINT32(cfgctrl, MPS2SCC), + VMSTATE_UINT32(cfgstat, MPS2SCC), + VMSTATE_UINT32(dll, MPS2SCC), + VMSTATE_UINT32_ARRAY(oscclk, MPS2SCC, NUM_OSCCLK), + VMSTATE_END_OF_LIST() + } +}; + +static Property mps2_scc_properties[] = { + /* Values for various read-only ID registers (which are specific + * to the board model or FPGA image) + */ + DEFINE_PROP_UINT32("scc-cfg4", MPS2SCC, aid, 0), + DEFINE_PROP_UINT32("scc-aid", MPS2SCC, aid, 0), + DEFINE_PROP_UINT32("scc-id", MPS2SCC, aid, 0), + /* These are the initial settings for the source clocks on the board. + * In hardware they can be configured via a config file read by the + * motherboard configuration controller to suit the FPGA image. + * These default values are used by most of the standard FPGA images. + */ + DEFINE_PROP_UINT32("oscclk0", MPS2SCC, oscclk_reset[0], 50000000), + DEFINE_PROP_UINT32("oscclk1", MPS2SCC, oscclk_reset[1], 24576000), + DEFINE_PROP_UINT32("oscclk2", MPS2SCC, oscclk_reset[2], 25000000), + DEFINE_PROP_END_OF_LIST(), +}; + +static void mps2_scc_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->realize = mps2_scc_realize; + dc->vmsd = &mps2_scc_vmstate; + dc->reset = mps2_scc_reset; + dc->props = mps2_scc_properties; +} + +static const TypeInfo mps2_scc_info = { + .name = TYPE_MPS2_SCC, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(MPS2SCC), + .instance_init = mps2_scc_init, + .class_init = mps2_scc_class_init, +}; + +static void mps2_scc_register_types(void) +{ + type_register_static(&mps2_scc_info); +} + +type_init(mps2_scc_register_types); diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak index c75f52c..bbdd3c1 100644 --- a/default-configs/arm-softmmu.mak +++ b/default-configs/arm-softmmu.mak @@ -99,6 +99,8 @@ CONFIG_STM32F205_SOC=y CONFIG_CMSDK_APB_TIMER=y CONFIG_CMSDK_APB_UART=y +CONFIG_MPS2_SCC=y + CONFIG_VERSATILE_PCI=y CONFIG_VERSATILE_I2C=y diff --git a/hw/misc/trace-events b/hw/misc/trace-events index 0cc556c..28b8cd1 100644 --- a/hw/misc/trace-events +++ b/hw/misc/trace-events @@ -53,3 +53,11 @@ milkymist_pfpu_pulse_irq(void) "Pulse IRQ" # hw/misc/aspeed_scu.c aspeed_scu_write(uint64_t offset, unsigned size, uint32_t data) "To 0x%" PRIx64 " of size %u: 0x%" PRIx32 + +# hw/misc/mps2_scc.c +mps2_scc_read(uint64_t offset, uint64_t data, unsigned size) "MPS2 SCC read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u" +mps2_scc_write(uint64_t offset, uint64_t data, unsigned size) "MPS2 SCC write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u" +mps2_scc_reset(void) "MPS2 SCC: reset" +mps2_scc_leds(char led7, char led6, char led5, char led4, char led3, char led2, char led1, char led0) "MPS2 SCC LEDs: %c%c%c%c%c%c%c%c" +mps2_scc_cfg_write(unsigned function, unsigned device, uint32_t value) "MPS2 SCC config write: function %d device %d data 0x%" PRIx32 +mps2_scc_cfg_read(unsigned function, unsigned device, uint32_t value) "MPS2 SCC config read: function %d device %d data 0x%" PRIx32 From patchwork Fri Jul 14 10:51:25 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 107768 Delivered-To: patches@linaro.org Received: by 10.140.101.44 with SMTP id t41csp729868qge; Fri, 14 Jul 2017 03:51:32 -0700 (PDT) X-Received: by 10.25.22.202 with SMTP id 71mr3192341lfw.59.1500029492036; Fri, 14 Jul 2017 03:51:32 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1500029492; cv=none; d=google.com; s=arc-20160816; b=qWvLTvX+h6TZCOics4MzSEs0WlgkJ4pKcZSWL3npV2U4jJ7mYZ1GXVTL6AN5r1x16M LhKtMirTqih7HuCnGl+DPDkJ3oi70QcZeeRyw/RTwS5Y8fmH3O6AwTV6j8dQ/qismum5 B9ya0p1+4EORQ+bGtzCV9FpPZ5C9YYLjs3+yEWQFJTbiMpq3asbG7ZwtlByddE810umo pGH1wNPtjUrkEHYT8SE7mmIgjzaKTRvL/wDSoolJFnyCsvXK1DUjkvjIEfEYjA0XjkkL JfiS7D9189vzJ+ELVaHLWLsJm3QPMRMjD3L1XMqAUgCDDFkL+n0PFrGPz1gu16F8NWF5 7XZA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:arc-authentication-results; bh=1B+F7XrHoM26UDT01XTx3mvZHtTLclp+kIPrBJ5cWZ0=; b=ztS/v6H395w2jhE/1hHywI0jktfmxYMCt8+NY/JNzg92uPsKFtdXqt2UkkGT60nS1C 8/KxvOET44mvW5I8yi675P+pGp1s7Ltlt1vinBzIuYWBI4pyhRZcJvPLB+eu59dX0c/2 hZjSUDueAmxfIvY2t9njjgQ2VpPbXk1adH2MTYQF6TxJpw9y51gRQKZsvxHgD9zL19xB fsS2mBzZr8LFoNzeVflExoIclJzaGta6L74D7TdGwYXMy0V1xvJXpNbRymqKdNuVz2Ie Wl93IEbQ6cRZimKWj4cD2uap6qGrvRartMOdHO8ng2n0zq4TrIv7dQBWaZgkcrn8LKNO Ji8w== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of pm215@archaic.org.uk designates 2001:8b0:1d0::2 as permitted sender) smtp.mailfrom=pm215@archaic.org.uk; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from orth.archaic.org.uk (orth.archaic.org.uk. [2001:8b0:1d0::2]) by mx.google.com with ESMTPS id n13si3913658lje.48.2017.07.14.03.51.31 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 14 Jul 2017 03:51:32 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of pm215@archaic.org.uk designates 2001:8b0:1d0::2 as permitted sender) client-ip=2001:8b0:1d0::2; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of pm215@archaic.org.uk designates 2001:8b0:1d0::2 as permitted sender) smtp.mailfrom=pm215@archaic.org.uk; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from pm215 by orth.archaic.org.uk with local (Exim 4.84_2) (envelope-from ) id 1dVyC3-0007l8-9O; Fri, 14 Jul 2017 11:51:31 +0100 From: Peter Maydell To: qemu-arm@nongnu.org, qemu-devel@nongnu.org Cc: patches@linaro.org, =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= , Alistair Francis Subject: [PATCH v2 7/9] hw/arm/mps2: Add SCC Date: Fri, 14 Jul 2017 11:51:25 +0100 Message-Id: <1500029487-14822-8-git-send-email-peter.maydell@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1500029487-14822-1-git-send-email-peter.maydell@linaro.org> References: <1500029487-14822-1-git-send-email-peter.maydell@linaro.org> MIME-Version: 1.0 Add the SCC to the MPS2 board models. Signed-off-by: Peter Maydell Reviewed-by: Philippe Mathieu-Daudé --- hw/arm/mps2.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) -- 2.7.4 diff --git a/hw/arm/mps2.c b/hw/arm/mps2.c index 0de0ffcb..bdc631a 100644 --- a/hw/arm/mps2.c +++ b/hw/arm/mps2.c @@ -34,6 +34,7 @@ #include "hw/misc/unimp.h" #include "hw/char/cmsdk-apb-uart.h" #include "hw/timer/cmsdk-apb-timer.h" +#include "hw/misc/mps2-scc.h" typedef enum MPS2FPGAType { FPGA_AN385, @@ -44,6 +45,7 @@ typedef struct { MachineClass parent; MPS2FPGAType fpga_type; const char *cpu_model; + uint32_t scc_id; } MPS2MachineClass; typedef struct { @@ -60,6 +62,7 @@ typedef struct { MemoryRegion blockram_m2; MemoryRegion blockram_m3; MemoryRegion sram; + MPS2SCC scc; } MPS2MachineState; #define TYPE_MPS2_MACHINE "mps2" @@ -103,7 +106,7 @@ static void mps2_common_init(MachineState *machine) MPS2MachineState *mms = MPS2_MACHINE(machine); MPS2MachineClass *mmc = MPS2_MACHINE_GET_CLASS(machine); MemoryRegion *system_memory = get_system_memory(); - DeviceState *armv7m; + DeviceState *armv7m, *sccdev; if (!machine->cpu_model) { machine->cpu_model = mmc->cpu_model; @@ -296,6 +299,16 @@ static void mps2_common_init(MachineState *machine) cmsdk_apb_timer_create(0x40000000, qdev_get_gpio_in(armv7m, 8), SYSCLK_FRQ); cmsdk_apb_timer_create(0x40001000, qdev_get_gpio_in(armv7m, 9), SYSCLK_FRQ); + object_initialize(&mms->scc, sizeof(mms->scc), TYPE_MPS2_SCC); + sccdev = DEVICE(&mms->scc); + qdev_set_parent_bus(armv7m, sysbus_get_default()); + qdev_prop_set_uint32(sccdev, "scc-cfg4", 0x2); + qdev_prop_set_uint32(sccdev, "scc-aid", 0x02000008); + qdev_prop_set_uint32(sccdev, "scc-id", mmc->scc_id); + object_property_set_bool(OBJECT(&mms->scc), true, "realized", + &error_fatal); + sysbus_mmio_map(SYS_BUS_DEVICE(sccdev), 0, 0x4002f000); + system_clock_scale = NANOSECONDS_PER_SECOND / SYSCLK_FRQ; armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, @@ -318,6 +331,7 @@ static void mps2_an385_class_init(ObjectClass *oc, void *data) mc->desc = "ARM MPS2 with AN385 FPGA image for Cortex-M3"; mmc->fpga_type = FPGA_AN385; mmc->cpu_model = "cortex-m3"; + mmc->scc_id = 0x41040000 | (385 << 4); } static void mps2_an511_class_init(ObjectClass *oc, void *data) @@ -328,6 +342,7 @@ static void mps2_an511_class_init(ObjectClass *oc, void *data) mc->desc = "ARM MPS2 with AN511 DesignStart FPGA image for Cortex-M3"; mmc->fpga_type = FPGA_AN511; mmc->cpu_model = "cortex-m3"; + mmc->scc_id = 0x4104000 | (511 << 4); } static const TypeInfo mps2_info = { From patchwork Fri Jul 14 10:51:26 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 107767 Delivered-To: patches@linaro.org Received: by 10.140.101.44 with SMTP id t41csp729870qge; Fri, 14 Jul 2017 03:51:32 -0700 (PDT) X-Received: by 10.223.177.129 with SMTP id q1mr4308291wra.82.1500029492164; Fri, 14 Jul 2017 03:51:32 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1500029492; cv=none; d=google.com; s=arc-20160816; b=Ku6+OqU/OXBenj+m7G73DbZl3tLW9hQvj0vQkA5HlXw+tJJ619xLP/GfcirKfCEKCX mWfb+OGf5U+2BuxFLW6V5lmkd4yKWByHw8DTxFlX/9kQQcvvleKZwbncUjCfL9MpZSfy QcxGGdb2F+EAr6/0US1p+uDA+6gyMXtGk4Od20ExvK7W6eI0v2z0pQKBZd+m3ompcJHd /fMK5fNl97qtEPEagMCt2I8tBli3OADFp6LI7a4WzH2fKa2H261c1skgwteKm2+UuPKn FRfpXECcKcgXt2gBNjF30RjFkIfpOVYP5a4c5jBX1v6MqoDZEjJfyIEB4ZBtRQItVLtD o/iA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=references:in-reply-to:message-id:date:subject:cc:to:from :arc-authentication-results; bh=Ib5qjF6V1Xog+q12Z6XgE4Gj9if8VsqjpQOSwkwD7d8=; b=uYH0iK+qfVzYR409Mrbe/pZrRqhvoaWaKnsHYnMXIcczdFJ0vG9dB++qMoL4GgwpKO DWuupkUhJngvbnWuHaUNcasBIUu/JcydFc85V2YdmpklxaUz691BtN8W+7qOxi93dvrs aTolWpgdCe/UqG6+t5Cql5Csi4apkjCnbPaYsliV9YxSQa5IasOkXipd1ptkcyvW6NFG kwBQfTVpQ/j2stJEV9rwzb+9ITnUNRHIkSR91W6TC1ffiy/V+syjuDDjMdN+X0KHp3Dj o99OJ+tAhoAguSQrDxIpADh9LRTMP6ati6DepV3wAP7Zg6hv+nBtd47VR4alPEJQAbsX EK0Q== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of pm215@archaic.org.uk designates 2001:8b0:1d0::2 as permitted sender) smtp.mailfrom=pm215@archaic.org.uk; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from orth.archaic.org.uk (orth.archaic.org.uk. [2001:8b0:1d0::2]) by mx.google.com with ESMTPS id c67si1896009wmf.186.2017.07.14.03.51.31 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 14 Jul 2017 03:51:32 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of pm215@archaic.org.uk designates 2001:8b0:1d0::2 as permitted sender) client-ip=2001:8b0:1d0::2; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of pm215@archaic.org.uk designates 2001:8b0:1d0::2 as permitted sender) smtp.mailfrom=pm215@archaic.org.uk; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from pm215 by orth.archaic.org.uk with local (Exim 4.84_2) (envelope-from ) id 1dVyC3-0007lk-Ne; Fri, 14 Jul 2017 11:51:31 +0100 From: Peter Maydell To: qemu-arm@nongnu.org, qemu-devel@nongnu.org Cc: patches@linaro.org, =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= , Alistair Francis Subject: [PATCH v2 8/9] hw/arm/mps2: Add ethernet Date: Fri, 14 Jul 2017 11:51:26 +0100 Message-Id: <1500029487-14822-9-git-send-email-peter.maydell@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1500029487-14822-1-git-send-email-peter.maydell@linaro.org> References: <1500029487-14822-1-git-send-email-peter.maydell@linaro.org> The MPS2 FPGA images support ethernet via a LAN9220. We use QEMU's LAN9118 model, which is software compatible except that it is missing the checksum-offload feature. Signed-off-by: Peter Maydell --- hw/arm/mps2.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) -- 2.7.4 Reviewed-by: Alex Bennée Reviewed-by: Philippe Mathieu-Daudé diff --git a/hw/arm/mps2.c b/hw/arm/mps2.c index bdc631a..6adfb22 100644 --- a/hw/arm/mps2.c +++ b/hw/arm/mps2.c @@ -35,6 +35,8 @@ #include "hw/char/cmsdk-apb-uart.h" #include "hw/timer/cmsdk-apb-timer.h" #include "hw/misc/mps2-scc.h" +#include "hw/devices.h" +#include "net/net.h" typedef enum MPS2FPGAType { FPGA_AN385, @@ -210,7 +212,6 @@ static void mps2_common_init(MachineState *machine) create_unimplemented_device("Extra peripheral region @0x40020000", 0x40020000, 0x00010000); create_unimplemented_device("RESERVED 4", 0x40030000, 0x001D0000); - create_unimplemented_device("Ethernet", 0x40200000, 0x00100000); create_unimplemented_device("VGA", 0x41000000, 0x0200000); switch (mmc->fpga_type) { @@ -309,6 +310,13 @@ static void mps2_common_init(MachineState *machine) &error_fatal); sysbus_mmio_map(SYS_BUS_DEVICE(sccdev), 0, 0x4002f000); + /* In hardware this is a LAN9220; the LAN9118 is software compatible + * except that it doesn't support the checksum-offload feature. + */ + lan9118_init(&nd_table[0], 0x40200000, + qdev_get_gpio_in(armv7m, + mmc->fpga_type == FPGA_AN385 ? 13 : 47)); + system_clock_scale = NANOSECONDS_PER_SECOND / SYSCLK_FRQ; armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, From patchwork Fri Jul 14 10:51:27 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 107769 Delivered-To: patches@linaro.org Received: by 10.140.101.44 with SMTP id t41csp729880qge; Fri, 14 Jul 2017 03:51:32 -0700 (PDT) X-Received: by 10.28.218.145 with SMTP id r139mr2341800wmg.69.1500029492753; Fri, 14 Jul 2017 03:51:32 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1500029492; cv=none; d=google.com; s=arc-20160816; b=sWpvdt2k/3XHJYU7ODz73XI9bdyeDseH74MJwVk6AsbOIzIPjNdgEcsh0GPd6bLuQL GE/Y8c+ZjJnKJGPf0IV63ZaTcT65bpNT9z9dmZt1e2BQwxziHjbSUvkTxP2SsuWDweIw 42NQ28IsokA+VCqF2w2tZDroQA/1zOjn90tL1wfNKAumZng6XS+2GA4ohj5KjSs5o8KB 3X7CF8nOz+HJtS3KHkLMAFc/ud6tvDQKOxY3y7Fd3A95BOrbI+rpDy0D8KJwbhXOft/8 MvA0/SSyv8mTgtOWTdbk9Kw3HIAfAUScDclVe4SrOARNlldNU241RSwbh5I3M41ZcMUX yghg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=references:in-reply-to:message-id:date:subject:cc:to:from :arc-authentication-results; bh=oGL8N2Ir72Wq2PwdocMLtocdYZ7JNW1vuknL23TNHbA=; b=x5vg2XWiri2cWbcsfHYXmlZD2CIapu/SzHjlfgjr7+Ov0SM9p918vOc97Dr7IgaqGC RS3tc++ZLic/xF4FXO03kYO1hNYkrDgUAS/ynI6ZQ4A8TZ6DzeeyT5jIeeCD498JBdHE uP7i8qa5f/fXDlyfeiO+ytQZRO7Na3VOjmUX5L9KJR3TDvoQwS7Dm6oWPllpBQBxVDQo gJPrtzLeJ5AAqHLF18Lig1k9GhBpPDJR4NJL7b8iU8+JqxhKo3lP4WMIifECP8KUb3tY 43NhTiRqrQpKLZvbeWJivg7EjciTfJ6w/LC0/BHL7kFro05W8b2Mwtx9cKheYMmTddyW 6CSA== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of pm215@archaic.org.uk designates 2001:8b0:1d0::2 as permitted sender) smtp.mailfrom=pm215@archaic.org.uk; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from orth.archaic.org.uk (orth.archaic.org.uk. [2001:8b0:1d0::2]) by mx.google.com with ESMTPS id m84si2008948wmc.86.2017.07.14.03.51.32 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 14 Jul 2017 03:51:32 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of pm215@archaic.org.uk designates 2001:8b0:1d0::2 as permitted sender) client-ip=2001:8b0:1d0::2; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of pm215@archaic.org.uk designates 2001:8b0:1d0::2 as permitted sender) smtp.mailfrom=pm215@archaic.org.uk; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from pm215 by orth.archaic.org.uk with local (Exim 4.84_2) (envelope-from ) id 1dVyC4-0007lz-7E; Fri, 14 Jul 2017 11:51:32 +0100 From: Peter Maydell To: qemu-arm@nongnu.org, qemu-devel@nongnu.org Cc: patches@linaro.org, =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= , Alistair Francis Subject: [PATCH v2 9/9] MAINTAINERS: Add entries for MPS2 board Date: Fri, 14 Jul 2017 11:51:27 +0100 Message-Id: <1500029487-14822-10-git-send-email-peter.maydell@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1500029487-14822-1-git-send-email-peter.maydell@linaro.org> References: <1500029487-14822-1-git-send-email-peter.maydell@linaro.org> Add entries to the MAINTAINERS file for the new MPS2 board and devices. Since the CMSDK devices are not specific to the MPS2 board, extend the existing 'PrimeCell' section to cover CMSDK devices as well; in both cases these are devices implemented by ARM and provided as RTL that may be used in multiple SoCs and boards. Signed-off-by: Peter Maydell --- MAINTAINERS | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) -- 2.7.4 Reviewed-by: Alex Bennée Reviewed-by: Philippe Mathieu-Daudé diff --git a/MAINTAINERS b/MAINTAINERS index 9529c94..10f5cd6 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -380,7 +380,7 @@ F: hw/*/allwinner* F: include/hw/*/allwinner* F: hw/arm/cubieboard.c -ARM PrimeCell +ARM PrimeCell and CMSDK devices M: Peter Maydell L: qemu-arm@nongnu.org S: Maintained @@ -394,6 +394,10 @@ F: hw/intc/pl190.c F: hw/sd/pl181.c F: hw/timer/pl031.c F: include/hw/arm/primecell.h +F: hw/timer/cmsdk-apb-timer.c +F: include/hw/timer/cmsdk-apb-timer.h +F: hw/char/cmsdk-apb-uart.c +F: include/hw/char/cmsdk-apb-uart.h ARM cores M: Peter Maydell @@ -455,6 +459,14 @@ S: Maintained F: hw/arm/integratorcp.c F: hw/misc/arm_integrator_debug.c +MPS2 +M: Peter Maydell +L: qemu-arm@nongnu.org +S: Maintained +F: hw/arm/mps2.c +F: hw/misc/mps2-scc.c +F: include/hw/misc/mps2-scc.h + Musicpal M: Jan Kiszka L: qemu-arm@nongnu.org