summary refs log tree commit diff stats
path: root/tests/qtest/stm32l4x5_rcc-test.c
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2024-03-05 13:54:54 +0000
committerPeter Maydell <peter.maydell@linaro.org>2024-03-05 13:54:54 +0000
commitdb596ae19040574e41d086e78469014191d7d7fc (patch)
tree8c2b6253966f2dfed3983b6aea86b83b6c840900 /tests/qtest/stm32l4x5_rcc-test.c
parent7d4e29ef805f7ebc03e547bb8ae82a86ee69c41b (diff)
parent7558300c53057126514ee0fd5cf629c65ccc20e1 (diff)
downloadfocaccia-qemu-db596ae19040574e41d086e78469014191d7d7fc.tar.gz
focaccia-qemu-db596ae19040574e41d086e78469014191d7d7fc.zip
Merge tag 'pull-target-arm-20240305' of https://git.linaro.org/people/pmaydell/qemu-arm into staging
target-arm queue:
 * raspi: Implement Broadcom Serial Controller (BSC) for BCM2835 boards
 * hw/char/pl011: Add support for loopback
 * STM32L4x5: Implement RCC clock control device
 * target/arm: Do memory type alignment checks
 * atomic.h: Reword confusing comment for qatomic_cmpxchg
 * qemu-options.hx: Don't claim "-serial" has limit of 4 serial ports

# -----BEGIN PGP SIGNATURE-----
#
# iQJNBAABCAA3FiEE4aXFk81BneKOgxXPPCUl7RQ2DN4FAmXnI4gZHHBldGVyLm1h
# eWRlbGxAbGluYXJvLm9yZwAKCRA8JSXtFDYM3p5ED/wOtAHA3PK+WbQhVhnji3+k
# gdhvVcldf+HLaI2v4tfaW152xjY80/j3PQFNkzptoXENA9U51F47oNYOIfULLZZX
# FTKmw/mjTBc2LqJ8gLpS8Wkr/PFtDq9JJzDwZd0MwguXpzIJp31JJpESvXlAqjjv
# FhuAcqNNuGwI2SXCBmp2lPoEMn8ExLDoG9rmzjxVZeZCyzUjVnJYM61ykhC4ByvK
# j5+/a7pUcpgHSX5cbq7kFloPOx3JXI5lS6xUKhGXXk75qHRwiQIsxMcPq8PD1+ok
# yrmp7cySwK8I7AlIPdDjpJmhU0OiBu+PkYiXmHlF2nvaUy6M0nVX2lSTzqj6VpVV
# 7yYhvWXHrtIA9AUspqTRsX7tP7iMJkco7qWfKSzYl+3pTbxS4+rEoee4jNR3hqsU
# lbWC47sNVtTN507qIL1dcsu+BaeSsYVftfxtFql3odTqRB+ticsjDfKg69dRSFyk
# SS0t8Zy3TdomcEoQkAv/ZSpkQnQUGavbRumCG58lJdiTwTuJUmGi1ufKBrD/GeKj
# IlDEl9yvKiR8uvdjj6EQqr5kOj09mmN5nvokNsq5a4aNXBYoesszWK2xodzXE2x5
# M9DHJ3S8xnN++p1idS2bikwEklG1XVQ/q52bDXQkUmQSNerVS1PCvg9hzYqA+x53
# ihJtMcsmGVfxY8aQHyHweA==
# =isAe
# -----END PGP SIGNATURE-----
# gpg: Signature made Tue 05 Mar 2024 13:52:08 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-20240305' of https://git.linaro.org/people/pmaydell/qemu-arm:
  qemu-options.hx: Don't claim "-serial" has limit of 4 serial ports
  atomic.h: Reword confusing comment for qatomic_cmpxchg
  target/arm: Do memory type alignment check when translation enabled
  target/arm: Do memory type alignment check when translation disabled
  accel/tcg: Add TLB_CHECK_ALIGNED
  accel/tcg: Add tlb_fill_flags to CPUTLBEntryFull
  exec/memattrs: Remove target_tlb_bit*
  target/arm: Support 32-byte alignment in pow2_align
  tests/qtest/stm32l4x5_rcc-test.c: Add tests for the STM32L4x5_RCC
  hw/arm/stm32l4x5_soc.c: Use the RCC Sysclk
  hw/misc/stm32l4x5_rcc: Add write protections to CR register
  hw/misc/stm32l4x5_rcc: Handle Register Updates
  hw/misc/stm32l4x5_rcc: Initialize PLLs and clock multiplexers
  hw/misc/stm32l4x5_rcc: Add an internal PLL Clock object
  hw/misc/stm32l4x5_rcc: Add an internal clock multiplexer object
  hw/misc/stm32l4x5_rcc: Implement STM32L4x5_RCC skeleton
  hw/char/pl011: Add support for loopback
  tests/qtest: Add testcase for BCM2835 BSC
  hw/arm: Connect BSC to BCM2835 board as I2C0, I2C1 and I2C2
  hw/i2c: Implement Broadcom Serial Controller (BSC)

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'tests/qtest/stm32l4x5_rcc-test.c')
-rw-r--r--tests/qtest/stm32l4x5_rcc-test.c189
1 files changed, 189 insertions, 0 deletions
diff --git a/tests/qtest/stm32l4x5_rcc-test.c b/tests/qtest/stm32l4x5_rcc-test.c
new file mode 100644
index 0000000000..d927c655d1
--- /dev/null
+++ b/tests/qtest/stm32l4x5_rcc-test.c
@@ -0,0 +1,189 @@
+/*
+ * QTest testcase for STM32L4x5_RCC
+ *
+ * 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.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/registerfields.h"
+#include "libqtest-single.h"
+#include "hw/misc/stm32l4x5_rcc_internals.h"
+
+#define RCC_BASE_ADDR 0x40021000
+#define NVIC_ISER 0xE000E100
+#define NVIC_ISPR 0xE000E200
+#define NVIC_ICPR 0xE000E280
+#define RCC_IRQ 5
+
+static void enable_nvic_irq(unsigned int n)
+{
+    writel(NVIC_ISER, 1 << n);
+}
+
+static void unpend_nvic_irq(unsigned int n)
+{
+    writel(NVIC_ICPR, 1 << n);
+}
+
+static bool check_nvic_pending(unsigned int n)
+{
+    return readl(NVIC_ISPR) & (1 << n);
+}
+
+static void rcc_writel(unsigned int offset, uint32_t value)
+{
+    writel(RCC_BASE_ADDR + offset, value);
+}
+
+static uint32_t rcc_readl(unsigned int offset)
+{
+    return readl(RCC_BASE_ADDR + offset);
+}
+
+static void test_init_msi(void)
+{
+    /* MSIRANGE can be set only when MSI is OFF or READY */
+    rcc_writel(A_CR, R_CR_MSION_MASK);
+    /* Wait until MSI is stable */
+    g_assert_true((rcc_readl(A_CR) & R_CR_MSIRDY_MASK) == R_CR_MSIRDY_MASK);
+    /* TODO find a way to test MSI value */
+}
+
+static void test_set_msi_as_sysclk(void)
+{
+    /* Clocking from MSI, in case MSI was not the default source */
+    rcc_writel(A_CFGR, 0);
+    /* Wait until MSI is selected and stable */
+    g_assert_true((rcc_readl(A_CFGR) & R_CFGR_SWS_MASK) == 0);
+}
+
+static void test_init_pll(void)
+{
+    uint32_t value;
+
+    /*
+     * Update PLL and set MSI as the source clock.
+     * PLLM = 1 --> 000
+     * PLLN = 40 --> 40
+     * PPLLR = 2 --> 00
+     * PLLDIV = unused, PLLP = unused (SAI3), PLLQ = unused (48M1)
+     * SRC = MSI --> 01
+     */
+    rcc_writel(A_PLLCFGR, R_PLLCFGR_PLLREN_MASK |
+            (40 << R_PLLCFGR_PLLN_SHIFT) |
+            (0b01 << R_PLLCFGR_PLLSRC_SHIFT));
+
+    /* PLL activation */
+    value = rcc_readl(A_CR);
+    rcc_writel(A_CR, value | R_CR_PLLON_MASK);
+
+    /* Waiting for PLL lock. */
+    g_assert_true((rcc_readl(A_CR) & R_CR_PLLRDY_MASK) == R_CR_PLLRDY_MASK);
+
+    /* Switches on the PLL clock source */
+    value = rcc_readl(A_CFGR);
+    rcc_writel(A_CFGR, (value & ~R_CFGR_SW_MASK) |
+        (0b11 << R_CFGR_SW_SHIFT));
+
+    /* Wait until SYSCLK is stable. */
+    g_assert_true((rcc_readl(A_CFGR) & R_CFGR_SWS_MASK) ==
+        (0b11 << R_CFGR_SWS_SHIFT));
+}
+
+static void test_activate_lse(void)
+{
+    /* LSE activation, no LSE Bypass */
+    rcc_writel(A_BDCR, R_BDCR_LSEDRV_MASK | R_BDCR_LSEON_MASK);
+    g_assert_true((rcc_readl(A_BDCR) & R_BDCR_LSERDY_MASK) == R_BDCR_LSERDY_MASK);
+}
+
+static void test_irq(void)
+{
+    enable_nvic_irq(RCC_IRQ);
+
+    rcc_writel(A_CIER, R_CIER_LSIRDYIE_MASK);
+    rcc_writel(A_CSR, R_CSR_LSION_MASK);
+    g_assert_true(check_nvic_pending(RCC_IRQ));
+    rcc_writel(A_CICR, R_CICR_LSIRDYC_MASK);
+    unpend_nvic_irq(RCC_IRQ);
+
+    rcc_writel(A_CIER, R_CIER_LSERDYIE_MASK);
+    rcc_writel(A_BDCR, R_BDCR_LSEON_MASK);
+    g_assert_true(check_nvic_pending(RCC_IRQ));
+    rcc_writel(A_CICR, R_CICR_LSERDYC_MASK);
+    unpend_nvic_irq(RCC_IRQ);
+
+    /*
+     * MSI has been enabled by previous tests,
+     * shouln't generate an interruption.
+     */
+    rcc_writel(A_CIER, R_CIER_MSIRDYIE_MASK);
+    rcc_writel(A_CR, R_CR_MSION_MASK);
+    g_assert_false(check_nvic_pending(RCC_IRQ));
+
+    rcc_writel(A_CIER, R_CIER_HSIRDYIE_MASK);
+    rcc_writel(A_CR, R_CR_HSION_MASK);
+    g_assert_true(check_nvic_pending(RCC_IRQ));
+    rcc_writel(A_CICR, R_CICR_HSIRDYC_MASK);
+    unpend_nvic_irq(RCC_IRQ);
+
+    rcc_writel(A_CIER, R_CIER_HSERDYIE_MASK);
+    rcc_writel(A_CR, R_CR_HSEON_MASK);
+    g_assert_true(check_nvic_pending(RCC_IRQ));
+    rcc_writel(A_CICR, R_CICR_HSERDYC_MASK);
+    unpend_nvic_irq(RCC_IRQ);
+
+    /*
+     * PLL has been enabled by previous tests,
+     * shouln't generate an interruption.
+     */
+    rcc_writel(A_CIER, R_CIER_PLLRDYIE_MASK);
+    rcc_writel(A_CR, R_CR_PLLON_MASK);
+    g_assert_false(check_nvic_pending(RCC_IRQ));
+
+    rcc_writel(A_CIER, R_CIER_PLLSAI1RDYIE_MASK);
+    rcc_writel(A_CR, R_CR_PLLSAI1ON_MASK);
+    g_assert_true(check_nvic_pending(RCC_IRQ));
+    rcc_writel(A_CICR, R_CICR_PLLSAI1RDYC_MASK);
+    unpend_nvic_irq(RCC_IRQ);
+
+    rcc_writel(A_CIER, R_CIER_PLLSAI2RDYIE_MASK);
+    rcc_writel(A_CR, R_CR_PLLSAI2ON_MASK);
+    g_assert_true(check_nvic_pending(RCC_IRQ));
+    rcc_writel(A_CICR, R_CICR_PLLSAI2RDYC_MASK);
+    unpend_nvic_irq(RCC_IRQ);
+}
+
+int main(int argc, char **argv)
+{
+    int ret;
+
+    g_test_init(&argc, &argv, NULL);
+    g_test_set_nonfatal_assertions();
+    /*
+     * These test separately that we can enable the plls, change the sysclk,
+     * and enable different devices.
+     * They are dependent on one another.
+     * We assume that all operations that would take some time to have an effect
+     * (e.g. changing the PLL frequency) are done instantaneously.
+     */
+    qtest_add_func("stm32l4x5/rcc/init_msi", test_init_msi);
+    qtest_add_func("stm32l4x5/rcc/set_msi_as_sysclk",
+        test_set_msi_as_sysclk);
+    qtest_add_func("stm32l4x5/rcc/activate_lse", test_activate_lse);
+    qtest_add_func("stm32l4x5/rcc/init_pll", test_init_pll);
+
+    qtest_add_func("stm32l4x5/rcc/irq", test_irq);
+
+    qtest_start("-machine b-l475e-iot01a");
+    ret = g_test_run();
+    qtest_end();
+
+    return ret;
+}