{"id":2231480,"url":"http://patchwork.ozlabs.org/api/patches/2231480/?format=json","web_url":"http://patchwork.ozlabs.org/project/qemu-devel/patch/6471a3d10ae02224fbc2ca5b47888b5e05cf4a4c.1777571962.git.matyas.bobek@gmail.com/","project":{"id":14,"url":"http://patchwork.ozlabs.org/api/projects/14/?format=json","name":"QEMU Development","link_name":"qemu-devel","list_id":"qemu-devel.nongnu.org","list_email":"qemu-devel@nongnu.org","web_url":"","scm_url":"","webscm_url":"","list_archive_url":"","list_archive_url_format":"","commit_url_format":""},"msgid":"<6471a3d10ae02224fbc2ca5b47888b5e05cf4a4c.1777571962.git.matyas.bobek@gmail.com>","list_archive_url":null,"date":"2026-04-30T18:26:08","name":"[v3,6/7] tests: Add qtests for FlexCAN","commit_ref":null,"pull_url":null,"state":"new","archived":false,"hash":"081f38013e83ff953583a2026e85baaed7847369","submitter":{"id":92267,"url":"http://patchwork.ozlabs.org/api/people/92267/?format=json","name":"Matyáš Bobek","email":"matyas.bobek@gmail.com"},"delegate":null,"mbox":"http://patchwork.ozlabs.org/project/qemu-devel/patch/6471a3d10ae02224fbc2ca5b47888b5e05cf4a4c.1777571962.git.matyas.bobek@gmail.com/mbox/","series":[{"id":502356,"url":"http://patchwork.ozlabs.org/api/series/502356/?format=json","web_url":"http://patchwork.ozlabs.org/project/qemu-devel/list/?series=502356","date":"2026-04-30T18:26:02","name":"hw/arm/sabrelite: Add FlexCAN support","version":3,"mbox":"http://patchwork.ozlabs.org/series/502356/mbox/"}],"comments":"http://patchwork.ozlabs.org/api/patches/2231480/comments/","check":"pending","checks":"http://patchwork.ozlabs.org/api/patches/2231480/checks/","tags":{},"related":[],"headers":{"Return-Path":"<qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org>","X-Original-To":"incoming@patchwork.ozlabs.org","Delivered-To":"patchwork-incoming@legolas.ozlabs.org","Authentication-Results":["legolas.ozlabs.org;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256\n header.s=20251104 header.b=TsZ6jW8n;\n\tdkim-atps=neutral","legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org\n (client-ip=209.51.188.17; helo=lists1p.gnu.org;\n envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org;\n receiver=patchwork.ozlabs.org)"],"Received":["from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17])\n\t(using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits))\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4g62hx1vbMz23gq\n\tfor <incoming@patchwork.ozlabs.org>; Fri, 01 May 2026 04:27:44 +1000 (AEST)","from localhost ([::1] helo=lists1p.gnu.org)\n\tby lists1p.gnu.org with esmtp (Exim 4.90_1)\n\t(envelope-from <qemu-devel-bounces@nongnu.org>)\n\tid 1wIW6Y-0006kx-RN; Thu, 30 Apr 2026 14:27:18 -0400","from eggs.gnu.org ([2001:470:142:3::10])\n by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)\n (Exim 4.90_1) (envelope-from <matyas.bobek@gmail.com>)\n id 1wIW61-0006Xa-Sg\n for qemu-devel@nongnu.org; Thu, 30 Apr 2026 14:26:49 -0400","from mail-wr1-x42b.google.com ([2a00:1450:4864:20::42b])\n by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128)\n (Exim 4.90_1) (envelope-from <matyas.bobek@gmail.com>)\n id 1wIW5k-0005V6-2b\n for qemu-devel@nongnu.org; Thu, 30 Apr 2026 14:26:34 -0400","by mail-wr1-x42b.google.com with SMTP id\n ffacd0b85a97d-4486b5fcf3cso1118309f8f.2\n for <qemu-devel@nongnu.org>; Thu, 30 Apr 2026 11:26:26 -0700 (PDT)","from acidburn.pod.cvut.cz (acidburn.pod.cvut.cz. [147.32.90.2])\n by smtp.gmail.com with ESMTPSA id\n ffacd0b85a97d-447b76e5c00sm14674925f8f.25.2026.04.30.11.26.24\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Thu, 30 Apr 2026 11:26:24 -0700 (PDT)"],"DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=gmail.com; s=20251104; t=1777573585; x=1778178385; darn=nongnu.org;\n h=content-transfer-encoding:mime-version:references:in-reply-to\n :message-id:date:subject:cc:to:from:from:to:cc:subject:date\n :message-id:reply-to;\n bh=hxCDHRKw0pb6rpAfP+SyKu+qGTn17v+2MO3K8eQPUxA=;\n b=TsZ6jW8n8vX0ABZNfL6Draq0g9LXNFNpdHJofAEJkjoS0YE5RWn1EccOGUVz8Y+eX/\n lDgtSI5F5v/rUiPMvBsGugKk+CMGOZ4lFTYtTol4krqUpyrmjshLFw6blcwLtYBOqwfv\n etTSaUR7+HkGNzRXGNvi26uhjC7cJcUGaotwAEghsQmizHDUk+WUiPV4oJkhMoFmz03M\n /j72c5R0ZZ+A8RZSorFfNIeRb1gtMF46FGHoYKlY89RoFEQaGIJtFsfT4jBiAK4lQpvt\n rkWK/ojkibwGDiuenwSNz0R1RyiyryhYyplAceJax4sx5yI1fAwUvojvE4f4Rn+eFLMV\n t7EQ==","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20251104; t=1777573585; x=1778178385;\n h=content-transfer-encoding:mime-version:references:in-reply-to\n :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from\n :to:cc:subject:date:message-id:reply-to;\n bh=hxCDHRKw0pb6rpAfP+SyKu+qGTn17v+2MO3K8eQPUxA=;\n b=E9FuWGYEThd4S3mC3u6PRoEZdy1iY1j8AuCzwBLDenW7zpV8h56FBhIRW3Ppi/jLNn\n 6FEENPQm0ogX9wdL1A+zYaWurkh4oNbdkcmxdya9KJcxBzRiKT0RU1e189ly3L1Swrwh\n D6lLMwd8hWUeaz9nsSWgzmY6u+bHU7ZuhvyBZq/Giy7oaCveBiv0rHRPmSuoUq09p2x3\n LTXujyyUPYYyNBSileNIstx4idmITuaeG+z5lbaPNlHFg+J64EtWuUK7lz/hJU4XYidj\n Uc3mxiTJ9nkU/m6GRgKm30hw+avQORgVNVLIwXVNmkYU1NoBRyGLwagLGdEtSk8YPHbm\n G/Fg==","X-Gm-Message-State":"AOJu0YyeG7pUxOd2tZYyVW5LHTY82PKI7okMB7U4o6r9hsnPYhlROMAV\n As3Y7OO2SgeJJkF6CdLQJjUf+DTrIlx8zeYeurBEpWf/hs22Q8AqbGu4ZuaaIJ40","X-Gm-Gg":"AeBDietC7PlYphQOH0PrqvZwFQvYwU5ssA+HK7dhgt4VMVrBztaxFOpZUbNXF1LiaDH\n cijb1GaYAnwm3Gv7Or2NeQzgW98Nc2X5Iiv7M4Kra7wCpJ+tS5DwKyn15BrWzrTwvDc3y80LjHK\n bPyt0SwZ6jPhglPb9HRgm8XqXQjtQ66Wq0o1DcXUTqy9nTFYeRGLXLDKVhQpdLgXQWFXDz+ZIcf\n 3yzOFeSWPzTLs4kbyyjP1a7BcAVEks/+OkWBGFjMDoqSM0orClC3CoboQYUvJwAoV0xiCbZQZsi\n ASPtnsE3lGbQ+pd/x/zSYJZgYXfZEvp+P5wCJ1uCKA8DhLupgTzotPfkdNTgnXaqT0t4wEi23gw\n 03Db0V5jvttu7L2UvbvzMWVCKaYgMxyxbMrbVbux+cByy2hOS8zEwnY+10Ha/rImgmn1XcQnS4o\n RvXOVmGHGYnRF2bFLtzXDncStqJ/HjyDHXTvTT4RYjaww7N8SagZ/LdFPqRvQIYhXUH4KUIU94o\n yg=","X-Received":"by 2002:a5d:5f91:0:b0:441:1fa5:457e with SMTP id\n ffacd0b85a97d-4493dcd3c8dmr6620263f8f.13.1777573585159;\n Thu, 30 Apr 2026 11:26:25 -0700 (PDT)","From":"=?utf-8?b?TWF0ecOhxaEgQm9iZWs=?= <matyas.bobek@gmail.com>","To":"qemu-devel@nongnu.org, Matyas Bobek <bobekmat@fel.cvut.cz>,\n Pavel Pisa <pisa@fel.cvut.cz>, Bernhard Beschow <shentey@gmail.com>","Cc":"qemu-arm@nongnu.org, Marc Kleine-Budde <mkl@pengutronix.de>,\n Oliver Hartkopp <socketcan@hartkopp.net>,\n Nikita Ostrenkov <n.ostrenkov@gmail.com>,\n Peter Maydell <peter.maydell@linaro.org>,\n =?utf-8?b?TWF0ecOhxaEgQm9iZWs=?= <matyas.bobek@gmail.com>","Subject":"[PATCH v3 6/7] tests: Add qtests for FlexCAN","Date":"Thu, 30 Apr 2026 20:26:08 +0200","Message-ID":"\n <6471a3d10ae02224fbc2ca5b47888b5e05cf4a4c.1777571962.git.matyas.bobek@gmail.com>","X-Mailer":"git-send-email 2.53.0","In-Reply-To":"<cover.1777571962.git.matyas.bobek@gmail.com>","References":"<cover.1777571962.git.matyas.bobek@gmail.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=UTF-8","Content-Transfer-Encoding":"8bit","Received-SPF":"pass client-ip=2a00:1450:4864:20::42b;\n envelope-from=matyas.bobek@gmail.com; helo=mail-wr1-x42b.google.com","X-Spam_score_int":"-10","X-Spam_score":"-1.1","X-Spam_bar":"-","X-Spam_report":"(-1.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1,\n DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FORGED_GMAIL_RCVD=1,\n FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001,\n SPF_PASS=-0.001 autolearn=no autolearn_force=no","X-Spam_action":"no action","X-BeenThere":"qemu-devel@nongnu.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"qemu development <qemu-devel.nongnu.org>","List-Unsubscribe":"<https://lists.nongnu.org/mailman/options/qemu-devel>,\n <mailto:qemu-devel-request@nongnu.org?subject=unsubscribe>","List-Archive":"<https://lists.nongnu.org/archive/html/qemu-devel>","List-Post":"<mailto:qemu-devel@nongnu.org>","List-Help":"<mailto:qemu-devel-request@nongnu.org?subject=help>","List-Subscribe":"<https://lists.nongnu.org/mailman/listinfo/qemu-devel>,\n <mailto:qemu-devel-request@nongnu.org?subject=subscribe>","Errors-To":"qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org","Sender":"qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org"},"content":"The tests do not test all of the FlexCAN emulator functionality.\n\nSigned-off-by: Matyáš Bobek <matyas.bobek@gmail.com>\nSigned-off-by: Pavel Pisa <pisa@fel.cvut.cz>\nTested-by: Pavel Pisa <pisa@fel.cvut.cz>\nReviewed-by: Bernhard Beschow <shentey@gmail.com>\nReviewed-by: Pavel Pisa <pisa@fel.cvut.cz>\n---\n MAINTAINERS                |   1 +\n tests/qtest/flexcan-test.c | 421 +++++++++++++++++++++++++++++++++++++\n tests/qtest/meson.build    |   1 +\n 3 files changed, 423 insertions(+)\n create mode 100644 tests/qtest/flexcan-test.c","diff":"diff --git a/MAINTAINERS b/MAINTAINERS\nindex 59a3614a58..7b1fe85961 100644\n--- a/MAINTAINERS\n+++ b/MAINTAINERS\n@@ -2098,6 +2098,7 @@ S: Maintained\n F: hw/net/can/flexcan.c\n F: hw/net/can/flexcan_regs.h\n F: include/hw/net/flexcan.h\n+F: tests/qtest/flexcan-test.c\n \n EDU\n M: Jiri Slaby <jslaby@suse.cz>\ndiff --git a/tests/qtest/flexcan-test.c b/tests/qtest/flexcan-test.c\nnew file mode 100644\nindex 0000000000..87d947a806\n--- /dev/null\n+++ b/tests/qtest/flexcan-test.c\n@@ -0,0 +1,421 @@\n+/*\n+ * QTests for FlexCAN CAN controller device model\n+ *\n+ * Copyright (c) 2025 Matyas Bobek <matyas.bobek@gmail.com>\n+ *\n+ * SPDX-License-Identifier: GPL-2.0-or-later\n+ */\n+\n+#include \"qemu/osdep.h\"\n+#include \"libqtest-single.h\"\n+\n+#include \"hw/net/flexcan.h\"\n+#include \"hw/net/can/flexcan_regs.h\"\n+\n+#define FSL_IMX6_CAN2_ADDR 0x02094000\n+#define FSL_IMX6_CAN2_SIZE 0x4000\n+#define FSL_IMX6_CAN1_ADDR 0x02090000\n+#define FSL_IMX6_CAN1_SIZE 0x4000\n+\n+#define FC_QEMU_ARGS \"-nographic -M sabrelite \" \\\n+                     \"-object can-bus,id=qcan0  \" \\\n+                     \"-machine canbus0=qcan0 -machine canbus1=qcan0\"\n+\n+/* used for masking out unused/reserved bits */\n+#define FC_MB_CNT_USED_MASK (~0xF080FFFFu)\n+\n+#define FCREG(BASE_ADDR, REG) ((BASE_ADDR) + offsetof(FlexcanRegs, REG))\n+#define FCMB(BASE_ADDR, MB_IDX, WORD_IDX) (FCREG(BASE_ADDR, mbs) + \\\n+    0x10 * (MB_IDX) + 4 * (WORD_IDX))\n+\n+typedef struct FcTestFrame {\n+    uint32_t id;\n+    uint32_t data[2];\n+    uint8_t len;\n+    bool ide;\n+    bool rtr;\n+\n+    /* rx only */\n+    bool expect_overrun;\n+} FcTestFrame;\n+\n+static const FcTestFrame fc_test_frame_1 = {\n+    .id = 0x5AF,\n+    .len = 8,\n+    .data = {\n+        0x01020304,\n+        0x0A0B0C0D\n+    },\n+    .ide = false\n+};\n+\n+static const FcTestFrame fc_test_frame_1_ide = {\n+    .id = 0x105AF5AF,\n+    .len = 8,\n+    .data = {\n+        0x01020304,\n+        0x0A0B0C0D\n+    },\n+    .ide = true\n+};\n+\n+static void fc_reset(hwaddr ba, uint32_t mcr_flags)\n+{\n+    /* disable */\n+    writel(FCREG(ba, mcr), 0xD890000F);\n+\n+    /* enable in freeze mode */\n+    writel(FCREG(ba, mcr), 0x5980000F);\n+\n+    /* soft reset */\n+    writel(FCREG(ba, mcr), 0x5980000F | FLEXCAN_MCR_SOFTRST);\n+\n+    g_assert_cmpuint(readl(FCREG(ba, mcr)), ==, 0x5980000F);\n+    g_assert_cmpuint(readl(FCREG(ba, ctrl)), ==, 0);\n+    g_assert_cmpuint(readl(FCREG(ba, ctrl2)), ==, 0);\n+\n+    writel(FCREG(ba, mcr), (0x5980000F & ~FLEXCAN_MCR_HALT) | mcr_flags);\n+    writel(FCREG(ba, ctrl2), FLEXCAN_CTRL2_RRS);\n+\n+    /* initialize all mailboxes as rx inactive */\n+    for (int i = 0; i < FLEXCAN_MAILBOX_COUNT; i++) {\n+        writel(FCMB(ba, i, 0), FLEXCAN_MB_CODE_RX_INACTIVE);\n+        writel(FCMB(ba, i, 1), 0);\n+        writel(FCMB(ba, i, 2), 0);\n+        writel(FCMB(ba, i, 3), 0);\n+    }\n+}\n+\n+static uint64_t fc_get_irqs(hwaddr ba)\n+{\n+    return (uint64_t)readl(FCREG(ba, iflag1)) |\n+        ((uint64_t)readl(FCREG(ba, iflag2)) << 32);\n+}\n+\n+static void fc_clear_irq(hwaddr ba, int idx)\n+{\n+    if (idx >= 32) {\n+        writel(FCREG(ba, iflag2), (uint32_t)1 << (idx - 32));\n+    } else {\n+        writel(FCREG(ba, iflag1), (uint32_t)1 << idx);\n+    }\n+\n+    g_assert_cmpuint(fc_get_irqs(ba) & ((uint64_t)1 << idx), ==, 0);\n+}\n+\n+static void fc_setup_rx_mb(hwaddr ba, int mbidx)\n+{\n+    writel(FCMB(ba, mbidx, 0), FLEXCAN_MB_CODE_RX_EMPTY);\n+    writel(FCMB(ba, mbidx, 1), 0);\n+    /* the data value should be ignored for RX mb */\n+    writel(FCMB(ba, mbidx, 2), 0);\n+    writel(FCMB(ba, mbidx, 3), 0);\n+\n+    g_assert_cmpuint(readl(FCMB(ba, mbidx, 0)), ==, FLEXCAN_MB_CODE_RX_EMPTY);\n+}\n+\n+static void fc_tx(hwaddr ba, int mbidx, const FcTestFrame *frame)\n+{\n+    g_assert_cmpuint(frame->len, <=, 8);\n+\n+    writel(FCMB(ba, mbidx, 0), FLEXCAN_MB_CODE_TX_INACTIVE);\n+    uint32_t id = frame->ide ? frame->id : frame->id << 18;\n+    writel(FCMB(ba, mbidx, 1), id);\n+    writel(FCMB(ba, mbidx, 2), frame->data[0]);\n+    writel(FCMB(ba, mbidx, 3), frame->data[1]);\n+\n+    uint32_t ctrl = FLEXCAN_MB_CODE_TX_DATA | FLEXCAN_MB_CNT_LENGTH(frame->len);\n+    if (frame->ide) {\n+        ctrl |= FLEXCAN_MB_CNT_IDE | FLEXCAN_MB_CNT_SRR;\n+    }\n+    if (frame->rtr) {\n+        ctrl |= FLEXCAN_MB_CNT_RTR;\n+    }\n+    writel(FCMB(ba, mbidx, 0), ctrl);\n+\n+    /* check frame was transmitted */\n+    g_assert_cmpuint(fc_get_irqs(ba) & ((uint64_t)1 << mbidx),\n+                     !=, 0);\n+\n+    uint32_t xpectd_ctrl = (ctrl & ~FLEXCAN_MB_CODE_MASK) |\n+        FLEXCAN_MB_CODE_TX_INACTIVE;\n+    g_assert_cmpuint(readl(FCMB(ba, mbidx, 0)) & FC_MB_CNT_USED_MASK, ==,\n+                     xpectd_ctrl);\n+    /* other fields should stay unchanged */\n+    g_assert_cmpuint(readl(FCMB(ba, mbidx, 1)), ==, id);\n+    g_assert_cmpuint(readl(FCMB(ba, mbidx, 2)), ==, frame->data[0]);\n+    g_assert_cmpuint(readl(FCMB(ba, mbidx, 3)), ==, frame->data[1]);\n+}\n+\n+static void fc_rx_check(hwaddr ba, int mbidx, const FcTestFrame *frame)\n+{\n+    uint32_t xpectd_ctrl = frame->expect_overrun ? FLEXCAN_MB_CODE_RX_OVERRUN\n+                             : FLEXCAN_MB_CODE_RX_FULL;\n+    xpectd_ctrl |= FLEXCAN_MB_CNT_LENGTH(frame->len) | FLEXCAN_MB_CNT_SRR;\n+    if (frame->ide) {\n+        xpectd_ctrl |= FLEXCAN_MB_CNT_IDE;\n+    }\n+    if (frame->rtr) {\n+        xpectd_ctrl |= FLEXCAN_MB_CNT_RTR;\n+    }\n+\n+    uint32_t xpectd_id = frame->ide ? frame->id : frame->id << 18;\n+\n+    uint32_t ctrl = readl(FCMB(ba, mbidx, 0)) & FC_MB_CNT_USED_MASK;\n+    if ((ctrl & FLEXCAN_MB_CODE_MASK) == FLEXCAN_MB_CODE_RX_EMPTY) {\n+        fprintf(stderr, \"expected frame (id=0x%X) not received\\n\", frame->id);\n+    }\n+\n+    g_assert_cmpuint(ctrl, ==, xpectd_ctrl);\n+    g_assert_cmpuint(readl(FCMB(ba, mbidx, 1)), ==, xpectd_id);\n+    g_assert_cmpuint(readl(FCMB(ba, mbidx, 2)), ==, frame->data[0]);\n+    g_assert_cmpuint(readl(FCMB(ba, mbidx, 3)), ==, frame->data[1]);\n+}\n+\n+static void fc_check_empty_multi(hwaddr ba, int idx_count, int mbidxs[])\n+{\n+    for (int i = 0; i < FLEXCAN_MAILBOX_COUNT; i++) {\n+        bool check_empty = true;\n+        int ctrl = readl(FCMB(ba, i, 0));\n+\n+        for (int j = 0; j < idx_count; j++) {\n+            if (i == mbidxs[j]) {\n+                check_empty = false;\n+            }\n+        }\n+\n+        if (check_empty) {\n+            if (!(ctrl == FLEXCAN_MB_CODE_RX_EMPTY ||\n+                  ctrl == FLEXCAN_MB_CODE_RX_INACTIVE)) {\n+                g_assert_cmpuint(ctrl, ==, FLEXCAN_MB_CODE_RX_INACTIVE);\n+            }\n+            g_assert_cmpuint(readl(FCMB(ba, i, 1)), ==, 0);\n+            g_assert_cmpuint(readl(FCMB(ba, i, 2)), ==, 0);\n+            g_assert_cmpuint(readl(FCMB(ba, i, 3)), ==, 0);\n+        } else {\n+            g_assert_cmpuint(\n+                ctrl & FLEXCAN_MB_CODE_MASK, !=,\n+                FLEXCAN_MB_CODE_RX_INACTIVE\n+            );\n+        }\n+    }\n+}\n+\n+static void fc_check_empty(hwaddr ba, int mbidx)\n+{\n+    fc_check_empty_multi(ba, 1, &mbidx);\n+}\n+\n+static void flexcan_test_linux_probe_impl(hwaddr fba)\n+{\n+    /* -- test a Linux driver-like probe sequence -- */\n+    /* disable */\n+    writel(FCREG(fba, mcr), 0xD890000F);\n+    g_assert_cmpuint(readl(FCREG(fba, mcr)), ==, 0xD890000F);\n+    g_assert_cmpuint(readl(FCREG(fba, ctrl)), ==, 0);\n+\n+    /* set bit in reserved field we do not implement (CTRL_CLK_SRC) */\n+    writel(FCREG(fba, ctrl), 0x00002000);\n+    g_assert_cmpuint(readl(FCREG(fba, mcr)), ==, 0xD890000F);\n+\n+    /* enable in freeze mode */\n+    writel(FCREG(fba, mcr), 0x5980000F);\n+    g_assert_cmpuint(readl(FCREG(fba, mcr)), ==, 0x5980000F);\n+\n+    /* enable Rx-FIFO */\n+    writel(FCREG(fba, mcr), 0x7980000F);\n+    g_assert_cmpuint(readl(FCREG(fba, mcr)), ==, 0x7980000F);\n+    g_assert_cmpuint(readl(FCREG(fba, ecr)), ==, 0);\n+\n+    /* disable */\n+    writel(FCREG(fba, mcr), 0xF890000F);\n+    g_assert_cmpuint(readl(FCREG(fba, mcr)), ==, 0xF890000F);\n+}\n+\n+static void flexcan_test_freeze_disable_interaction_impl(hwaddr fba)\n+{\n+    /* -- test normal <=> freeze <=> disable transitions -- */\n+\n+    /* leave freeze in disabled, FRZ_ACK should stay cleared */\n+    writel(FCREG(fba, mcr), 0xF890000F); /* disable */\n+    g_assert_cmpuint(readl(FCREG(fba, mcr)), ==, 0xF890000F);\n+    writel(FCREG(fba, mcr), 0xB890000F);  /* by clearing FRZ */\n+    g_assert_cmpuint(readl(FCREG(fba, mcr)), ==, 0xB890000F);\n+\n+    writel(FCREG(fba, mcr), 0xF890000F); /* disable */\n+    g_assert_cmpuint(readl(FCREG(fba, mcr)), ==, 0xF890000F);\n+    writel(FCREG(fba, mcr), 0xE890000F);  /* by clearing HALT */\n+    g_assert_cmpuint(readl(FCREG(fba, mcr)), ==, 0xE890000F);\n+\n+    writel(FCREG(fba, mcr), 0xF890000F); /* disable */\n+    g_assert_cmpuint(readl(FCREG(fba, mcr)), ==, 0xF890000F);\n+    writel(FCREG(fba, mcr), 0xA890000F);  /* by clearing both */\n+    g_assert_cmpuint(readl(FCREG(fba, mcr)), ==, 0xA890000F);\n+\n+    /* enter and leave freeze */\n+    writel(FCREG(fba, mcr), 0x7980000F); /* enable in freeze mode */\n+    g_assert_cmpuint(readl(FCREG(fba, mcr)), ==, 0x7980000F);\n+    writel(FCREG(fba, mcr), 0x3980000F); /* leave by clearing FRZ */\n+    g_assert_cmpuint(readl(FCREG(fba, mcr)), ==, 0x3080000F);\n+\n+    writel(FCREG(fba, mcr), 0x7980000F); /* enable in freeze mode */\n+    g_assert_cmpuint(readl(FCREG(fba, mcr)), ==, 0x7980000F);\n+    writel(FCREG(fba, mcr), 0x6980000F); /* leave by clearing HALT */\n+    g_assert_cmpuint(readl(FCREG(fba, mcr)), ==, 0x6080000F);\n+}\n+\n+static void flexcan_test_mailbox_io_impl(hwaddr ba_tx, hwaddr ba_rx)\n+{\n+    /* -- test correct handling of mailbox IO -- */\n+    const int test_1_mbidx = 0;\n+    fc_reset(ba_tx,\n+             FLEXCAN_MCR_SRX_DIS | FLEXCAN_MCR_MAXMB(FLEXCAN_MAILBOX_COUNT));\n+    fc_reset(ba_rx,\n+             FLEXCAN_MCR_SRX_DIS | FLEXCAN_MCR_MAXMB(FLEXCAN_MAILBOX_COUNT));\n+\n+    fc_setup_rx_mb(ba_rx, test_1_mbidx);\n+    fc_tx(ba_tx, test_1_mbidx, &fc_test_frame_1_ide);\n+    g_assert_cmpuint(fc_get_irqs(ba_rx), ==, 1 << test_1_mbidx);\n+    fc_rx_check(ba_rx, test_1_mbidx, &fc_test_frame_1_ide);\n+    readl(FCREG(ba_rx, timer)); /* reset lock */\n+\n+    writel(FCMB(ba_rx, test_1_mbidx, 0), 0);\n+    g_assert_cmpuint(readl(FCMB(ba_rx, test_1_mbidx, 0)), ==, 0);\n+    writel(FCMB(ba_rx, test_1_mbidx, 1), 0x99AABBCC);\n+    g_assert_cmpuint(readl(FCMB(ba_rx, test_1_mbidx, 1)), ==, 0x99AABBCC);\n+}\n+\n+static void flexcan_test_dual_transmit_receive_impl(hwaddr ba_tx, hwaddr ba_rx)\n+{\n+    /* -- test TX and RX between the two FlexCAN instances -- */\n+    const int test_1_mbidx = 50;\n+    const int test_rounds = 50;\n+\n+    /* self-receive enabled on tx FC */\n+    fc_reset(ba_tx,\n+             FLEXCAN_MCR_MAXMB(FLEXCAN_MAILBOX_COUNT));\n+    fc_reset(ba_rx,\n+             FLEXCAN_MCR_SRX_DIS | FLEXCAN_MCR_MAXMB(FLEXCAN_MAILBOX_COUNT));\n+\n+    /* tests self-receive on tx and reception on rx */\n+    fc_setup_rx_mb(ba_rx, test_1_mbidx);\n+    fc_check_empty(ba_rx, test_1_mbidx);\n+    fc_setup_rx_mb(ba_tx, test_1_mbidx + 1);\n+    fc_check_empty(ba_tx, test_1_mbidx + 1);\n+    g_assert_cmpuint(fc_get_irqs(ba_rx), ==, 0);\n+    g_assert_cmpuint(fc_get_irqs(ba_tx), ==, 0);\n+\n+    fc_tx(ba_tx, test_1_mbidx, &fc_test_frame_1);\n+    fc_clear_irq(ba_tx, test_1_mbidx);\n+\n+    fc_rx_check(ba_rx, test_1_mbidx, &fc_test_frame_1);\n+    fc_check_empty(ba_rx, test_1_mbidx);\n+    fc_rx_check(ba_tx, test_1_mbidx + 1, &fc_test_frame_1);\n+    int tx_non_empty_mbidxs[] = {test_1_mbidx, test_1_mbidx + 1};\n+\n+    fc_check_empty_multi(ba_tx, 2, tx_non_empty_mbidxs);\n+    fc_clear_irq(ba_rx, test_1_mbidx);\n+    fc_clear_irq(ba_tx, test_1_mbidx + 1);\n+    readl(FCREG(ba_rx, timer)); /* reset lock */\n+\n+    for (int ridx = 0; ridx < test_rounds; ridx++) {\n+        /* test extended IDs sent to all mailboxes */\n+        for (int i = 0; i < FLEXCAN_MAILBOX_COUNT; i++) {\n+            fc_setup_rx_mb(ba_rx, i);\n+        }\n+        fc_check_empty_multi(ba_rx, 0, NULL);\n+        g_assert_cmpuint(fc_get_irqs(ba_rx), ==, 0);\n+        g_assert_cmpuint(fc_get_irqs(ba_tx), ==, 0);\n+\n+        for (int i = 0; i < FLEXCAN_MAILBOX_COUNT; i++) {\n+            fc_tx(ba_tx, i, &fc_test_frame_1_ide);\n+        }\n+        g_assert_cmpuint(fc_get_irqs(ba_rx), ==, UINT64_MAX);\n+        g_assert_cmpuint(fc_get_irqs(ba_tx), ==, UINT64_MAX);\n+        for (int i = 0; i < FLEXCAN_MAILBOX_COUNT; i++) {\n+            fc_rx_check(ba_rx, i, &fc_test_frame_1_ide);\n+        }\n+\n+        /* reset interrupts */\n+        writel(FCREG(ba_rx, iflag1), UINT32_MAX);\n+        writel(FCREG(ba_rx, iflag2), UINT32_MAX);\n+        writel(FCREG(ba_tx, iflag1), UINT32_MAX);\n+        writel(FCREG(ba_tx, iflag2), UINT32_MAX);\n+        g_assert_cmpuint(fc_get_irqs(ba_rx), ==, 0);\n+        g_assert_cmpuint(fc_get_irqs(ba_tx), ==, 0);\n+    }\n+}\n+\n+static void flexcan_test_tx_abort_impl(hwaddr ba)\n+{\n+    /* -- test the TX abort feature -- */\n+    fc_reset(ba,\n+             FLEXCAN_MCR_SRX_DIS | FLEXCAN_MCR_MAXMB(FLEXCAN_MAILBOX_COUNT));\n+\n+\n+    for (int mbidx = 0; mbidx < FLEXCAN_MAILBOX_COUNT; mbidx++) {\n+        fc_tx(ba, mbidx, &fc_test_frame_1);\n+\n+        writel(FCMB(ba, mbidx, 0), FLEXCAN_MB_CODE_TX_ABORT);\n+        g_assert_cmpuint(readl(FCMB(ba, mbidx, 0)), ==,\n+                         FLEXCAN_MB_CODE_TX_INACTIVE);\n+    }\n+}\n+\n+static void flexcan_test_freeze_disable_interaction(void)\n+{\n+    qtest_start(FC_QEMU_ARGS);\n+    flexcan_test_freeze_disable_interaction_impl(FSL_IMX6_CAN1_ADDR);\n+    flexcan_test_freeze_disable_interaction_impl(FSL_IMX6_CAN2_ADDR);\n+    qtest_end();\n+}\n+\n+static void flexcan_test_linux_probe(void)\n+{\n+    qtest_start(FC_QEMU_ARGS);\n+    flexcan_test_linux_probe_impl(FSL_IMX6_CAN1_ADDR);\n+    flexcan_test_linux_probe_impl(FSL_IMX6_CAN2_ADDR);\n+    qtest_end();\n+}\n+\n+static void flexcan_test_dual_transmit_receive(void)\n+{\n+    qtest_start(FC_QEMU_ARGS);\n+    flexcan_test_dual_transmit_receive_impl(FSL_IMX6_CAN1_ADDR,\n+                                            FSL_IMX6_CAN2_ADDR);\n+    flexcan_test_dual_transmit_receive_impl(FSL_IMX6_CAN2_ADDR,\n+                                            FSL_IMX6_CAN1_ADDR);\n+    qtest_end();\n+}\n+\n+static void flexcan_test_tx_abort(void)\n+{\n+    qtest_start(FC_QEMU_ARGS);\n+    flexcan_test_tx_abort_impl(FSL_IMX6_CAN1_ADDR);\n+    flexcan_test_tx_abort_impl(FSL_IMX6_CAN2_ADDR);\n+    qtest_end();\n+}\n+\n+static void flexcan_test_mailbox_io(void)\n+{\n+    qtest_start(FC_QEMU_ARGS);\n+    flexcan_test_mailbox_io_impl(FSL_IMX6_CAN1_ADDR, FSL_IMX6_CAN2_ADDR);\n+    flexcan_test_mailbox_io_impl(FSL_IMX6_CAN2_ADDR, FSL_IMX6_CAN1_ADDR);\n+    qtest_end();\n+}\n+\n+int main(int argc, char **argv)\n+{\n+    g_test_init(&argc, &argv, NULL);\n+\n+    qtest_add_func(\"/net/flexcan/linux_probe\", flexcan_test_linux_probe);\n+    qtest_add_func(\"/net/flexcan/freeze_disable_interaction\",\n+                   flexcan_test_freeze_disable_interaction);\n+    qtest_add_func(\"/net/flexcan/dual_transmit_receive\",\n+                   flexcan_test_dual_transmit_receive);\n+    qtest_add_func(\"/net/flexcan/tx_abort\",\n+                   flexcan_test_tx_abort);\n+    qtest_add_func(\"/net/flexcan/mailbox_io\", flexcan_test_mailbox_io);\n+\n+    return g_test_run();\n+}\ndiff --git a/tests/qtest/meson.build b/tests/qtest/meson.build\nindex 43f83ffd3a..17e68d9963 100644\n--- a/tests/qtest/meson.build\n+++ b/tests/qtest/meson.build\n@@ -248,6 +248,7 @@ qtests_arm = \\\n   (config_all_devices.has_key('CONFIG_MICROBIT') ? ['microbit-test'] : []) + \\\n   (config_all_devices.has_key('CONFIG_STM32L4X5_SOC') ? qtests_stm32l4x5 : []) + \\\n   (config_all_devices.has_key('CONFIG_FSI_APB2OPB_ASPEED') ? ['aspeed_fsi-test'] : []) + \\\n+  (config_all_devices.has_key('CONFIG_CAN_FLEXCAN') ? ['flexcan-test'] : []) + \\\n   (config_all_devices.has_key('CONFIG_STM32L4X5_SOC') and\n    config_all_devices.has_key('CONFIG_DM163')? ['dm163-test'] : []) + \\\n   ['arm-cpu-features',\n","prefixes":["v3","6/7"]}