Merge tag 'pull-target-arm-20240118' of https://git.linaro.org/people/pmaydell/qemu-arm into staging

target-arm queue:
 * docs/devel/docs: Document .hx file syntax
 * arm_pamax() no longer needs to do feature propagation
 * docs/system/arm/virt.rst: Improve 'highmem' option docs
 * STM32L4x5 Implement SYSCFG and EXTI devices
 * hw/timer: fix systick trace message
 * hw/arm/virt: Consolidate valid CPU types
 * load_elf: fix iterator's type for elf file processing

# -----BEGIN PGP SIGNATURE-----
#
# iQJNBAABCAA3FiEE4aXFk81BneKOgxXPPCUl7RQ2DN4FAmWpHM4ZHHBldGVyLm1h
# eWRlbGxAbGluYXJvLm9yZwAKCRA8JSXtFDYM3pZxD/sGIXvTeoOCsum7OFpArKoQ
# J+wcy74pO526IDzjudgtwP8kFW09oVblMPgrt/68F9LY4Oa7sDNAZX/Xqlhs/hdJ
# SVbOXArRmyLvgLpn8KVii9xk9iI/olMGt0S6KcXAErdgFud+JcCevbS0D5fAF4Ua
# /G/4ldnwr+WcYUA5IIoi02ymSBm5VNeH2bKu0MPS3xpizjzgOFxWTBYwq3zkZYWD
# w5GjH9+F+IC67CiAlCLvuQBqpGLdRwFBttU05hLtGXuSlnvS+FtJTooI7gGD17CR
# 2wTa7qF716qDN1lNSIvxA6t8/dWNMIYCZYdlxJml476WzP3jECpth2WFWqE0G3yg
# Orr7sFVB8X6JmtlR34srW6e3CZA3t+4FIWqcdELFLi5IQtJeer90jqQ9xwx4SttJ
# nsHdy5M8txWSa61yAaDTXMID/smVlC7sWTKJrR9kV7v5+b9OPQ/R8k0mCODl5Aer
# mzAVuCvUQVYK3j7fzprGrlldla57s3v78OAhqACLgKflK0+aJSJjglulPrSMK1z5
# bRPS5jLZjFwEi2VaLVg3LPJiBMDj1s/wAl0ycfCQSv2oEzvmpkw+Ar1HDc2NFe+d
# 9dunbdhAZJMwh+ABIg7iMj+l0ncOXDa4DS+6BnjRxfECCa172u3viq1HATkLLAFI
# GTkcJ5hIQzNEeg9ob0MDIg==
# =Rfpe
# -----END PGP SIGNATURE-----
# gpg: Signature made Thu 18 Jan 2024 12:42:54 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-20240118' of https://git.linaro.org/people/pmaydell/qemu-arm:
  load_elf: fix iterator's type for elf file processing
  hw/arm/virt: Consolidate valid CPU types
  hw/timer: fix systick trace message
  tests/qtest: Add STM32L4x5 SYSCFG QTest testcase
  hw/arm: Connect STM32L4x5 SYSCFG to STM32L4x5 SoC
  hw/misc: Implement STM32L4x5 SYSCFG
  tests/qtest: Add STM32L4x5 EXTI QTest testcase
  hw/arm: Connect STM32L4x5 EXTI to STM32L4x5 SoC
  hw/misc: Implement STM32L4x5 EXTI
  docs/system/arm/virt.rst: Improve 'highmem' option docs
  target/arm: arm_pamax() no longer needs to do feature propagation
  docs/devel/docs: Document .hx file syntax

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell
2024-01-18 12:48:17 +00:00
26 changed files with 1719 additions and 29 deletions
+1
View File
@@ -4175,6 +4175,7 @@ F: docs/conf.py
F: docs/*/conf.py
F: docs/sphinx/
F: docs/_templates/
F: docs/devel/docs.rst
Miscellaneous
-------------
+60
View File
@@ -0,0 +1,60 @@
==================
QEMU Documentation
==================
QEMU's documentation is written in reStructuredText format and
built using the Sphinx documentation generator. We generate both
the HTML manual and the manpages from the some documentation sources.
hxtool and .hx files
--------------------
The documentation for QEMU command line options and Human Monitor Protocol
(HMP) commands is written in files with the ``.hx`` suffix. These
are processed in two ways:
* ``scripts/hxtool`` creates C header files from them, which are included
in QEMU to do things like handle the ``--help`` option output
* a Sphinx extension in ``docs/sphinx/hxtool.py`` generates rST output
to be included in the HTML or manpage documentation
The syntax of these ``.hx`` files is simple. It is broadly an
alternation of C code put into the C output and rST format text
put into the documention. A few special directives are recognised;
these are all-caps and must be at the beginning of the line.
``HXCOMM`` is the comment marker. The line, including any arbitrary
text after the marker, is discarded and appears neither in the C output
nor the documentation output.
``SRST`` starts a reStructuredText section. Following lines
are put into the documentation verbatim, and discarded from the C output.
``ERST`` ends the documentation section started with ``SRST``,
and switches back to a C code section.
``DEFHEADING()`` defines a heading that should appear in both the
``--help`` output and in the documentation. This directive should
be in the C code block. If there is a string inside the brackets,
this is the heading to use. If this string is empty, it produces
a blank line in the ``--help`` output and is ignored for the rST
output.
``ARCHHEADING()`` is a variant of ``DEFHEADING()`` which produces
the heading only if the specified guest architecture was compiled
into QEMU. This should be avoided in new documentation.
Within C code sections, you should check the comments at the top
of the file to see what the expected usage is, because this
varies between files. For instance in ``qemu-options.hx`` we use
the ``DEF()`` macro to define each option and specify its ``--help``
text, but in ``hmp-commands.hx`` the C code sections are elements
of an array of structs of type ``HMPCommand`` which define the
name, behaviour and help text for each monitor command.
In the file ``qemu-options.hx``, do not try to define a
reStructuredText label within a documentation section. This file
is included into two separate Sphinx documents, and some
versions of Sphinx will complain about the duplicate label
that results.
+1
View File
@@ -10,6 +10,7 @@ the basics if you are adding new files and targets to the build.
build-system
kconfig
docs
testing
acpi-bits
qtest
+3 -4
View File
@@ -12,20 +12,19 @@ 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:
Currently B-L475E-IOT01A machine's only supports the following devices:
- Cortex-M4F based STM32L4x5 SoC
- STM32L4x5 EXTI (Extended interrupts and events controller)
- STM32L4x5 SYSCFG (System configuration controller)
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
+7 -1
View File
@@ -96,7 +96,13 @@ mte
highmem
Set ``on``/``off`` to enable/disable placing devices and RAM in physical
address space above 32 bits. The default is ``on`` for machine types
later than ``virt-2.12``.
later than ``virt-2.12`` when the CPU supports an address space
bigger than 32 bits (i.e. 64-bit CPUs, and 32-bit CPUs with the
Large Physical Address Extension (LPAE) feature). If you want to
boot a 32-bit kernel which does not have ``CONFIG_LPAE`` enabled on
a CPU type which implements LPAE, you will need to manually set
this to ``off``; otherwise some devices, such as the PCI controller,
will not be accessible.
compact-highmem
Set ``on``/``off`` to enable/disable the compact layout for high memory regions.
+5 -5
View File
@@ -1,8 +1,8 @@
HXCOMM Use DEFHEADING() to define headings in both help text and rST.
HXCOMM Text between SRST and ERST is copied to the rST version and
HXCOMM discarded from C version.
HXCOMM DEF(command, args, callback, arg_string, help) is used to construct
HXCOMM monitor info commands
HXCOMM See docs/devel/docs.rst for the format of this file.
HXCOMM
HXCOMM This file defines the contents of an array of HMPCommand structs
HXCOMM which specify the name, behaviour and help text for HMP commands.
HXCOMM Text between SRST and ERST is rST format documentation.
HXCOMM HXCOMM can be used for comments, discarded from both rST and C.
HXCOMM
HXCOMM In this file, generally SRST fragments should have two extra
+5 -5
View File
@@ -1,8 +1,8 @@
HXCOMM Use DEFHEADING() to define headings in both help text and rST.
HXCOMM Text between SRST and ERST is copied to the rST version and
HXCOMM discarded from C version.
HXCOMM DEF(command, args, callback, arg_string, help) is used to construct
HXCOMM monitor commands
HXCOMM See docs/devel/docs.rst for the format of this file.
HXCOMM
HXCOMM This file defines the contents of an array of HMPCommand structs
HXCOMM which specify the name, behaviour and help text for HMP commands.
HXCOMM Text between SRST and ERST is rST format documentation.
HXCOMM HXCOMM can be used for comments, discarded from both rST and C.
+2
View File
@@ -459,6 +459,8 @@ config STM32L4X5_SOC
bool
select ARM_V7M
select OR_IRQ
select STM32L4X5_SYSCFG
select STM32L4X5_EXTI
config XLNX_ZYNQMP_ARM
bool
+71 -2
View File
@@ -36,10 +36,53 @@
#define SRAM2_BASE_ADDRESS 0x10000000
#define SRAM2_SIZE (32 * KiB)
#define EXTI_ADDR 0x40010400
#define SYSCFG_ADDR 0x40010000
#define NUM_EXTI_IRQ 40
/* Match exti line connections with their CPU IRQ number */
/* See Vector Table (Reference Manual p.396) */
static const int exti_irq[NUM_EXTI_IRQ] = {
6, /* GPIO[0] */
7, /* GPIO[1] */
8, /* GPIO[2] */
9, /* GPIO[3] */
10, /* GPIO[4] */
23, 23, 23, 23, 23, /* GPIO[5..9] */
40, 40, 40, 40, 40, 40, /* GPIO[10..15] */
1, /* PVD */
67, /* OTG_FS_WKUP, Direct */
41, /* RTC_ALARM */
2, /* RTC_TAMP_STAMP2/CSS_LSE */
3, /* RTC wakeup timer */
63, /* COMP1 */
63, /* COMP2 */
31, /* I2C1 wakeup, Direct */
33, /* I2C2 wakeup, Direct */
72, /* I2C3 wakeup, Direct */
37, /* USART1 wakeup, Direct */
38, /* USART2 wakeup, Direct */
39, /* USART3 wakeup, Direct */
52, /* UART4 wakeup, Direct */
53, /* UART4 wakeup, Direct */
70, /* LPUART1 wakeup, Direct */
65, /* LPTIM1, Direct */
66, /* LPTIM2, Direct */
76, /* SWPMI1 wakeup, Direct */
1, /* PVM1 wakeup */
1, /* PVM2 wakeup */
1, /* PVM3 wakeup */
1, /* PVM4 wakeup */
78 /* LCD wakeup, Direct */
};
static void stm32l4x5_soc_initfn(Object *obj)
{
Stm32l4x5SocState *s = STM32L4X5_SOC(obj);
object_initialize_child(obj, "exti", &s->exti, TYPE_STM32L4X5_EXTI);
object_initialize_child(obj, "syscfg", &s->syscfg, TYPE_STM32L4X5_SYSCFG);
s->sysclk = qdev_init_clock_in(DEVICE(s), "sysclk", NULL, NULL, 0);
s->refclk = qdev_init_clock_in(DEVICE(s), "refclk", NULL, NULL, 0);
}
@@ -51,6 +94,7 @@ static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
const Stm32l4x5SocClass *sc = STM32L4X5_SOC_GET_CLASS(dev_soc);
MemoryRegion *system_memory = get_system_memory();
DeviceState *armv7m;
SysBusDevice *busdev;
/*
* We use s->refclk internally and only define it with qdev_init_clock_in()
@@ -113,6 +157,33 @@ static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
return;
}
/* System configuration controller */
busdev = SYS_BUS_DEVICE(&s->syscfg);
if (!sysbus_realize(busdev, errp)) {
return;
}
sysbus_mmio_map(busdev, 0, SYSCFG_ADDR);
/*
* TODO: when the GPIO device is implemented, connect it
* to SYCFG using `qdev_connect_gpio_out`, NUM_GPIOS and
* GPIO_NUM_PINS.
*/
/* EXTI device */
busdev = SYS_BUS_DEVICE(&s->exti);
if (!sysbus_realize(busdev, errp)) {
return;
}
sysbus_mmio_map(busdev, 0, EXTI_ADDR);
for (unsigned i = 0; i < NUM_EXTI_IRQ; i++) {
sysbus_connect_irq(busdev, i, qdev_get_gpio_in(armv7m, exti_irq[i]));
}
for (unsigned i = 0; i < 16; i++) {
qdev_connect_gpio_out(DEVICE(&s->syscfg), i,
qdev_get_gpio_in(DEVICE(&s->exti), i));
}
/* APB1 BUS */
create_unimplemented_device("TIM2", 0x40000000, 0x400);
create_unimplemented_device("TIM3", 0x40000400, 0x400);
@@ -150,10 +221,8 @@ static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
/* 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 */
+6 -2
View File
@@ -2905,6 +2905,7 @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
#ifdef CONFIG_TCG
ARM_CPU_TYPE_NAME("cortex-a7"),
ARM_CPU_TYPE_NAME("cortex-a15"),
#ifdef TARGET_AARCH64
ARM_CPU_TYPE_NAME("cortex-a35"),
ARM_CPU_TYPE_NAME("cortex-a55"),
ARM_CPU_TYPE_NAME("cortex-a72"),
@@ -2914,12 +2915,15 @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
ARM_CPU_TYPE_NAME("neoverse-n1"),
ARM_CPU_TYPE_NAME("neoverse-v1"),
ARM_CPU_TYPE_NAME("neoverse-n2"),
#endif
#endif /* TARGET_AARCH64 */
#endif /* CONFIG_TCG */
#ifdef TARGET_AARCH64
ARM_CPU_TYPE_NAME("cortex-a53"),
ARM_CPU_TYPE_NAME("cortex-a57"),
#if defined(CONFIG_KVM) || defined(CONFIG_HVF)
ARM_CPU_TYPE_NAME("host"),
#endif
#endif /* CONFIG_KVM || CONFIG_HVF */
#endif /* TARGET_AARCH64 */
ARM_CPU_TYPE_NAME("max"),
NULL
};
+6
View File
@@ -87,6 +87,12 @@ config STM32F4XX_SYSCFG
config STM32F4XX_EXTI
bool
config STM32L4X5_EXTI
bool
config STM32L4X5_SYSCFG
bool
config MIPS_ITU
bool
+2
View File
@@ -110,6 +110,8 @@ system_ss.add(when: 'CONFIG_XLNX_VERSAL_TRNG', if_true: files(
system_ss.add(when: 'CONFIG_STM32F2XX_SYSCFG', if_true: files('stm32f2xx_syscfg.c'))
system_ss.add(when: 'CONFIG_STM32F4XX_SYSCFG', if_true: files('stm32f4xx_syscfg.c'))
system_ss.add(when: 'CONFIG_STM32F4XX_EXTI', if_true: files('stm32f4xx_exti.c'))
system_ss.add(when: 'CONFIG_STM32L4X5_EXTI', if_true: files('stm32l4x5_exti.c'))
system_ss.add(when: 'CONFIG_STM32L4X5_SYSCFG', if_true: files('stm32l4x5_syscfg.c'))
system_ss.add(when: 'CONFIG_MPS2_FPGAIO', if_true: files('mps2-fpgaio.c'))
system_ss.add(when: 'CONFIG_MPS2_SCC', if_true: files('mps2-scc.c'))
+290
View File
@@ -0,0 +1,290 @@
/*
* STM32L4x5 EXTI (Extended interrupts and events controller)
*
* Copyright (c) 2023 Arnaud Minier <arnaud.minier@telecom-paris.fr>
* Copyright (c) 2023 Samuel Tardieu <samuel.tardieu@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 based on the stm32f4xx_exti 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/log.h"
#include "trace.h"
#include "hw/irq.h"
#include "migration/vmstate.h"
#include "hw/misc/stm32l4x5_exti.h"
#define EXTI_IMR1 0x00
#define EXTI_EMR1 0x04
#define EXTI_RTSR1 0x08
#define EXTI_FTSR1 0x0C
#define EXTI_SWIER1 0x10
#define EXTI_PR1 0x14
#define EXTI_IMR2 0x20
#define EXTI_EMR2 0x24
#define EXTI_RTSR2 0x28
#define EXTI_FTSR2 0x2C
#define EXTI_SWIER2 0x30
#define EXTI_PR2 0x34
#define EXTI_NUM_GPIO_EVENT_IN_LINES 16
#define EXTI_MAX_IRQ_PER_BANK 32
#define EXTI_IRQS_BANK0 32
#define EXTI_IRQS_BANK1 8
static const unsigned irqs_per_bank[EXTI_NUM_REGISTER] = {
EXTI_IRQS_BANK0,
EXTI_IRQS_BANK1,
};
static const uint32_t exti_romask[EXTI_NUM_REGISTER] = {
0xff820000, /* 0b11111111_10000010_00000000_00000000 */
0x00000087, /* 0b00000000_00000000_00000000_10000111 */
};
static unsigned regbank_index_by_irq(unsigned irq)
{
return irq >= EXTI_MAX_IRQ_PER_BANK ? 1 : 0;
}
static unsigned regbank_index_by_addr(hwaddr addr)
{
return addr >= EXTI_IMR2 ? 1 : 0;
}
static unsigned valid_mask(unsigned bank)
{
return MAKE_64BIT_MASK(0, irqs_per_bank[bank]);
}
static unsigned configurable_mask(unsigned bank)
{
return valid_mask(bank) & ~exti_romask[bank];
}
static void stm32l4x5_exti_reset_hold(Object *obj)
{
Stm32l4x5ExtiState *s = STM32L4X5_EXTI(obj);
for (unsigned bank = 0; bank < EXTI_NUM_REGISTER; bank++) {
s->imr[bank] = exti_romask[bank];
s->emr[bank] = 0x00000000;
s->rtsr[bank] = 0x00000000;
s->ftsr[bank] = 0x00000000;
s->swier[bank] = 0x00000000;
s->pr[bank] = 0x00000000;
}
}
static void stm32l4x5_exti_set_irq(void *opaque, int irq, int level)
{
Stm32l4x5ExtiState *s = opaque;
const unsigned bank = regbank_index_by_irq(irq);
const int oirq = irq;
trace_stm32l4x5_exti_set_irq(irq, level);
/* Shift the value to enable access in x2 registers. */
irq %= EXTI_MAX_IRQ_PER_BANK;
/* If the interrupt is masked, pr won't be raised */
if (!extract32(s->imr[bank], irq, 1)) {
return;
}
if (((1 << irq) & s->rtsr[bank]) && level) {
/* Rising Edge */
s->pr[bank] |= 1 << irq;
qemu_irq_pulse(s->irq[oirq]);
} else if (((1 << irq) & s->ftsr[bank]) && !level) {
/* Falling Edge */
s->pr[bank] |= 1 << irq;
qemu_irq_pulse(s->irq[oirq]);
}
/*
* In the following situations :
* - falling edge but rising trigger selected
* - rising edge but falling trigger selected
* - no trigger selected
* No action is required
*/
}
static uint64_t stm32l4x5_exti_read(void *opaque, hwaddr addr,
unsigned int size)
{
Stm32l4x5ExtiState *s = opaque;
uint32_t r = 0;
const unsigned bank = regbank_index_by_addr(addr);
switch (addr) {
case EXTI_IMR1:
case EXTI_IMR2:
r = s->imr[bank];
break;
case EXTI_EMR1:
case EXTI_EMR2:
r = s->emr[bank];
break;
case EXTI_RTSR1:
case EXTI_RTSR2:
r = s->rtsr[bank];
break;
case EXTI_FTSR1:
case EXTI_FTSR2:
r = s->ftsr[bank];
break;
case EXTI_SWIER1:
case EXTI_SWIER2:
r = s->swier[bank];
break;
case EXTI_PR1:
case EXTI_PR2:
r = s->pr[bank];
break;
default:
qemu_log_mask(LOG_GUEST_ERROR,
"STM32L4X5_exti_read: Bad offset 0x%" HWADDR_PRIx "\n",
addr);
break;
}
trace_stm32l4x5_exti_read(addr, r);
return r;
}
static void stm32l4x5_exti_write(void *opaque, hwaddr addr,
uint64_t val64, unsigned int size)
{
Stm32l4x5ExtiState *s = opaque;
const unsigned bank = regbank_index_by_addr(addr);
trace_stm32l4x5_exti_write(addr, val64);
switch (addr) {
case EXTI_IMR1:
case EXTI_IMR2:
s->imr[bank] = val64 & valid_mask(bank);
return;
case EXTI_EMR1:
case EXTI_EMR2:
s->emr[bank] = val64 & valid_mask(bank);
return;
case EXTI_RTSR1:
case EXTI_RTSR2:
s->rtsr[bank] = val64 & configurable_mask(bank);
return;
case EXTI_FTSR1:
case EXTI_FTSR2:
s->ftsr[bank] = val64 & configurable_mask(bank);
return;
case EXTI_SWIER1:
case EXTI_SWIER2: {
const uint32_t set = val64 & configurable_mask(bank);
const uint32_t pend = set & ~s->swier[bank] & s->imr[bank] &
~s->pr[bank];
s->swier[bank] = set;
s->pr[bank] |= pend;
for (unsigned i = 0; i < irqs_per_bank[bank]; i++) {
if (extract32(pend, i, 1)) {
qemu_irq_pulse(s->irq[i + 32 * bank]);
}
}
return;
}
case EXTI_PR1:
case EXTI_PR2: {
const uint32_t cleared = s->pr[bank] & val64 & configurable_mask(bank);
/* This bit is cleared by writing a 1 to it */
s->pr[bank] &= ~cleared;
/* Software triggered interrupts are cleared as well */
s->swier[bank] &= ~cleared;
return;
}
default:
qemu_log_mask(LOG_GUEST_ERROR,
"STM32L4X5_exti_write: Bad offset 0x%" HWADDR_PRIx "\n",
addr);
}
}
static const MemoryRegionOps stm32l4x5_exti_ops = {
.read = stm32l4x5_exti_read,
.write = stm32l4x5_exti_write,
.endianness = DEVICE_NATIVE_ENDIAN,
.impl.min_access_size = 4,
.impl.max_access_size = 4,
.impl.unaligned = false,
.valid.min_access_size = 4,
.valid.max_access_size = 4,
.valid.unaligned = false,
};
static void stm32l4x5_exti_init(Object *obj)
{
Stm32l4x5ExtiState *s = STM32L4X5_EXTI(obj);
for (size_t i = 0; i < EXTI_NUM_INTERRUPT_OUT_LINES; i++) {
sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq[i]);
}
memory_region_init_io(&s->mmio, obj, &stm32l4x5_exti_ops, s,
TYPE_STM32L4X5_EXTI, 0x400);
sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
qdev_init_gpio_in(DEVICE(obj), stm32l4x5_exti_set_irq,
EXTI_NUM_GPIO_EVENT_IN_LINES);
}
static const VMStateDescription vmstate_stm32l4x5_exti = {
.name = TYPE_STM32L4X5_EXTI,
.version_id = 1,
.minimum_version_id = 1,
.fields = (VMStateField[]) {
VMSTATE_UINT32_ARRAY(imr, Stm32l4x5ExtiState, EXTI_NUM_REGISTER),
VMSTATE_UINT32_ARRAY(emr, Stm32l4x5ExtiState, EXTI_NUM_REGISTER),
VMSTATE_UINT32_ARRAY(rtsr, Stm32l4x5ExtiState, EXTI_NUM_REGISTER),
VMSTATE_UINT32_ARRAY(ftsr, Stm32l4x5ExtiState, EXTI_NUM_REGISTER),
VMSTATE_UINT32_ARRAY(swier, Stm32l4x5ExtiState, EXTI_NUM_REGISTER),
VMSTATE_UINT32_ARRAY(pr, Stm32l4x5ExtiState, EXTI_NUM_REGISTER),
VMSTATE_END_OF_LIST()
}
};
static void stm32l4x5_exti_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
ResettableClass *rc = RESETTABLE_CLASS(klass);
dc->vmsd = &vmstate_stm32l4x5_exti;
rc->phases.hold = stm32l4x5_exti_reset_hold;
}
static const TypeInfo stm32l4x5_exti_types[] = {
{
.name = TYPE_STM32L4X5_EXTI,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(Stm32l4x5ExtiState),
.instance_init = stm32l4x5_exti_init,
.class_init = stm32l4x5_exti_class_init,
}
};
DEFINE_TYPES(stm32l4x5_exti_types)
+266
View File
@@ -0,0 +1,266 @@
/*
* STM32L4x5 SYSCFG (System Configuration Controller)
*
* 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 based on the stm32f4xx_syscfg 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/log.h"
#include "trace.h"
#include "hw/irq.h"
#include "migration/vmstate.h"
#include "hw/misc/stm32l4x5_syscfg.h"
#define SYSCFG_MEMRMP 0x00
#define SYSCFG_CFGR1 0x04
#define SYSCFG_EXTICR1 0x08
#define SYSCFG_EXTICR2 0x0C
#define SYSCFG_EXTICR3 0x10
#define SYSCFG_EXTICR4 0x14
#define SYSCFG_SCSR 0x18
#define SYSCFG_CFGR2 0x1C
#define SYSCFG_SWPR 0x20
#define SYSCFG_SKR 0x24
#define SYSCFG_SWPR2 0x28
/* 00000000_00000000_00000001_00000111 */
#define ACTIVABLE_BITS_MEMRP 0x00000107
/* 11111100_11111111_00000001_00000000 */
#define ACTIVABLE_BITS_CFGR1 0xFCFF0100
/* 00000000_00000000_00000000_00000001 */
#define FIREWALL_DISABLE_CFGR1 0x00000001
/* 00000000_00000000_11111111_11111111 */
#define ACTIVABLE_BITS_EXTICR 0x0000FFFF
/* 00000000_00000000_00000000_00000011 */
/* #define ACTIVABLE_BITS_SCSR 0x00000003 */
/* 00000000_00000000_00000000_00001111 */
#define ECC_LOCK_CFGR2 0x0000000F
/* 00000000_00000000_00000001_00000000 */
#define SRAM2_PARITY_ERROR_FLAG_CFGR2 0x00000100
/* 00000000_00000000_00000000_11111111 */
#define ACTIVABLE_BITS_SKR 0x000000FF
#define NUM_LINES_PER_EXTICR_REG 4
static void stm32l4x5_syscfg_hold_reset(Object *obj)
{
Stm32l4x5SyscfgState *s = STM32L4X5_SYSCFG(obj);
s->memrmp = 0x00000000;
s->cfgr1 = 0x7C000001;
s->exticr[0] = 0x00000000;
s->exticr[1] = 0x00000000;
s->exticr[2] = 0x00000000;
s->exticr[3] = 0x00000000;
s->scsr = 0x00000000;
s->cfgr2 = 0x00000000;
s->swpr = 0x00000000;
s->skr = 0x00000000;
s->swpr2 = 0x00000000;
}
static void stm32l4x5_syscfg_set_irq(void *opaque, int irq, int level)
{
Stm32l4x5SyscfgState *s = opaque;
const uint8_t gpio = irq / GPIO_NUM_PINS;
const int line = irq % GPIO_NUM_PINS;
const int exticr_reg = line / NUM_LINES_PER_EXTICR_REG;
const int startbit = (line % NUM_LINES_PER_EXTICR_REG) * 4;
g_assert(gpio < NUM_GPIOS);
trace_stm32l4x5_syscfg_set_irq(gpio, line, level);
if (extract32(s->exticr[exticr_reg], startbit, 4) == gpio) {
trace_stm32l4x5_syscfg_forward_exti(line);
qemu_set_irq(s->gpio_out[line], level);
}
}
static uint64_t stm32l4x5_syscfg_read(void *opaque, hwaddr addr,
unsigned int size)
{
Stm32l4x5SyscfgState *s = opaque;
trace_stm32l4x5_syscfg_read(addr);
switch (addr) {
case SYSCFG_MEMRMP:
return s->memrmp;
case SYSCFG_CFGR1:
return s->cfgr1;
case SYSCFG_EXTICR1...SYSCFG_EXTICR4:
return s->exticr[(addr - SYSCFG_EXTICR1) / 4];
case SYSCFG_SCSR:
return s->scsr;
case SYSCFG_CFGR2:
return s->cfgr2;
case SYSCFG_SWPR:
return s->swpr;
case SYSCFG_SKR:
return s->skr;
case SYSCFG_SWPR2:
return s->swpr2;
default:
qemu_log_mask(LOG_GUEST_ERROR,
"%s: Bad offset 0x%" HWADDR_PRIx "\n", __func__, addr);
return 0;
}
}
static void stm32l4x5_syscfg_write(void *opaque, hwaddr addr,
uint64_t value, unsigned int size)
{
Stm32l4x5SyscfgState *s = opaque;
trace_stm32l4x5_syscfg_write(addr, value);
switch (addr) {
case SYSCFG_MEMRMP:
qemu_log_mask(LOG_UNIMP,
"%s: Changing the memory mapping isn't supported\n",
__func__);
s->memrmp = value & ACTIVABLE_BITS_MEMRP;
return;
case SYSCFG_CFGR1:
qemu_log_mask(LOG_UNIMP,
"%s: Functions in CFGRx aren't supported\n",
__func__);
/* bit 0 (firewall dis.) is cleared by software, set only by reset. */
s->cfgr1 = (s->cfgr1 & value & FIREWALL_DISABLE_CFGR1) |
(value & ACTIVABLE_BITS_CFGR1);
return;
case SYSCFG_EXTICR1...SYSCFG_EXTICR4:
s->exticr[(addr - SYSCFG_EXTICR1) / 4] =
(value & ACTIVABLE_BITS_EXTICR);
return;
case SYSCFG_SCSR:
qemu_log_mask(LOG_UNIMP,
"%s: Erasing SRAM2 isn't supported\n",
__func__);
/*
* only non reserved bits are :
* bit 0 (write-protected by a passkey), bit 1 (meant to be read)
* so it serves no purpose yet to add :
* s->scsr = value & 0x3;
*/
return;
case SYSCFG_CFGR2:
qemu_log_mask(LOG_UNIMP,
"%s: Functions in CFGRx aren't supported\n",
__func__);
/* bit 8 (SRAM2 PEF) is cleared by software by writing a '1'.*/
/* bits[3:0] (ECC Lock) are set by software, cleared only by reset.*/
s->cfgr2 = (s->cfgr2 | (value & ECC_LOCK_CFGR2)) &
~(value & SRAM2_PARITY_ERROR_FLAG_CFGR2);
return;
case SYSCFG_SWPR:
qemu_log_mask(LOG_UNIMP,
"%s: Write protecting SRAM2 isn't supported\n",
__func__);
/* These bits are set by software and cleared only by reset.*/
s->swpr |= value;
return;
case SYSCFG_SKR:
qemu_log_mask(LOG_UNIMP,
"%s: Erasing SRAM2 isn't supported\n",
__func__);
s->skr = value & ACTIVABLE_BITS_SKR;
return;
case SYSCFG_SWPR2:
qemu_log_mask(LOG_UNIMP,
"%s: Write protecting SRAM2 isn't supported\n",
__func__);
/* These bits are set by software and cleared only by reset.*/
s->swpr2 |= value;
return;
default:
qemu_log_mask(LOG_GUEST_ERROR,
"%s: Bad offset 0x%" HWADDR_PRIx "\n", __func__, addr);
}
}
static const MemoryRegionOps stm32l4x5_syscfg_ops = {
.read = stm32l4x5_syscfg_read,
.write = stm32l4x5_syscfg_write,
.endianness = DEVICE_NATIVE_ENDIAN,
.impl.min_access_size = 4,
.impl.max_access_size = 4,
.impl.unaligned = false,
.valid.min_access_size = 4,
.valid.max_access_size = 4,
.valid.unaligned = false,
};
static void stm32l4x5_syscfg_init(Object *obj)
{
Stm32l4x5SyscfgState *s = STM32L4X5_SYSCFG(obj);
memory_region_init_io(&s->mmio, obj, &stm32l4x5_syscfg_ops, s,
TYPE_STM32L4X5_SYSCFG, 0x400);
sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
qdev_init_gpio_in(DEVICE(obj), stm32l4x5_syscfg_set_irq,
GPIO_NUM_PINS * NUM_GPIOS);
qdev_init_gpio_out(DEVICE(obj), s->gpio_out, GPIO_NUM_PINS);
}
static const VMStateDescription vmstate_stm32l4x5_syscfg = {
.name = TYPE_STM32L4X5_SYSCFG,
.version_id = 1,
.minimum_version_id = 1,
.fields = (VMStateField[]) {
VMSTATE_UINT32(memrmp, Stm32l4x5SyscfgState),
VMSTATE_UINT32(cfgr1, Stm32l4x5SyscfgState),
VMSTATE_UINT32_ARRAY(exticr, Stm32l4x5SyscfgState,
SYSCFG_NUM_EXTICR),
VMSTATE_UINT32(scsr, Stm32l4x5SyscfgState),
VMSTATE_UINT32(cfgr2, Stm32l4x5SyscfgState),
VMSTATE_UINT32(swpr, Stm32l4x5SyscfgState),
VMSTATE_UINT32(skr, Stm32l4x5SyscfgState),
VMSTATE_UINT32(swpr2, Stm32l4x5SyscfgState),
VMSTATE_END_OF_LIST()
}
};
static void stm32l4x5_syscfg_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
ResettableClass *rc = RESETTABLE_CLASS(klass);
dc->vmsd = &vmstate_stm32l4x5_syscfg;
rc->phases.hold = stm32l4x5_syscfg_hold_reset;
}
static const TypeInfo stm32l4x5_syscfg_info[] = {
{
.name = TYPE_STM32L4X5_SYSCFG,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(Stm32l4x5SyscfgState),
.instance_init = stm32l4x5_syscfg_init,
.class_init = stm32l4x5_syscfg_class_init,
}
};
DEFINE_TYPES(stm32l4x5_syscfg_info)
+11
View File
@@ -163,6 +163,17 @@ stm32f4xx_exti_set_irq(int irq, int level) "Set EXTI: %d to %d"
stm32f4xx_exti_read(uint64_t addr) "reg read: addr: 0x%" PRIx64 " "
stm32f4xx_exti_write(uint64_t addr, uint64_t data) "reg write: addr: 0x%" PRIx64 " val: 0x%" PRIx64 ""
# stm32l4x5_syscfg.c
stm32l4x5_syscfg_set_irq(int gpio, int line, int level) "irq from GPIO: %d, line: %d, level: %d"
stm32l4x5_syscfg_forward_exti(int irq) "irq %d forwarded to EXTI"
stm32l4x5_syscfg_read(uint64_t addr) "reg read: addr: 0x%" PRIx64 " "
stm32l4x5_syscfg_write(uint64_t addr, uint64_t data) "reg write: addr: 0x%" PRIx64 " val: 0x%" PRIx64 ""
# stm32l4x5_exti.c
stm32l4x5_exti_set_irq(int irq, int level) "Set EXTI: %d to %d"
stm32l4x5_exti_read(uint64_t addr, uint64_t data) "reg read: addr: 0x%" PRIx64 " val: 0x%" PRIx64 ""
stm32l4x5_exti_write(uint64_t addr, uint64_t data) "reg write: addr: 0x%" PRIx64 " val: 0x%" PRIx64 ""
# tz-mpc.c
tz_mpc_reg_read(uint32_t offset, uint64_t data, unsigned size) "TZ MPC regs read: offset 0x%x data 0x%" PRIx64 " size %u"
tz_mpc_reg_write(uint32_t offset, uint64_t data, unsigned size) "TZ MPC regs write: offset 0x%x data 0x%" PRIx64 " size %u"
+1 -1
View File
@@ -35,7 +35,7 @@ aspeed_timer_read(uint64_t offset, unsigned size, uint64_t value) "From 0x%" PRI
# armv7m_systick.c
systick_reload(void) "systick reload"
systick_timer_tick(void) "systick reload"
systick_timer_tick(void) "systick tick"
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"
+5
View File
@@ -26,6 +26,8 @@
#include "exec/memory.h"
#include "hw/arm/armv7m.h"
#include "hw/misc/stm32l4x5_syscfg.h"
#include "hw/misc/stm32l4x5_exti.h"
#include "qom/object.h"
#define TYPE_STM32L4X5_SOC "stm32l4x5-soc"
@@ -39,6 +41,9 @@ struct Stm32l4x5SocState {
ARMv7MState armv7m;
Stm32l4x5ExtiState exti;
Stm32l4x5SyscfgState syscfg;
MemoryRegion sram1;
MemoryRegion sram2;
MemoryRegion flash;
+1 -1
View File
@@ -500,7 +500,7 @@ static ssize_t glue(load_elf, SZ)(const char *name, int fd,
}
if (data_swab) {
int j;
elf_word j;
for (j = 0; j < file_size; j += (1 << data_swab)) {
uint8_t *dp = data + j;
switch (data_swab) {
+51
View File
@@ -0,0 +1,51 @@
/*
* STM32L4x5 EXTI (Extended interrupts and events controller)
*
* 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 based on the stm32f4xx_exti 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
*/
#ifndef HW_STM32L4X5_EXTI_H
#define HW_STM32L4X5_EXTI_H
#include "hw/sysbus.h"
#include "qom/object.h"
#define TYPE_STM32L4X5_EXTI "stm32l4x5-exti"
OBJECT_DECLARE_SIMPLE_TYPE(Stm32l4x5ExtiState, STM32L4X5_EXTI)
#define EXTI_NUM_INTERRUPT_OUT_LINES 40
#define EXTI_NUM_REGISTER 2
struct Stm32l4x5ExtiState {
SysBusDevice parent_obj;
MemoryRegion mmio;
uint32_t imr[EXTI_NUM_REGISTER];
uint32_t emr[EXTI_NUM_REGISTER];
uint32_t rtsr[EXTI_NUM_REGISTER];
uint32_t ftsr[EXTI_NUM_REGISTER];
uint32_t swier[EXTI_NUM_REGISTER];
uint32_t pr[EXTI_NUM_REGISTER];
qemu_irq irq[EXTI_NUM_INTERRUPT_OUT_LINES];
};
#endif
+54
View File
@@ -0,0 +1,54 @@
/*
* STM32L4x5 SYSCFG (System Configuration Controller)
*
* 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 based on the stm32f4xx_syscfg 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
*/
#ifndef HW_STM32L4X5_SYSCFG_H
#define HW_STM32L4X5_SYSCFG_H
#include "hw/sysbus.h"
#include "qom/object.h"
#define TYPE_STM32L4X5_SYSCFG "stm32l4x5-syscfg"
OBJECT_DECLARE_SIMPLE_TYPE(Stm32l4x5SyscfgState, STM32L4X5_SYSCFG)
#define NUM_GPIOS 8
#define GPIO_NUM_PINS 16
#define SYSCFG_NUM_EXTICR 4
struct Stm32l4x5SyscfgState {
SysBusDevice parent_obj;
MemoryRegion mmio;
uint32_t memrmp;
uint32_t cfgr1;
uint32_t exticr[SYSCFG_NUM_EXTICR];
uint32_t scsr;
uint32_t cfgr2;
uint32_t swpr;
uint32_t skr;
uint32_t swpr2;
qemu_irq gpio_out[GPIO_NUM_PINS];
};
#endif

Some files were not shown because too many files have changed in this diff Show More