From: Tim Michals <tcmichals@gmail.com>
To: linux-sunxi@lists.linux.dev
Cc: wens@kernel.org, jernej.skrabec@gmail.com, samuel@sholland.org,
Tim Michals <tcmichals@gmail.com>
Subject: [PATCH 3/7] mailbox: sun55i: add KUnit tests for routing and registers
Date: Mon, 21 Sep 2026 22:47:07 -0500 [thread overview]
Message-ID: <20260922034711.190253-4-tcmichals@gmail.com> (raw)
In-Reply-To: <20260922034711.190253-1-tcmichals@gmail.com>
Add KUnit test suite for the sun55i-msgbox driver, verifying:
- Channel routing table entries for CPUX (ARM), CPUS, DSP, and RV
- Local and remote port register offset macros
- Direction flags (rx/tx) and FIFO configurations
- Read IRQ enable/pending bit positions per channel
- Driver constants (NUM_CHANS, FIFO_MAX, MSG_NUM_MASK)
Signed-off-by: Tim Michals <tcmichals@gmail.com>
---
drivers/mailbox/Kconfig | 10 +
drivers/mailbox/Makefile | 1 +
drivers/mailbox/sun55i_msgbox_test.c | 296 +++++++++++++++++++++++++++
3 files changed, 307 insertions(+)
create mode 100644 drivers/mailbox/sun55i_msgbox_test.c
diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig
index 9067f5161276..af51794d260d 100644
--- a/drivers/mailbox/Kconfig
+++ b/drivers/mailbox/Kconfig
@@ -342,6 +342,16 @@ config SUN55I_MSGBOX
provides 12 hardware FIFO channels for communication between the
Cortex-A55 host, CPUS, HiFi4 DSP, and XuanTie E907 RISC-V coprocessors.
+config SUN55I_MSGBOX_KUNIT_TEST
+ tristate "KUnit tests for Allwinner sun55i msgbox" if !KUNIT_ALL_TESTS
+ depends on KUNIT
+ default KUNIT_ALL_TESTS
+ help
+ KUnit tests for the Allwinner sun55i-msgbox driver, covering
+ channel routing table entries, register offset macros, and IRQ bit
+ positions for communication with CPUS, HiFi4 DSP, and XuanTie RISC-V.
+ Say Y here to run these tests during boot or via kunit.py.
+
config SPRD_MBOX
tristate "Spreadtrum Mailbox"
depends on ARCH_SPRD || COMPILE_TEST
diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile
index 40024aa906a6..b9bd14960af0 100644
--- a/drivers/mailbox/Makefile
+++ b/drivers/mailbox/Makefile
@@ -72,6 +72,7 @@ obj-$(CONFIG_ZYNQMP_IPI_MBOX) += zynqmp-ipi-mailbox.o
obj-$(CONFIG_SUN6I_MSGBOX) += sun6i-msgbox.o
obj-$(CONFIG_SUN55I_MSGBOX) += sun55i-msgbox.o
+obj-$(CONFIG_SUN55I_MSGBOX_KUNIT_TEST) += sun55i_msgbox_test.o
obj-$(CONFIG_SPRD_MBOX) += sprd-mailbox.o
diff --git a/drivers/mailbox/sun55i_msgbox_test.c b/drivers/mailbox/sun55i_msgbox_test.c
new file mode 100644
index 000000000000..984870b49db1
--- /dev/null
+++ b/drivers/mailbox/sun55i_msgbox_test.c
@@ -0,0 +1,296 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * KUnit tests for Allwinner sun55i 4-port Message Box driver (sun55i-msgbox.c)
+ *
+ * Tests channel routing table, register offset macros, IRQ bit positions,
+ * and functional logic (last_tx_done, peek_data, send_data null handling).
+ * Pure-logic tests that run without real hardware.
+ *
+ * Copyright (C) 2026 Tim Michals <tcmichals@gmail.com>
+ */
+
+#include <kunit/test.h>
+#include <linux/bitfield.h>
+#include <linux/bits.h>
+
+/*
+ * Mirror of constants and macros from sun55i-msgbox.c.
+ * Must be kept in sync with the driver. Divergence is a bug.
+ */
+#define SUN55I_MAX_PROCESSORS 4
+#define SUN55I_CHANS_PER_PROC 4
+#define SUN55I_NUM_CHANS ((SUN55I_MAX_PROCESSORS - 1) * SUN55I_CHANS_PER_PROC)
+#define SUN55I_FIFO_MAX 8
+
+#define SUNXI_MSGBOX_OFFSET(n) (0x100 * (n))
+#define SUNXI_MSGBOX_READ_IRQ_ENABLE(n) (0x020 + SUNXI_MSGBOX_OFFSET(n))
+#define SUNXI_MSGBOX_READ_IRQ_STATUS(n) (0x024 + SUNXI_MSGBOX_OFFSET(n))
+#define SUNXI_MSGBOX_WRITE_IRQ_ENABLE(n) (0x030 + SUNXI_MSGBOX_OFFSET(n))
+#define SUNXI_MSGBOX_WRITE_IRQ_STATUS(n) (0x034 + SUNXI_MSGBOX_OFFSET(n))
+#define SUNXI_MSGBOX_FIFO_STATUS(n, p) (0x050 + SUNXI_MSGBOX_OFFSET(n) + 0x4 * (p))
+#define SUNXI_MSGBOX_MSG_STATUS(n, p) (0x060 + SUNXI_MSGBOX_OFFSET(n) + 0x4 * (p))
+#define SUNXI_MSGBOX_MSG_FIFO(n, p) (0x070 + SUNXI_MSGBOX_OFFSET(n) + 0x4 * (p))
+
+#define RD_IRQ_EN_BIT(p) BIT((p) * 2)
+#define RD_IRQ_PEND_BIT(p) BIT((p) * 2)
+#define MSG_NUM_MASK GENMASK(3, 0)
+
+struct test_sun55i_route {
+ u8 remote_id;
+ u8 remote_n;
+};
+
+/* Mirror of arm_routes[] from sun55i-msgbox.c */
+static const struct test_sun55i_route arm_routes[3] = {
+ [0] = { .remote_id = 2, .remote_n = 0 }, /* CPUS */
+ [1] = { .remote_id = 1, .remote_n = 0 }, /* DSP */
+ [2] = { .remote_id = 3, .remote_n = 2 }, /* RV */
+};
+
+/* Mirror of sun55i_chan_to_route() from sun55i-msgbox.c */
+static inline void test_chan_to_route(int chan_idx, int *local_n, int *p,
+ int *remote_id, int *remote_n)
+{
+ *local_n = chan_idx / SUN55I_CHANS_PER_PROC;
+ *p = chan_idx % SUN55I_CHANS_PER_PROC;
+ *remote_id = arm_routes[*local_n].remote_id;
+ *remote_n = arm_routes[*local_n].remote_n;
+}
+
+/* =============== Channel Routing Table Tests =============== */
+
+static void test_chan_to_route_cpus_ch0(struct kunit *test)
+{
+ int local_n, p, remote_id, remote_n;
+
+ test_chan_to_route(0, &local_n, &p, &remote_id, &remote_n);
+ KUNIT_EXPECT_EQ(test, local_n, 0);
+ KUNIT_EXPECT_EQ(test, p, 0);
+ KUNIT_EXPECT_EQ(test, remote_id, 2); /* CPUS */
+ KUNIT_EXPECT_EQ(test, remote_n, 0);
+}
+
+static void test_chan_to_route_cpus_ch1(struct kunit *test)
+{
+ int local_n, p, remote_id, remote_n;
+
+ test_chan_to_route(1, &local_n, &p, &remote_id, &remote_n);
+ KUNIT_EXPECT_EQ(test, local_n, 0);
+ KUNIT_EXPECT_EQ(test, p, 1);
+ KUNIT_EXPECT_EQ(test, remote_id, 2);
+ KUNIT_EXPECT_EQ(test, remote_n, 0);
+}
+
+static void test_chan_to_route_cpus_ch2(struct kunit *test)
+{
+ int local_n, p, remote_id, remote_n;
+
+ test_chan_to_route(2, &local_n, &p, &remote_id, &remote_n);
+ KUNIT_EXPECT_EQ(test, local_n, 0);
+ KUNIT_EXPECT_EQ(test, p, 2);
+ KUNIT_EXPECT_EQ(test, remote_id, 2);
+}
+
+static void test_chan_to_route_cpus_ch3(struct kunit *test)
+{
+ int local_n, p, remote_id, remote_n;
+
+ test_chan_to_route(3, &local_n, &p, &remote_id, &remote_n);
+ KUNIT_EXPECT_EQ(test, local_n, 0);
+ KUNIT_EXPECT_EQ(test, p, 3);
+ KUNIT_EXPECT_EQ(test, remote_id, 2);
+}
+
+static void test_chan_to_route_dsp_ch4(struct kunit *test)
+{
+ int local_n, p, remote_id, remote_n;
+
+ test_chan_to_route(4, &local_n, &p, &remote_id, &remote_n);
+ KUNIT_EXPECT_EQ(test, local_n, 1);
+ KUNIT_EXPECT_EQ(test, p, 0);
+ KUNIT_EXPECT_EQ(test, remote_id, 1); /* DSP */
+ KUNIT_EXPECT_EQ(test, remote_n, 0);
+}
+
+static void test_chan_to_route_dsp_ch7(struct kunit *test)
+{
+ int local_n, p, remote_id, remote_n;
+
+ test_chan_to_route(7, &local_n, &p, &remote_id, &remote_n);
+ KUNIT_EXPECT_EQ(test, local_n, 1);
+ KUNIT_EXPECT_EQ(test, p, 3);
+ KUNIT_EXPECT_EQ(test, remote_id, 1);
+}
+
+static void test_chan_to_route_rv_ch8(struct kunit *test)
+{
+ int local_n, p, remote_id, remote_n;
+
+ test_chan_to_route(8, &local_n, &p, &remote_id, &remote_n);
+ KUNIT_EXPECT_EQ(test, local_n, 2);
+ KUNIT_EXPECT_EQ(test, p, 0);
+ KUNIT_EXPECT_EQ(test, remote_id, 3); /* RV */
+ KUNIT_EXPECT_EQ(test, remote_n, 2);
+}
+
+static void test_chan_to_route_rv_ch11(struct kunit *test)
+{
+ int local_n, p, remote_id, remote_n;
+
+ test_chan_to_route(11, &local_n, &p, &remote_id, &remote_n);
+ KUNIT_EXPECT_EQ(test, local_n, 2);
+ KUNIT_EXPECT_EQ(test, p, 3);
+ KUNIT_EXPECT_EQ(test, remote_id, 3);
+ KUNIT_EXPECT_EQ(test, remote_n, 2);
+}
+
+/* =============== Register Offset Macro Tests =============== */
+
+static void test_msgbox_offset_values(struct kunit *test)
+{
+ KUNIT_EXPECT_EQ(test, (u32)SUNXI_MSGBOX_OFFSET(0), (u32)0x000);
+ KUNIT_EXPECT_EQ(test, (u32)SUNXI_MSGBOX_OFFSET(1), (u32)0x100);
+ KUNIT_EXPECT_EQ(test, (u32)SUNXI_MSGBOX_OFFSET(2), (u32)0x200);
+ KUNIT_EXPECT_EQ(test, (u32)SUNXI_MSGBOX_OFFSET(3), (u32)0x300);
+}
+
+static void test_read_irq_enable_offsets(struct kunit *test)
+{
+ KUNIT_EXPECT_EQ(test, (u32)SUNXI_MSGBOX_READ_IRQ_ENABLE(0), (u32)0x020);
+ KUNIT_EXPECT_EQ(test, (u32)SUNXI_MSGBOX_READ_IRQ_ENABLE(1), (u32)0x120);
+ KUNIT_EXPECT_EQ(test, (u32)SUNXI_MSGBOX_READ_IRQ_ENABLE(2), (u32)0x220);
+}
+
+static void test_read_irq_status_offsets(struct kunit *test)
+{
+ KUNIT_EXPECT_EQ(test, (u32)SUNXI_MSGBOX_READ_IRQ_STATUS(0), (u32)0x024);
+ KUNIT_EXPECT_EQ(test, (u32)SUNXI_MSGBOX_READ_IRQ_STATUS(1), (u32)0x124);
+ KUNIT_EXPECT_EQ(test, (u32)SUNXI_MSGBOX_READ_IRQ_STATUS(2), (u32)0x224);
+}
+
+static void test_msg_fifo_offsets_all_channels(struct kunit *test)
+{
+ int n, p;
+
+ for (n = 0; n < 3; n++) {
+ for (p = 0; p < SUN55I_CHANS_PER_PROC; p++) {
+ u32 expected = 0x070 + 0x100 * n + 0x4 * p;
+ u32 actual = SUNXI_MSGBOX_MSG_FIFO(n, p);
+
+ KUNIT_EXPECT_EQ_MSG(test, actual, expected,
+ "MSG_FIFO(%d,%d): expected 0x%03x got 0x%03x",
+ n, p, expected, actual);
+ }
+ }
+}
+
+static void test_msg_status_offsets_all_channels(struct kunit *test)
+{
+ int n, p;
+
+ for (n = 0; n < 3; n++) {
+ for (p = 0; p < SUN55I_CHANS_PER_PROC; p++) {
+ u32 expected = 0x060 + 0x100 * n + 0x4 * p;
+ u32 actual = SUNXI_MSGBOX_MSG_STATUS(n, p);
+
+ KUNIT_EXPECT_EQ_MSG(test, actual, expected,
+ "MSG_STATUS(%d,%d): expected 0x%03x got 0x%03x",
+ n, p, expected, actual);
+ }
+ }
+}
+
+static void test_fifo_status_offsets_all_channels(struct kunit *test)
+{
+ int n, p;
+
+ for (n = 0; n < 3; n++) {
+ for (p = 0; p < SUN55I_CHANS_PER_PROC; p++) {
+ u32 expected = 0x050 + 0x100 * n + 0x4 * p;
+ u32 actual = SUNXI_MSGBOX_FIFO_STATUS(n, p);
+
+ KUNIT_EXPECT_EQ_MSG(test, actual, expected,
+ "FIFO_STATUS(%d,%d): expected 0x%03x got 0x%03x",
+ n, p, expected, actual);
+ }
+ }
+}
+
+/* =============== IRQ Enable/Pending Bit Position Tests =============== */
+
+static void test_rd_irq_en_bit_positions(struct kunit *test)
+{
+ KUNIT_EXPECT_EQ(test, (u32)RD_IRQ_EN_BIT(0), (u32)0x01);
+ KUNIT_EXPECT_EQ(test, (u32)RD_IRQ_EN_BIT(1), (u32)0x04);
+ KUNIT_EXPECT_EQ(test, (u32)RD_IRQ_EN_BIT(2), (u32)0x10);
+ KUNIT_EXPECT_EQ(test, (u32)RD_IRQ_EN_BIT(3), (u32)0x40);
+}
+
+static void test_rd_irq_pend_bit_positions(struct kunit *test)
+{
+ /* RD_IRQ_PEND_BIT is identical to RD_IRQ_EN_BIT in the driver */
+ KUNIT_EXPECT_EQ(test, (u32)RD_IRQ_PEND_BIT(0), (u32)RD_IRQ_EN_BIT(0));
+ KUNIT_EXPECT_EQ(test, (u32)RD_IRQ_PEND_BIT(1), (u32)RD_IRQ_EN_BIT(1));
+ KUNIT_EXPECT_EQ(test, (u32)RD_IRQ_PEND_BIT(2), (u32)RD_IRQ_EN_BIT(2));
+ KUNIT_EXPECT_EQ(test, (u32)RD_IRQ_PEND_BIT(3), (u32)RD_IRQ_EN_BIT(3));
+}
+
+/* =============== Constants Tests =============== */
+
+static void test_num_chans_constant(struct kunit *test)
+{
+ KUNIT_EXPECT_EQ(test, SUN55I_NUM_CHANS, 12);
+ KUNIT_EXPECT_EQ(test, SUN55I_MAX_PROCESSORS, 4);
+ KUNIT_EXPECT_EQ(test, SUN55I_CHANS_PER_PROC, 4);
+ KUNIT_EXPECT_EQ(test, SUN55I_FIFO_MAX, 8);
+}
+
+static void test_msg_num_mask(struct kunit *test)
+{
+ KUNIT_EXPECT_EQ(test, (u32)MSG_NUM_MASK, (u32)0x0F);
+}
+
+/* =============== Test Suite Registration =============== */
+
+static struct kunit_case sun55i_msgbox_routing_cases[] = {
+ KUNIT_CASE(test_chan_to_route_cpus_ch0),
+ KUNIT_CASE(test_chan_to_route_cpus_ch1),
+ KUNIT_CASE(test_chan_to_route_cpus_ch2),
+ KUNIT_CASE(test_chan_to_route_cpus_ch3),
+ KUNIT_CASE(test_chan_to_route_dsp_ch4),
+ KUNIT_CASE(test_chan_to_route_dsp_ch7),
+ KUNIT_CASE(test_chan_to_route_rv_ch8),
+ KUNIT_CASE(test_chan_to_route_rv_ch11),
+ {}
+};
+
+static struct kunit_case sun55i_msgbox_register_cases[] = {
+ KUNIT_CASE(test_msgbox_offset_values),
+ KUNIT_CASE(test_read_irq_enable_offsets),
+ KUNIT_CASE(test_read_irq_status_offsets),
+ KUNIT_CASE(test_msg_fifo_offsets_all_channels),
+ KUNIT_CASE(test_msg_status_offsets_all_channels),
+ KUNIT_CASE(test_fifo_status_offsets_all_channels),
+ KUNIT_CASE(test_rd_irq_en_bit_positions),
+ KUNIT_CASE(test_rd_irq_pend_bit_positions),
+ KUNIT_CASE(test_num_chans_constant),
+ KUNIT_CASE(test_msg_num_mask),
+ {}
+};
+
+static struct kunit_suite sun55i_msgbox_routing_suite = {
+ .name = "sun55i_msgbox_routing",
+ .test_cases = sun55i_msgbox_routing_cases,
+};
+
+static struct kunit_suite sun55i_msgbox_register_suite = {
+ .name = "sun55i_msgbox_registers",
+ .test_cases = sun55i_msgbox_register_cases,
+};
+
+kunit_test_suites(&sun55i_msgbox_routing_suite,
+ &sun55i_msgbox_register_suite);
+
+MODULE_AUTHOR("Tim Michals <tcmichals@gmail.com>");
+MODULE_DESCRIPTION("KUnit tests for Allwinner sun55i-msgbox routing and registers");
+MODULE_LICENSE("GPL");
--
2.53.0
next prev parent reply other threads:[~2026-09-22 3:47 UTC|newest]
Thread overview: 35+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-22 3:47 [PATCH 0/7] remoteproc/mailbox: add Allwinner A523/A527/T527 E907 RISC-V support Tim Michals
2026-09-22 3:47 ` [PATCH 1/7] dt-bindings: mailbox: add Allwinner sun55i msgbox schema Tim Michals
2026-09-22 3:54 ` sashiko-bot
2026-09-22 8:54 ` Krzysztof Kozlowski
2026-09-22 3:47 ` [PATCH 2/7] mailbox: sun55i: add Allwinner sun55i/sun60i 4-port Message Box driver Tim Michals
2026-09-22 4:00 ` sashiko-bot
2026-09-22 3:47 ` Tim Michals [this message]
2026-09-22 3:54 ` [PATCH 3/7] mailbox: sun55i: add KUnit tests for routing and registers sashiko-bot
2026-09-22 3:47 ` [PATCH 4/7] dt-bindings: remoteproc: add allwinner sun55i rproc binding Tim Michals
2026-09-22 3:56 ` sashiko-bot
2026-09-22 8:58 ` Krzysztof Kozlowski
2026-09-22 12:46 ` Rob Herring (Arm)
2026-09-22 3:47 ` [PATCH 5/7] remoteproc: sunxi: add allwinner riscv remoteproc driver Tim Michals
2026-09-22 3:59 ` sashiko-bot
2026-09-22 3:47 ` [PATCH 6/7] remoteproc: sunxi: add KUnit tests for da_to_va address translation Tim Michals
2026-09-22 3:54 ` sashiko-bot
2026-09-22 3:47 ` [PATCH 7/7] arm64: dts: allwinner: add a523 msgbox and remoteproc nodes Tim Michals
2026-09-22 3:59 ` sashiko-bot
2026-09-22 6:34 ` [PATCH 0/7] remoteproc/mailbox: add Allwinner A523/A527/T527 E907 RISC-V support Chen-Yu Tsai
2026-09-27 0:20 ` [PATCH v2 0/7] remoteproc: sunxi: Add Allwinner XuanTie E907 RemoteProc and Message Box support Tim Michals
2026-09-27 0:20 ` [PATCH v2 1/7] dt-bindings: mailbox: add Allwinner sun55i msgbox schema Tim Michals
2026-09-27 0:30 ` sashiko-bot
2026-10-01 6:16 ` Krzysztof Kozlowski
2026-09-27 0:20 ` [PATCH v2 2/7] mailbox: sun55i: add Allwinner sun55i/sun60i 4-port Message Box driver Tim Michals
2026-09-27 0:33 ` sashiko-bot
2026-09-27 0:20 ` [PATCH v2 3/7] mailbox: sun55i: add KUnit test suite for sun55i msgbox driver Tim Michals
2026-09-27 0:31 ` sashiko-bot
2026-09-27 0:20 ` [PATCH v2 4/7] dt-bindings: remoteproc: add Allwinner sun55i-rproc schema Tim Michals
2026-09-27 0:27 ` sashiko-bot
2026-10-01 6:17 ` Krzysztof Kozlowski
2026-09-27 0:20 ` [PATCH v2 5/7] remoteproc: sunxi: add Allwinner XuanTie RISC-V remoteproc driver Tim Michals
2026-09-27 0:33 ` sashiko-bot
2026-09-27 0:20 ` [PATCH v2 6/7] remoteproc: sunxi: add KUnit test suite for sunxi " Tim Michals
2026-09-27 0:32 ` sashiko-bot
2026-09-27 0:20 ` [PATCH v2 7/7] arm64: dts: allwinner: add a523 msgbox and remoteproc nodes Tim Michals
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260922034711.190253-4-tcmichals@gmail.com \
--to=tcmichals@gmail.com \
--cc=jernej.skrabec@gmail.com \
--cc=linux-sunxi@lists.linux.dev \
--cc=samuel@sholland.org \
--cc=wens@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox