mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge tag 'pull-target-arm-20240111' of https://git.linaro.org/people/pmaydell/qemu-arm into staging
target-arm queue:
* Emulate FEAT_NV, FEAT_NV2
* add cache controller for Freescale i.MX6
* Add minimal support for the B-L475E-IOT01A board
* Allow SoC models to configure M-profile CPUs with correct number
of NVIC priority bits
* Add missing QOM parent for v7-M SoCs
* Set CTR_EL0.{IDC,DIC} for the 'max' CPU
* hw/intc/arm_gicv3_cpuif: handle LPIs in in the list registers
# -----BEGIN PGP SIGNATURE-----
#
# iQJNBAABCAA3FiEE4aXFk81BneKOgxXPPCUl7RQ2DN4FAmWfypMZHHBldGVyLm1h
# eWRlbGxAbGluYXJvLm9yZwAKCRA8JSXtFDYM3sleD/4tQOMteba5BNMDns6R96E4
# kj5q0Iy9XyzQ486Q4cIZXI5N3BddCp2ks8WeS2W3w4IT/lms0U6UwXV4E98I4I/b
# KSfOoUd/cp8IvdvzfpWbmQcPMoauHZdCUN33pYYXOjfi1RkpzgNU5Qgh09Nl/xYU
# V3oaEvWhLtepT/fwJLYxoqVHDaEmyW+6zriF0+eGjZvkhgPyhllla9eti7AyHTfH
# T3A4Fyx/wudRE3NP6xsLfxldriJTxQeba+TqLSh3IXn/PMtK13/ARsY/hl72Q4ML
# Fgad8Zho4eXbuOQ9oiqb7gp4K3IKd9/8FbCzECoIAq7AnLAD4KwpLQR8GULRvYW3
# 0eQq2txTXQWNcmWpIyDRRME+qeNVwWSk+QJDs5WuhVqlVQ4hpqtgFf1EX+7ORdS1
# WG0fb8etvr8oCSkzCmP/o6xYGJ0EyTVMU5DmWviy3bxMrUMcmobjvCQr/n2gC713
# 1NDmEaYPbl+pX8EMu8byst7/No2PXRgIO0UVVb4KZybfhNy+BBs+LiMVlSRS5YH4
# 8NWtoYZlG9RcPnY+8Xrxz9VTi2cNAAcdbf5uK3snJxkFV2SmV3oBoMxWen3mee0f
# 2PNVEbt9zvPV8hViBVLsqRhVXd9wMq6motIRlkKge1u1TvwIxO21ibykI3tvYOGv
# BffIjhUdnYtX90JAtXtFDw==
# =yQwf
# -----END PGP SIGNATURE-----
# gpg: Signature made Thu 11 Jan 2024 11:01:39 GMT
# gpg: using RSA key E1A5C593CD419DE28E8315CF3C2525ED14360CDE
# gpg: issuer "peter.maydell@linaro.org"
# gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" [ultimate]
# gpg: aka "Peter Maydell <pmaydell@gmail.com>" [ultimate]
# gpg: aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>" [ultimate]
# gpg: aka "Peter Maydell <peter@archaic.org.uk>" [ultimate]
# Primary key fingerprint: E1A5 C593 CD41 9DE2 8E83 15CF 3C25 25ED 1436 0CDE
* tag 'pull-target-arm-20240111' of https://git.linaro.org/people/pmaydell/qemu-arm: (41 commits)
target/arm: Add FEAT_NV2 to max, neoverse-n2, neoverse-v1 CPUs
target/arm: Enhance CPU_LOG_INT to show SPSR on AArch64 exception-entry
target/arm: Report HCR_EL2.{NV,NV1,NV2} in cpu dumps
hw/intc/arm_gicv3_cpuif: Mark up VNCR offsets for GIC CPU registers
target/arm: Mark up VNCR offsets (offsets >= 0x200, except GIC)
target/arm: Mark up VNCR offsets (offsets 0x168..0x1f8)
target/arm: Mark up VNCR offsets (offsets 0x100..0x160)
target/arm: Mark up VNCR offsets (offsets 0x0..0xff)
target/arm: Report VNCR_EL2 based faults correctly
target/arm: Implement FEAT_NV2 redirection of sysregs to RAM
target/arm: Handle FEAT_NV2 redirection of SPSR_EL2, ELR_EL2, ESR_EL2, FAR_EL2
target/arm: Handle FEAT_NV2 changes to when SPSR_EL1.M reports EL2
target/arm: Implement VNCR_EL2 register
target/arm: Handle HCR_EL2 accesses for FEAT_NV2 bits
target/arm: Add FEAT_NV to max, neoverse-n2, neoverse-v1 CPUs
target/arm: Handle FEAT_NV page table attribute changes
target/arm: Treat LDTR* and STTR* as LDR/STR when NV, NV1 is 1, 1
target/arm: Don't honour PSTATE.PAN when HCR_EL2.{NV, NV1} == {1, 1}
target/arm: Always use arm_pan_enabled() when checking if PAN is enabled
target/arm: Trap registers when HCR_EL2.{NV, NV1} == {1, 1}
...
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
+15
@@ -1122,6 +1122,21 @@ L: qemu-arm@nongnu.org
|
||||
S: Maintained
|
||||
F: hw/arm/olimex-stm32-h405.c
|
||||
|
||||
STM32L4x5 SoC Family
|
||||
M: Arnaud Minier <arnaud.minier@telecom-paris.fr>
|
||||
M: Inès Varhol <ines.varhol@telecom-paris.fr>
|
||||
L: qemu-arm@nongnu.org
|
||||
S: Maintained
|
||||
F: hw/arm/stm32l4x5_soc.c
|
||||
F: include/hw/arm/stm32l4x5_soc.h
|
||||
|
||||
B-L475E-IOT01A IoT Node
|
||||
M: Arnaud Minier <arnaud.minier@telecom-paris.fr>
|
||||
M: Inès Varhol <ines.varhol@telecom-paris.fr>
|
||||
L: qemu-arm@nongnu.org
|
||||
S: Maintained
|
||||
F: hw/arm/b-l475e-iot01a.c
|
||||
|
||||
SmartFusion2
|
||||
M: Subbaraya Sundeep <sundeep.lkml@gmail.com>
|
||||
M: Peter Maydell <peter.maydell@linaro.org>
|
||||
|
||||
@@ -19,6 +19,7 @@ CONFIG_ARM_VIRT=y
|
||||
# CONFIG_NSERIES=n
|
||||
# CONFIG_STELLARIS=n
|
||||
# CONFIG_STM32VLDISCOVERY=n
|
||||
# CONFIG_B_L475E_IOT01A=n
|
||||
# CONFIG_REALVIEW=n
|
||||
# CONFIG_VERSATILE=n
|
||||
# CONFIG_VEXPRESS=n
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
B-L475E-IOT01A IoT Node (``b-l475e-iot01a``)
|
||||
============================================
|
||||
|
||||
The B-L475E-IOT01A IoT Node uses the STM32L475VG SoC which is based on
|
||||
ARM Cortex-M4F core. It is part of STMicroelectronics
|
||||
:doc:`STM32 boards </system/arm/stm32>` and more specifically the STM32L4
|
||||
ultra-low power series. The STM32L4x5 chip runs at up to 80 MHz and
|
||||
integrates 128 KiB of SRAM and up to 1MiB of Flash. The B-L475E-IOT01A board
|
||||
namely features 64 Mibit QSPI Flash, BT, WiFi and RF connectivity,
|
||||
USART, I2C, SPI, CAN and USB OTG, as well as a variety of sensors.
|
||||
|
||||
Supported devices
|
||||
"""""""""""""""""
|
||||
|
||||
Currently, B-L475E-IOT01A machine's implementation is minimal,
|
||||
it only supports the following device:
|
||||
|
||||
- Cortex-M4F based STM32L4x5 SoC
|
||||
|
||||
Missing devices
|
||||
"""""""""""""""
|
||||
|
||||
The B-L475E-IOT01A does *not* support the following devices:
|
||||
|
||||
- Extended interrupts and events controller (EXTI)
|
||||
- Reset and clock control (RCC)
|
||||
- Serial ports (UART)
|
||||
- System configuration controller (SYSCFG)
|
||||
- General-purpose I/Os (GPIO)
|
||||
- Analog to Digital Converter (ADC)
|
||||
- SPI controller
|
||||
- Timer controller (TIMER)
|
||||
|
||||
See the complete list of unimplemented peripheral devices
|
||||
in the STM32L4x5 module : ``./hw/arm/stm32l4x5_soc.c``
|
||||
|
||||
Boot options
|
||||
""""""""""""
|
||||
|
||||
The B-L475E-IOT01A machine can be started using the ``-kernel``
|
||||
option to load a firmware. Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ qemu-system-arm -M b-l475e-iot01a -kernel firmware.bin
|
||||
|
||||
@@ -63,6 +63,8 @@ the following architecture extensions:
|
||||
- FEAT_MTE (Memory Tagging Extension)
|
||||
- FEAT_MTE2 (Memory Tagging Extension)
|
||||
- FEAT_MTE3 (MTE Asymmetric Fault Handling)
|
||||
- FEAT_NV (Nested Virtualization)
|
||||
- FEAT_NV2 (Enhanced nested virtualization support)
|
||||
- FEAT_PACIMP (Pointer authentication - IMPLEMENTATION DEFINED algorithm)
|
||||
- FEAT_PACQARMA3 (Pointer authentication - QARMA3 algorithm)
|
||||
- FEAT_PACQARMA5 (Pointer authentication - QARMA5 algorithm)
|
||||
|
||||
@@ -16,11 +16,13 @@ based on this chip :
|
||||
|
||||
- ``netduino2`` Netduino 2 board with STM32F205RFT6 microcontroller
|
||||
|
||||
The STM32F4 series is based on ARM Cortex-M4F core. This series is pin-to-pin
|
||||
compatible with STM32F2 series. The following machines are based on this chip :
|
||||
The STM32F4 series is based on ARM Cortex-M4F core, as well as the STM32L4
|
||||
ultra-low-power series. The STM32F4 series is pin-to-pin compatible with STM32F2 series.
|
||||
The following machines are based on this ARM Cortex-M4F chip :
|
||||
|
||||
- ``netduinoplus2`` Netduino Plus 2 board with STM32F405RGT6 microcontroller
|
||||
- ``olimex-stm32-h405`` Olimex STM32 H405 board with STM32F405RGT6 microcontroller
|
||||
- ``b-l475e-iot01a`` :doc:`B-L475E-IOT01A IoT Node </system/arm/b-l475e-iot01a>` board with STM32L475VG microcontroller
|
||||
|
||||
There are many other STM32 series that are currently not supported by QEMU.
|
||||
|
||||
|
||||
@@ -84,6 +84,7 @@ undocumented; you can get a complete list by running
|
||||
arm/vexpress
|
||||
arm/aspeed
|
||||
arm/bananapi_m2u.rst
|
||||
arm/b-l475e-iot01a.rst
|
||||
arm/sabrelite
|
||||
arm/digic
|
||||
arm/cubieboard
|
||||
|
||||
@@ -449,6 +449,17 @@ config STM32F405_SOC
|
||||
select STM32F4XX_SYSCFG
|
||||
select STM32F4XX_EXTI
|
||||
|
||||
config B_L475E_IOT01A
|
||||
bool
|
||||
default y
|
||||
depends on TCG && ARM
|
||||
select STM32L4X5_SOC
|
||||
|
||||
config STM32L4X5_SOC
|
||||
bool
|
||||
select ARM_V7M
|
||||
select OR_IRQ
|
||||
|
||||
config XLNX_ZYNQMP_ARM
|
||||
bool
|
||||
default y if PIXMAN
|
||||
@@ -537,6 +548,7 @@ config FSL_IMX6
|
||||
select IMX_I2C
|
||||
select IMX_USBPHY
|
||||
select WDT_IMX2
|
||||
select PL310 # cache controller
|
||||
select SDHCI
|
||||
|
||||
config ASPEED_SOC
|
||||
|
||||
@@ -256,6 +256,8 @@ static void armv7m_instance_init(Object *obj)
|
||||
object_initialize_child(obj, "nvic", &s->nvic, TYPE_NVIC);
|
||||
object_property_add_alias(obj, "num-irq",
|
||||
OBJECT(&s->nvic), "num-irq");
|
||||
object_property_add_alias(obj, "num-prio-bits",
|
||||
OBJECT(&s->nvic), "num-prio-bits");
|
||||
|
||||
object_initialize_child(obj, "systick-reg-ns", &s->systick[M_REG_NS],
|
||||
TYPE_SYSTICK);
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* B-L475E-IOT01A Discovery Kit machine
|
||||
* (B-L475E-IOT01A IoT Node)
|
||||
*
|
||||
* Copyright (c) 2023 Arnaud Minier <arnaud.minier@telecom-paris.fr>
|
||||
* Copyright (c) 2023 Inès Varhol <ines.varhol@telecom-paris.fr>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*
|
||||
* This work is heavily inspired by the netduinoplus2 by Alistair Francis.
|
||||
* Original code is licensed under the MIT License:
|
||||
*
|
||||
* Copyright (c) 2014 Alistair Francis <alistair@alistair23.me>
|
||||
*/
|
||||
|
||||
/*
|
||||
* The reference used is the STMicroElectronics UM2153 User manual
|
||||
* Discovery kit for IoT node, multi-channel communication with STM32L4.
|
||||
* https://www.st.com/en/evaluation-tools/b-l475e-iot01a.html#documentation
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qapi/error.h"
|
||||
#include "hw/boards.h"
|
||||
#include "hw/qdev-properties.h"
|
||||
#include "hw/qdev-clock.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "hw/arm/stm32l4x5_soc.h"
|
||||
#include "hw/arm/boot.h"
|
||||
|
||||
/* Main SYSCLK frequency in Hz (80MHz) */
|
||||
#define MAIN_SYSCLK_FREQ_HZ 80000000ULL
|
||||
|
||||
static void b_l475e_iot01a_init(MachineState *machine)
|
||||
{
|
||||
const Stm32l4x5SocClass *sc;
|
||||
DeviceState *dev;
|
||||
Clock *sysclk;
|
||||
|
||||
/* This clock doesn't need migration because it is fixed-frequency */
|
||||
sysclk = clock_new(OBJECT(machine), "SYSCLK");
|
||||
clock_set_hz(sysclk, MAIN_SYSCLK_FREQ_HZ);
|
||||
|
||||
dev = qdev_new(TYPE_STM32L4X5XG_SOC);
|
||||
object_property_add_child(OBJECT(machine), "soc", OBJECT(dev));
|
||||
qdev_connect_clock_in(dev, "sysclk", sysclk);
|
||||
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
|
||||
|
||||
sc = STM32L4X5_SOC_GET_CLASS(dev);
|
||||
armv7m_load_kernel(ARM_CPU(first_cpu),
|
||||
machine->kernel_filename,
|
||||
0, sc->flash_size);
|
||||
}
|
||||
|
||||
static void b_l475e_iot01a_machine_init(MachineClass *mc)
|
||||
{
|
||||
static const char *machine_valid_cpu_types[] = {
|
||||
ARM_CPU_TYPE_NAME("cortex-m4"),
|
||||
NULL
|
||||
};
|
||||
mc->desc = "B-L475E-IOT01A Discovery Kit (Cortex-M4)";
|
||||
mc->init = b_l475e_iot01a_init;
|
||||
mc->valid_cpu_types = machine_valid_cpu_types;
|
||||
|
||||
/* SRAM pre-allocated as part of the SoC instantiation */
|
||||
mc->default_ram_size = 0;
|
||||
}
|
||||
|
||||
DEFINE_MACHINE("b-l475e-iot01a", b_l475e_iot01a_machine_init)
|
||||
@@ -154,6 +154,9 @@ static void fsl_imx6_realize(DeviceState *dev, Error **errp)
|
||||
qdev_get_gpio_in(DEVICE(&s->cpu[i]), ARM_CPU_FIQ));
|
||||
}
|
||||
|
||||
/* L2 cache controller */
|
||||
sysbus_create_simple("l2x0", FSL_IMX6_PL310_ADDR, NULL);
|
||||
|
||||
if (!sysbus_realize(SYS_BUS_DEVICE(&s->ccm), errp)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -42,6 +42,8 @@ arm_ss.add(when: 'CONFIG_RASPI', if_true: files('bcm2836.c', 'raspi.c'))
|
||||
arm_ss.add(when: 'CONFIG_STM32F100_SOC', if_true: files('stm32f100_soc.c'))
|
||||
arm_ss.add(when: 'CONFIG_STM32F205_SOC', if_true: files('stm32f205_soc.c'))
|
||||
arm_ss.add(when: 'CONFIG_STM32F405_SOC', if_true: files('stm32f405_soc.c'))
|
||||
arm_ss.add(when: 'CONFIG_B_L475E_IOT01A', if_true: files('b-l475e-iot01a.c'))
|
||||
arm_ss.add(when: 'CONFIG_STM32L4X5_SOC', if_true: files('stm32l4x5_soc.c'))
|
||||
arm_ss.add(when: 'CONFIG_XLNX_ZYNQMP_ARM', if_true: files('xlnx-zynqmp.c', 'xlnx-zcu102.c'))
|
||||
arm_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files('xlnx-versal.c', 'xlnx-versal-virt.c'))
|
||||
arm_ss.add(when: 'CONFIG_FSL_IMX25', if_true: files('fsl-imx25.c', 'imx25_pdk.c'))
|
||||
|
||||
@@ -60,6 +60,7 @@ static void emcraft_sf2_s2s010_init(MachineState *machine)
|
||||
memory_region_add_subregion(sysmem, DDR_BASE_ADDRESS, ddr);
|
||||
|
||||
dev = qdev_new(TYPE_MSF2_SOC);
|
||||
object_property_add_child(OBJECT(machine), "soc", OBJECT(dev));
|
||||
qdev_prop_set_string(dev, "part-name", "M2S010");
|
||||
qdev_prop_set_string(dev, "cpu-type", mc->default_cpu_type);
|
||||
|
||||
|
||||
@@ -44,6 +44,7 @@ static void netduino2_init(MachineState *machine)
|
||||
clock_set_hz(sysclk, SYSCLK_FRQ);
|
||||
|
||||
dev = qdev_new(TYPE_STM32F205_SOC);
|
||||
object_property_add_child(OBJECT(machine), "soc", OBJECT(dev));
|
||||
qdev_connect_clock_in(dev, "sysclk", sysclk);
|
||||
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
|
||||
|
||||
|
||||
@@ -44,6 +44,7 @@ static void netduinoplus2_init(MachineState *machine)
|
||||
clock_set_hz(sysclk, SYSCLK_FRQ);
|
||||
|
||||
dev = qdev_new(TYPE_STM32F405_SOC);
|
||||
object_property_add_child(OBJECT(machine), "soc", OBJECT(dev));
|
||||
qdev_connect_clock_in(dev, "sysclk", sysclk);
|
||||
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
|
||||
|
||||
|
||||
@@ -47,6 +47,7 @@ static void olimex_stm32_h405_init(MachineState *machine)
|
||||
clock_set_hz(sysclk, SYSCLK_FRQ);
|
||||
|
||||
dev = qdev_new(TYPE_STM32F405_SOC);
|
||||
object_property_add_child(OBJECT(machine), "soc", OBJECT(dev));
|
||||
qdev_connect_clock_in(dev, "sysclk", sysclk);
|
||||
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
|
||||
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
#define BP_GAMEPAD 0x04
|
||||
|
||||
#define NUM_IRQ_LINES 64
|
||||
#define NUM_PRIO_BITS 3
|
||||
|
||||
typedef const struct {
|
||||
const char *name;
|
||||
@@ -1067,6 +1068,7 @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board)
|
||||
|
||||
nvic = qdev_new(TYPE_ARMV7M);
|
||||
qdev_prop_set_uint32(nvic, "num-irq", NUM_IRQ_LINES);
|
||||
qdev_prop_set_uint8(nvic, "num-prio-bits", NUM_PRIO_BITS);
|
||||
qdev_prop_set_string(nvic, "cpu-type", ms->cpu_type);
|
||||
qdev_prop_set_bit(nvic, "enable-bitband", true);
|
||||
qdev_connect_clock_in(nvic, "cpuclk",
|
||||
|
||||
@@ -115,6 +115,7 @@ static void stm32f100_soc_realize(DeviceState *dev_soc, Error **errp)
|
||||
/* Init ARMv7m */
|
||||
armv7m = DEVICE(&s->armv7m);
|
||||
qdev_prop_set_uint32(armv7m, "num-irq", 61);
|
||||
qdev_prop_set_uint8(armv7m, "num-prio-bits", 4);
|
||||
qdev_prop_set_string(armv7m, "cpu-type", ARM_CPU_TYPE_NAME("cortex-m3"));
|
||||
qdev_prop_set_bit(armv7m, "enable-bitband", true);
|
||||
qdev_connect_clock_in(armv7m, "cpuclk", s->sysclk);
|
||||
|
||||
@@ -127,6 +127,7 @@ static void stm32f205_soc_realize(DeviceState *dev_soc, Error **errp)
|
||||
|
||||
armv7m = DEVICE(&s->armv7m);
|
||||
qdev_prop_set_uint32(armv7m, "num-irq", 96);
|
||||
qdev_prop_set_uint8(armv7m, "num-prio-bits", 4);
|
||||
qdev_prop_set_string(armv7m, "cpu-type", ARM_CPU_TYPE_NAME("cortex-m3"));
|
||||
qdev_prop_set_bit(armv7m, "enable-bitband", true);
|
||||
qdev_connect_clock_in(armv7m, "cpuclk", s->sysclk);
|
||||
|
||||
@@ -149,6 +149,7 @@ static void stm32f405_soc_realize(DeviceState *dev_soc, Error **errp)
|
||||
|
||||
armv7m = DEVICE(&s->armv7m);
|
||||
qdev_prop_set_uint32(armv7m, "num-irq", 96);
|
||||
qdev_prop_set_uint8(armv7m, "num-prio-bits", 4);
|
||||
qdev_prop_set_string(armv7m, "cpu-type", ARM_CPU_TYPE_NAME("cortex-m4"));
|
||||
qdev_prop_set_bit(armv7m, "enable-bitband", true);
|
||||
qdev_connect_clock_in(armv7m, "cpuclk", s->sysclk);
|
||||
|
||||
@@ -0,0 +1,266 @@
|
||||
/*
|
||||
* STM32L4x5 SoC family
|
||||
*
|
||||
* Copyright (c) 2023 Arnaud Minier <arnaud.minier@telecom-paris.fr>
|
||||
* Copyright (c) 2023 Inès Varhol <ines.varhol@telecom-paris.fr>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*
|
||||
* This work is heavily inspired by the stm32f405_soc by Alistair Francis.
|
||||
* Original code is licensed under the MIT License:
|
||||
*
|
||||
* Copyright (c) 2014 Alistair Francis <alistair@alistair23.me>
|
||||
*/
|
||||
|
||||
/*
|
||||
* The reference used is the STMicroElectronics RM0351 Reference manual
|
||||
* for STM32L4x5 and STM32L4x6 advanced Arm ® -based 32-bit MCUs.
|
||||
* https://www.st.com/en/microcontrollers-microprocessors/stm32l4x5/documentation.html
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/units.h"
|
||||
#include "qapi/error.h"
|
||||
#include "exec/address-spaces.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "hw/arm/stm32l4x5_soc.h"
|
||||
#include "hw/qdev-clock.h"
|
||||
#include "hw/misc/unimp.h"
|
||||
|
||||
#define FLASH_BASE_ADDRESS 0x08000000
|
||||
#define SRAM1_BASE_ADDRESS 0x20000000
|
||||
#define SRAM1_SIZE (96 * KiB)
|
||||
#define SRAM2_BASE_ADDRESS 0x10000000
|
||||
#define SRAM2_SIZE (32 * KiB)
|
||||
|
||||
static void stm32l4x5_soc_initfn(Object *obj)
|
||||
{
|
||||
Stm32l4x5SocState *s = STM32L4X5_SOC(obj);
|
||||
|
||||
s->sysclk = qdev_init_clock_in(DEVICE(s), "sysclk", NULL, NULL, 0);
|
||||
s->refclk = qdev_init_clock_in(DEVICE(s), "refclk", NULL, NULL, 0);
|
||||
}
|
||||
|
||||
static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
|
||||
{
|
||||
ERRP_GUARD();
|
||||
Stm32l4x5SocState *s = STM32L4X5_SOC(dev_soc);
|
||||
const Stm32l4x5SocClass *sc = STM32L4X5_SOC_GET_CLASS(dev_soc);
|
||||
MemoryRegion *system_memory = get_system_memory();
|
||||
DeviceState *armv7m;
|
||||
|
||||
/*
|
||||
* We use s->refclk internally and only define it with qdev_init_clock_in()
|
||||
* so it is correctly parented and not leaked on an init/deinit; it is not
|
||||
* intended as an externally exposed clock.
|
||||
*/
|
||||
if (clock_has_source(s->refclk)) {
|
||||
error_setg(errp, "refclk clock must not be wired up by the board code");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!clock_has_source(s->sysclk)) {
|
||||
error_setg(errp, "sysclk clock must be wired up by the board code");
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: ideally we should model the SoC RCC and its ability to
|
||||
* change the sysclk frequency and define different sysclk sources.
|
||||
*/
|
||||
|
||||
/* The refclk always runs at frequency HCLK / 8 */
|
||||
clock_set_mul_div(s->refclk, 8, 1);
|
||||
clock_set_source(s->refclk, s->sysclk);
|
||||
|
||||
if (!memory_region_init_rom(&s->flash, OBJECT(dev_soc), "flash",
|
||||
sc->flash_size, errp)) {
|
||||
return;
|
||||
}
|
||||
memory_region_init_alias(&s->flash_alias, OBJECT(dev_soc),
|
||||
"flash_boot_alias", &s->flash, 0,
|
||||
sc->flash_size);
|
||||
|
||||
memory_region_add_subregion(system_memory, FLASH_BASE_ADDRESS, &s->flash);
|
||||
memory_region_add_subregion(system_memory, 0, &s->flash_alias);
|
||||
|
||||
if (!memory_region_init_ram(&s->sram1, OBJECT(dev_soc), "SRAM1", SRAM1_SIZE,
|
||||
errp)) {
|
||||
return;
|
||||
}
|
||||
memory_region_add_subregion(system_memory, SRAM1_BASE_ADDRESS, &s->sram1);
|
||||
|
||||
if (!memory_region_init_ram(&s->sram2, OBJECT(dev_soc), "SRAM2", SRAM2_SIZE,
|
||||
errp)) {
|
||||
return;
|
||||
}
|
||||
memory_region_add_subregion(system_memory, SRAM2_BASE_ADDRESS, &s->sram2);
|
||||
|
||||
object_initialize_child(OBJECT(dev_soc), "armv7m", &s->armv7m, TYPE_ARMV7M);
|
||||
armv7m = DEVICE(&s->armv7m);
|
||||
qdev_prop_set_uint32(armv7m, "num-irq", 96);
|
||||
qdev_prop_set_uint32(armv7m, "num-prio-bits", 4);
|
||||
qdev_prop_set_string(armv7m, "cpu-type", ARM_CPU_TYPE_NAME("cortex-m4"));
|
||||
qdev_prop_set_bit(armv7m, "enable-bitband", true);
|
||||
qdev_connect_clock_in(armv7m, "cpuclk", s->sysclk);
|
||||
qdev_connect_clock_in(armv7m, "refclk", s->refclk);
|
||||
object_property_set_link(OBJECT(&s->armv7m), "memory",
|
||||
OBJECT(system_memory), &error_abort);
|
||||
if (!sysbus_realize(SYS_BUS_DEVICE(&s->armv7m), errp)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* APB1 BUS */
|
||||
create_unimplemented_device("TIM2", 0x40000000, 0x400);
|
||||
create_unimplemented_device("TIM3", 0x40000400, 0x400);
|
||||
create_unimplemented_device("TIM4", 0x40000800, 0x400);
|
||||
create_unimplemented_device("TIM5", 0x40000C00, 0x400);
|
||||
create_unimplemented_device("TIM6", 0x40001000, 0x400);
|
||||
create_unimplemented_device("TIM7", 0x40001400, 0x400);
|
||||
/* RESERVED: 0x40001800, 0x1000 */
|
||||
create_unimplemented_device("RTC", 0x40002800, 0x400);
|
||||
create_unimplemented_device("WWDG", 0x40002C00, 0x400);
|
||||
create_unimplemented_device("IWDG", 0x40003000, 0x400);
|
||||
/* RESERVED: 0x40001800, 0x400 */
|
||||
create_unimplemented_device("SPI2", 0x40003800, 0x400);
|
||||
create_unimplemented_device("SPI3", 0x40003C00, 0x400);
|
||||
/* RESERVED: 0x40004000, 0x400 */
|
||||
create_unimplemented_device("USART2", 0x40004400, 0x400);
|
||||
create_unimplemented_device("USART3", 0x40004800, 0x400);
|
||||
create_unimplemented_device("UART4", 0x40004C00, 0x400);
|
||||
create_unimplemented_device("UART5", 0x40005000, 0x400);
|
||||
create_unimplemented_device("I2C1", 0x40005400, 0x400);
|
||||
create_unimplemented_device("I2C2", 0x40005800, 0x400);
|
||||
create_unimplemented_device("I2C3", 0x40005C00, 0x400);
|
||||
/* RESERVED: 0x40006000, 0x400 */
|
||||
create_unimplemented_device("CAN1", 0x40006400, 0x400);
|
||||
/* RESERVED: 0x40006800, 0x400 */
|
||||
create_unimplemented_device("PWR", 0x40007000, 0x400);
|
||||
create_unimplemented_device("DAC1", 0x40007400, 0x400);
|
||||
create_unimplemented_device("OPAMP", 0x40007800, 0x400);
|
||||
create_unimplemented_device("LPTIM1", 0x40007C00, 0x400);
|
||||
create_unimplemented_device("LPUART1", 0x40008000, 0x400);
|
||||
/* RESERVED: 0x40008400, 0x400 */
|
||||
create_unimplemented_device("SWPMI1", 0x40008800, 0x400);
|
||||
/* RESERVED: 0x40008C00, 0x800 */
|
||||
create_unimplemented_device("LPTIM2", 0x40009400, 0x400);
|
||||
/* RESERVED: 0x40009800, 0x6800 */
|
||||
|
||||
/* APB2 BUS */
|
||||
create_unimplemented_device("SYSCFG", 0x40010000, 0x30);
|
||||
create_unimplemented_device("VREFBUF", 0x40010030, 0x1D0);
|
||||
create_unimplemented_device("COMP", 0x40010200, 0x200);
|
||||
create_unimplemented_device("EXTI", 0x40010400, 0x400);
|
||||
/* RESERVED: 0x40010800, 0x1400 */
|
||||
create_unimplemented_device("FIREWALL", 0x40011C00, 0x400);
|
||||
/* RESERVED: 0x40012000, 0x800 */
|
||||
create_unimplemented_device("SDMMC1", 0x40012800, 0x400);
|
||||
create_unimplemented_device("TIM1", 0x40012C00, 0x400);
|
||||
create_unimplemented_device("SPI1", 0x40013000, 0x400);
|
||||
create_unimplemented_device("TIM8", 0x40013400, 0x400);
|
||||
create_unimplemented_device("USART1", 0x40013800, 0x400);
|
||||
/* RESERVED: 0x40013C00, 0x400 */
|
||||
create_unimplemented_device("TIM15", 0x40014000, 0x400);
|
||||
create_unimplemented_device("TIM16", 0x40014400, 0x400);
|
||||
create_unimplemented_device("TIM17", 0x40014800, 0x400);
|
||||
/* RESERVED: 0x40014C00, 0x800 */
|
||||
create_unimplemented_device("SAI1", 0x40015400, 0x400);
|
||||
create_unimplemented_device("SAI2", 0x40015800, 0x400);
|
||||
/* RESERVED: 0x40015C00, 0x400 */
|
||||
create_unimplemented_device("DFSDM1", 0x40016000, 0x400);
|
||||
/* RESERVED: 0x40016400, 0x9C00 */
|
||||
|
||||
/* AHB1 BUS */
|
||||
create_unimplemented_device("DMA1", 0x40020000, 0x400);
|
||||
create_unimplemented_device("DMA2", 0x40020400, 0x400);
|
||||
/* RESERVED: 0x40020800, 0x800 */
|
||||
create_unimplemented_device("RCC", 0x40021000, 0x400);
|
||||
/* RESERVED: 0x40021400, 0xC00 */
|
||||
create_unimplemented_device("FLASH", 0x40022000, 0x400);
|
||||
/* RESERVED: 0x40022400, 0xC00 */
|
||||
create_unimplemented_device("CRC", 0x40023000, 0x400);
|
||||
/* RESERVED: 0x40023400, 0x400 */
|
||||
create_unimplemented_device("TSC", 0x40024000, 0x400);
|
||||
|
||||
/* RESERVED: 0x40024400, 0x7FDBC00 */
|
||||
|
||||
/* AHB2 BUS */
|
||||
create_unimplemented_device("GPIOA", 0x48000000, 0x400);
|
||||
create_unimplemented_device("GPIOB", 0x48000400, 0x400);
|
||||
create_unimplemented_device("GPIOC", 0x48000800, 0x400);
|
||||
create_unimplemented_device("GPIOD", 0x48000C00, 0x400);
|
||||
create_unimplemented_device("GPIOE", 0x48001000, 0x400);
|
||||
create_unimplemented_device("GPIOF", 0x48001400, 0x400);
|
||||
create_unimplemented_device("GPIOG", 0x48001800, 0x400);
|
||||
create_unimplemented_device("GPIOH", 0x48001C00, 0x400);
|
||||
/* RESERVED: 0x48002000, 0x7FDBC00 */
|
||||
create_unimplemented_device("OTG_FS", 0x50000000, 0x40000);
|
||||
create_unimplemented_device("ADC", 0x50040000, 0x400);
|
||||
/* RESERVED: 0x50040400, 0x20400 */
|
||||
create_unimplemented_device("RNG", 0x50060800, 0x400);
|
||||
|
||||
/* AHB3 BUS */
|
||||
create_unimplemented_device("FMC", 0xA0000000, 0x1000);
|
||||
create_unimplemented_device("QUADSPI", 0xA0001000, 0x400);
|
||||
}
|
||||
|
||||
static void stm32l4x5_soc_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
|
||||
dc->realize = stm32l4x5_soc_realize;
|
||||
/* Reason: Mapped at fixed location on the system bus */
|
||||
dc->user_creatable = false;
|
||||
/* No vmstate or reset required: device has no internal state */
|
||||
}
|
||||
|
||||
static void stm32l4x5xc_soc_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
Stm32l4x5SocClass *ssc = STM32L4X5_SOC_CLASS(oc);
|
||||
|
||||
ssc->flash_size = 256 * KiB;
|
||||
}
|
||||
|
||||
static void stm32l4x5xe_soc_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
Stm32l4x5SocClass *ssc = STM32L4X5_SOC_CLASS(oc);
|
||||
|
||||
ssc->flash_size = 512 * KiB;
|
||||
}
|
||||
|
||||
static void stm32l4x5xg_soc_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
Stm32l4x5SocClass *ssc = STM32L4X5_SOC_CLASS(oc);
|
||||
|
||||
ssc->flash_size = 1 * MiB;
|
||||
}
|
||||
|
||||
static const TypeInfo stm32l4x5_soc_types[] = {
|
||||
{
|
||||
.name = TYPE_STM32L4X5XC_SOC,
|
||||
.parent = TYPE_STM32L4X5_SOC,
|
||||
.class_init = stm32l4x5xc_soc_class_init,
|
||||
}, {
|
||||
.name = TYPE_STM32L4X5XE_SOC,
|
||||
.parent = TYPE_STM32L4X5_SOC,
|
||||
.class_init = stm32l4x5xe_soc_class_init,
|
||||
}, {
|
||||
.name = TYPE_STM32L4X5XG_SOC,
|
||||
.parent = TYPE_STM32L4X5_SOC,
|
||||
.class_init = stm32l4x5xg_soc_class_init,
|
||||
}, {
|
||||
.name = TYPE_STM32L4X5_SOC,
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
.instance_size = sizeof(Stm32l4x5SocState),
|
||||
.instance_init = stm32l4x5_soc_initfn,
|
||||
.class_size = sizeof(Stm32l4x5SocClass),
|
||||
.class_init = stm32l4x5_soc_class_init,
|
||||
.abstract = true,
|
||||
}
|
||||
};
|
||||
|
||||
DEFINE_TYPES(stm32l4x5_soc_types)
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user