Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/2231480/?format=api
{ "id": 2231480, "url": "http://patchwork.ozlabs.org/api/patches/2231480/?format=api", "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=api", "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=api", "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=api", "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" ] }