target-arm queue:
* hw/core/clock: allow clock_propagate on child clocks * hvf: arm: Remove unused PL1_WRITE_MASK define * target/arm: Restrict translation disabled alignment check to VMSA * docs/system/arm/emulation.rst: Add missing implemented features * target/arm: Enable FEAT_CSV2_3, FEAT_ETS2, FEAT_Spec_FPACC for 'max' * tests/avocado: update sunxi kernel from armbian to 6.6.16 * target/arm: Make new CPUs default to 1GHz generic timer * hw/dmax/xlnx_dpdma: fix handling of address_extension descriptor fields * hw/char/stm32l4x5_usart: Fix memory corruption by adding correct class_size * hw/arm/npcm7xx: Store derivative OTP fuse key in little endian * hw/arm: Add DM163 display to B-L475E-IOT01A board -----BEGIN PGP SIGNATURE----- iQJNBAABCAA3FiEE4aXFk81BneKOgxXPPCUl7RQ2DN4FAmYxILcZHHBldGVyLm1h eWRlbGxAbGluYXJvLm9yZwAKCRA8JSXtFDYM3pRzD/40UZrhNbS+FEANkXJ7qpUm giCKn8hVwteWY4T4LugUK9987lU0HZ7CGfsHoSaWNwa7RBdKUoDRqi/CQ1kCfeDO XET42do+6SJhak+4wmzEfYD+K7wnlauun0/dyqCjd2+JP0bln/MIY5r8JCN1GiYS YSAAKoZqAfG1bC3HmxELI9min09GPT+tzw0PAyVJipRtfE+ykZXoCytu0GWU5jB+ VBI6SGmqMPd/c/7JfJV8KP8R0Mn3etA3hbOCx7YDL6cUmbepWtNPV8dLeTwofrpa 01uqN83PpbbSYr96QdXXa7Ov105hQH7e8jmr9+7jTpd3f9U7+GwsxxqDR1KDHLgn pUGZneoTDTkJugfXM28A0VoVB3eyJYPCLE9QQ/HXpChXc62NOQV5jcECgLiUDujH hVbeGEG0KViQlhMUfI3vIfTaIjEALDcNw5bxVUCqg8vdO6UtTXqqWdaS4Xgne8HB KeCu5xXngXEZjIgidZkmIC15FD60B19JdQz2WR+6BDCw8Ajm9iPWlj+ftZztuX/S cFSUZ05BPbTkBzAHG4GBvjXTdwsxX2acGBNtdETOQAxhkoRcug0Pn+BmrZQLqkm5 mPKPW9FFxIkkgeK/ZdA4uIEwDZX/LQlnrX129XGt7DVr+yDNKekaVGfLL8x8alT1 3v0Ni/nntc6QtZDB88OIzA== =vAf/ -----END PGP SIGNATURE----- Merge tag 'pull-target-arm-20240430' of https://git.linaro.org/people/pmaydell/qemu-arm into staging target-arm queue: * hw/core/clock: allow clock_propagate on child clocks * hvf: arm: Remove unused PL1_WRITE_MASK define * target/arm: Restrict translation disabled alignment check to VMSA * docs/system/arm/emulation.rst: Add missing implemented features * target/arm: Enable FEAT_CSV2_3, FEAT_ETS2, FEAT_Spec_FPACC for 'max' * tests/avocado: update sunxi kernel from armbian to 6.6.16 * target/arm: Make new CPUs default to 1GHz generic timer * hw/dmax/xlnx_dpdma: fix handling of address_extension descriptor fields * hw/char/stm32l4x5_usart: Fix memory corruption by adding correct class_size * hw/arm/npcm7xx: Store derivative OTP fuse key in little endian * hw/arm: Add DM163 display to B-L475E-IOT01A board # -----BEGIN PGP SIGNATURE----- # # iQJNBAABCAA3FiEE4aXFk81BneKOgxXPPCUl7RQ2DN4FAmYxILcZHHBldGVyLm1h # eWRlbGxAbGluYXJvLm9yZwAKCRA8JSXtFDYM3pRzD/40UZrhNbS+FEANkXJ7qpUm # giCKn8hVwteWY4T4LugUK9987lU0HZ7CGfsHoSaWNwa7RBdKUoDRqi/CQ1kCfeDO # XET42do+6SJhak+4wmzEfYD+K7wnlauun0/dyqCjd2+JP0bln/MIY5r8JCN1GiYS # YSAAKoZqAfG1bC3HmxELI9min09GPT+tzw0PAyVJipRtfE+ykZXoCytu0GWU5jB+ # VBI6SGmqMPd/c/7JfJV8KP8R0Mn3etA3hbOCx7YDL6cUmbepWtNPV8dLeTwofrpa # 01uqN83PpbbSYr96QdXXa7Ov105hQH7e8jmr9+7jTpd3f9U7+GwsxxqDR1KDHLgn # pUGZneoTDTkJugfXM28A0VoVB3eyJYPCLE9QQ/HXpChXc62NOQV5jcECgLiUDujH # hVbeGEG0KViQlhMUfI3vIfTaIjEALDcNw5bxVUCqg8vdO6UtTXqqWdaS4Xgne8HB # KeCu5xXngXEZjIgidZkmIC15FD60B19JdQz2WR+6BDCw8Ajm9iPWlj+ftZztuX/S # cFSUZ05BPbTkBzAHG4GBvjXTdwsxX2acGBNtdETOQAxhkoRcug0Pn+BmrZQLqkm5 # mPKPW9FFxIkkgeK/ZdA4uIEwDZX/LQlnrX129XGt7DVr+yDNKekaVGfLL8x8alT1 # 3v0Ni/nntc6QtZDB88OIzA== # =vAf/ # -----END PGP SIGNATURE----- # gpg: Signature made Tue 30 Apr 2024 09:47:51 AM PDT # gpg: using RSA key E1A5C593CD419DE28E8315CF3C2525ED14360CDE # gpg: issuer "peter.maydell@linaro.org" # gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" [full] # gpg: aka "Peter Maydell <pmaydell@gmail.com>" [full] # gpg: aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>" [full] # gpg: aka "Peter Maydell <peter@archaic.org.uk>" [unknown] * tag 'pull-target-arm-20240430' of https://git.linaro.org/people/pmaydell/qemu-arm: (21 commits) tests/qtest : Add testcase for DM163 hw/arm : Connect DM163 to B-L475E-IOT01A hw/arm : Create Bl475eMachineState hw/arm : Pass STM32L4x5 SYSCFG gpios to STM32L4x5 SoC hw/display : Add device DM163 hw/arm/npcm7xx: Store derivative OTP fuse key in little endian hw/char/stm32l4x5_usart: Fix memory corruption by adding correct class_size hw/dmax/xlnx_dpdma: fix handling of address_extension descriptor fields target/arm: Default to 1GHz cntfrq for 'max' and new CPUs hw/watchdog/sbsa_gwdt: Make watchdog timer frequency a QOM property hw/arm/sbsa-ref: Force CPU generic timer to 62.5MHz target/arm: Refactor default generic timer frequency handling tests/avocado: update sunxi kernel from armbian to 6.6.16 target/arm: Enable FEAT_Spec_FPACC for -cpu max target/arm: Implement ID_AA64MMFR3_EL1 target/arm: Enable FEAT_ETS2 for -cpu max target/arm: Enable FEAT_CSV2_3 for -cpu max docs/system/arm/emulation.rst: Add missing implemented features target/arm: Restrict translation disabled alignment check to VMSA hvf: arm: Remove PL1_WRITE_MASK ... Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
commit
9c6c079bc6
@ -12,7 +12,7 @@ USART, I2C, SPI, CAN and USB OTG, as well as a variety of sensors.
|
||||
Supported devices
|
||||
"""""""""""""""""
|
||||
|
||||
Currently B-L475E-IOT01A machine's only supports the following devices:
|
||||
Currently B-L475E-IOT01A machines support the following devices:
|
||||
|
||||
- Cortex-M4F based STM32L4x5 SoC
|
||||
- STM32L4x5 EXTI (Extended interrupts and events controller)
|
||||
@ -20,6 +20,7 @@ Currently B-L475E-IOT01A machine's only supports the following devices:
|
||||
- STM32L4x5 RCC (Reset and clock control)
|
||||
- STM32L4x5 GPIOs (General-purpose I/Os)
|
||||
- STM32L4x5 USARTs, UARTs and LPUART (Serial ports)
|
||||
- optional 8x8 led display (based on DM163 driver)
|
||||
|
||||
Missing devices
|
||||
"""""""""""""""
|
||||
|
@ -8,36 +8,60 @@ Armv8 versions of the A-profile architecture. It also has support for
|
||||
the following architecture extensions:
|
||||
|
||||
- FEAT_AA32BF16 (AArch32 BFloat16 instructions)
|
||||
- FEAT_AA32EL0 (Support for AArch32 at EL0)
|
||||
- FEAT_AA32EL1 (Support for AArch32 at EL1)
|
||||
- FEAT_AA32EL2 (Support for AArch32 at EL2)
|
||||
- FEAT_AA32EL3 (Support for AArch32 at EL3)
|
||||
- FEAT_AA32HPD (AArch32 hierarchical permission disables)
|
||||
- FEAT_AA32I8MM (AArch32 Int8 matrix multiplication instructions)
|
||||
- FEAT_AA64EL0 (Support for AArch64 at EL0)
|
||||
- FEAT_AA64EL1 (Support for AArch64 at EL1)
|
||||
- FEAT_AA64EL2 (Support for AArch64 at EL2)
|
||||
- FEAT_AA64EL3 (Support for AArch64 at EL3)
|
||||
- FEAT_AdvSIMD (Advanced SIMD Extension)
|
||||
- FEAT_AES (AESD and AESE instructions)
|
||||
- FEAT_Armv9_Crypto (Armv9 Cryptographic Extension)
|
||||
- FEAT_ASID16 (16 bit ASID)
|
||||
- FEAT_BBM at level 2 (Translation table break-before-make levels)
|
||||
- FEAT_BF16 (AArch64 BFloat16 instructions)
|
||||
- FEAT_BTI (Branch Target Identification)
|
||||
- FEAT_CCIDX (Extended cache index)
|
||||
- FEAT_CRC32 (CRC32 instructions)
|
||||
- FEAT_Crypto (Cryptographic Extension)
|
||||
- FEAT_CSV2 (Cache speculation variant 2)
|
||||
- FEAT_CSV2_1p1 (Cache speculation variant 2, version 1.1)
|
||||
- FEAT_CSV2_1p2 (Cache speculation variant 2, version 1.2)
|
||||
- FEAT_CSV2_2 (Cache speculation variant 2, version 2)
|
||||
- FEAT_CSV2_3 (Cache speculation variant 2, version 3)
|
||||
- FEAT_CSV3 (Cache speculation variant 3)
|
||||
- FEAT_DGH (Data gathering hint)
|
||||
- FEAT_DIT (Data Independent Timing instructions)
|
||||
- FEAT_DPB (DC CVAP instruction)
|
||||
- FEAT_DPB2 (DC CVADP instruction)
|
||||
- FEAT_Debugv8p1 (Debug with VHE)
|
||||
- FEAT_Debugv8p2 (Debug changes for v8.2)
|
||||
- FEAT_Debugv8p4 (Debug changes for v8.4)
|
||||
- FEAT_DotProd (Advanced SIMD dot product instructions)
|
||||
- FEAT_DoubleFault (Double Fault Extension)
|
||||
- FEAT_E0PD (Preventing EL0 access to halves of address maps)
|
||||
- FEAT_ECV (Enhanced Counter Virtualization)
|
||||
- FEAT_EL0 (Support for execution at EL0)
|
||||
- FEAT_EL1 (Support for execution at EL1)
|
||||
- FEAT_EL2 (Support for execution at EL2)
|
||||
- FEAT_EL3 (Support for execution at EL3)
|
||||
- FEAT_EPAC (Enhanced pointer authentication)
|
||||
- FEAT_ETS (Enhanced Translation Synchronization)
|
||||
- FEAT_ETS2 (Enhanced Translation Synchronization)
|
||||
- FEAT_EVT (Enhanced Virtualization Traps)
|
||||
- FEAT_F32MM (Single-precision Matrix Multiplication)
|
||||
- FEAT_F64MM (Double-precision Matrix Multiplication)
|
||||
- FEAT_FCMA (Floating-point complex number instructions)
|
||||
- FEAT_FGT (Fine-Grained Traps)
|
||||
- FEAT_FHM (Floating-point half-precision multiplication instructions)
|
||||
- FEAT_FP (Floating Point extensions)
|
||||
- FEAT_FP16 (Half-precision floating-point data processing)
|
||||
- FEAT_FPAC (Faulting on AUT* instructions)
|
||||
- FEAT_FPACCOMBINE (Faulting on combined pointer authentication instructions)
|
||||
- FEAT_FPACC_SPEC (Speculative behavior of combined pointer authentication instructions)
|
||||
- FEAT_FRINTTS (Floating-point to integer instructions)
|
||||
- FEAT_FlagM (Flag manipulation instructions v2)
|
||||
- FEAT_FlagM2 (Enhancements to flag manipulation instructions)
|
||||
@ -60,10 +84,13 @@ the following architecture extensions:
|
||||
- FEAT_LSE (Large System Extensions)
|
||||
- FEAT_LSE2 (Large System Extensions v2)
|
||||
- FEAT_LVA (Large Virtual Address space)
|
||||
- FEAT_MixedEnd (Mixed-endian support)
|
||||
- FEAT_MixdEndEL0 (Mixed-endian support at EL0)
|
||||
- FEAT_MOPS (Standardization of memory operations)
|
||||
- FEAT_MTE (Memory Tagging Extension)
|
||||
- FEAT_MTE2 (Memory Tagging Extension)
|
||||
- FEAT_MTE3 (MTE Asymmetric Fault Handling)
|
||||
- FEAT_MTE_ASYM_FAULT (Memory tagging asymmetric faults)
|
||||
- FEAT_NMI (Non-maskable Interrupt)
|
||||
- FEAT_NV (Nested Virtualization)
|
||||
- FEAT_NV2 (Enhanced nested virtualization support)
|
||||
@ -76,6 +103,7 @@ the following architecture extensions:
|
||||
- FEAT_PAuth (Pointer authentication)
|
||||
- FEAT_PAuth2 (Enhancements to pointer authentication)
|
||||
- FEAT_PMULL (PMULL, PMULL2 instructions)
|
||||
- FEAT_PMUv3 (PMU extension version 3)
|
||||
- FEAT_PMUv3p1 (PMU Extensions v3.1)
|
||||
- FEAT_PMUv3p4 (PMU Extensions v3.4)
|
||||
- FEAT_PMUv3p5 (PMU Extensions v3.5)
|
||||
@ -97,8 +125,18 @@ the following architecture extensions:
|
||||
- FEAT_SME_FA64 (Full A64 instruction set in Streaming SVE mode)
|
||||
- FEAT_SME_F64F64 (Double-precision floating-point outer product instructions)
|
||||
- FEAT_SME_I16I64 (16-bit to 64-bit integer widening outer product instructions)
|
||||
- FEAT_SVE (Scalable Vector Extension)
|
||||
- FEAT_SVE_AES (Scalable Vector AES instructions)
|
||||
- FEAT_SVE_BitPerm (Scalable Vector Bit Permutes instructions)
|
||||
- FEAT_SVE_PMULL128 (Scalable Vector PMULL instructions)
|
||||
- FEAT_SVE_SHA3 (Scalable Vector SHA3 instructions)
|
||||
- FEAT_SVE_SM4 (Scalable Vector SM4 instructions)
|
||||
- FEAT_SVE2 (Scalable Vector Extension version 2)
|
||||
- FEAT_SPECRES (Speculation restriction instructions)
|
||||
- FEAT_SSBS (Speculative Store Bypass Safe)
|
||||
- FEAT_TGran16K (Support for 16KB memory translation granule size at stage 1)
|
||||
- FEAT_TGran4K (Support for 4KB memory translation granule size at stage 1)
|
||||
- FEAT_TGran64K (Support for 64KB memory translation granule size at stage 1)
|
||||
- FEAT_TIDCP1 (EL0 use of IMPLEMENTATION DEFINED functionality)
|
||||
- FEAT_TLBIOS (TLB invalidate instructions in Outer Shareable domain)
|
||||
- FEAT_TLBIRANGE (TLB invalidate range instructions)
|
||||
@ -109,8 +147,6 @@ the following architecture extensions:
|
||||
- FEAT_VHE (Virtualization Host Extensions)
|
||||
- FEAT_VMID16 (16-bit VMID)
|
||||
- FEAT_XNX (Translation table stage 2 Unprivileged Execute-never)
|
||||
- SVE (The Scalable Vector Extension)
|
||||
- SVE2 (The Scalable Vector Extension v2)
|
||||
|
||||
For information on the specifics of these extensions, please refer
|
||||
to the `Armv8-A Arm Architecture Reference Manual
|
||||
|
@ -468,6 +468,7 @@ config B_L475E_IOT01A
|
||||
default y
|
||||
depends on TCG && ARM
|
||||
select STM32L4X5_SOC
|
||||
imply DM163
|
||||
|
||||
config STM32L4X5_SOC
|
||||
bool
|
||||
|
@ -2,8 +2,8 @@
|
||||
* 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>
|
||||
* Copyright (c) 2023-2024 Arnaud Minier <arnaud.minier@telecom-paris.fr>
|
||||
* Copyright (c) 2023-2024 Inès Varhol <ines.varhol@telecom-paris.fr>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*
|
||||
@ -27,38 +27,111 @@
|
||||
#include "hw/boards.h"
|
||||
#include "hw/qdev-properties.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "hw/arm/stm32l4x5_soc.h"
|
||||
#include "hw/arm/boot.h"
|
||||
#include "hw/core/split-irq.h"
|
||||
#include "hw/arm/stm32l4x5_soc.h"
|
||||
#include "hw/gpio/stm32l4x5_gpio.h"
|
||||
#include "hw/display/dm163.h"
|
||||
|
||||
/* B-L475E-IOT01A implementation is derived from netduinoplus2 */
|
||||
/* B-L475E-IOT01A implementation is inspired from netduinoplus2 and arduino */
|
||||
|
||||
static void b_l475e_iot01a_init(MachineState *machine)
|
||||
/*
|
||||
* There are actually 14 input pins in the DM163 device.
|
||||
* Here the DM163 input pin EN isn't connected to the STM32L4x5
|
||||
* GPIOs as the IM120417002 colors shield doesn't actually use
|
||||
* this pin to drive the RGB matrix.
|
||||
*/
|
||||
#define NUM_DM163_INPUTS 13
|
||||
|
||||
static const unsigned dm163_input[NUM_DM163_INPUTS] = {
|
||||
1 * GPIO_NUM_PINS + 2, /* ROW0 PB2 */
|
||||
0 * GPIO_NUM_PINS + 15, /* ROW1 PA15 */
|
||||
0 * GPIO_NUM_PINS + 2, /* ROW2 PA2 */
|
||||
0 * GPIO_NUM_PINS + 7, /* ROW3 PA7 */
|
||||
0 * GPIO_NUM_PINS + 6, /* ROW4 PA6 */
|
||||
0 * GPIO_NUM_PINS + 5, /* ROW5 PA5 */
|
||||
1 * GPIO_NUM_PINS + 0, /* ROW6 PB0 */
|
||||
0 * GPIO_NUM_PINS + 3, /* ROW7 PA3 */
|
||||
0 * GPIO_NUM_PINS + 4, /* SIN (SDA) PA4 */
|
||||
1 * GPIO_NUM_PINS + 1, /* DCK (SCK) PB1 */
|
||||
2 * GPIO_NUM_PINS + 3, /* RST_B (RST) PC3 */
|
||||
2 * GPIO_NUM_PINS + 4, /* LAT_B (LAT) PC4 */
|
||||
2 * GPIO_NUM_PINS + 5, /* SELBK (SB) PC5 */
|
||||
};
|
||||
|
||||
#define TYPE_B_L475E_IOT01A MACHINE_TYPE_NAME("b-l475e-iot01a")
|
||||
OBJECT_DECLARE_SIMPLE_TYPE(Bl475eMachineState, B_L475E_IOT01A)
|
||||
|
||||
typedef struct Bl475eMachineState {
|
||||
MachineState parent_obj;
|
||||
|
||||
Stm32l4x5SocState soc;
|
||||
SplitIRQ gpio_splitters[NUM_DM163_INPUTS];
|
||||
DM163State dm163;
|
||||
} Bl475eMachineState;
|
||||
|
||||
static void bl475e_init(MachineState *machine)
|
||||
{
|
||||
Bl475eMachineState *s = B_L475E_IOT01A(machine);
|
||||
const Stm32l4x5SocClass *sc;
|
||||
DeviceState *dev;
|
||||
DeviceState *dev, *gpio_out_splitter;
|
||||
unsigned gpio, pin;
|
||||
|
||||
dev = qdev_new(TYPE_STM32L4X5XG_SOC);
|
||||
object_property_add_child(OBJECT(machine), "soc", OBJECT(dev));
|
||||
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
|
||||
object_initialize_child(OBJECT(machine), "soc", &s->soc,
|
||||
TYPE_STM32L4X5XG_SOC);
|
||||
sysbus_realize(SYS_BUS_DEVICE(&s->soc), &error_fatal);
|
||||
|
||||
sc = STM32L4X5_SOC_GET_CLASS(dev);
|
||||
armv7m_load_kernel(ARM_CPU(first_cpu),
|
||||
machine->kernel_filename,
|
||||
0, sc->flash_size);
|
||||
sc = STM32L4X5_SOC_GET_CLASS(&s->soc);
|
||||
armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, 0,
|
||||
sc->flash_size);
|
||||
|
||||
if (object_class_by_name(TYPE_DM163)) {
|
||||
object_initialize_child(OBJECT(machine), "dm163",
|
||||
&s->dm163, TYPE_DM163);
|
||||
dev = DEVICE(&s->dm163);
|
||||
qdev_realize(dev, NULL, &error_abort);
|
||||
|
||||
for (unsigned i = 0; i < NUM_DM163_INPUTS; i++) {
|
||||
object_initialize_child(OBJECT(machine), "gpio-out-splitters[*]",
|
||||
&s->gpio_splitters[i], TYPE_SPLIT_IRQ);
|
||||
gpio_out_splitter = DEVICE(&s->gpio_splitters[i]);
|
||||
qdev_prop_set_uint32(gpio_out_splitter, "num-lines", 2);
|
||||
qdev_realize(gpio_out_splitter, NULL, &error_fatal);
|
||||
|
||||
qdev_connect_gpio_out(gpio_out_splitter, 0,
|
||||
qdev_get_gpio_in(DEVICE(&s->soc), dm163_input[i]));
|
||||
qdev_connect_gpio_out(gpio_out_splitter, 1,
|
||||
qdev_get_gpio_in(dev, i));
|
||||
gpio = dm163_input[i] / GPIO_NUM_PINS;
|
||||
pin = dm163_input[i] % GPIO_NUM_PINS;
|
||||
qdev_connect_gpio_out(DEVICE(&s->soc.gpio[gpio]), pin,
|
||||
qdev_get_gpio_in(DEVICE(gpio_out_splitter), 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void b_l475e_iot01a_machine_init(MachineClass *mc)
|
||||
static void bl475e_machine_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
MachineClass *mc = MACHINE_CLASS(oc);
|
||||
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->init = bl475e_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)
|
||||
static const TypeInfo bl475e_machine_type[] = {
|
||||
{
|
||||
.name = TYPE_B_L475E_IOT01A,
|
||||
.parent = TYPE_MACHINE,
|
||||
.instance_size = sizeof(Bl475eMachineState),
|
||||
.class_init = bl475e_machine_init,
|
||||
}
|
||||
};
|
||||
|
||||
DEFINE_TYPES(bl475e_machine_type)
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "hw/qdev-clock.h"
|
||||
#include "hw/qdev-properties.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qemu/bswap.h"
|
||||
#include "qemu/units.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "target/arm/cpu-qom.h"
|
||||
@ -386,7 +387,7 @@ static void npcm7xx_init_fuses(NPCM7xxState *s)
|
||||
* The initial mask of disabled modules indicates the chip derivative (e.g.
|
||||
* NPCM750 or NPCM730).
|
||||
*/
|
||||
value = tswap32(nc->disabled_modules);
|
||||
value = cpu_to_le32(nc->disabled_modules);
|
||||
npcm7xx_otp_array_write(&s->fuse_array, &value, NPCM7XX_FUSE_DERIVATIVE,
|
||||
sizeof(value));
|
||||
}
|
||||
|
@ -60,6 +60,19 @@
|
||||
#define NUM_SMMU_IRQS 4
|
||||
#define NUM_SATA_PORTS 6
|
||||
|
||||
/*
|
||||
* Generic timer frequency in Hz (which drives both the CPU generic timers
|
||||
* and the SBSA watchdog-timer). Older versions of the TF-A firmware
|
||||
* typically used with sbsa-ref (including the binaries in our Avocado test
|
||||
* Aarch64SbsarefMachine.test_sbsaref_alpine_linux_max_pauth_impdef
|
||||
* assume it is this value.
|
||||
*
|
||||
* TODO: this value is not architecturally correct for an Armv8.6 or
|
||||
* better CPU, so we should move to 1GHz once the TF-A fix above has
|
||||
* made it into a release and into our Avocado test.
|
||||
*/
|
||||
#define SBSA_GTIMER_HZ 62500000
|
||||
|
||||
enum {
|
||||
SBSA_FLASH,
|
||||
SBSA_MEM,
|
||||
@ -530,6 +543,7 @@ static void create_wdt(const SBSAMachineState *sms)
|
||||
SysBusDevice *s = SYS_BUS_DEVICE(dev);
|
||||
int irq = sbsa_ref_irqmap[SBSA_GWDT_WS0];
|
||||
|
||||
qdev_prop_set_uint64(dev, "clock-frequency", SBSA_GTIMER_HZ);
|
||||
sysbus_realize_and_unref(s, &error_fatal);
|
||||
sysbus_mmio_map(s, 0, rbase);
|
||||
sysbus_mmio_map(s, 1, cbase);
|
||||
@ -767,6 +781,8 @@ static void sbsa_ref_init(MachineState *machine)
|
||||
&error_abort);
|
||||
}
|
||||
|
||||
object_property_set_int(cpuobj, "cntfrq", SBSA_GTIMER_HZ, &error_abort);
|
||||
|
||||
object_property_set_link(cpuobj, "memory", OBJECT(sysmem),
|
||||
&error_abort);
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
/*
|
||||
* STM32L4x5 SoC family
|
||||
*
|
||||
* Copyright (c) 2023 Arnaud Minier <arnaud.minier@telecom-paris.fr>
|
||||
* Copyright (c) 2023 Inès Varhol <ines.varhol@telecom-paris.fr>
|
||||
* Copyright (c) 2023-2024 Arnaud Minier <arnaud.minier@telecom-paris.fr>
|
||||
* Copyright (c) 2023-2024 Inès Varhol <ines.varhol@telecom-paris.fr>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*
|
||||
@ -250,6 +250,8 @@ static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
|
||||
}
|
||||
}
|
||||
|
||||
qdev_pass_gpios(DEVICE(&s->syscfg), dev_soc, NULL);
|
||||
|
||||
/* EXTI device */
|
||||
busdev = SYS_BUS_DEVICE(&s->exti);
|
||||
if (!sysbus_realize(busdev, errp)) {
|
||||
|
@ -108,7 +108,6 @@ static void clock_propagate_period(Clock *clk, bool call_callbacks)
|
||||
|
||||
void clock_propagate(Clock *clk)
|
||||
{
|
||||
assert(clk->source == NULL);
|
||||
trace_clock_propagate(CLOCK_PATH(clk));
|
||||
clock_propagate_period(clk, true);
|
||||
}
|
||||
|
@ -33,7 +33,9 @@
|
||||
#include "hw/virtio/virtio-iommu.h"
|
||||
#include "audio/audio.h"
|
||||
|
||||
GlobalProperty hw_compat_9_0[] = {};
|
||||
GlobalProperty hw_compat_9_0[] = {
|
||||
{"arm-cpu", "backcompat-cntfrq", "true" },
|
||||
};
|
||||
const size_t hw_compat_9_0_len = G_N_ELEMENTS(hw_compat_9_0);
|
||||
|
||||
GlobalProperty hw_compat_8_2[] = {
|
||||
|
@ -140,3 +140,6 @@ config XLNX_DISPLAYPORT
|
||||
bool
|
||||
# defaults to "N", enabled by specific boards
|
||||
depends on PIXMAN
|
||||
|
||||
config DM163
|
||||
bool
|
||||
|
349
hw/display/dm163.c
Normal file
349
hw/display/dm163.c
Normal file
@ -0,0 +1,349 @@
|
||||
/*
|
||||
* QEMU DM163 8x3-channel constant current led driver
|
||||
* driving columns of associated 8x8 RGB matrix.
|
||||
*
|
||||
* Copyright (C) 2024 Samuel Tardieu <sam@rfc1149.net>
|
||||
* Copyright (C) 2024 Arnaud Minier <arnaud.minier@telecom-paris.fr>
|
||||
* Copyright (C) 2024 Inès Varhol <ines.varhol@telecom-paris.fr>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
/*
|
||||
* The reference used for the DM163 is the following :
|
||||
* http://www.siti.com.tw/product/spec/LED/DM163.pdf
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qapi/error.h"
|
||||
#include "migration/vmstate.h"
|
||||
#include "hw/irq.h"
|
||||
#include "hw/qdev-properties.h"
|
||||
#include "hw/display/dm163.h"
|
||||
#include "ui/console.h"
|
||||
#include "trace.h"
|
||||
|
||||
#define LED_SQUARE_SIZE 100
|
||||
/* Number of frames a row stays visible after being turned off. */
|
||||
#define ROW_PERSISTENCE 3
|
||||
#define TURNED_OFF_ROW (COLOR_BUFFER_SIZE - 1)
|
||||
|
||||
static const VMStateDescription vmstate_dm163 = {
|
||||
.name = TYPE_DM163,
|
||||
.version_id = 1,
|
||||
.minimum_version_id = 1,
|
||||
.fields = (const VMStateField[]) {
|
||||
VMSTATE_UINT64_ARRAY(bank0_shift_register, DM163State, 3),
|
||||
VMSTATE_UINT64_ARRAY(bank1_shift_register, DM163State, 3),
|
||||
VMSTATE_UINT16_ARRAY(latched_outputs, DM163State, DM163_NUM_LEDS),
|
||||
VMSTATE_UINT16_ARRAY(outputs, DM163State, DM163_NUM_LEDS),
|
||||
VMSTATE_UINT8(dck, DM163State),
|
||||
VMSTATE_UINT8(en_b, DM163State),
|
||||
VMSTATE_UINT8(lat_b, DM163State),
|
||||
VMSTATE_UINT8(rst_b, DM163State),
|
||||
VMSTATE_UINT8(selbk, DM163State),
|
||||
VMSTATE_UINT8(sin, DM163State),
|
||||
VMSTATE_UINT8(activated_rows, DM163State),
|
||||
VMSTATE_UINT32_2DARRAY(buffer, DM163State, COLOR_BUFFER_SIZE,
|
||||
RGB_MATRIX_NUM_COLS),
|
||||
VMSTATE_UINT8(last_buffer_idx, DM163State),
|
||||
VMSTATE_UINT8_ARRAY(buffer_idx_of_row, DM163State, RGB_MATRIX_NUM_ROWS),
|
||||
VMSTATE_UINT8_ARRAY(row_persistence_delay, DM163State,
|
||||
RGB_MATRIX_NUM_ROWS),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
|
||||
static void dm163_reset_hold(Object *obj, ResetType type)
|
||||
{
|
||||
DM163State *s = DM163(obj);
|
||||
|
||||
s->sin = 0;
|
||||
s->dck = 0;
|
||||
s->rst_b = 0;
|
||||
/* Ensuring the first falling edge of lat_b isn't missed */
|
||||
s->lat_b = 1;
|
||||
s->selbk = 0;
|
||||
s->en_b = 0;
|
||||
/* Reset stops the PWM, not the shift and latched registers. */
|
||||
memset(s->outputs, 0, sizeof(s->outputs));
|
||||
|
||||
s->activated_rows = 0;
|
||||
s->redraw = 0;
|
||||
trace_dm163_redraw(s->redraw);
|
||||
for (unsigned i = 0; i < COLOR_BUFFER_SIZE; i++) {
|
||||
memset(s->buffer[i], 0, sizeof(s->buffer[0]));
|
||||
}
|
||||
s->last_buffer_idx = 0;
|
||||
memset(s->buffer_idx_of_row, TURNED_OFF_ROW, sizeof(s->buffer_idx_of_row));
|
||||
memset(s->row_persistence_delay, 0, sizeof(s->row_persistence_delay));
|
||||
}
|
||||
|
||||
static void dm163_dck_gpio_handler(void *opaque, int line, int new_state)
|
||||
{
|
||||
DM163State *s = opaque;
|
||||
|
||||
if (new_state && !s->dck) {
|
||||
/*
|
||||
* On raising dck, sample selbk to get the bank to use, and
|
||||
* sample sin for the bit to enter into the bank shift buffer.
|
||||
*/
|
||||
uint64_t *sb =
|
||||
s->selbk ? s->bank1_shift_register : s->bank0_shift_register;
|
||||
/* Output the outgoing bit on sout */
|
||||
const bool sout = (s->selbk ? sb[2] & MAKE_64BIT_MASK(63, 1) :
|
||||
sb[2] & MAKE_64BIT_MASK(15, 1)) != 0;
|
||||
qemu_set_irq(s->sout, sout);
|
||||
/* Enter sin into the shift buffer */
|
||||
sb[2] = (sb[2] << 1) | ((sb[1] >> 63) & 1);
|
||||
sb[1] = (sb[1] << 1) | ((sb[0] >> 63) & 1);
|
||||
sb[0] = (sb[0] << 1) | s->sin;
|
||||
}
|
||||
|
||||
s->dck = new_state;
|
||||
trace_dm163_dck(new_state);
|
||||
}
|
||||
|
||||
static void dm163_propagate_outputs(DM163State *s)
|
||||
{
|
||||
s->last_buffer_idx = (s->last_buffer_idx + 1) % RGB_MATRIX_NUM_ROWS;
|
||||
/* Values are output when reset is high and enable is low. */
|
||||
if (s->rst_b && !s->en_b) {
|
||||
memcpy(s->outputs, s->latched_outputs, sizeof(s->outputs));
|
||||
} else {
|
||||
memset(s->outputs, 0, sizeof(s->outputs));
|
||||
}
|
||||
for (unsigned x = 0; x < RGB_MATRIX_NUM_COLS; x++) {
|
||||
/* Grouping the 3 RGB channels in a pixel value */
|
||||
const uint16_t b = extract16(s->outputs[3 * x + 0], 6, 8);
|
||||
const uint16_t g = extract16(s->outputs[3 * x + 1], 6, 8);
|
||||
const uint16_t r = extract16(s->outputs[3 * x + 2], 6, 8);
|
||||
uint32_t rgba = 0;
|
||||
|
||||
trace_dm163_channels(3 * x + 2, r);
|
||||
trace_dm163_channels(3 * x + 1, g);
|
||||
trace_dm163_channels(3 * x + 0, b);
|
||||
|
||||
rgba = deposit32(rgba, 0, 8, r);
|
||||
rgba = deposit32(rgba, 8, 8, g);
|
||||
rgba = deposit32(rgba, 16, 8, b);
|
||||
|
||||
/* Led values are sent from the last one to the first one */
|
||||
s->buffer[s->last_buffer_idx][RGB_MATRIX_NUM_COLS - x - 1] = rgba;
|
||||
}
|
||||
for (unsigned row = 0; row < RGB_MATRIX_NUM_ROWS; row++) {
|
||||
if (s->activated_rows & (1 << row)) {
|
||||
s->buffer_idx_of_row[row] = s->last_buffer_idx;
|
||||
s->redraw |= (1 << row);
|
||||
trace_dm163_redraw(s->redraw);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void dm163_en_b_gpio_handler(void *opaque, int line, int new_state)
|
||||
{
|
||||
DM163State *s = opaque;
|
||||
|
||||
s->en_b = new_state;
|
||||
dm163_propagate_outputs(s);
|
||||
trace_dm163_en_b(new_state);
|
||||
}
|
||||
|
||||
static uint8_t dm163_bank0(const DM163State *s, uint8_t led)
|
||||
{
|
||||
/*
|
||||
* Bank 0 uses 6 bits per led, so a value may be stored accross
|
||||
* two uint64_t entries.
|
||||
*/
|
||||
const uint8_t low_bit = 6 * led;
|
||||
const uint8_t low_word = low_bit / 64;
|
||||
const uint8_t high_word = (low_bit + 5) / 64;
|
||||
const uint8_t low_shift = low_bit % 64;
|
||||
|
||||
if (low_word == high_word) {
|
||||
/* Simple case: the value belongs to one entry. */
|
||||
return extract64(s->bank0_shift_register[low_word], low_shift, 6);
|
||||
}
|
||||
|
||||
const uint8_t nb_bits_in_low_word = 64 - low_shift;
|
||||
const uint8_t nb_bits_in_high_word = 6 - nb_bits_in_low_word;
|
||||
|
||||
const uint64_t bits_in_low_word = \
|
||||
extract64(s->bank0_shift_register[low_word], low_shift,
|
||||
nb_bits_in_low_word);
|
||||
const uint64_t bits_in_high_word = \
|
||||
extract64(s->bank0_shift_register[high_word], 0,
|
||||
nb_bits_in_high_word);
|
||||
uint8_t val = 0;
|
||||
|
||||
val = deposit32(val, 0, nb_bits_in_low_word, bits_in_low_word);
|
||||
val = deposit32(val, nb_bits_in_low_word, nb_bits_in_high_word,
|
||||
bits_in_high_word);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static uint8_t dm163_bank1(const DM163State *s, uint8_t led)
|
||||
{
|
||||
const uint64_t entry = s->bank1_shift_register[led / RGB_MATRIX_NUM_COLS];
|
||||
return extract64(entry, 8 * (led % RGB_MATRIX_NUM_COLS), 8);
|
||||
}
|
||||
|
||||
static void dm163_lat_b_gpio_handler(void *opaque, int line, int new_state)
|
||||
{
|
||||
DM163State *s = opaque;
|
||||
|
||||
if (s->lat_b && !new_state) {
|
||||
for (int led = 0; led < DM163_NUM_LEDS; led++) {
|
||||
s->latched_outputs[led] = dm163_bank0(s, led) * dm163_bank1(s, led);
|
||||
}
|
||||
dm163_propagate_outputs(s);
|
||||
}
|
||||
|
||||
s->lat_b = new_state;
|
||||
trace_dm163_lat_b(new_state);
|
||||
}
|
||||
|
||||
static void dm163_rst_b_gpio_handler(void *opaque, int line, int new_state)
|
||||
{
|
||||
DM163State *s = opaque;
|
||||
|
||||
s->rst_b = new_state;
|
||||
dm163_propagate_outputs(s);
|
||||
trace_dm163_rst_b(new_state);
|
||||
}
|
||||
|
||||
static void dm163_selbk_gpio_handler(void *opaque, int line, int new_state)
|
||||
{
|
||||
DM163State *s = opaque;
|
||||
|
||||
s->selbk = new_state;
|
||||
trace_dm163_selbk(new_state);
|
||||
}
|
||||
|
||||
static void dm163_sin_gpio_handler(void *opaque, int line, int new_state)
|
||||
{
|
||||
DM163State *s = opaque;
|
||||
|
||||
s->sin = new_state;
|
||||
trace_dm163_sin(new_state);
|
||||
}
|
||||
|
||||
static void dm163_rows_gpio_handler(void *opaque, int line, int new_state)
|
||||
{
|
||||
DM163State *s = opaque;
|
||||
|
||||
if (new_state) {
|
||||
s->activated_rows |= (1 << line);
|
||||
s->buffer_idx_of_row[line] = s->last_buffer_idx;
|
||||
s->redraw |= (1 << line);
|
||||
trace_dm163_redraw(s->redraw);
|
||||
} else {
|
||||
s->activated_rows &= ~(1 << line);
|
||||
s->row_persistence_delay[line] = ROW_PERSISTENCE;
|
||||
}
|
||||
trace_dm163_activated_rows(s->activated_rows);
|
||||
}
|
||||
|
||||
static void dm163_invalidate_display(void *opaque)
|
||||
{
|
||||
DM163State *s = (DM163State *)opaque;
|
||||
s->redraw = 0xFF;
|
||||
trace_dm163_redraw(s->redraw);
|
||||
}
|
||||
|
||||
static void update_row_persistence_delay(DM163State *s, unsigned row)
|
||||
{
|
||||
if (s->row_persistence_delay[row]) {
|
||||
s->row_persistence_delay[row]--;
|
||||
} else {
|
||||
/*
|
||||
* If the ROW_PERSISTENCE delay is up,
|
||||
* the row is turned off.
|
||||
*/
|
||||
s->buffer_idx_of_row[row] = TURNED_OFF_ROW;
|
||||
s->redraw |= (1 << row);
|
||||
trace_dm163_redraw(s->redraw);
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t *update_display_of_row(DM163State *s, uint32_t *dest,
|
||||
unsigned row)
|
||||
{
|
||||
for (unsigned _ = 0; _ < LED_SQUARE_SIZE; _++) {
|
||||
for (int x = 0; x < RGB_MATRIX_NUM_COLS * LED_SQUARE_SIZE; x++) {
|
||||
/* UI layer guarantees that there's 32 bits per pixel (Mar 2024) */
|
||||
*dest++ = s->buffer[s->buffer_idx_of_row[row]][x / LED_SQUARE_SIZE];
|
||||
}
|
||||
}
|
||||
|
||||
dpy_gfx_update(s->console, 0, LED_SQUARE_SIZE * row,
|
||||
RGB_MATRIX_NUM_COLS * LED_SQUARE_SIZE, LED_SQUARE_SIZE);
|
||||
s->redraw &= ~(1 << row);
|
||||
trace_dm163_redraw(s->redraw);
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
static void dm163_update_display(void *opaque)
|
||||
{
|
||||
DM163State *s = (DM163State *)opaque;
|
||||
DisplaySurface *surface = qemu_console_surface(s->console);
|
||||
uint32_t *dest;
|
||||
|
||||
dest = surface_data(surface);
|
||||
for (unsigned row = 0; row < RGB_MATRIX_NUM_ROWS; row++) {
|
||||
update_row_persistence_delay(s, row);
|
||||
if (!extract8(s->redraw, row, 1)) {
|
||||
dest += LED_SQUARE_SIZE * LED_SQUARE_SIZE * RGB_MATRIX_NUM_COLS;
|
||||
continue;
|
||||
}
|
||||
dest = update_display_of_row(s, dest, row);
|
||||
}
|
||||
}
|
||||
|
||||
static const GraphicHwOps dm163_ops = {
|
||||
.invalidate = dm163_invalidate_display,
|
||||
.gfx_update = dm163_update_display,
|
||||
};
|
||||
|
||||
static void dm163_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
DM163State *s = DM163(dev);
|
||||
|
||||
qdev_init_gpio_in(dev, dm163_rows_gpio_handler, RGB_MATRIX_NUM_ROWS);
|
||||
qdev_init_gpio_in(dev, dm163_sin_gpio_handler, 1);
|
||||
qdev_init_gpio_in(dev, dm163_dck_gpio_handler, 1);
|
||||
qdev_init_gpio_in(dev, dm163_rst_b_gpio_handler, 1);
|
||||
qdev_init_gpio_in(dev, dm163_lat_b_gpio_handler, 1);
|
||||
qdev_init_gpio_in(dev, dm163_selbk_gpio_handler, 1);
|
||||
qdev_init_gpio_in(dev, dm163_en_b_gpio_handler, 1);
|
||||
qdev_init_gpio_out_named(dev, &s->sout, "sout", 1);
|
||||
|
||||
s->console = graphic_console_init(dev, 0, &dm163_ops, s);
|
||||
qemu_console_resize(s->console, RGB_MATRIX_NUM_COLS * LED_SQUARE_SIZE,
|
||||
RGB_MATRIX_NUM_ROWS * LED_SQUARE_SIZE);
|
||||
}
|
||||
|
||||
static void dm163_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
ResettableClass *rc = RESETTABLE_CLASS(klass);
|
||||
|
||||
dc->desc = "DM163";
|
||||
dc->vmsd = &vmstate_dm163;
|
||||
dc->realize = dm163_realize;
|
||||
rc->phases.hold = dm163_reset_hold;
|
||||
set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories);
|
||||
}
|
||||
|
||||
static const TypeInfo dm163_types[] = {
|
||||
{
|
||||
.name = TYPE_DM163,
|
||||
.parent = TYPE_DEVICE,
|
||||
.instance_size = sizeof(DM163State),
|
||||
.class_init = dm163_class_init
|
||||
}
|
||||
};
|
||||
|
||||
DEFINE_TYPES(dm163_types)
|
@ -38,6 +38,7 @@ system_ss.add(when: 'CONFIG_NEXTCUBE', if_true: files('next-fb.c'))
|
||||
|
||||
system_ss.add(when: 'CONFIG_VGA', if_true: files('vga.c'))
|
||||
system_ss.add(when: 'CONFIG_VIRTIO', if_true: files('virtio-dmabuf.c'))
|
||||
system_ss.add(when: 'CONFIG_DM163', if_true: files('dm163.c'))
|
||||
|
||||
if (config_all_devices.has_key('CONFIG_VGA_CIRRUS') or
|
||||
config_all_devices.has_key('CONFIG_VGA_PCI') or
|
||||
|
@ -177,3 +177,17 @@ macfb_ctrl_write(uint64_t addr, uint64_t value, unsigned int size) "addr 0x%"PRI
|
||||
macfb_sense_read(uint32_t value) "video sense: 0x%"PRIx32
|
||||
macfb_sense_write(uint32_t value) "video sense: 0x%"PRIx32
|
||||
macfb_update_mode(uint32_t width, uint32_t height, uint8_t depth) "setting mode to width %"PRId32 " height %"PRId32 " size %d"
|
||||
|
||||
# dm163.c
|
||||
dm163_redraw(uint8_t redraw) "0x%02x"
|
||||
dm163_dck(unsigned new_state) "dck : %u"
|
||||
dm163_en_b(unsigned new_state) "en_b : %u"
|
||||
dm163_rst_b(unsigned new_state) "rst_b : %u"
|
||||
dm163_lat_b(unsigned new_state) "lat_b : %u"
|
||||
dm163_sin(unsigned new_state) "sin : %u"
|
||||
dm163_selbk(unsigned new_state) "selbk : %u"
|
||||
dm163_activated_rows(int new_state) "Activated rows : 0x%" PRIx32 ""
|
||||
dm163_bits_ppi(unsigned dest_width) "dest_width : %u"
|
||||
dm163_leds(int led, uint32_t value) "led %d: 0x%x"
|
||||
dm163_channels(int channel, uint8_t value) "channel %d: 0x%x"
|
||||
dm163_refresh_rate(uint32_t rr) "refresh rate %d"
|
||||
|
@ -175,24 +175,24 @@ static uint64_t xlnx_dpdma_desc_get_source_address(DPDMADescriptor *desc,
|
||||
|
||||
switch (frag) {
|
||||
case 0:
|
||||
addr = desc->source_address
|
||||
+ (extract32(desc->address_extension, 16, 12) << 20);
|
||||
addr = (uint64_t)desc->source_address
|
||||
+ (extract64(desc->address_extension, 16, 16) << 32);
|
||||
break;
|
||||
case 1:
|
||||
addr = desc->source_address2
|
||||
+ (extract32(desc->address_extension_23, 0, 12) << 8);
|
||||
addr = (uint64_t)desc->source_address2
|
||||
+ (extract64(desc->address_extension_23, 0, 16) << 32);
|
||||
break;
|
||||
case 2:
|
||||
addr = desc->source_address3
|
||||
+ (extract32(desc->address_extension_23, 16, 12) << 20);
|
||||
addr = (uint64_t)desc->source_address3
|
||||
+ (extract64(desc->address_extension_23, 16, 16) << 32);
|
||||
break;
|
||||
case 3:
|
||||
addr = desc->source_address4
|
||||
+ (extract32(desc->address_extension_45, 0, 12) << 8);
|
||||
addr = (uint64_t)desc->source_address4
|
||||
+ (extract64(desc->address_extension_45, 0, 16) << 32);
|
||||
break;
|
||||
case 4:
|
||||
addr = desc->source_address5
|
||||
+ (extract32(desc->address_extension_45, 16, 12) << 20);
|
||||
addr = (uint64_t)desc->source_address5
|
||||
+ (extract64(desc->address_extension_45, 16, 16) << 32);
|
||||
break;
|
||||
default:
|
||||
addr = 0;
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "sysemu/reset.h"
|
||||
#include "sysemu/watchdog.h"
|
||||
#include "hw/qdev-properties.h"
|
||||
#include "hw/watchdog/sbsa_gwdt.h"
|
||||
#include "qemu/timer.h"
|
||||
#include "migration/vmstate.h"
|
||||
@ -109,7 +110,7 @@ static void sbsa_gwdt_update_timer(SBSA_GWDTState *s, WdtRefreshType rtype)
|
||||
timeout = s->woru;
|
||||
timeout <<= 32;
|
||||
timeout |= s->worl;
|
||||
timeout = muldiv64(timeout, NANOSECONDS_PER_SECOND, SBSA_TIMER_FREQ);
|
||||
timeout = muldiv64(timeout, NANOSECONDS_PER_SECOND, s->freq);
|
||||
timeout += qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
|
||||
|
||||
if ((rtype == EXPLICIT_REFRESH) || ((rtype == TIMEOUT_REFRESH) &&
|
||||
@ -261,6 +262,17 @@ static void wdt_sbsa_gwdt_realize(DeviceState *dev, Error **errp)
|
||||
dev);
|
||||
}
|
||||
|
||||
static Property wdt_sbsa_gwdt_props[] = {
|
||||
/*
|
||||
* Timer frequency in Hz. This must match the frequency used by
|
||||
* the CPU's generic timer. Default 62.5Hz matches QEMU's legacy
|
||||
* CPU timer frequency default.
|
||||
*/
|
||||
DEFINE_PROP_UINT64("clock-frequency", struct SBSA_GWDTState, freq,
|
||||
62500000),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
static void wdt_sbsa_gwdt_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
@ -271,6 +283,7 @@ static void wdt_sbsa_gwdt_class_init(ObjectClass *klass, void *data)
|
||||
set_bit(DEVICE_CATEGORY_WATCHDOG, dc->categories);
|
||||
dc->vmsd = &vmstate_sbsa_gwdt;
|
||||
dc->desc = "SBSA-compliant generic watchdog device";
|
||||
device_class_set_props(dc, wdt_sbsa_gwdt_props);
|
||||
}
|
||||
|
||||
static const TypeInfo wdt_sbsa_gwdt_info = {
|
||||
|
59
include/hw/display/dm163.h
Normal file
59
include/hw/display/dm163.h
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* QEMU DM163 8x3-channel constant current led driver
|
||||
* driving columns of associated 8x8 RGB matrix.
|
||||
*
|
||||
* Copyright (C) 2024 Samuel Tardieu <sam@rfc1149.net>
|
||||
* Copyright (C) 2024 Arnaud Minier <arnaud.minier@telecom-paris.fr>
|
||||
* Copyright (C) 2024 Inès Varhol <ines.varhol@telecom-paris.fr>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef HW_DISPLAY_DM163_H
|
||||
#define HW_DISPLAY_DM163_H
|
||||
|
||||
#include "qom/object.h"
|
||||
#include "hw/qdev-core.h"
|
||||
|
||||
#define TYPE_DM163 "dm163"
|
||||
OBJECT_DECLARE_SIMPLE_TYPE(DM163State, DM163);
|
||||
|
||||
#define RGB_MATRIX_NUM_ROWS 8
|
||||
#define RGB_MATRIX_NUM_COLS 8
|
||||
#define DM163_NUM_LEDS (RGB_MATRIX_NUM_COLS * 3)
|
||||
/* The last row is filled with 0 (turned off row) */
|
||||
#define COLOR_BUFFER_SIZE (RGB_MATRIX_NUM_ROWS + 1)
|
||||
|
||||
typedef struct DM163State {
|
||||
DeviceState parent_obj;
|
||||
|
||||
/* DM163 driver */
|
||||
uint64_t bank0_shift_register[3];
|
||||
uint64_t bank1_shift_register[3];
|
||||
uint16_t latched_outputs[DM163_NUM_LEDS];
|
||||
uint16_t outputs[DM163_NUM_LEDS];
|
||||
qemu_irq sout;
|
||||
|
||||
uint8_t sin;
|
||||
uint8_t dck;
|
||||
uint8_t rst_b;
|
||||
uint8_t lat_b;
|
||||
uint8_t selbk;
|
||||
uint8_t en_b;
|
||||
|
||||
/* IM120417002 colors shield */
|
||||
uint8_t activated_rows;
|
||||
|
||||
/* 8x8 RGB matrix */
|
||||
QemuConsole *console;
|
||||
uint8_t redraw;
|
||||
/* Rows currently being displayed on the matrix. */
|
||||
/* The last row is filled with 0 (turned off row) */
|
||||
uint32_t buffer[COLOR_BUFFER_SIZE][RGB_MATRIX_NUM_COLS];
|
||||
uint8_t last_buffer_idx;
|
||||
uint8_t buffer_idx_of_row[RGB_MATRIX_NUM_ROWS];
|
||||
/* Used to simulate retinal persistence of rows */
|
||||
uint8_t row_persistence_delay[RGB_MATRIX_NUM_ROWS];
|
||||
} DM163State;
|
||||
|
||||
#endif /* HW_DISPLAY_DM163_H */
|
@ -55,8 +55,6 @@
|
||||
#define SBSA_GWDT_RMMIO_SIZE 0x1000
|
||||
#define SBSA_GWDT_CMMIO_SIZE 0x1000
|
||||
|
||||
#define SBSA_TIMER_FREQ 62500000 /* Hz */
|
||||
|
||||
typedef struct SBSA_GWDTState {
|
||||
/* <private> */
|
||||
SysBusDevice parent_obj;
|
||||
@ -67,6 +65,7 @@ typedef struct SBSA_GWDTState {
|
||||
qemu_irq irq;
|
||||
|
||||
QEMUTimer *timer;
|
||||
uint64_t freq;
|
||||
|
||||
uint32_t id;
|
||||
uint32_t wcs;
|
||||
|
@ -1506,9 +1506,12 @@ static void arm_cpu_initfn(Object *obj)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 0 means "unset, use the default value". That default might vary depending
|
||||
* on the CPU type, and is set in the realize fn.
|
||||
*/
|
||||
static Property arm_cpu_gt_cntfrq_property =
|
||||
DEFINE_PROP_UINT64("cntfrq", ARMCPU, gt_cntfrq_hz,
|
||||
NANOSECONDS_PER_SECOND / GTIMER_SCALE);
|
||||
DEFINE_PROP_UINT64("cntfrq", ARMCPU, gt_cntfrq_hz, 0);
|
||||
|
||||
static Property arm_cpu_reset_cbar_property =
|
||||
DEFINE_PROP_UINT64("reset-cbar", ARMCPU, reset_cbar, 0);
|
||||
@ -1954,6 +1957,26 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
|
||||
return;
|
||||
}
|
||||
|
||||
if (!cpu->gt_cntfrq_hz) {
|
||||
/*
|
||||
* 0 means "the board didn't set a value, use the default". (We also
|
||||
* get here for the CONFIG_USER_ONLY case.)
|
||||
* ARMv8.6 and later CPUs architecturally must use a 1GHz timer; before
|
||||
* that it was an IMPDEF choice, and QEMU initially picked 62.5MHz,
|
||||
* which gives a 16ns tick period.
|
||||
*
|
||||
* We will use the back-compat value:
|
||||
* - for QEMU CPU types added before we standardized on 1GHz
|
||||
* - for versioned machine types with a version of 9.0 or earlier
|
||||
*/
|
||||
if (arm_feature(env, ARM_FEATURE_BACKCOMPAT_CNTFRQ) ||
|
||||
cpu->backcompat_cntfrq) {
|
||||
cpu->gt_cntfrq_hz = GTIMER_BACKCOMPAT_HZ;
|
||||
} else {
|
||||
cpu->gt_cntfrq_hz = GTIMER_DEFAULT_HZ;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
/* The NVIC and M-profile CPU are two halves of a single piece of
|
||||
* hardware; trying to use one without the other is a command line
|
||||
@ -2002,18 +2025,7 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
|
||||
}
|
||||
|
||||
{
|
||||
uint64_t scale;
|
||||
|
||||
if (arm_feature(env, ARM_FEATURE_GENERIC_TIMER)) {
|
||||
if (!cpu->gt_cntfrq_hz) {
|
||||
error_setg(errp, "Invalid CNTFRQ: %"PRId64"Hz",
|
||||
cpu->gt_cntfrq_hz);
|
||||
return;
|
||||
}
|
||||
scale = gt_cntfrq_period_ns(cpu);
|
||||
} else {
|
||||
scale = GTIMER_SCALE;
|
||||
}
|
||||
uint64_t scale = gt_cntfrq_period_ns(cpu);
|
||||
|
||||
cpu->gt_timer[GTIMER_PHYS] = timer_new(QEMU_CLOCK_VIRTUAL, scale,
|
||||
arm_gt_ptimer_cb, cpu);
|
||||
@ -2571,6 +2583,8 @@ static Property arm_cpu_properties[] = {
|
||||
mp_affinity, ARM64_AFFINITY_INVALID),
|
||||
DEFINE_PROP_INT32("node-id", ARMCPU, node_id, CPU_UNSET_NUMA_NODE_ID),
|
||||
DEFINE_PROP_INT32("core-count", ARMCPU, core_count, -1),
|
||||
/* True to default to the backward-compat old CNTFRQ rather than 1Ghz */
|
||||
DEFINE_PROP_BOOL("backcompat-cntfrq", ARMCPU, backcompat_cntfrq, false),
|
||||
DEFINE_PROP_END_OF_LIST()
|
||||
};
|
||||
|
||||
|
@ -956,6 +956,9 @@ struct ArchCPU {
|
||||
*/
|
||||
bool host_cpu_probe_failed;
|
||||
|
||||
/* QOM property to indicate we should use the back-compat CNTFRQ default */
|
||||
bool backcompat_cntfrq;
|
||||
|
||||
/* Specify the number of cores in this CPU cluster. Used for the L2CTLR
|
||||
* register.
|
||||
*/
|
||||
@ -1011,6 +1014,7 @@ struct ArchCPU {
|
||||
uint64_t id_aa64mmfr0;
|
||||
uint64_t id_aa64mmfr1;
|
||||
uint64_t id_aa64mmfr2;
|
||||
uint64_t id_aa64mmfr3;
|
||||
uint64_t id_aa64dfr0;
|
||||
uint64_t id_aa64dfr1;
|
||||
uint64_t id_aa64zfr0;
|
||||
@ -2206,6 +2210,22 @@ FIELD(ID_AA64MMFR2, BBM, 52, 4)
|
||||
FIELD(ID_AA64MMFR2, EVT, 56, 4)
|
||||
FIELD(ID_AA64MMFR2, E0PD, 60, 4)
|
||||
|
||||
FIELD(ID_AA64MMFR3, TCRX, 0, 4)
|
||||
FIELD(ID_AA64MMFR3, SCTLRX, 4, 4)
|
||||
FIELD(ID_AA64MMFR3, S1PIE, 8, 4)
|
||||
FIELD(ID_AA64MMFR3, S2PIE, 12, 4)
|
||||
FIELD(ID_AA64MMFR3, S1POE, 16, 4)
|
||||
FIELD(ID_AA64MMFR3, S2POE, 20, 4)
|
||||
FIELD(ID_AA64MMFR3, AIE, 24, 4)
|
||||
FIELD(ID_AA64MMFR3, MEC, 28, 4)
|
||||
FIELD(ID_AA64MMFR3, D128, 32, 4)
|
||||
FIELD(ID_AA64MMFR3, D128_2, 36, 4)
|
||||
FIELD(ID_AA64MMFR3, SNERR, 40, 4)
|
||||
FIELD(ID_AA64MMFR3, ANERR, 44, 4)
|
||||
FIELD(ID_AA64MMFR3, SDERR, 52, 4)
|
||||
FIELD(ID_AA64MMFR3, ADERR, 56, 4)
|
||||
FIELD(ID_AA64MMFR3, SPEC_FPACC, 60, 4)
|
||||
|
||||
FIELD(ID_AA64DFR0, DEBUGVER, 0, 4)
|
||||
FIELD(ID_AA64DFR0, TRACEVER, 4, 4)
|
||||
FIELD(ID_AA64DFR0, PMUVER, 8, 4)
|
||||
@ -2356,6 +2376,14 @@ enum arm_features {
|
||||
ARM_FEATURE_M_SECURITY, /* M profile Security Extension */
|
||||
ARM_FEATURE_M_MAIN, /* M profile Main Extension */
|
||||
ARM_FEATURE_V8_1M, /* M profile extras only in v8.1M and later */
|
||||
/*
|
||||
* ARM_FEATURE_BACKCOMPAT_CNTFRQ makes the CPU default cntfrq be 62.5MHz
|
||||
* if the board doesn't set a value, instead of 1GHz. It is for backwards
|
||||
* compatibility and used only with CPU definitions that were already
|
||||
* in QEMU before we changed the default. It should not be set on any
|
||||
* CPU types added in future.
|
||||
*/
|
||||
ARM_FEATURE_BACKCOMPAT_CNTFRQ, /* 62.5MHz timer default */
|
||||
};
|
||||
|
||||
static inline int arm_feature(CPUARMState *env, int feature)
|
||||
|
@ -599,6 +599,7 @@ static void aarch64_a57_initfn(Object *obj)
|
||||
set_feature(&cpu->env, ARM_FEATURE_V8);
|
||||
set_feature(&cpu->env, ARM_FEATURE_NEON);
|
||||
set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
|
||||
set_feature(&cpu->env, ARM_FEATURE_BACKCOMPAT_CNTFRQ);
|
||||
set_feature(&cpu->env, ARM_FEATURE_AARCH64);
|
||||
set_feature(&cpu->env, ARM_FEATURE_CBAR_RO);
|
||||
set_feature(&cpu->env, ARM_FEATURE_EL2);
|
||||
@ -656,6 +657,7 @@ static void aarch64_a53_initfn(Object *obj)
|
||||
set_feature(&cpu->env, ARM_FEATURE_V8);
|
||||
set_feature(&cpu->env, ARM_FEATURE_NEON);
|
||||
set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
|
||||
set_feature(&cpu->env, ARM_FEATURE_BACKCOMPAT_CNTFRQ);
|
||||
set_feature(&cpu->env, ARM_FEATURE_AARCH64);
|
||||
set_feature(&cpu->env, ARM_FEATURE_CBAR_RO);
|
||||
set_feature(&cpu->env, ARM_FEATURE_EL2);
|
||||
|
@ -2474,6 +2474,13 @@ static const ARMCPRegInfo v6k_cp_reginfo[] = {
|
||||
.resetvalue = 0 },
|
||||
};
|
||||
|
||||
static void arm_gt_cntfrq_reset(CPUARMState *env, const ARMCPRegInfo *opaque)
|
||||
{
|
||||
ARMCPU *cpu = env_archcpu(env);
|
||||
|
||||
cpu->env.cp15.c14_cntfrq = cpu->gt_cntfrq_hz;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
|
||||
static CPAccessResult gt_cntfrq_access(CPUARMState *env, const ARMCPRegInfo *ri,
|
||||
@ -3228,13 +3235,6 @@ void arm_gt_hvtimer_cb(void *opaque)
|
||||
gt_recalc_timer(cpu, GTIMER_HYPVIRT);
|
||||
}
|
||||
|
||||
static void arm_gt_cntfrq_reset(CPUARMState *env, const ARMCPRegInfo *opaque)
|
||||
{
|
||||
ARMCPU *cpu = env_archcpu(env);
|
||||
|
||||
cpu->env.cp15.c14_cntfrq = cpu->gt_cntfrq_hz;
|
||||
}
|
||||
|
||||
static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
|
||||
/*
|
||||
* Note that CNTFRQ is purely reads-as-written for the benefit
|
||||
@ -3514,7 +3514,7 @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
|
||||
.opc0 = 3, .opc1 = 3, .crn = 14, .crm = 0, .opc2 = 0,
|
||||
.type = ARM_CP_CONST, .access = PL0_R /* no PL1_RW in linux-user */,
|
||||
.fieldoffset = offsetof(CPUARMState, cp15.c14_cntfrq),
|
||||
.resetvalue = NANOSECONDS_PER_SECOND / GTIMER_SCALE,
|
||||
.resetfn = arm_gt_cntfrq_reset,
|
||||
},
|
||||
{ .name = "CNTVCT_EL0", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 3, .opc1 = 3, .crn = 14, .crm = 0, .opc2 = 2,
|
||||
@ -9004,11 +9004,11 @@ void register_cp_regs_for_features(ARMCPU *cpu)
|
||||
.access = PL1_R, .type = ARM_CP_CONST,
|
||||
.accessfn = access_aa64_tid3,
|
||||
.resetvalue = cpu->isar.id_aa64mmfr2 },
|
||||
{ .name = "ID_AA64MMFR3_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
|
||||
{ .name = "ID_AA64MMFR3_EL1", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 3,
|
||||
.access = PL1_R, .type = ARM_CP_CONST,
|
||||
.accessfn = access_aa64_tid3,
|
||||
.resetvalue = 0 },
|
||||
.resetvalue = cpu->isar.id_aa64mmfr3 },
|
||||
{ .name = "ID_AA64MMFR4_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 4,
|
||||
.access = PL1_R, .type = ARM_CP_CONST,
|
||||
@ -9165,6 +9165,8 @@ void register_cp_regs_for_features(ARMCPU *cpu)
|
||||
.exported_bits = R_ID_AA64MMFR1_AFP_MASK },
|
||||
{ .name = "ID_AA64MMFR2_EL1",
|
||||
.exported_bits = R_ID_AA64MMFR2_AT_MASK },
|
||||
{ .name = "ID_AA64MMFR3_EL1",
|
||||
.exported_bits = 0 },
|
||||
{ .name = "ID_AA64MMFR*_EL1_RESERVED",
|
||||
.is_glob = true },
|
||||
{ .name = "ID_AA64DFR0_EL1",
|
||||
|
@ -150,7 +150,6 @@ void hvf_arm_init_debug(void)
|
||||
|
||||
#define HVF_SYSREG(crn, crm, op0, op1, op2) \
|
||||
ENCODE_AA64_CP_REG(CP_REG_ARM64_SYSREG_CP, crn, crm, op0, op1, op2)
|
||||
#define PL1_WRITE_MASK 0x4
|
||||
|
||||
#define SYSREG_OP0_SHIFT 20
|
||||
#define SYSREG_OP0_MASK 0x3
|
||||
@ -498,6 +497,7 @@ static struct hvf_sreg_match hvf_sreg_match[] = {
|
||||
#endif
|
||||
{ HV_SYS_REG_ID_AA64MMFR1_EL1, HVF_SYSREG(0, 7, 3, 0, 1) },
|
||||
{ HV_SYS_REG_ID_AA64MMFR2_EL1, HVF_SYSREG(0, 7, 3, 0, 2) },
|
||||
/* Add ID_AA64MMFR3_EL1 here when HVF supports it */
|
||||
|
||||
{ HV_SYS_REG_MDSCR_EL1, HVF_SYSREG(0, 2, 2, 0, 2) },
|
||||
{ HV_SYS_REG_SCTLR_EL1, HVF_SYSREG(1, 0, 3, 0, 0) },
|
||||
@ -856,6 +856,7 @@ static bool hvf_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
|
||||
{ HV_SYS_REG_ID_AA64MMFR0_EL1, &host_isar.id_aa64mmfr0 },
|
||||
{ HV_SYS_REG_ID_AA64MMFR1_EL1, &host_isar.id_aa64mmfr1 },
|
||||
{ HV_SYS_REG_ID_AA64MMFR2_EL1, &host_isar.id_aa64mmfr2 },
|
||||
/* Add ID_AA64MMFR3_EL1 here when HVF supports it */
|
||||
};
|
||||
hv_vcpu_t fd;
|
||||
hv_return_t r = HV_SUCCESS;
|
||||
|
@ -60,10 +60,19 @@ static inline bool excp_is_internal(int excp)
|
||||
|| excp == EXCP_SEMIHOST;
|
||||
}
|
||||
|
||||
/* Scale factor for generic timers, ie number of ns per tick.
|
||||
* This gives a 62.5MHz timer.
|
||||
/*
|
||||
* Default frequency for the generic timer, in Hz.
|
||||
* ARMv8.6 and later CPUs architecturally must use a 1GHz timer; before
|
||||
* that it was an IMPDEF choice, and QEMU initially picked 62.5MHz,
|
||||
* which gives a 16ns tick period.
|
||||
*
|
||||
* We will use the back-compat value:
|
||||
* - for QEMU CPU types added before we standardized on 1GHz
|
||||
* - for versioned machine types with a version of 9.0 or earlier
|
||||
* In any case, the machine model may override via the cntfrq property.
|
||||
*/
|
||||
#define GTIMER_SCALE 16
|
||||
#define GTIMER_DEFAULT_HZ 1000000000
|
||||
#define GTIMER_BACKCOMPAT_HZ 62500000
|
||||
|
||||
/* Bit definitions for the v7M CONTROL register */
|
||||
FIELD(V7M_CONTROL, NPRIV, 0, 1)
|
||||
|
@ -331,6 +331,8 @@ static bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
|
||||
ARM64_SYS_REG(3, 0, 0, 7, 1));
|
||||
err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64mmfr2,
|
||||
ARM64_SYS_REG(3, 0, 0, 7, 2));
|
||||
err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64mmfr3,
|
||||
ARM64_SYS_REG(3, 0, 0, 7, 3));
|
||||
|
||||
/*
|
||||
* Note that if AArch32 support is not present in the host,
|
||||
|
@ -67,7 +67,7 @@ void aa32_max_features(ARMCPU *cpu)
|
||||
cpu->isar.id_mmfr4 = t;
|
||||
|
||||
t = cpu->isar.id_mmfr5;
|
||||
t = FIELD_DP32(t, ID_MMFR5, ETS, 1); /* FEAT_ETS */
|
||||
t = FIELD_DP32(t, ID_MMFR5, ETS, 2); /* FEAT_ETS2 */
|
||||
cpu->isar.id_mmfr5 = t;
|
||||
|
||||
t = cpu->isar.id_pfr0;
|
||||
@ -457,6 +457,7 @@ static void cortex_a7_initfn(Object *obj)
|
||||
set_feature(&cpu->env, ARM_FEATURE_NEON);
|
||||
set_feature(&cpu->env, ARM_FEATURE_THUMB2EE);
|
||||
set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
|
||||
set_feature(&cpu->env, ARM_FEATURE_BACKCOMPAT_CNTFRQ);
|
||||
set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
|
||||
set_feature(&cpu->env, ARM_FEATURE_CBAR_RO);
|
||||
set_feature(&cpu->env, ARM_FEATURE_EL2);
|
||||
@ -505,6 +506,7 @@ static void cortex_a15_initfn(Object *obj)
|
||||
set_feature(&cpu->env, ARM_FEATURE_NEON);
|
||||
set_feature(&cpu->env, ARM_FEATURE_THUMB2EE);
|
||||
set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
|
||||
set_feature(&cpu->env, ARM_FEATURE_BACKCOMPAT_CNTFRQ);
|
||||
set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
|
||||
set_feature(&cpu->env, ARM_FEATURE_CBAR_RO);
|
||||
set_feature(&cpu->env, ARM_FEATURE_EL2);
|
||||
@ -696,6 +698,7 @@ static void cortex_r52_initfn(Object *obj)
|
||||
set_feature(&cpu->env, ARM_FEATURE_PMSA);
|
||||
set_feature(&cpu->env, ARM_FEATURE_NEON);
|
||||
set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
|
||||
set_feature(&cpu->env, ARM_FEATURE_BACKCOMPAT_CNTFRQ);
|
||||
set_feature(&cpu->env, ARM_FEATURE_CBAR_RO);
|
||||
set_feature(&cpu->env, ARM_FEATURE_AUXCR);
|
||||
cpu->midr = 0x411fd133; /* r1p3 */
|
||||
@ -924,6 +927,7 @@ static void arm_max_initfn(Object *obj)
|
||||
set_feature(&cpu->env, ARM_FEATURE_V8);
|
||||
set_feature(&cpu->env, ARM_FEATURE_NEON);
|
||||
set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
|
||||
set_feature(&cpu->env, ARM_FEATURE_BACKCOMPAT_CNTFRQ);
|
||||
set_feature(&cpu->env, ARM_FEATURE_CBAR_RO);
|
||||
set_feature(&cpu->env, ARM_FEATURE_EL2);
|
||||
set_feature(&cpu->env, ARM_FEATURE_EL3);
|
||||
|
@ -63,6 +63,7 @@ static void aarch64_a35_initfn(Object *obj)
|
||||
set_feature(&cpu->env, ARM_FEATURE_V8);
|
||||
set_feature(&cpu->env, ARM_FEATURE_NEON);
|
||||
set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
|
||||
set_feature(&cpu->env, ARM_FEATURE_BACKCOMPAT_CNTFRQ);
|
||||
set_feature(&cpu->env, ARM_FEATURE_AARCH64);
|
||||
set_feature(&cpu->env, ARM_FEATURE_CBAR_RO);
|
||||
set_feature(&cpu->env, ARM_FEATURE_EL2);
|
||||
@ -231,6 +232,7 @@ static void aarch64_a55_initfn(Object *obj)
|
||||
set_feature(&cpu->env, ARM_FEATURE_V8);
|
||||
set_feature(&cpu->env, ARM_FEATURE_NEON);
|
||||
set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
|
||||
set_feature(&cpu->env, ARM_FEATURE_BACKCOMPAT_CNTFRQ);
|
||||
set_feature(&cpu->env, ARM_FEATURE_AARCH64);
|
||||
set_feature(&cpu->env, ARM_FEATURE_CBAR_RO);
|
||||
set_feature(&cpu->env, ARM_FEATURE_EL2);
|
||||
@ -299,6 +301,7 @@ static void aarch64_a72_initfn(Object *obj)
|
||||
set_feature(&cpu->env, ARM_FEATURE_V8);
|
||||
set_feature(&cpu->env, ARM_FEATURE_NEON);
|
||||
set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
|
||||
set_feature(&cpu->env, ARM_FEATURE_BACKCOMPAT_CNTFRQ);
|
||||
set_feature(&cpu->env, ARM_FEATURE_AARCH64);
|
||||
set_feature(&cpu->env, ARM_FEATURE_CBAR_RO);
|
||||
set_feature(&cpu->env, ARM_FEATURE_EL2);
|
||||
@ -354,6 +357,7 @@ static void aarch64_a76_initfn(Object *obj)
|
||||
set_feature(&cpu->env, ARM_FEATURE_V8);
|
||||
set_feature(&cpu->env, ARM_FEATURE_NEON);
|
||||
set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
|
||||
set_feature(&cpu->env, ARM_FEATURE_BACKCOMPAT_CNTFRQ);
|
||||
set_feature(&cpu->env, ARM_FEATURE_AARCH64);
|
||||
set_feature(&cpu->env, ARM_FEATURE_CBAR_RO);
|
||||
set_feature(&cpu->env, ARM_FEATURE_EL2);
|
||||
@ -423,6 +427,7 @@ static void aarch64_a64fx_initfn(Object *obj)
|
||||
set_feature(&cpu->env, ARM_FEATURE_V8);
|
||||
set_feature(&cpu->env, ARM_FEATURE_NEON);
|
||||
set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
|
||||
set_feature(&cpu->env, ARM_FEATURE_BACKCOMPAT_CNTFRQ);
|
||||
set_feature(&cpu->env, ARM_FEATURE_AARCH64);
|
||||
set_feature(&cpu->env, ARM_FEATURE_EL2);
|
||||
set_feature(&cpu->env, ARM_FEATURE_EL3);
|
||||
@ -592,6 +597,7 @@ static void aarch64_neoverse_n1_initfn(Object *obj)
|
||||
set_feature(&cpu->env, ARM_FEATURE_V8);
|
||||
set_feature(&cpu->env, ARM_FEATURE_NEON);
|
||||
set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
|
||||
set_feature(&cpu->env, ARM_FEATURE_BACKCOMPAT_CNTFRQ);
|
||||
set_feature(&cpu->env, ARM_FEATURE_AARCH64);
|
||||
set_feature(&cpu->env, ARM_FEATURE_CBAR_RO);
|
||||
set_feature(&cpu->env, ARM_FEATURE_EL2);
|
||||
@ -663,6 +669,7 @@ static void aarch64_neoverse_v1_initfn(Object *obj)
|
||||
set_feature(&cpu->env, ARM_FEATURE_V8);
|
||||
set_feature(&cpu->env, ARM_FEATURE_NEON);
|
||||
set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
|
||||
set_feature(&cpu->env, ARM_FEATURE_BACKCOMPAT_CNTFRQ);
|
||||
set_feature(&cpu->env, ARM_FEATURE_AARCH64);
|
||||
set_feature(&cpu->env, ARM_FEATURE_CBAR_RO);
|
||||
set_feature(&cpu->env, ARM_FEATURE_EL2);
|
||||
@ -885,6 +892,7 @@ static void aarch64_a710_initfn(Object *obj)
|
||||
set_feature(&cpu->env, ARM_FEATURE_V8);
|
||||
set_feature(&cpu->env, ARM_FEATURE_NEON);
|
||||
set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
|
||||
set_feature(&cpu->env, ARM_FEATURE_BACKCOMPAT_CNTFRQ);
|
||||
set_feature(&cpu->env, ARM_FEATURE_AARCH64);
|
||||
set_feature(&cpu->env, ARM_FEATURE_CBAR_RO);
|
||||
set_feature(&cpu->env, ARM_FEATURE_EL2);
|
||||
@ -982,6 +990,7 @@ static void aarch64_neoverse_n2_initfn(Object *obj)
|
||||
set_feature(&cpu->env, ARM_FEATURE_V8);
|
||||
set_feature(&cpu->env, ARM_FEATURE_NEON);
|
||||
set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
|
||||
set_feature(&cpu->env, ARM_FEATURE_BACKCOMPAT_CNTFRQ);
|
||||
set_feature(&cpu->env, ARM_FEATURE_AARCH64);
|
||||
set_feature(&cpu->env, ARM_FEATURE_CBAR_RO);
|
||||
set_feature(&cpu->env, ARM_FEATURE_EL2);
|
||||
@ -1077,6 +1086,15 @@ void aarch64_max_tcg_initfn(Object *obj)
|
||||
uint64_t t;
|
||||
uint32_t u;
|
||||
|
||||
/*
|
||||
* Unset ARM_FEATURE_BACKCOMPAT_CNTFRQ, which we would otherwise default
|
||||
* to because we started with aarch64_a57_initfn(). A 'max' CPU might
|
||||
* be a v8.6-or-later one, in which case the cntfrq must be 1GHz; and
|
||||
* because it is our "may change" CPU type we are OK with it not being
|
||||
* backwards-compatible with how it worked in old QEMU.
|
||||
*/
|
||||
unset_feature(&cpu->env, ARM_FEATURE_BACKCOMPAT_CNTFRQ);
|
||||
|
||||
/*
|
||||
* Reset MIDR so the guest doesn't mistake our 'max' CPU type for a real
|
||||
* one and try to apply errata workarounds or use impdef features we
|
||||
@ -1159,7 +1177,7 @@ void aarch64_max_tcg_initfn(Object *obj)
|
||||
t = FIELD_DP64(t, ID_AA64PFR0, SVE, 1);
|
||||
t = FIELD_DP64(t, ID_AA64PFR0, SEL2, 1); /* FEAT_SEL2 */
|
||||
t = FIELD_DP64(t, ID_AA64PFR0, DIT, 1); /* FEAT_DIT */
|
||||
t = FIELD_DP64(t, ID_AA64PFR0, CSV2, 2); /* FEAT_CSV2_2 */
|
||||
t = FIELD_DP64(t, ID_AA64PFR0, CSV2, 3); /* FEAT_CSV2_3 */
|
||||
t = FIELD_DP64(t, ID_AA64PFR0, CSV3, 1); /* FEAT_CSV3 */
|
||||
cpu->isar.id_aa64pfr0 = t;
|
||||
|
||||
@ -1174,7 +1192,7 @@ void aarch64_max_tcg_initfn(Object *obj)
|
||||
t = FIELD_DP64(t, ID_AA64PFR1, MTE, 3); /* FEAT_MTE3 */
|
||||
t = FIELD_DP64(t, ID_AA64PFR1, RAS_FRAC, 0); /* FEAT_RASv1p1 + FEAT_DoubleFault */
|
||||
t = FIELD_DP64(t, ID_AA64PFR1, SME, 1); /* FEAT_SME */
|
||||
t = FIELD_DP64(t, ID_AA64PFR1, CSV2_FRAC, 0); /* FEAT_CSV2_2 */
|
||||
t = FIELD_DP64(t, ID_AA64PFR1, CSV2_FRAC, 0); /* FEAT_CSV2_3 */
|
||||
t = FIELD_DP64(t, ID_AA64PFR1, NMI, 1); /* FEAT_NMI */
|
||||
cpu->isar.id_aa64pfr1 = t;
|
||||
|
||||
@ -1196,7 +1214,7 @@ void aarch64_max_tcg_initfn(Object *obj)
|
||||
t = FIELD_DP64(t, ID_AA64MMFR1, LO, 1); /* FEAT_LOR */
|
||||
t = FIELD_DP64(t, ID_AA64MMFR1, PAN, 3); /* FEAT_PAN3 */
|
||||
t = FIELD_DP64(t, ID_AA64MMFR1, XNX, 1); /* FEAT_XNX */
|
||||
t = FIELD_DP64(t, ID_AA64MMFR1, ETS, 1); /* FEAT_ETS */
|
||||
t = FIELD_DP64(t, ID_AA64MMFR1, ETS, 2); /* FEAT_ETS2 */
|
||||
t = FIELD_DP64(t, ID_AA64MMFR1, HCX, 1); /* FEAT_HCX */
|
||||
t = FIELD_DP64(t, ID_AA64MMFR1, TIDCP1, 1); /* FEAT_TIDCP1 */
|
||||
cpu->isar.id_aa64mmfr1 = t;
|
||||
@ -1217,6 +1235,10 @@ void aarch64_max_tcg_initfn(Object *obj)
|
||||
t = FIELD_DP64(t, ID_AA64MMFR2, E0PD, 1); /* FEAT_E0PD */
|
||||
cpu->isar.id_aa64mmfr2 = t;
|
||||
|
||||
t = cpu->isar.id_aa64mmfr3;
|
||||
t = FIELD_DP64(t, ID_AA64MMFR3, SPEC_FPACC, 1); /* FEAT_FPACC_SPEC */
|
||||
cpu->isar.id_aa64mmfr3 = t;
|
||||
|
||||
t = cpu->isar.id_aa64zfr0;
|
||||
t = FIELD_DP64(t, ID_AA64ZFR0, SVEVER, 1);
|
||||
t = FIELD_DP64(t, ID_AA64ZFR0, AES, 2); /* FEAT_SVE_PMULL128 */
|
||||
|
@ -38,8 +38,16 @@ static bool aprofile_require_alignment(CPUARMState *env, int el, uint64_t sctlr)
|
||||
}
|
||||
|
||||
/*
|
||||
* If translation is disabled, then the default memory type is
|
||||
* Device(-nGnRnE) instead of Normal, which requires that alignment
|
||||
* With PMSA, when the MPU is disabled, all memory types in the
|
||||
* default map are Normal, so don't need aligment enforcing.
|
||||
*/
|
||||
if (arm_feature(env, ARM_FEATURE_PMSA)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* With VMSA, if translation is disabled, then the default memory type
|
||||
* is Device(-nGnRnE) instead of Normal, which requires that alignment
|
||||
* be enforced. Since this affects all ram, it is most efficient
|
||||
* to handle this during translation.
|
||||
*/
|
||||
|
@ -646,12 +646,12 @@ class BootLinuxConsole(LinuxKernelTest):
|
||||
:avocado: tags=accel:tcg
|
||||
"""
|
||||
deb_url = ('https://apt.armbian.com/pool/main/l/'
|
||||
'linux-5.10.16-sunxi/linux-image-current-sunxi_21.02.2_armhf.deb')
|
||||
deb_hash = '9fa84beda245cabf0b4fa84cf6eaa7738ead1da0'
|
||||
'linux-6.6.16/linux-image-current-sunxi_24.2.1_armhf__6.6.16-Seb3e-D6b4a-P2359-Ce96bHfe66-HK01ba-V014b-B067e-R448a.deb')
|
||||
deb_hash = 'f7c3c8c5432f765445dc6e7eab02f3bbe668256b'
|
||||
deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
|
||||
kernel_path = self.extract_from_deb(deb_path,
|
||||
'/boot/vmlinuz-5.10.16-sunxi')
|
||||
dtb_path = '/usr/lib/linux-image-current-sunxi/sun4i-a10-cubieboard.dtb'
|
||||
'/boot/vmlinuz-6.6.16-current-sunxi')
|
||||
dtb_path = '/usr/lib/linux-image-6.6.16-current-sunxi/sun4i-a10-cubieboard.dtb'
|
||||
dtb_path = self.extract_from_deb(deb_path, dtb_path)
|
||||
initrd_url = ('https://github.com/groeck/linux-build-test/raw/'
|
||||
'2eb0a73b5d5a28df3170c546ddaaa9757e1e0848/rootfs/'
|
||||
@ -690,12 +690,12 @@ class BootLinuxConsole(LinuxKernelTest):
|
||||
:avocado: tags=accel:tcg
|
||||
"""
|
||||
deb_url = ('https://apt.armbian.com/pool/main/l/'
|
||||
'linux-5.10.16-sunxi/linux-image-current-sunxi_21.02.2_armhf.deb')
|
||||
deb_hash = '9fa84beda245cabf0b4fa84cf6eaa7738ead1da0'
|
||||
'linux-6.6.16/linux-image-current-sunxi_24.2.1_armhf__6.6.16-Seb3e-D6b4a-P2359-Ce96bHfe66-HK01ba-V014b-B067e-R448a.deb')
|
||||
deb_hash = 'f7c3c8c5432f765445dc6e7eab02f3bbe668256b'
|
||||
deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
|
||||
kernel_path = self.extract_from_deb(deb_path,
|
||||
'/boot/vmlinuz-5.10.16-sunxi')
|
||||
dtb_path = '/usr/lib/linux-image-current-sunxi/sun4i-a10-cubieboard.dtb'
|
||||
'/boot/vmlinuz-6.6.16-current-sunxi')
|
||||
dtb_path = '/usr/lib/linux-image-6.6.16-current-sunxi/sun4i-a10-cubieboard.dtb'
|
||||
dtb_path = self.extract_from_deb(deb_path, dtb_path)
|
||||
rootfs_url = ('https://github.com/groeck/linux-build-test/raw/'
|
||||
'2eb0a73b5d5a28df3170c546ddaaa9757e1e0848/rootfs/'
|
||||
@ -872,13 +872,13 @@ class BootLinuxConsole(LinuxKernelTest):
|
||||
:avocado: tags=machine:bpim2u
|
||||
:avocado: tags=accel:tcg
|
||||
"""
|
||||
deb_url = ('https://apt.armbian.com/pool/main/l/linux-5.10.16-sunxi/'
|
||||
'linux-image-current-sunxi_21.02.2_armhf.deb')
|
||||
deb_hash = '9fa84beda245cabf0b4fa84cf6eaa7738ead1da0'
|
||||
deb_url = ('https://apt.armbian.com/pool/main/l/'
|
||||
'linux-6.6.16/linux-image-current-sunxi_24.2.1_armhf__6.6.16-Seb3e-D6b4a-P2359-Ce96bHfe66-HK01ba-V014b-B067e-R448a.deb')
|
||||
deb_hash = 'f7c3c8c5432f765445dc6e7eab02f3bbe668256b'
|
||||
deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
|
||||
kernel_path = self.extract_from_deb(deb_path,
|
||||
'/boot/vmlinuz-5.10.16-sunxi')
|
||||
dtb_path = ('/usr/lib/linux-image-current-sunxi/'
|
||||
'/boot/vmlinuz-6.6.16-current-sunxi')
|
||||
dtb_path = ('/usr/lib/linux-image-6.6.16-current-sunxi/'
|
||||
'sun8i-r40-bananapi-m2-ultra.dtb')
|
||||
dtb_path = self.extract_from_deb(deb_path, dtb_path)
|
||||
|
||||
@ -899,13 +899,13 @@ class BootLinuxConsole(LinuxKernelTest):
|
||||
:avocado: tags=accel:tcg
|
||||
:avocado: tags=machine:bpim2u
|
||||
"""
|
||||
deb_url = ('https://apt.armbian.com/pool/main/l/linux-5.10.16-sunxi/'
|
||||
'linux-image-current-sunxi_21.02.2_armhf.deb')
|
||||
deb_hash = '9fa84beda245cabf0b4fa84cf6eaa7738ead1da0'
|
||||
deb_url = ('https://apt.armbian.com/pool/main/l/'
|
||||
'linux-6.6.16/linux-image-current-sunxi_24.2.1_armhf__6.6.16-Seb3e-D6b4a-P2359-Ce96bHfe66-HK01ba-V014b-B067e-R448a.deb')
|
||||
deb_hash = 'f7c3c8c5432f765445dc6e7eab02f3bbe668256b'
|
||||
deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
|
||||
kernel_path = self.extract_from_deb(deb_path,
|
||||
'/boot/vmlinuz-5.10.16-sunxi')
|
||||
dtb_path = ('/usr/lib/linux-image-current-sunxi/'
|
||||
'/boot/vmlinuz-6.6.16-current-sunxi')
|
||||
dtb_path = ('/usr/lib/linux-image-6.6.16-current-sunxi/'
|
||||
'sun8i-r40-bananapi-m2-ultra.dtb')
|
||||
dtb_path = self.extract_from_deb(deb_path, dtb_path)
|
||||
initrd_url = ('https://github.com/groeck/linux-build-test/raw/'
|
||||
@ -946,13 +946,13 @@ class BootLinuxConsole(LinuxKernelTest):
|
||||
"""
|
||||
self.require_netdev('user')
|
||||
|
||||
deb_url = ('https://apt.armbian.com/pool/main/l/linux-5.10.16-sunxi/'
|
||||
'linux-image-current-sunxi_21.02.2_armhf.deb')
|
||||
deb_hash = '9fa84beda245cabf0b4fa84cf6eaa7738ead1da0'
|
||||
deb_url = ('https://apt.armbian.com/pool/main/l/'
|
||||
'linux-6.6.16/linux-image-current-sunxi_24.2.1_armhf__6.6.16-Seb3e-D6b4a-P2359-Ce96bHfe66-HK01ba-V014b-B067e-R448a.deb')
|
||||
deb_hash = 'f7c3c8c5432f765445dc6e7eab02f3bbe668256b'
|
||||
deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
|
||||
kernel_path = self.extract_from_deb(deb_path,
|
||||
'/boot/vmlinuz-5.10.16-sunxi')
|
||||
dtb_path = ('/usr/lib/linux-image-current-sunxi/'
|
||||
'/boot/vmlinuz-6.6.16-current-sunxi')
|
||||
dtb_path = ('/usr/lib/linux-image-6.6.16-current-sunxi/'
|
||||
'sun8i-r40-bananapi-m2-ultra.dtb')
|
||||
dtb_path = self.extract_from_deb(deb_path, dtb_path)
|
||||
rootfs_url = ('http://storage.kernelci.org/images/rootfs/buildroot/'
|
||||
@ -1049,12 +1049,12 @@ class BootLinuxConsole(LinuxKernelTest):
|
||||
:avocado: tags=accel:tcg
|
||||
"""
|
||||
deb_url = ('https://apt.armbian.com/pool/main/l/'
|
||||
'linux-5.10.16-sunxi/linux-image-current-sunxi_21.02.2_armhf.deb')
|
||||
deb_hash = '9fa84beda245cabf0b4fa84cf6eaa7738ead1da0'
|
||||
'linux-6.6.16/linux-image-current-sunxi_24.2.1_armhf__6.6.16-Seb3e-D6b4a-P2359-Ce96bHfe66-HK01ba-V014b-B067e-R448a.deb')
|
||||
deb_hash = 'f7c3c8c5432f765445dc6e7eab02f3bbe668256b'
|
||||
deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
|
||||
kernel_path = self.extract_from_deb(deb_path,
|
||||
'/boot/vmlinuz-5.10.16-sunxi')
|
||||
dtb_path = '/usr/lib/linux-image-current-sunxi/sun8i-h3-orangepi-pc.dtb'
|
||||
'/boot/vmlinuz-6.6.16-current-sunxi')
|
||||
dtb_path = '/usr/lib/linux-image-6.6.16-current-sunxi/sun8i-h3-orangepi-pc.dtb'
|
||||
dtb_path = self.extract_from_deb(deb_path, dtb_path)
|
||||
|
||||
self.vm.set_console()
|
||||
@ -1075,12 +1075,12 @@ class BootLinuxConsole(LinuxKernelTest):
|
||||
:avocado: tags=machine:orangepi-pc
|
||||
"""
|
||||
deb_url = ('https://apt.armbian.com/pool/main/l/'
|
||||
'linux-5.10.16-sunxi/linux-image-current-sunxi_21.02.2_armhf.deb')
|
||||
deb_hash = '9fa84beda245cabf0b4fa84cf6eaa7738ead1da0'
|
||||
'linux-6.6.16/linux-image-current-sunxi_24.2.1_armhf__6.6.16-Seb3e-D6b4a-P2359-Ce96bHfe66-HK01ba-V014b-B067e-R448a.deb')
|
||||
deb_hash = 'f7c3c8c5432f765445dc6e7eab02f3bbe668256b'
|
||||
deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
|
||||
kernel_path = self.extract_from_deb(deb_path,
|
||||
'/boot/vmlinuz-5.10.16-sunxi')
|
||||
dtb_path = '/usr/lib/linux-image-current-sunxi/sun8i-h3-orangepi-pc.dtb'
|
||||
'/boot/vmlinuz-6.6.16-current-sunxi')
|
||||
dtb_path = '/usr/lib/linux-image-6.6.16-current-sunxi/sun8i-h3-orangepi-pc.dtb'
|
||||
dtb_path = self.extract_from_deb(deb_path, dtb_path)
|
||||
initrd_url = ('https://github.com/groeck/linux-build-test/raw/'
|
||||
'2eb0a73b5d5a28df3170c546ddaaa9757e1e0848/rootfs/'
|
||||
@ -1121,12 +1121,12 @@ class BootLinuxConsole(LinuxKernelTest):
|
||||
self.require_netdev('user')
|
||||
|
||||
deb_url = ('https://apt.armbian.com/pool/main/l/'
|
||||
'linux-5.10.16-sunxi/linux-image-current-sunxi_21.02.2_armhf.deb')
|
||||
deb_hash = '9fa84beda245cabf0b4fa84cf6eaa7738ead1da0'
|
||||
'linux-6.6.16/linux-image-current-sunxi_24.2.1_armhf__6.6.16-Seb3e-D6b4a-P2359-Ce96bHfe66-HK01ba-V014b-B067e-R448a.deb')
|
||||
deb_hash = 'f7c3c8c5432f765445dc6e7eab02f3bbe668256b'
|
||||
deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
|
||||
kernel_path = self.extract_from_deb(deb_path,
|
||||
'/boot/vmlinuz-5.10.16-sunxi')
|
||||
dtb_path = '/usr/lib/linux-image-current-sunxi/sun8i-h3-orangepi-pc.dtb'
|
||||
'/boot/vmlinuz-6.6.16-current-sunxi')
|
||||
dtb_path = '/usr/lib/linux-image-6.6.16-current-sunxi/sun8i-h3-orangepi-pc.dtb'
|
||||
dtb_path = self.extract_from_deb(deb_path, dtb_path)
|
||||
rootfs_url = ('http://storage.kernelci.org/images/rootfs/buildroot/'
|
||||
'buildroot-baseline/20221116.0/armel/rootfs.ext2.xz')
|
||||
|
@ -203,12 +203,12 @@ class ReplayKernelNormal(ReplayKernelBase):
|
||||
:avocado: tags=machine:cubieboard
|
||||
"""
|
||||
deb_url = ('https://apt.armbian.com/pool/main/l/'
|
||||
'linux-5.10.16-sunxi/linux-image-current-sunxi_21.02.2_armhf.deb')
|
||||
deb_hash = '9fa84beda245cabf0b4fa84cf6eaa7738ead1da0'
|
||||
'linux-6.6.16/linux-image-current-sunxi_24.2.1_armhf__6.6.16-Seb3e-D6b4a-P2359-Ce96bHfe66-HK01ba-V014b-B067e-R448a.deb')
|
||||
deb_hash = 'f7c3c8c5432f765445dc6e7eab02f3bbe668256b'
|
||||
deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
|
||||
kernel_path = self.extract_from_deb(deb_path,
|
||||
'/boot/vmlinuz-5.10.16-sunxi')
|
||||
dtb_path = '/usr/lib/linux-image-current-sunxi/sun4i-a10-cubieboard.dtb'
|
||||
'/boot/vmlinuz-6.6.16-current-sunxi')
|
||||
dtb_path = '/usr/lib/linux-image-6.6.16-current-sunxi/sun4i-a10-cubieboard.dtb'
|
||||
dtb_path = self.extract_from_deb(deb_path, dtb_path)
|
||||
initrd_url = ('https://github.com/groeck/linux-build-test/raw/'
|
||||
'2eb0a73b5d5a28df3170c546ddaaa9757e1e0848/rootfs/'
|
||||
|
194
tests/qtest/dm163-test.c
Normal file
194
tests/qtest/dm163-test.c
Normal file
@ -0,0 +1,194 @@
|
||||
/*
|
||||
* QTest testcase for DM163
|
||||
*
|
||||
* Copyright (C) 2024 Samuel Tardieu <sam@rfc1149.net>
|
||||
* Copyright (C) 2024 Arnaud Minier <arnaud.minier@telecom-paris.fr>
|
||||
* Copyright (C) 2024 Inès Varhol <ines.varhol@telecom-paris.fr>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "libqtest.h"
|
||||
|
||||
enum DM163_INPUTS {
|
||||
SIN = 8,
|
||||
DCK = 9,
|
||||
RST_B = 10,
|
||||
LAT_B = 11,
|
||||
SELBK = 12,
|
||||
EN_B = 13
|
||||
};
|
||||
|
||||
#define DEVICE_NAME "/machine/dm163"
|
||||
#define GPIO_OUT(name, value) qtest_set_irq_in(qts, DEVICE_NAME, NULL, name, \
|
||||
value)
|
||||
#define GPIO_PULSE(name) \
|
||||
do { \
|
||||
GPIO_OUT(name, 1); \
|
||||
GPIO_OUT(name, 0); \
|
||||
} while (0)
|
||||
|
||||
|
||||
static void rise_gpio_pin_dck(QTestState *qts)
|
||||
{
|
||||
/* Configure output mode for pin PB1 */
|
||||
qtest_writel(qts, 0x48000400, 0xFFFFFEB7);
|
||||
/* Write 1 in ODR for PB1 */
|
||||
qtest_writel(qts, 0x48000414, 0x00000002);
|
||||
}
|
||||
|
||||
static void lower_gpio_pin_dck(QTestState *qts)
|
||||
{
|
||||
/* Configure output mode for pin PB1 */
|
||||
qtest_writel(qts, 0x48000400, 0xFFFFFEB7);
|
||||
/* Write 0 in ODR for PB1 */
|
||||
qtest_writel(qts, 0x48000414, 0x00000000);
|
||||
}
|
||||
|
||||
static void rise_gpio_pin_selbk(QTestState *qts)
|
||||
{
|
||||
/* Configure output mode for pin PC5 */
|
||||
qtest_writel(qts, 0x48000800, 0xFFFFF7FF);
|
||||
/* Write 1 in ODR for PC5 */
|
||||
qtest_writel(qts, 0x48000814, 0x00000020);
|
||||
}
|
||||
|
||||
static void lower_gpio_pin_selbk(QTestState *qts)
|
||||
{
|
||||
/* Configure output mode for pin PC5 */
|
||||
qtest_writel(qts, 0x48000800, 0xFFFFF7FF);
|
||||
/* Write 0 in ODR for PC5 */
|
||||
qtest_writel(qts, 0x48000814, 0x00000000);
|
||||
}
|
||||
|
||||
static void rise_gpio_pin_lat_b(QTestState *qts)
|
||||
{
|
||||
/* Configure output mode for pin PC4 */
|
||||
qtest_writel(qts, 0x48000800, 0xFFFFFDFF);
|
||||
/* Write 1 in ODR for PC4 */
|
||||
qtest_writel(qts, 0x48000814, 0x00000010);
|
||||
}
|
||||
|
||||
static void lower_gpio_pin_lat_b(QTestState *qts)
|
||||
{
|
||||
/* Configure output mode for pin PC4 */
|
||||
qtest_writel(qts, 0x48000800, 0xFFFFFDFF);
|
||||
/* Write 0 in ODR for PC4 */
|
||||
qtest_writel(qts, 0x48000814, 0x00000000);
|
||||
}
|
||||
|
||||
static void rise_gpio_pin_rst_b(QTestState *qts)
|
||||
{
|
||||
/* Configure output mode for pin PC3 */
|
||||
qtest_writel(qts, 0x48000800, 0xFFFFFF7F);
|
||||
/* Write 1 in ODR for PC3 */
|
||||
qtest_writel(qts, 0x48000814, 0x00000008);
|
||||
}
|
||||
|
||||
static void lower_gpio_pin_rst_b(QTestState *qts)
|
||||
{
|
||||
/* Configure output mode for pin PC3 */
|
||||
qtest_writel(qts, 0x48000800, 0xFFFFFF7F);
|
||||
/* Write 0 in ODR for PC3 */
|
||||
qtest_writel(qts, 0x48000814, 0x00000000);
|
||||
}
|
||||
|
||||
static void rise_gpio_pin_sin(QTestState *qts)
|
||||
{
|
||||
/* Configure output mode for pin PA4 */
|
||||
qtest_writel(qts, 0x48000000, 0xFFFFFDFF);
|
||||
/* Write 1 in ODR for PA4 */
|
||||
qtest_writel(qts, 0x48000014, 0x00000010);
|
||||
}
|
||||
|
||||
static void lower_gpio_pin_sin(QTestState *qts)
|
||||
{
|
||||
/* Configure output mode for pin PA4 */
|
||||
qtest_writel(qts, 0x48000000, 0xFFFFFDFF);
|
||||
/* Write 0 in ODR for PA4 */
|
||||
qtest_writel(qts, 0x48000014, 0x00000000);
|
||||
}
|
||||
|
||||
static void test_dm163_bank(const void *opaque)
|
||||
{
|
||||
const unsigned bank = (uintptr_t) opaque;
|
||||
const int width = bank ? 192 : 144;
|
||||
|
||||
QTestState *qts = qtest_initf("-M b-l475e-iot01a");
|
||||
qtest_irq_intercept_out_named(qts, DEVICE_NAME, "sout");
|
||||
GPIO_OUT(RST_B, 1);
|
||||
GPIO_OUT(EN_B, 0);
|
||||
GPIO_OUT(DCK, 0);
|
||||
GPIO_OUT(SELBK, bank);
|
||||
GPIO_OUT(LAT_B, 1);
|
||||
|
||||
/* Fill bank with zeroes */
|
||||
GPIO_OUT(SIN, 0);
|
||||
for (int i = 0; i < width; i++) {
|
||||
GPIO_PULSE(DCK);
|
||||
}
|
||||
/* Fill bank with ones, check that we get the previous zeroes */
|
||||
GPIO_OUT(SIN, 1);
|
||||
for (int i = 0; i < width; i++) {
|
||||
GPIO_PULSE(DCK);
|
||||
g_assert(!qtest_get_irq(qts, 0));
|
||||
}
|
||||
|
||||
/* Pulse one more bit in the bank, check that we get a one */
|
||||
GPIO_PULSE(DCK);
|
||||
g_assert(qtest_get_irq(qts, 0));
|
||||
|
||||
qtest_quit(qts);
|
||||
}
|
||||
|
||||
static void test_dm163_gpio_connection(void)
|
||||
{
|
||||
QTestState *qts = qtest_init("-M b-l475e-iot01a");
|
||||
qtest_irq_intercept_in(qts, DEVICE_NAME);
|
||||
|
||||
g_assert_false(qtest_get_irq(qts, SIN));
|
||||
g_assert_false(qtest_get_irq(qts, DCK));
|
||||
g_assert_false(qtest_get_irq(qts, RST_B));
|
||||
g_assert_false(qtest_get_irq(qts, LAT_B));
|
||||
g_assert_false(qtest_get_irq(qts, SELBK));
|
||||
|
||||
rise_gpio_pin_dck(qts);
|
||||
g_assert_true(qtest_get_irq(qts, DCK));
|
||||
lower_gpio_pin_dck(qts);
|
||||
g_assert_false(qtest_get_irq(qts, DCK));
|
||||
|
||||
rise_gpio_pin_lat_b(qts);
|
||||
g_assert_true(qtest_get_irq(qts, LAT_B));
|
||||
lower_gpio_pin_lat_b(qts);
|
||||
g_assert_false(qtest_get_irq(qts, LAT_B));
|
||||
|
||||
rise_gpio_pin_selbk(qts);
|
||||
g_assert_true(qtest_get_irq(qts, SELBK));
|
||||
lower_gpio_pin_selbk(qts);
|
||||
g_assert_false(qtest_get_irq(qts, SELBK));
|
||||
|
||||
rise_gpio_pin_rst_b(qts);
|
||||
g_assert_true(qtest_get_irq(qts, RST_B));
|
||||
lower_gpio_pin_rst_b(qts);
|
||||
g_assert_false(qtest_get_irq(qts, RST_B));
|
||||
|
||||
rise_gpio_pin_sin(qts);
|
||||
g_assert_true(qtest_get_irq(qts, SIN));
|
||||
lower_gpio_pin_sin(qts);
|
||||
g_assert_false(qtest_get_irq(qts, SIN));
|
||||
|
||||
g_assert_false(qtest_get_irq(qts, DCK));
|
||||
g_assert_false(qtest_get_irq(qts, LAT_B));
|
||||
g_assert_false(qtest_get_irq(qts, SELBK));
|
||||
g_assert_false(qtest_get_irq(qts, RST_B));
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
g_test_init(&argc, &argv, NULL);
|
||||
qtest_add_data_func("/dm163/bank0", (void *)0, test_dm163_bank);
|
||||
qtest_add_data_func("/dm163/bank1", (void *)1, test_dm163_bank);
|
||||
qtest_add_func("/dm163/gpio_connection", test_dm163_gpio_connection);
|
||||
return g_test_run();
|
||||
}
|
@ -224,6 +224,8 @@ qtests_arm = \
|
||||
(config_all_devices.has_key('CONFIG_MICROBIT') ? ['microbit-test'] : []) + \
|
||||
(config_all_devices.has_key('CONFIG_STM32L4X5_SOC') ? qtests_stm32l4x5 : []) + \
|
||||
(config_all_devices.has_key('CONFIG_FSI_APB2OPB_ASPEED') ? ['aspeed_fsi-test'] : []) + \
|
||||
(config_all_devices.has_key('CONFIG_STM32L4X5_SOC') and
|
||||
config_all_devices.has_key('CONFIG_DM163')? ['dm163-test'] : []) + \
|
||||
['arm-cpu-features',
|
||||
'boot-serial-test']
|
||||
|
||||
|
@ -43,6 +43,9 @@
|
||||
#define OTYPER_PUSH_PULL 0
|
||||
#define OTYPER_OPEN_DRAIN 1
|
||||
|
||||
/* SoC forwards GPIOs to SysCfg */
|
||||
#define SYSCFG "/machine/soc"
|
||||
|
||||
const uint32_t moder_reset[NUM_GPIOS] = {
|
||||
0xABFFFFFF,
|
||||
0xFFFFFEBF,
|
||||
@ -284,7 +287,7 @@ static void test_gpio_output_mode(const void *data)
|
||||
uint32_t gpio = test_gpio_addr(data);
|
||||
unsigned int gpio_id = get_gpio_id(gpio);
|
||||
|
||||
qtest_irq_intercept_in(global_qtest, "/machine/soc/syscfg");
|
||||
qtest_irq_intercept_in(global_qtest, SYSCFG);
|
||||
|
||||
/* Set a bit in ODR and check nothing happens */
|
||||
gpio_set_bit(gpio, ODR, pin, 1);
|
||||
@ -319,7 +322,7 @@ static void test_gpio_input_mode(const void *data)
|
||||
uint32_t gpio = test_gpio_addr(data);
|
||||
unsigned int gpio_id = get_gpio_id(gpio);
|
||||
|
||||
qtest_irq_intercept_in(global_qtest, "/machine/soc/syscfg");
|
||||
qtest_irq_intercept_in(global_qtest, SYSCFG);
|
||||
|
||||
/* Configure a line as input, raise it, and check that the pin is high */
|
||||
gpio_set_2bits(gpio, MODER, pin, MODER_INPUT);
|
||||
@ -348,7 +351,7 @@ static void test_pull_up_pull_down(const void *data)
|
||||
uint32_t gpio = test_gpio_addr(data);
|
||||
unsigned int gpio_id = get_gpio_id(gpio);
|
||||
|
||||
qtest_irq_intercept_in(global_qtest, "/machine/soc/syscfg");
|
||||
qtest_irq_intercept_in(global_qtest, SYSCFG);
|
||||
|
||||
/* Configure a line as input with pull-up, check the line is set high */
|
||||
gpio_set_2bits(gpio, MODER, pin, MODER_INPUT);
|
||||
@ -378,7 +381,7 @@ static void test_push_pull(const void *data)
|
||||
uint32_t gpio = test_gpio_addr(data);
|
||||
uint32_t gpio2 = GPIO_BASE_ADDR + (GPIO_H - gpio);
|
||||
|
||||
qtest_irq_intercept_in(global_qtest, "/machine/soc/syscfg");
|
||||
qtest_irq_intercept_in(global_qtest, SYSCFG);
|
||||
|
||||
/* Setting a line high externally, configuring it in push-pull output */
|
||||
/* And checking the pin was disconnected */
|
||||
@ -425,7 +428,7 @@ static void test_open_drain(const void *data)
|
||||
uint32_t gpio = test_gpio_addr(data);
|
||||
uint32_t gpio2 = GPIO_BASE_ADDR + (GPIO_H - gpio);
|
||||
|
||||
qtest_irq_intercept_in(global_qtest, "/machine/soc/syscfg");
|
||||
qtest_irq_intercept_in(global_qtest, SYSCFG);
|
||||
|
||||
/* Setting a line high externally, configuring it in open-drain output */
|
||||
/* And checking the pin was disconnected */
|
||||
|
@ -1,8 +1,8 @@
|
||||
/*
|
||||
* QTest testcase for STM32L4x5_SYSCFG
|
||||
*
|
||||
* Copyright (c) 2023 Arnaud Minier <arnaud.minier@telecom-paris.fr>
|
||||
* Copyright (c) 2023 Inès Varhol <ines.varhol@telecom-paris.fr>
|
||||
* Copyright (c) 2024 Arnaud Minier <arnaud.minier@telecom-paris.fr>
|
||||
* Copyright (c) 2024 Inès Varhol <ines.varhol@telecom-paris.fr>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
@ -25,6 +25,10 @@
|
||||
#define SYSCFG_SWPR2 0x28
|
||||
#define INVALID_ADDR 0x2C
|
||||
|
||||
/* SoC forwards GPIOs to SysCfg */
|
||||
#define SYSCFG "/machine/soc"
|
||||
#define EXTI "/machine/soc/exti"
|
||||
|
||||
static void syscfg_writel(unsigned int offset, uint32_t value)
|
||||
{
|
||||
writel(SYSCFG_BASE_ADDR + offset, value);
|
||||
@ -37,8 +41,7 @@ static uint32_t syscfg_readl(unsigned int offset)
|
||||
|
||||
static void syscfg_set_irq(int num, int level)
|
||||
{
|
||||
qtest_set_irq_in(global_qtest, "/machine/soc/syscfg",
|
||||
NULL, num, level);
|
||||
qtest_set_irq_in(global_qtest, SYSCFG, NULL, num, level);
|
||||
}
|
||||
|
||||
static void system_reset(void)
|
||||
@ -197,7 +200,7 @@ static void test_interrupt(void)
|
||||
* Test that GPIO rising lines result in an irq
|
||||
* with the right configuration
|
||||
*/
|
||||
qtest_irq_intercept_in(global_qtest, "/machine/soc/exti");
|
||||
qtest_irq_intercept_in(global_qtest, EXTI);
|
||||
|
||||
/* GPIOA is the default source for EXTI lines 0 to 15 */
|
||||
|
||||
@ -230,7 +233,7 @@ static void test_irq_pin_multiplexer(void)
|
||||
* Test that syscfg irq sets the right exti irq
|
||||
*/
|
||||
|
||||
qtest_irq_intercept_in(global_qtest, "/machine/soc/exti");
|
||||
qtest_irq_intercept_in(global_qtest, EXTI);
|
||||
|
||||
syscfg_set_irq(0, 1);
|
||||
|
||||
@ -257,7 +260,7 @@ static void test_irq_gpio_multiplexer(void)
|
||||
* Test that an irq is generated only by the right GPIO
|
||||
*/
|
||||
|
||||
qtest_irq_intercept_in(global_qtest, "/machine/soc/exti");
|
||||
qtest_irq_intercept_in(global_qtest, EXTI);
|
||||
|
||||
/* GPIOA is the default source for EXTI lines 0 to 15 */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user