From nobody Fri May 17 22:23:27 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; arc=pass (i=1 dmarc=pass fromdomain=amd.com); dmarc=pass(p=quarantine dis=none) header.from=amd.com ARC-Seal: i=2; a=rsa-sha256; t=1670379354; cv=pass; d=zohomail.com; s=zohoarc; b=d3hLWNJp0hNqetlGmtUC6zvio0Fjou38so7Yb9ZAjP4ttryYewD4dSckj3m8pCcGC74bHV/a88/8YbhtYUQse2aO1z2HakPkFqStkhg8C/ChdIabGD9E3YW9kr1sFb/cYZJ7mPf1JBGYUI8o8RCfOy2/zH9Y03BXI3ihPP/2CgQ= ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1670379354; h=Content-Type:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=pW7CC5VEoARhhjXPOwPqIdbk8b2xiNoS5jfjgYKi5KI=; b=NnmPWYLgHCwavsq8JfVnvnHdxFxRg6ZTRSpCB6ZWTilqnx6J9ng/hFPfsL+2I3a2Yw+EqOkf+LEN88S44vk6LmX2cwxWW+0cVkfyqPxiRcojlXwcvLTeHfHqlafAXnqxHEnaypMULWfllmUWQZ7gXZmRrIK8ojdkECXPtVDhpVU= ARC-Authentication-Results: i=2; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; arc=pass (i=1 dmarc=pass fromdomain=amd.com); dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 167037935498380.38428554160794; Tue, 6 Dec 2022 18:15:54 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1p2jwT-0000ME-LA; Tue, 06 Dec 2022 21:13:49 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1p2jwO-0000JI-Vq for qemu-devel@nongnu.org; Tue, 06 Dec 2022 21:13:45 -0500 Received: from mail-mw2nam12on2061c.outbound.protection.outlook.com ([2a01:111:f400:fe5a::61c] helo=NAM12-MW2-obe.outbound.protection.outlook.com) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1p2jwM-00087F-UA for qemu-devel@nongnu.org; Tue, 06 Dec 2022 21:13:44 -0500 Received: from DS7PR03CA0196.namprd03.prod.outlook.com (2603:10b6:5:3b6::21) by DS7PR12MB5766.namprd12.prod.outlook.com (2603:10b6:8:75::12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5880.14; Wed, 7 Dec 2022 02:13:39 +0000 Received: from DM6NAM11FT039.eop-nam11.prod.protection.outlook.com (2603:10b6:5:3b6:cafe::67) by DS7PR03CA0196.outlook.office365.com (2603:10b6:5:3b6::21) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5880.14 via Frontend Transport; Wed, 7 Dec 2022 02:13:39 +0000 Received: from SATLEXMB04.amd.com (165.204.84.17) by DM6NAM11FT039.mail.protection.outlook.com (10.13.172.83) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.5901.14 via Frontend Transport; Wed, 7 Dec 2022 02:13:39 +0000 Received: from SATLEXMB03.amd.com (10.181.40.144) by SATLEXMB04.amd.com (10.181.40.145) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2375.34; Tue, 6 Dec 2022 20:13:38 -0600 Received: from xsjfnuv50.xilinx.com (10.180.168.240) by SATLEXMB03.amd.com (10.181.40.144) with Microsoft SMTP Server id 15.1.2375.34 via Frontend Transport; Tue, 6 Dec 2022 20:13:38 -0600 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=LJ818mCscMRL0UCzdtyno8PJ/F6DhgR7GMnG+r5G5ClWD+zTfXLzD9y7DFB0pPvxaCtwdL0amSNmaa70dNdQNp9fuxUVSGWR9DDOZV3RfZ/MyqJqMNDqdLOELkXufFVD72A9NbC7MjoY7ylTpAhTZK5hrb7wmA4JTSrpWbhzDF/4pIMXb4Qo1Bvw/r9ypWkixJ4+XG1PPUikrQHgSAnHYhvD6U0FZsGjSOpQuRDPbKdVbIWLX4b7r+b5gYMNgFukIjUgN1UcXXyk19cJevaDK93GKiuiPP1RZoaIfwN/JWzRlmiaujTYZ1LHLnk6gZDOHjIJCKQL18F8cTFo0Kko6g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=pW7CC5VEoARhhjXPOwPqIdbk8b2xiNoS5jfjgYKi5KI=; b=Cn+8dg6l2uUKGkCz4oSFhER2p96LWOpnLT+8595AXTK0uuDbX654GikhID4xdkVQw2GT0l2xBNunZhst+SxqoH9jn2cbRj3IJBp/N6H+fmTebwlE61L7U1evchrJRfWYLDiLMu2keQEyOl0KhdCByFjOWe5L7NAF1eV//C8dMgjXKpHVrMBXCQH+zqa3G4/3EObNlyWi+XmUuvXgMiIWD8H2r6LOUFXf1nEe2L0rxssjjDW8tLwMXY759dZ3ASNLJx9qFVZUgfpfq2JQPGqXhfp1qV6Z4Rm4NLeqVMz4veplGAO3mKZ/D9Mikp+mRnFELWyFBhAsef4pNNvMLrAT9Q== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 165.204.84.17) smtp.rcpttodomain=nongnu.org smtp.mailfrom=amd.com; dmarc=pass (p=quarantine sp=quarantine pct=100) action=none header.from=amd.com; dkim=none (message not signed); arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amd.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=pW7CC5VEoARhhjXPOwPqIdbk8b2xiNoS5jfjgYKi5KI=; b=Sq9cJ9ChowwknnaiRigR38Q9yonUN8DthGHJFOeLWfULtsD2y3jNNaj+beLdW73jLqe1fSkL2w+5hrqwSm7A6sZNVVB3JPp4bU0J0RCqkudm2iyz2bQrsCU8idne/NKaLGNsAs0GBzTtI//wPawTVeTQyfMN0xNelmw7/axaqI8= X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 165.204.84.17) smtp.mailfrom=amd.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=amd.com; Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: Pass (protection.outlook.com: domain of amd.com designates 165.204.84.17 as permitted sender) receiver=protection.outlook.com; client-ip=165.204.84.17; helo=SATLEXMB04.amd.com; pr=C From: Vikram Garhwal To: CC: , , Subject: [QEMU][PATCH v3 1/4] MAINTAINERS: Include canfd tests under Xilinx CAN Date: Tue, 6 Dec 2022 18:13:18 -0800 Message-ID: <20221207021322.16165-2-vikram.garhwal@amd.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20221207021322.16165-1-vikram.garhwal@amd.com> References: <20221207021322.16165-1-vikram.garhwal@amd.com> MIME-Version: 1.0 X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: DM6NAM11FT039:EE_|DS7PR12MB5766:EE_ X-MS-Office365-Filtering-Correlation-Id: bea65f70-9e4c-42fd-b870-08dad7f8a7ac X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: KOu1t1O56W3CAKCZReC9L2JngqOdwLIibnhb4r7RB+UvMb0fxQr9flaUzbIC/iEMSNWiIdeT8zyHCzG46P8n0xt4EEgtP6MRkgxcrQsG2K5EUrET9fo7turBFcvMs/wXKbhgSPOC9FYPlozNhbUBEzoKCvDkHzGTvDvat0Zvf+3nBuKtGR7bqCoOgsPjUkNuVxbmG9Cp7OJDOkvUJsK9f4K9feklfGasd6Dog0jQGHpCTBOsQ0aP2fxvTBKdx+LGZADZBzPB+V3QzD7Vnm8qa5gbdg5/YosHvLpkuj+Y/X9u3j5LQKuSVrd3EcUw2o7ZKoVlpZoHEfoThbIULQBxtLFNVE9z8VyY/TifC7ThVN855thGYcTDylT3Ukv2OowTKF1pBQm6xrLnGKcygeA1ReRfC5HGs7/lHW0o7BdrN0N2sn4Os0TnPqeCdBuz0oy0wiW3vw3VkQ5Q+PwYBeAMWBMc0tN592zFKUa5e1BnZ+gYknbmRryQBuOyNZxv9nMf6stBFRWLWOSuSjIl+5TM7KoEu7V+3C6entwa6u9LYacn9qZ5ym76ngfCoxB0EZE+yxQZ/1aNyNzCVxTf4GsfL4J2xXF7xAth732y5GYFzpmHuLktYsWf58lY5AbY+hyDcYKIp0QJ84Nl6/ayMiKlVRDQxaD2MVS+u5BGj4n2P3MFdImPHIN7hdrWnL/Aqzp4RKPZWVefGXh44ExEILUvPGvxdP8FXkBw4xeOK1VvrJw= X-Forefront-Antispam-Report: CIP:165.204.84.17; CTRY:US; LANG:en; SCL:1; SRV:; IPV:CAL; SFV:NSPM; H:SATLEXMB04.amd.com; PTR:InfoDomainNonexistent; CAT:NONE; SFS:(13230022)(4636009)(376002)(136003)(39860400002)(346002)(396003)(451199015)(40470700004)(46966006)(36840700001)(316002)(336012)(2906002)(70206006)(8676002)(44832011)(356005)(70586007)(4326008)(81166007)(36756003)(40460700003)(82310400005)(82740400003)(186003)(26005)(478600001)(6916009)(54906003)(1076003)(36860700001)(40480700001)(6666004)(2616005)(86362001)(426003)(8936002)(47076005)(83380400001)(41300700001)(4744005)(5660300002)(36900700001); DIR:OUT; SFP:1101; X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 07 Dec 2022 02:13:39.0540 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: bea65f70-9e4c-42fd-b870-08dad7f8a7ac X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=3dd8961f-e488-4e60-8e11-a82d994e183d; Ip=[165.204.84.17]; Helo=[SATLEXMB04.amd.com] X-MS-Exchange-CrossTenant-AuthSource: DM6NAM11FT039.eop-nam11.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: DS7PR12MB5766 Received-SPF: softfail client-ip=2a01:111:f400:fe5a::61c; envelope-from=vikram.garhwal@amd.com; helo=NAM12-MW2-obe.outbound.protection.outlook.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @amd.com) X-ZM-MESSAGEID: 1670379357209100010 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Signed-off-by: Vikram Garhwal Reviewed-by: Peter Maydell --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 6966490c94..a76221f260 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1753,7 +1753,7 @@ M: Francisco Iglesias S: Maintained F: hw/net/can/xlnx-* F: include/hw/net/xlnx-* -F: tests/qtest/xlnx-can-test* +F: tests/qtest/xlnx-can*-test* =20 EDU M: Jiri Slaby --=20 2.17.1 From nobody Fri May 17 22:23:27 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; arc=pass (i=1 dmarc=pass fromdomain=amd.com); dmarc=pass(p=quarantine dis=none) header.from=amd.com ARC-Seal: i=2; a=rsa-sha256; t=1670379370; cv=pass; d=zohomail.com; s=zohoarc; b=Gxnl8YKMPcgQOj7NHnQ1n5ajD1ivs9sQrBgv1Z2LiUDGaE+nyR4valzfgppr+wCmd4Aa8IUoXkKBuTVh4oPXRF4sd52TcXN2EuQ0k6iLZJo3ORz+L4B3xC3D48mp9laF1JgulRbrpxAZO+2OH3nVQcsynqu5G4rRlr6DJwBzrbI= ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1670379370; h=Content-Type:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=59p0JK7r01ntafBmnaTZaDgKXctXXV1SBdrO0AMZUVs=; b=KAx+vWW2IuPPGHfu5K61wOsZu6GNOuhT3D632JN9KFNuw+aETE6ryWpnhrRHWg8s5+quMtlQ6H7+Syx6WKn+p6aVAMtD9Bvhoc66L/7IEuKL+EMIRI/xo1NwXI8wmzU6i1LdK74SnssebIy9JSYr+GO5/t9ChnrM2M1w83OALNM= ARC-Authentication-Results: i=2; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; arc=pass (i=1 dmarc=pass fromdomain=amd.com); dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1670379370213747.6053028358159; Tue, 6 Dec 2022 18:16:10 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1p2jwd-0000Or-JA; Tue, 06 Dec 2022 21:13:59 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1p2jwY-0000Nb-2l; Tue, 06 Dec 2022 21:13:54 -0500 Received: from mail-bn8nam04on20630.outbound.protection.outlook.com ([2a01:111:f400:7e8d::630] helo=NAM04-BN8-obe.outbound.protection.outlook.com) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1p2jwT-000897-6c; Tue, 06 Dec 2022 21:13:53 -0500 Received: from DS7PR03CA0195.namprd03.prod.outlook.com (2603:10b6:5:3b6::20) by DS7PR12MB5888.namprd12.prod.outlook.com (2603:10b6:8:7b::16) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5880.14; Wed, 7 Dec 2022 02:13:40 +0000 Received: from DM6NAM11FT039.eop-nam11.prod.protection.outlook.com (2603:10b6:5:3b6:cafe::4c) by DS7PR03CA0195.outlook.office365.com (2603:10b6:5:3b6::20) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5880.14 via Frontend Transport; Wed, 7 Dec 2022 02:13:40 +0000 Received: from SATLEXMB04.amd.com (165.204.84.17) by DM6NAM11FT039.mail.protection.outlook.com (10.13.172.83) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.5901.14 via Frontend Transport; Wed, 7 Dec 2022 02:13:40 +0000 Received: from SATLEXMB03.amd.com (10.181.40.144) by SATLEXMB04.amd.com (10.181.40.145) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2375.34; Tue, 6 Dec 2022 20:13:39 -0600 Received: from xsjfnuv50.xilinx.com (10.180.168.240) by SATLEXMB03.amd.com (10.181.40.144) with Microsoft SMTP Server id 15.1.2375.34 via Frontend Transport; Tue, 6 Dec 2022 20:13:39 -0600 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=Yz8vlSeNwhp/XSMbpK4eG9AGwh5HLeHZN8h6OW6utrmiycvK9Pdi8bfc8K2DVVwtKZ7Hq+upQo9wA1MLk8/2gHe1Yj+Nk4YEqrxJHh9Wj7S8GaOHXPg5CsLhgmYTbb519dqMeV+iYkQM7NTwrD9MpVV6ogTcNZCEqMtqdUWIOHjaKe/1Jlpjrpd4ptKojNxM7TbKqO0fiogpXtyIxpNfN8Biu/rL03QjNL6cpAVC0U98lOKjybX5TyUNRY23jm/kzE/3aaYY+nH8ljxm6EyaMDPPZZCHgigqsu4z4VUX9hBM4+wtBxXMCg8UffXknQcKTu45vzaOs3BJ7RqrYHBTxg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=59p0JK7r01ntafBmnaTZaDgKXctXXV1SBdrO0AMZUVs=; b=cbpbyobcV9+R3T9GJdOR+Nfat8cAjW1eJXVnSW7v3E3nU642ziaWCDhkB4cu59ms+84r+ZLCh9kSwjPHsUZ90UhaoPArwe7Ds5P6sLUq9w//jtkvJsppU+arEl2UUSpHEad+InjAe+DbLUYJOsEqHDG5l+QmzQhxsTqeS1hFbTIEw7A2/CMj95oVhDg0dZlCSrtSeCRNCuYmdTcCOlbVWqQmzDodFqgxr6wPHh1BR3NEResaQtkHZfzpsPEJ8zFs8Swe2BhvwgxeG4/BosHLs20b4boolI61WOwK6TbrFHqdriYf0KiquFXAyh+jRyhvJfW7mCcpwzjKct7qpbuVlQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 165.204.84.17) smtp.rcpttodomain=nongnu.org smtp.mailfrom=amd.com; dmarc=pass (p=quarantine sp=quarantine pct=100) action=none header.from=amd.com; dkim=none (message not signed); arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amd.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=59p0JK7r01ntafBmnaTZaDgKXctXXV1SBdrO0AMZUVs=; b=mngXVibxtDuPqi6Lx7JwlGZ86quB3n+FtqAeeFQAeEkE97tuYIReYup3ctil4SHQDLEf1uH6rMASJSSBm0MnLBL/IEp387zu8r1E05jaix2vEgq+i5VkHCjF/RnTxbyVZ3rOo4GSo9Wap/Ix+khdx2HZpXemHuevQQhGi0uVTQo= X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 165.204.84.17) smtp.mailfrom=amd.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=amd.com; Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: Pass (protection.outlook.com: domain of amd.com designates 165.204.84.17 as permitted sender) receiver=protection.outlook.com; client-ip=165.204.84.17; helo=SATLEXMB04.amd.com; pr=C From: Vikram Garhwal To: CC: , , , Pavel Pisa , Vikram Garhwal , Jason Wang , Alistair Francis , "Edgar E. Iglesias" , "open list:Xilinx ZynqMP and..." Subject: [QEMU][PATCH v3 2/4] hw/net/can: Introduce Xilinx Versal CANFD controller Date: Tue, 6 Dec 2022 18:13:19 -0800 Message-ID: <20221207021322.16165-3-vikram.garhwal@amd.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20221207021322.16165-1-vikram.garhwal@amd.com> References: <20221207021322.16165-1-vikram.garhwal@amd.com> MIME-Version: 1.0 X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: DM6NAM11FT039:EE_|DS7PR12MB5888:EE_ X-MS-Office365-Filtering-Correlation-Id: 148a2763-2137-4172-1ecb-08dad7f8a89b X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: x/PtjbQmjdJhCWQLzlH0y+4O7GfnvjjvHLLbvgp0y7XC3fYDpTesmAfzqeATCMl++gbirvecNDoUSsTNidYSUuoExLGnDJZ9ZYgt2oe99Owl7XnqRCzIhyN4ia2n78WzNv+YxO17UbrJjmkl6VBArenwoVdEhU/F+rYhiYAZ8fa3k6/iHuAcrd/TettqFXb2mVWHXvV+yd/xIXcyEGsQBSMd6yxKKwO4VijAc/IzBRu5YPya63FcOpaSfCXcQhdYnhiLr0ibXqR+ku3ujEBq2NJ0Aoc/Z8+doCvcQUZ0Vbt9f8dp8G6x6WlCuuPVMtgfXYTCDHKSbN434HdCaERKj37iS6hqv4kT4I1XG8lsNyUB4n84ZquFecWynozGDudNBB7T7he1YSUkrocNXxTVj83hge67ZDiKwL7u/olKKLGdE+zTnmH4I2D8mwFnOqKX3LXjoIIU9IT1lTPLTm0/8D+3iwbPONIVaMEEQZoJxHrgvLNRUTkjbIEoFsONcJ2S5FNWlXwXOvMyV3QHmMQwOMABZHRqAZK6L64bJ5NS1tlWgLhNVTnECGEq1rP2DGAouby94cLs5OI37gmfwwFHsXaI1x9eE7Z2EzSvk1zLWhHpcVvpGHiMRqJmtsBFaBfwtvZj7LT6Qr+TifjHlD8sCbb50VdcTlnnGOd/pOkXfmy+y3+8W6WaY9YtCERjSM2wEne+ygZ2yaKMlsQ/Tm+hOSVx5nEewZk1oJON/zAYgqrfdVuQc0tS4z1I4us7GOoPzsm4uIvVU1My6SsSirHKGg== X-Forefront-Antispam-Report: CIP:165.204.84.17; CTRY:US; LANG:en; SCL:1; SRV:; IPV:CAL; SFV:NSPM; H:SATLEXMB04.amd.com; PTR:InfoDomainNonexistent; CAT:NONE; SFS:(13230022)(4636009)(136003)(39860400002)(376002)(396003)(346002)(451199015)(40470700004)(46966006)(36840700001)(44832011)(316002)(30864003)(41300700001)(54906003)(5660300002)(70206006)(6916009)(47076005)(478600001)(8936002)(4326008)(8676002)(70586007)(36756003)(83380400001)(426003)(1076003)(356005)(81166007)(36860700001)(2616005)(186003)(336012)(40460700003)(966005)(82310400005)(40480700001)(26005)(86362001)(6666004)(82740400003)(66899015)(2906002)(36900700001)(579004)(559001); DIR:OUT; SFP:1101; X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 07 Dec 2022 02:13:40.6164 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 148a2763-2137-4172-1ecb-08dad7f8a89b X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=3dd8961f-e488-4e60-8e11-a82d994e183d; Ip=[165.204.84.17]; Helo=[SATLEXMB04.amd.com] X-MS-Exchange-CrossTenant-AuthSource: DM6NAM11FT039.eop-nam11.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: DS7PR12MB5888 Received-SPF: softfail client-ip=2a01:111:f400:7e8d::630; envelope-from=vikram.garhwal@amd.com; helo=NAM04-BN8-obe.outbound.protection.outlook.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001, UPPERCASE_50_75=0.008 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: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @amd.com) X-ZM-MESSAGEID: 1670379371687100003 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The Xilinx Versal CANFD controller is developed based on SocketCAN, QEMU CA= N bus implementation. Bus connection and socketCAN connection for each CAN module can be set through command lines. Signed-off-by: Vikram Garhwal --- hw/net/can/meson.build | 1 + hw/net/can/trace-events | 7 + hw/net/can/xlnx-versal-canfd.c | 2121 ++++++++++++++++++++++++++++ include/hw/net/xlnx-versal-canfd.h | 90 ++ 4 files changed, 2219 insertions(+) create mode 100644 hw/net/can/xlnx-versal-canfd.c create mode 100644 include/hw/net/xlnx-versal-canfd.h diff --git a/hw/net/can/meson.build b/hw/net/can/meson.build index 8fabbd9ee6..8d85201cb0 100644 --- a/hw/net/can/meson.build +++ b/hw/net/can/meson.build @@ -5,3 +5,4 @@ softmmu_ss.add(when: 'CONFIG_CAN_PCI', if_true: files('can_= mioe3680_pci.c')) softmmu_ss.add(when: 'CONFIG_CAN_CTUCANFD', if_true: files('ctucan_core.c'= )) softmmu_ss.add(when: 'CONFIG_CAN_CTUCANFD_PCI', if_true: files('ctucan_pci= .c')) softmmu_ss.add(when: 'CONFIG_XLNX_ZYNQMP', if_true: files('xlnx-zynqmp-can= .c')) +softmmu_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files('xlnx-versal-can= fd.c')) diff --git a/hw/net/can/trace-events b/hw/net/can/trace-events index 8346a98ab5..de64ac1b31 100644 --- a/hw/net/can/trace-events +++ b/hw/net/can/trace-events @@ -7,3 +7,10 @@ xlnx_can_filter_mask_pre_write(uint8_t filter_num, uint32_= t value) "Filter%d MAS xlnx_can_tx_data(uint32_t id, uint8_t dlc, uint8_t db0, uint8_t db1, uint8= _t db2, uint8_t db3, uint8_t db4, uint8_t db5, uint8_t db6, uint8_t db7) "F= rame: ID: 0x%08x DLC: 0x%02x DATA: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02= x 0x%02x 0x%02x" xlnx_can_rx_data(uint32_t id, uint32_t dlc, uint8_t db0, uint8_t db1, uint= 8_t db2, uint8_t db3, uint8_t db4, uint8_t db5, uint8_t db6, uint8_t db7) "= Frame: ID: 0x%08x DLC: 0x%02x DATA: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%0= 2x 0x%02x 0x%02x" xlnx_can_rx_discard(uint32_t status) "Controller is not enabled for bus co= mmunication. Status Register: 0x%08x" + +# xlnx-versal-canfd.c +xlnx_canfd_update_irq(char *path, uint32_t isr, uint32_t ier, uint32_t irq= ) "%s: ISR: 0x%08x IER: 0x%08x IRQ: 0x%08x" +xlnx_canfd_rx_fifo_filter_reject(char *path, uint32_t id, uint8_t dlc) "%s= : Frame: ID: 0x%08x DLC: 0x%02x" +xlnx_canfd_rx_data(char *path, uint32_t id, uint8_t dlc, uint8_t flags) "%= s: Frame: ID: 0x%08x DLC: 0x%02x CANFD Flag: 0x%02x" +xlnx_canfd_tx_data(char *path, uint32_t id, uint8_t dlc, uint8_t flgas) "%= s: Frame: ID: 0x%08x DLC: 0x%02x CANFD Flag: 0x%02x" +xlnx_canfd_reset(char *path, uint32_t val) "%s: Resetting controller with = value =3D 0x%08x" diff --git a/hw/net/can/xlnx-versal-canfd.c b/hw/net/can/xlnx-versal-canfd.c new file mode 100644 index 0000000000..02a32d6042 --- /dev/null +++ b/hw/net/can/xlnx-versal-canfd.c @@ -0,0 +1,2121 @@ +/* + * QEMU model of the Xilinx Versal CANFD device. + * + * This implementation is based on the following datasheet: + * https://docs.xilinx.com/v/u/2.0-English/pg223-canfd + * + * Copyright (c) 2022 AMD Inc. + * + * Written-by: Vikram Garhwal + * + * Based on QEMU CANFD Device emulation implemented by Jin Yang, Deniz Ere= n and + * Pavel Pisa + * + * Permission is hereby granted, free of charge, to any person obtaining a= copy + * of this software and associated documentation files (the "Software"), t= o deal + * in the Software without restriction, including without limitation the r= ights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or se= ll + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included= in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS= OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OT= HER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING= FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS = IN + * THE SOFTWARE. + */ + +#include "qemu/osdep.h" +#include "hw/sysbus.h" +#include "hw/irq.h" +#include "hw/register.h" +#include "qapi/error.h" +#include "qemu/bitops.h" +#include "qemu/log.h" +#include "qemu/cutils.h" +#include "qemu/event_notifier.h" +#include "hw/qdev-properties.h" +#include "qom/object_interfaces.h" +#include "migration/vmstate.h" +#include "hw/net/xlnx-versal-canfd.h" +#include "trace.h" + +/* + * This is done to avoid the build issues on Windows machines. The ERROR f= ield + * of INTERRUPT_STATUS_REGISTER collides with a macro in the Windows build + * environment. + */ +#undef ERROR + +REG32(SOFTWARE_RESET_REGISTER, 0x0) + FIELD(SOFTWARE_RESET_REGISTER, CEN, 1, 1) + FIELD(SOFTWARE_RESET_REGISTER, SRST, 0, 1) +REG32(MODE_SELECT_REGISTER, 0x4) + FIELD(MODE_SELECT_REGISTER, ITO, 8, 8) + FIELD(MODE_SELECT_REGISTER, ABR, 7, 1) + FIELD(MODE_SELECT_REGISTER, SBR, 6, 1) + FIELD(MODE_SELECT_REGISTER, DPEE, 5, 1) + FIELD(MODE_SELECT_REGISTER, DAR, 4, 1) + FIELD(MODE_SELECT_REGISTER, BRSD, 3, 1) + FIELD(MODE_SELECT_REGISTER, SNOOP, 2, 1) + FIELD(MODE_SELECT_REGISTER, LBACK, 1, 1) + FIELD(MODE_SELECT_REGISTER, SLEEP, 0, 1) +REG32(ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER, 0x8) + FIELD(ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER, BRP, 0, 8) +REG32(ARBITRATION_PHASE_BIT_TIMING_REGISTER, 0xc) + FIELD(ARBITRATION_PHASE_BIT_TIMING_REGISTER, SJW, 16, 7) + FIELD(ARBITRATION_PHASE_BIT_TIMING_REGISTER, TS2, 8, 7) + FIELD(ARBITRATION_PHASE_BIT_TIMING_REGISTER, TS1, 0, 8) +REG32(ERROR_COUNTER_REGISTER, 0x10) + FIELD(ERROR_COUNTER_REGISTER, REC, 8, 8) + FIELD(ERROR_COUNTER_REGISTER, TEC, 0, 8) +REG32(ERROR_STATUS_REGISTER, 0x14) + FIELD(ERROR_STATUS_REGISTER, F_BERR, 11, 1) + FIELD(ERROR_STATUS_REGISTER, F_STER, 10, 1) + FIELD(ERROR_STATUS_REGISTER, F_FMER, 9, 1) + FIELD(ERROR_STATUS_REGISTER, F_CRCER, 8, 1) + FIELD(ERROR_STATUS_REGISTER, ACKER, 4, 1) + FIELD(ERROR_STATUS_REGISTER, BERR, 3, 1) + FIELD(ERROR_STATUS_REGISTER, STER, 2, 1) + FIELD(ERROR_STATUS_REGISTER, FMER, 1, 1) + FIELD(ERROR_STATUS_REGISTER, CRCER, 0, 1) +REG32(STATUS_REGISTER, 0x18) + FIELD(STATUS_REGISTER, TDCV, 16, 7) + FIELD(STATUS_REGISTER, SNOOP, 12, 1) + FIELD(STATUS_REGISTER, BSFR_CONFIG, 10, 1) + FIELD(STATUS_REGISTER, PEE_CONFIG, 9, 1) + FIELD(STATUS_REGISTER, ESTAT, 7, 2) + FIELD(STATUS_REGISTER, ERRWRN, 6, 1) + FIELD(STATUS_REGISTER, BBSY, 5, 1) + FIELD(STATUS_REGISTER, BIDLE, 4, 1) + FIELD(STATUS_REGISTER, NORMAL, 3, 1) + FIELD(STATUS_REGISTER, SLEEP, 2, 1) + FIELD(STATUS_REGISTER, LBACK, 1, 1) + FIELD(STATUS_REGISTER, CONFIG, 0, 1) +REG32(INTERRUPT_STATUS_REGISTER, 0x1c) + FIELD(INTERRUPT_STATUS_REGISTER, TXEWMFLL, 31, 1) + FIELD(INTERRUPT_STATUS_REGISTER, TXEOFLW, 30, 1) + FIELD(INTERRUPT_STATUS_REGISTER, RXBOFLW_BI, 24, 6) + FIELD(INTERRUPT_STATUS_REGISTER, RXLRM_BI, 18, 6) + FIELD(INTERRUPT_STATUS_REGISTER, RXMNF, 17, 1) + FIELD(INTERRUPT_STATUS_REGISTER, RXFWMFLL_1, 16, 1) + FIELD(INTERRUPT_STATUS_REGISTER, RXFOFLW_1, 15, 1) + FIELD(INTERRUPT_STATUS_REGISTER, TXCRS, 14, 1) + FIELD(INTERRUPT_STATUS_REGISTER, TXRRS, 13, 1) + FIELD(INTERRUPT_STATUS_REGISTER, RXFWMFLL, 12, 1) + FIELD(INTERRUPT_STATUS_REGISTER, WKUP, 11, 1) + FIELD(INTERRUPT_STATUS_REGISTER, SLP, 10, 1) + FIELD(INTERRUPT_STATUS_REGISTER, BSOFF, 9, 1) + FIELD(INTERRUPT_STATUS_REGISTER, ERROR, 8, 1) + FIELD(INTERRUPT_STATUS_REGISTER, RXFOFLW, 6, 1) + FIELD(INTERRUPT_STATUS_REGISTER, TSCNT_OFLW, 5, 1) + FIELD(INTERRUPT_STATUS_REGISTER, RXOK, 4, 1) + FIELD(INTERRUPT_STATUS_REGISTER, BSFRD, 3, 1) + FIELD(INTERRUPT_STATUS_REGISTER, PEE, 2, 1) + FIELD(INTERRUPT_STATUS_REGISTER, TXOK, 1, 1) + FIELD(INTERRUPT_STATUS_REGISTER, ARBLST, 0, 1) +REG32(INTERRUPT_ENABLE_REGISTER, 0x20) + FIELD(INTERRUPT_ENABLE_REGISTER, ETXEWMFLL, 31, 1) + FIELD(INTERRUPT_ENABLE_REGISTER, ETXEOFLW, 30, 1) + FIELD(INTERRUPT_ENABLE_REGISTER, ERXMNF, 17, 1) + FIELD(INTERRUPT_ENABLE_REGISTER, ERXFWMFLL_1, 16, 1) + FIELD(INTERRUPT_ENABLE_REGISTER, ERXFOFLW_1, 15, 1) + FIELD(INTERRUPT_ENABLE_REGISTER, ETXCRS, 14, 1) + FIELD(INTERRUPT_ENABLE_REGISTER, ETXRRS, 13, 1) + FIELD(INTERRUPT_ENABLE_REGISTER, ERXFWMFLL, 12, 1) + FIELD(INTERRUPT_ENABLE_REGISTER, EWKUP, 11, 1) + FIELD(INTERRUPT_ENABLE_REGISTER, ESLP, 10, 1) + FIELD(INTERRUPT_ENABLE_REGISTER, EBSOFF, 9, 1) + FIELD(INTERRUPT_ENABLE_REGISTER, EERROR, 8, 1) + FIELD(INTERRUPT_ENABLE_REGISTER, ERFXOFLW, 6, 1) + FIELD(INTERRUPT_ENABLE_REGISTER, ETSCNT_OFLW, 5, 1) + FIELD(INTERRUPT_ENABLE_REGISTER, ERXOK, 4, 1) + FIELD(INTERRUPT_ENABLE_REGISTER, EBSFRD, 3, 1) + FIELD(INTERRUPT_ENABLE_REGISTER, EPEE, 2, 1) + FIELD(INTERRUPT_ENABLE_REGISTER, ETXOK, 1, 1) + FIELD(INTERRUPT_ENABLE_REGISTER, EARBLOST, 0, 1) +REG32(INTERRUPT_CLEAR_REGISTER, 0x24) + FIELD(INTERRUPT_CLEAR_REGISTER, CTXEWMFLL, 31, 1) + FIELD(INTERRUPT_CLEAR_REGISTER, CTXEOFLW, 30, 1) + FIELD(INTERRUPT_CLEAR_REGISTER, CRXMNF, 17, 1) + FIELD(INTERRUPT_CLEAR_REGISTER, CRXFWMFLL_1, 16, 1) + FIELD(INTERRUPT_CLEAR_REGISTER, CRXFOFLW_1, 15, 1) + FIELD(INTERRUPT_CLEAR_REGISTER, CTXCRS, 14, 1) + FIELD(INTERRUPT_CLEAR_REGISTER, CTXRRS, 13, 1) + FIELD(INTERRUPT_CLEAR_REGISTER, CRXFWMFLL, 12, 1) + FIELD(INTERRUPT_CLEAR_REGISTER, CWKUP, 11, 1) + FIELD(INTERRUPT_CLEAR_REGISTER, CSLP, 10, 1) + FIELD(INTERRUPT_CLEAR_REGISTER, CBSOFF, 9, 1) + FIELD(INTERRUPT_CLEAR_REGISTER, CERROR, 8, 1) + FIELD(INTERRUPT_CLEAR_REGISTER, CRFXOFLW, 6, 1) + FIELD(INTERRUPT_CLEAR_REGISTER, CTSCNT_OFLW, 5, 1) + FIELD(INTERRUPT_CLEAR_REGISTER, CRXOK, 4, 1) + FIELD(INTERRUPT_CLEAR_REGISTER, CBSFRD, 3, 1) + FIELD(INTERRUPT_CLEAR_REGISTER, CPEE, 2, 1) + FIELD(INTERRUPT_CLEAR_REGISTER, CTXOK, 1, 1) + FIELD(INTERRUPT_CLEAR_REGISTER, CARBLOST, 0, 1) +REG32(TIMESTAMP_REGISTER, 0x28) + FIELD(TIMESTAMP_REGISTER, TIMESTAMP_CNT, 16, 16) + FIELD(TIMESTAMP_REGISTER, CTS, 0, 1) +REG32(DATA_PHASE_BAUD_RATE_PRESCALER_REGISTER, 0x88) + FIELD(DATA_PHASE_BAUD_RATE_PRESCALER_REGISTER, TDC, 16, 1) + FIELD(DATA_PHASE_BAUD_RATE_PRESCALER_REGISTER, TDCOFF, 8, 6) + FIELD(DATA_PHASE_BAUD_RATE_PRESCALER_REGISTER, DP_BRP, 0, 8) +REG32(DATA_PHASE_BIT_TIMING_REGISTER, 0x8c) + FIELD(DATA_PHASE_BIT_TIMING_REGISTER, DP_SJW, 16, 4) + FIELD(DATA_PHASE_BIT_TIMING_REGISTER, DP_TS2, 8, 4) + FIELD(DATA_PHASE_BIT_TIMING_REGISTER, DP_TS1, 0, 5) +REG32(TX_BUFFER_READY_REQUEST_REGISTER, 0x90) + FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR31, 31, 1) + FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR30, 30, 1) + FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR29, 29, 1) + FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR28, 28, 1) + FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR27, 27, 1) + FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR26, 26, 1) + FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR25, 25, 1) + FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR24, 24, 1) + FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR23, 23, 1) + FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR22, 22, 1) + FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR21, 21, 1) + FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR20, 20, 1) + FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR19, 19, 1) + FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR18, 18, 1) + FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR17, 17, 1) + FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR16, 16, 1) + FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR15, 15, 1) + FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR14, 14, 1) + FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR13, 13, 1) + FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR12, 12, 1) + FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR11, 11, 1) + FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR10, 10, 1) + FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR9, 9, 1) + FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR8, 8, 1) + FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR7, 7, 1) + FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR6, 6, 1) + FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR5, 5, 1) + FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR4, 4, 1) + FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR3, 3, 1) + FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR2, 2, 1) + FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR1, 1, 1) + FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR0, 0, 1) +REG32(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, 0x94) + FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS31, 31, 1) + FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS30, 30, 1) + FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS29, 29, 1) + FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS28, 28, 1) + FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS27, 27, 1) + FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS26, 26, 1) + FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS25, 25, 1) + FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS24, 24, 1) + FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS23, 23, 1) + FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS22, 22, 1) + FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS21, 21, 1) + FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS20, 20, 1) + FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS19, 19, 1) + FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS18, 18, 1) + FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS17, 17, 1) + FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS16, 16, 1) + FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS15, 15, 1) + FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS14, 14, 1) + FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS13, 13, 1) + FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS12, 12, 1) + FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS11, 11, 1) + FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS10, 10, 1) + FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS9, 9, 1) + FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS8, 8, 1) + FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS7, 7, 1) + FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS6, 6, 1) + FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS5, 5, 1) + FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS4, 4, 1) + FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS3, 3, 1) + FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS2, 2, 1) + FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS1, 1, 1) + FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS0, 0, 1) +REG32(TX_BUFFER_CANCEL_REQUEST_REGISTER, 0x98) + FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR31, 31, 1) + FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR30, 30, 1) + FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR29, 29, 1) + FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR28, 28, 1) + FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR27, 27, 1) + FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR26, 26, 1) + FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR25, 25, 1) + FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR24, 24, 1) + FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR23, 23, 1) + FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR22, 22, 1) + FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR21, 21, 1) + FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR20, 20, 1) + FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR19, 19, 1) + FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR18, 18, 1) + FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR17, 17, 1) + FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR16, 16, 1) + FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR15, 15, 1) + FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR14, 14, 1) + FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR13, 13, 1) + FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR12, 12, 1) + FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR11, 11, 1) + FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR10, 10, 1) + FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR9, 9, 1) + FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR8, 8, 1) + FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR7, 7, 1) + FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR6, 6, 1) + FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR5, 5, 1) + FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR4, 4, 1) + FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR3, 3, 1) + FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR2, 2, 1) + FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR1, 1, 1) + FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR0, 0, 1) +REG32(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, 0x9c) + FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS31= , 31, + 1) + FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS30= , 30, + 1) + FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS29= , 29, + 1) + FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS28= , 28, + 1) + FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS27= , 27, + 1) + FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS26= , 26, + 1) + FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS25= , 25, + 1) + FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS24= , 24, + 1) + FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS23= , 23, + 1) + FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS22= , 22, + 1) + FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS21= , 21, + 1) + FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS20= , 20, + 1) + FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS19= , 19, + 1) + FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS18= , 18, + 1) + FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS17= , 17, + 1) + FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS16= , 16, + 1) + FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS15= , 15, + 1) + FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS14= , 14, + 1) + FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS13= , 13, + 1) + FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS12= , 12, + 1) + FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS11= , 11, + 1) + FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS10= , 10, + 1) + FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS9,= 9, 1) + FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS8,= 8, 1) + FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS7,= 7, 1) + FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS6,= 6, 1) + FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS5,= 5, 1) + FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS4,= 4, 1) + FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS3,= 3, 1) + FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS2,= 2, 1) + FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS1,= 1, 1) + FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS0,= 0, 1) +REG32(TX_EVENT_FIFO_STATUS_REGISTER, 0xa0) + FIELD(TX_EVENT_FIFO_STATUS_REGISTER, TXE_FL, 8, 6) + FIELD(TX_EVENT_FIFO_STATUS_REGISTER, TXE_IRI, 7, 1) + FIELD(TX_EVENT_FIFO_STATUS_REGISTER, TXE_RI, 0, 5) +REG32(TX_EVENT_FIFO_WATERMARK_REGISTER, 0xa4) + FIELD(TX_EVENT_FIFO_WATERMARK_REGISTER, TXE_FWM, 0, 5) +REG32(ACCEPTANCE_FILTER_CONTROL_REGISTER, 0xe0) + FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF31, 31, 1) + FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF30, 30, 1) + FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF29, 29, 1) + FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF28, 28, 1) + FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF27, 27, 1) + FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF26, 26, 1) + FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF25, 25, 1) + FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF24, 24, 1) + FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF23, 23, 1) + FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF22, 22, 1) + FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF21, 21, 1) + FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF20, 20, 1) + FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF19, 19, 1) + FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF18, 18, 1) + FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF17, 17, 1) + FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF16, 16, 1) + FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF15, 15, 1) + FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF14, 14, 1) + FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF13, 13, 1) + FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF12, 12, 1) + FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF11, 11, 1) + FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF10, 10, 1) + FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF9, 9, 1) + FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF8, 8, 1) + FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF7, 7, 1) + FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF6, 6, 1) + FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF5, 5, 1) + FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF4, 4, 1) + FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF3, 3, 1) + FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF2, 2, 1) + FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF1, 1, 1) + FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF0, 0, 1) +REG32(RX_FIFO_STATUS_REGISTER, 0xe8) + FIELD(RX_FIFO_STATUS_REGISTER, FL_1, 24, 7) + FIELD(RX_FIFO_STATUS_REGISTER, IRI_1, 23, 1) + FIELD(RX_FIFO_STATUS_REGISTER, RI_1, 16, 6) + FIELD(RX_FIFO_STATUS_REGISTER, FL, 8, 7) + FIELD(RX_FIFO_STATUS_REGISTER, IRI, 7, 1) + FIELD(RX_FIFO_STATUS_REGISTER, RI, 0, 6) +REG32(RX_FIFO_WATERMARK_REGISTER, 0xec) + FIELD(RX_FIFO_WATERMARK_REGISTER, RXFP, 16, 5) + FIELD(RX_FIFO_WATERMARK_REGISTER, RXFWM_1, 8, 6) + FIELD(RX_FIFO_WATERMARK_REGISTER, RXFWM, 0, 6) +REG32(TB_ID_REGISTER, 0x100) + FIELD(TB_ID_REGISTER, ID, 21, 11) + FIELD(TB_ID_REGISTER, SRR_RTR_RRS, 20, 1) + FIELD(TB_ID_REGISTER, IDE, 19, 1) + FIELD(TB_ID_REGISTER, ID_EXT, 1, 18) + FIELD(TB_ID_REGISTER, RTR_RRS, 0, 1) +REG32(TB0_DLC_REGISTER, 0x104) + FIELD(TB0_DLC_REGISTER, DLC, 28, 4) + FIELD(TB0_DLC_REGISTER, FDF, 27, 1) + FIELD(TB0_DLC_REGISTER, BRS, 26, 1) + FIELD(TB0_DLC_REGISTER, RSVD2, 25, 1) + FIELD(TB0_DLC_REGISTER, EFC, 24, 1) + FIELD(TB0_DLC_REGISTER, MM, 16, 8) + FIELD(TB0_DLC_REGISTER, RSVD1, 0, 16) +REG32(TB_DW0_REGISTER, 0x108) + FIELD(TB_DW0_REGISTER, DATA_BYTES0, 24, 8) + FIELD(TB_DW0_REGISTER, DATA_BYTES1, 16, 8) + FIELD(TB_DW0_REGISTER, DATA_BYTES2, 8, 8) + FIELD(TB_DW0_REGISTER, DATA_BYTES3, 0, 8) +REG32(TB_DW1_REGISTER, 0x10c) + FIELD(TB_DW1_REGISTER, DATA_BYTES4, 24, 8) + FIELD(TB_DW1_REGISTER, DATA_BYTES5, 16, 8) + FIELD(TB_DW1_REGISTER, DATA_BYTES6, 8, 8) + FIELD(TB_DW1_REGISTER, DATA_BYTES7, 0, 8) +REG32(TB_DW2_REGISTER, 0x110) + FIELD(TB_DW2_REGISTER, DATA_BYTES8, 24, 8) + FIELD(TB_DW2_REGISTER, DATA_BYTES9, 16, 8) + FIELD(TB_DW2_REGISTER, DATA_BYTES10, 8, 8) + FIELD(TB_DW2_REGISTER, DATA_BYTES11, 0, 8) +REG32(TB_DW3_REGISTER, 0x114) + FIELD(TB_DW3_REGISTER, DATA_BYTES12, 24, 8) + FIELD(TB_DW3_REGISTER, DATA_BYTES13, 16, 8) + FIELD(TB_DW3_REGISTER, DATA_BYTES14, 8, 8) + FIELD(TB_DW3_REGISTER, DATA_BYTES15, 0, 8) +REG32(TB_DW4_REGISTER, 0x118) + FIELD(TB_DW4_REGISTER, DATA_BYTES16, 24, 8) + FIELD(TB_DW4_REGISTER, DATA_BYTES17, 16, 8) + FIELD(TB_DW4_REGISTER, DATA_BYTES18, 8, 8) + FIELD(TB_DW4_REGISTER, DATA_BYTES19, 0, 8) +REG32(TB_DW5_REGISTER, 0x11c) + FIELD(TB_DW5_REGISTER, DATA_BYTES20, 24, 8) + FIELD(TB_DW5_REGISTER, DATA_BYTES21, 16, 8) + FIELD(TB_DW5_REGISTER, DATA_BYTES22, 8, 8) + FIELD(TB_DW5_REGISTER, DATA_BYTES23, 0, 8) +REG32(TB_DW6_REGISTER, 0x120) + FIELD(TB_DW6_REGISTER, DATA_BYTES24, 24, 8) + FIELD(TB_DW6_REGISTER, DATA_BYTES25, 16, 8) + FIELD(TB_DW6_REGISTER, DATA_BYTES26, 8, 8) + FIELD(TB_DW6_REGISTER, DATA_BYTES27, 0, 8) +REG32(TB_DW7_REGISTER, 0x124) + FIELD(TB_DW7_REGISTER, DATA_BYTES28, 24, 8) + FIELD(TB_DW7_REGISTER, DATA_BYTES29, 16, 8) + FIELD(TB_DW7_REGISTER, DATA_BYTES30, 8, 8) + FIELD(TB_DW7_REGISTER, DATA_BYTES31, 0, 8) +REG32(TB_DW8_REGISTER, 0x128) + FIELD(TB_DW8_REGISTER, DATA_BYTES32, 24, 8) + FIELD(TB_DW8_REGISTER, DATA_BYTES33, 16, 8) + FIELD(TB_DW8_REGISTER, DATA_BYTES34, 8, 8) + FIELD(TB_DW8_REGISTER, DATA_BYTES35, 0, 8) +REG32(TB_DW9_REGISTER, 0x12c) + FIELD(TB_DW9_REGISTER, DATA_BYTES36, 24, 8) + FIELD(TB_DW9_REGISTER, DATA_BYTES37, 16, 8) + FIELD(TB_DW9_REGISTER, DATA_BYTES38, 8, 8) + FIELD(TB_DW9_REGISTER, DATA_BYTES39, 0, 8) +REG32(TB_DW10_REGISTER, 0x130) + FIELD(TB_DW10_REGISTER, DATA_BYTES40, 24, 8) + FIELD(TB_DW10_REGISTER, DATA_BYTES41, 16, 8) + FIELD(TB_DW10_REGISTER, DATA_BYTES42, 8, 8) + FIELD(TB_DW10_REGISTER, DATA_BYTES43, 0, 8) +REG32(TB_DW11_REGISTER, 0x134) + FIELD(TB_DW11_REGISTER, DATA_BYTES44, 24, 8) + FIELD(TB_DW11_REGISTER, DATA_BYTES45, 16, 8) + FIELD(TB_DW11_REGISTER, DATA_BYTES46, 8, 8) + FIELD(TB_DW11_REGISTER, DATA_BYTES47, 0, 8) +REG32(TB_DW12_REGISTER, 0x138) + FIELD(TB_DW12_REGISTER, DATA_BYTES48, 24, 8) + FIELD(TB_DW12_REGISTER, DATA_BYTES49, 16, 8) + FIELD(TB_DW12_REGISTER, DATA_BYTES50, 8, 8) + FIELD(TB_DW12_REGISTER, DATA_BYTES51, 0, 8) +REG32(TB_DW13_REGISTER, 0x13c) + FIELD(TB_DW13_REGISTER, DATA_BYTES52, 24, 8) + FIELD(TB_DW13_REGISTER, DATA_BYTES53, 16, 8) + FIELD(TB_DW13_REGISTER, DATA_BYTES54, 8, 8) + FIELD(TB_DW13_REGISTER, DATA_BYTES55, 0, 8) +REG32(TB_DW14_REGISTER, 0x140) + FIELD(TB_DW14_REGISTER, DATA_BYTES56, 24, 8) + FIELD(TB_DW14_REGISTER, DATA_BYTES57, 16, 8) + FIELD(TB_DW14_REGISTER, DATA_BYTES58, 8, 8) + FIELD(TB_DW14_REGISTER, DATA_BYTES59, 0, 8) +REG32(TB_DW15_REGISTER, 0x144) + FIELD(TB_DW15_REGISTER, DATA_BYTES60, 24, 8) + FIELD(TB_DW15_REGISTER, DATA_BYTES61, 16, 8) + FIELD(TB_DW15_REGISTER, DATA_BYTES62, 8, 8) + FIELD(TB_DW15_REGISTER, DATA_BYTES63, 0, 8) +REG32(AFMR_REGISTER, 0xa00) + FIELD(AFMR_REGISTER, AMID, 21, 11) + FIELD(AFMR_REGISTER, AMSRR, 20, 1) + FIELD(AFMR_REGISTER, AMIDE, 19, 1) + FIELD(AFMR_REGISTER, AMID_EXT, 1, 18) + FIELD(AFMR_REGISTER, AMRTR, 0, 1) +REG32(AFIR_REGISTER, 0xa04) + FIELD(AFIR_REGISTER, AIID, 21, 11) + FIELD(AFIR_REGISTER, AISRR, 20, 1) + FIELD(AFIR_REGISTER, AIIDE, 19, 1) + FIELD(AFIR_REGISTER, AIID_EXT, 1, 18) + FIELD(AFIR_REGISTER, AIRTR, 0, 1) +REG32(TXE_FIFO_TB_ID_REGISTER, 0x2000) + FIELD(TXE_FIFO_TB_ID_REGISTER, ID, 21, 11) + FIELD(TXE_FIFO_TB_ID_REGISTER, SRR_RTR_RRS, 20, 1) + FIELD(TXE_FIFO_TB_ID_REGISTER, IDE, 19, 1) + FIELD(TXE_FIFO_TB_ID_REGISTER, ID_EXT, 1, 18) + FIELD(TXE_FIFO_TB_ID_REGISTER, RTR_RRS, 0, 1) +REG32(TXE_FIFO_TB_DLC_REGISTER, 0x2004) + FIELD(TXE_FIFO_TB_DLC_REGISTER, DLC, 28, 4) + FIELD(TXE_FIFO_TB_DLC_REGISTER, FDF, 27, 1) + FIELD(TXE_FIFO_TB_DLC_REGISTER, BRS, 26, 1) + FIELD(TXE_FIFO_TB_DLC_REGISTER, ET, 24, 2) + FIELD(TXE_FIFO_TB_DLC_REGISTER, MM, 16, 8) + FIELD(TXE_FIFO_TB_DLC_REGISTER, TIMESTAMP, 0, 16) +REG32(RB_ID_REGISTER, 0x2100) + FIELD(RB_ID_REGISTER, ID, 21, 11) + FIELD(RB_ID_REGISTER, SRR_RTR_RRS, 20, 1) + FIELD(RB_ID_REGISTER, IDE, 19, 1) + FIELD(RB_ID_REGISTER, ID_EXT, 1, 18) + FIELD(RB_ID_REGISTER, RTR_RRS, 0, 1) +REG32(RB_DLC_REGISTER, 0x2104) + FIELD(RB_DLC_REGISTER, DLC, 28, 4) + FIELD(RB_DLC_REGISTER, FDF, 27, 1) + FIELD(RB_DLC_REGISTER, BRS, 26, 1) + FIELD(RB_DLC_REGISTER, ESI, 25, 1) + FIELD(RB_DLC_REGISTER, MATCHED_FILTER_INDEX, 16, 5) + FIELD(RB_DLC_REGISTER, TIMESTAMP, 0, 16) +REG32(RB_DW0_REGISTER, 0x2108) + FIELD(RB_DW0_REGISTER, DATA_BYTES0, 24, 8) + FIELD(RB_DW0_REGISTER, DATA_BYTES1, 16, 8) + FIELD(RB_DW0_REGISTER, DATA_BYTES2, 8, 8) + FIELD(RB_DW0_REGISTER, DATA_BYTES3, 0, 8) +REG32(RB_DW1_REGISTER, 0x210c) + FIELD(RB_DW1_REGISTER, DATA_BYTES4, 24, 8) + FIELD(RB_DW1_REGISTER, DATA_BYTES5, 16, 8) + FIELD(RB_DW1_REGISTER, DATA_BYTES6, 8, 8) + FIELD(RB_DW1_REGISTER, DATA_BYTES7, 0, 8) +REG32(RB_DW2_REGISTER, 0x2110) + FIELD(RB_DW2_REGISTER, DATA_BYTES8, 24, 8) + FIELD(RB_DW2_REGISTER, DATA_BYTES9, 16, 8) + FIELD(RB_DW2_REGISTER, DATA_BYTES10, 8, 8) + FIELD(RB_DW2_REGISTER, DATA_BYTES11, 0, 8) +REG32(RB_DW3_REGISTER, 0x2114) + FIELD(RB_DW3_REGISTER, DATA_BYTES12, 24, 8) + FIELD(RB_DW3_REGISTER, DATA_BYTES13, 16, 8) + FIELD(RB_DW3_REGISTER, DATA_BYTES14, 8, 8) + FIELD(RB_DW3_REGISTER, DATA_BYTES15, 0, 8) +REG32(RB_DW4_REGISTER, 0x2118) + FIELD(RB_DW4_REGISTER, DATA_BYTES16, 24, 8) + FIELD(RB_DW4_REGISTER, DATA_BYTES17, 16, 8) + FIELD(RB_DW4_REGISTER, DATA_BYTES18, 8, 8) + FIELD(RB_DW4_REGISTER, DATA_BYTES19, 0, 8) +REG32(RB_DW5_REGISTER, 0x211c) + FIELD(RB_DW5_REGISTER, DATA_BYTES20, 24, 8) + FIELD(RB_DW5_REGISTER, DATA_BYTES21, 16, 8) + FIELD(RB_DW5_REGISTER, DATA_BYTES22, 8, 8) + FIELD(RB_DW5_REGISTER, DATA_BYTES23, 0, 8) +REG32(RB_DW6_REGISTER, 0x2120) + FIELD(RB_DW6_REGISTER, DATA_BYTES24, 24, 8) + FIELD(RB_DW6_REGISTER, DATA_BYTES25, 16, 8) + FIELD(RB_DW6_REGISTER, DATA_BYTES26, 8, 8) + FIELD(RB_DW6_REGISTER, DATA_BYTES27, 0, 8) +REG32(RB_DW7_REGISTER, 0x2124) + FIELD(RB_DW7_REGISTER, DATA_BYTES28, 24, 8) + FIELD(RB_DW7_REGISTER, DATA_BYTES29, 16, 8) + FIELD(RB_DW7_REGISTER, DATA_BYTES30, 8, 8) + FIELD(RB_DW7_REGISTER, DATA_BYTES31, 0, 8) +REG32(RB_DW8_REGISTER, 0x2128) + FIELD(RB_DW8_REGISTER, DATA_BYTES32, 24, 8) + FIELD(RB_DW8_REGISTER, DATA_BYTES33, 16, 8) + FIELD(RB_DW8_REGISTER, DATA_BYTES34, 8, 8) + FIELD(RB_DW8_REGISTER, DATA_BYTES35, 0, 8) +REG32(RB_DW9_REGISTER, 0x212c) + FIELD(RB_DW9_REGISTER, DATA_BYTES36, 24, 8) + FIELD(RB_DW9_REGISTER, DATA_BYTES37, 16, 8) + FIELD(RB_DW9_REGISTER, DATA_BYTES38, 8, 8) + FIELD(RB_DW9_REGISTER, DATA_BYTES39, 0, 8) +REG32(RB_DW10_REGISTER, 0x2130) + FIELD(RB_DW10_REGISTER, DATA_BYTES40, 24, 8) + FIELD(RB_DW10_REGISTER, DATA_BYTES41, 16, 8) + FIELD(RB_DW10_REGISTER, DATA_BYTES42, 8, 8) + FIELD(RB_DW10_REGISTER, DATA_BYTES43, 0, 8) +REG32(RB_DW11_REGISTER, 0x2134) + FIELD(RB_DW11_REGISTER, DATA_BYTES44, 24, 8) + FIELD(RB_DW11_REGISTER, DATA_BYTES45, 16, 8) + FIELD(RB_DW11_REGISTER, DATA_BYTES46, 8, 8) + FIELD(RB_DW11_REGISTER, DATA_BYTES47, 0, 8) +REG32(RB_DW12_REGISTER, 0x2138) + FIELD(RB_DW12_REGISTER, DATA_BYTES48, 24, 8) + FIELD(RB_DW12_REGISTER, DATA_BYTES49, 16, 8) + FIELD(RB_DW12_REGISTER, DATA_BYTES50, 8, 8) + FIELD(RB_DW12_REGISTER, DATA_BYTES51, 0, 8) +REG32(RB_DW13_REGISTER, 0x213c) + FIELD(RB_DW13_REGISTER, DATA_BYTES52, 24, 8) + FIELD(RB_DW13_REGISTER, DATA_BYTES53, 16, 8) + FIELD(RB_DW13_REGISTER, DATA_BYTES54, 8, 8) + FIELD(RB_DW13_REGISTER, DATA_BYTES55, 0, 8) +REG32(RB_DW14_REGISTER, 0x2140) + FIELD(RB_DW14_REGISTER, DATA_BYTES56, 24, 8) + FIELD(RB_DW14_REGISTER, DATA_BYTES57, 16, 8) + FIELD(RB_DW14_REGISTER, DATA_BYTES58, 8, 8) + FIELD(RB_DW14_REGISTER, DATA_BYTES59, 0, 8) +REG32(RB_DW15_REGISTER, 0x2144) + FIELD(RB_DW15_REGISTER, DATA_BYTES60, 24, 8) + FIELD(RB_DW15_REGISTER, DATA_BYTES61, 16, 8) + FIELD(RB_DW15_REGISTER, DATA_BYTES62, 8, 8) + FIELD(RB_DW15_REGISTER, DATA_BYTES63, 0, 8) +REG32(RB_ID_REGISTER_1, 0x4100) + FIELD(RB_ID_REGISTER_1, ID, 21, 11) + FIELD(RB_ID_REGISTER_1, SRR_RTR_RRS, 20, 1) + FIELD(RB_ID_REGISTER_1, IDE, 19, 1) + FIELD(RB_ID_REGISTER_1, ID_EXT, 1, 18) + FIELD(RB_ID_REGISTER_1, RTR_RRS, 0, 1) +REG32(RB_DLC_REGISTER_1, 0x4104) + FIELD(RB_DLC_REGISTER_1, DLC, 28, 4) + FIELD(RB_DLC_REGISTER_1, FDF, 27, 1) + FIELD(RB_DLC_REGISTER_1, BRS, 26, 1) + FIELD(RB_DLC_REGISTER_1, ESI, 25, 1) + FIELD(RB_DLC_REGISTER_1, MATCHED_FILTER_INDEX, 16, 5) + FIELD(RB_DLC_REGISTER_1, TIMESTAMP, 0, 16) +REG32(RB0_DW0_REGISTER_1, 0x4108) + FIELD(RB0_DW0_REGISTER_1, DATA_BYTES0, 24, 8) + FIELD(RB0_DW0_REGISTER_1, DATA_BYTES1, 16, 8) + FIELD(RB0_DW0_REGISTER_1, DATA_BYTES2, 8, 8) + FIELD(RB0_DW0_REGISTER_1, DATA_BYTES3, 0, 8) +REG32(RB_DW1_REGISTER_1, 0x410c) + FIELD(RB_DW1_REGISTER_1, DATA_BYTES4, 24, 8) + FIELD(RB_DW1_REGISTER_1, DATA_BYTES5, 16, 8) + FIELD(RB_DW1_REGISTER_1, DATA_BYTES6, 8, 8) + FIELD(RB_DW1_REGISTER_1, DATA_BYTES7, 0, 8) +REG32(RB_DW2_REGISTER_1, 0x4110) + FIELD(RB_DW2_REGISTER_1, DATA_BYTES8, 24, 8) + FIELD(RB_DW2_REGISTER_1, DATA_BYTES9, 16, 8) + FIELD(RB_DW2_REGISTER_1, DATA_BYTES10, 8, 8) + FIELD(RB_DW2_REGISTER_1, DATA_BYTES11, 0, 8) +REG32(RB_DW3_REGISTER_1, 0x4114) + FIELD(RB_DW3_REGISTER_1, DATA_BYTES12, 24, 8) + FIELD(RB_DW3_REGISTER_1, DATA_BYTES13, 16, 8) + FIELD(RB_DW3_REGISTER_1, DATA_BYTES14, 8, 8) + FIELD(RB_DW3_REGISTER_1, DATA_BYTES15, 0, 8) +REG32(RB_DW4_REGISTER_1, 0x4118) + FIELD(RB_DW4_REGISTER_1, DATA_BYTES16, 24, 8) + FIELD(RB_DW4_REGISTER_1, DATA_BYTES17, 16, 8) + FIELD(RB_DW4_REGISTER_1, DATA_BYTES18, 8, 8) + FIELD(RB_DW4_REGISTER_1, DATA_BYTES19, 0, 8) +REG32(RB_DW5_REGISTER_1, 0x411c) + FIELD(RB_DW5_REGISTER_1, DATA_BYTES20, 24, 8) + FIELD(RB_DW5_REGISTER_1, DATA_BYTES21, 16, 8) + FIELD(RB_DW5_REGISTER_1, DATA_BYTES22, 8, 8) + FIELD(RB_DW5_REGISTER_1, DATA_BYTES23, 0, 8) +REG32(RB_DW6_REGISTER_1, 0x4120) + FIELD(RB_DW6_REGISTER_1, DATA_BYTES24, 24, 8) + FIELD(RB_DW6_REGISTER_1, DATA_BYTES25, 16, 8) + FIELD(RB_DW6_REGISTER_1, DATA_BYTES26, 8, 8) + FIELD(RB_DW6_REGISTER_1, DATA_BYTES27, 0, 8) +REG32(RB_DW7_REGISTER_1, 0x4124) + FIELD(RB_DW7_REGISTER_1, DATA_BYTES28, 24, 8) + FIELD(RB_DW7_REGISTER_1, DATA_BYTES29, 16, 8) + FIELD(RB_DW7_REGISTER_1, DATA_BYTES30, 8, 8) + FIELD(RB_DW7_REGISTER_1, DATA_BYTES31, 0, 8) +REG32(RB_DW8_REGISTER_1, 0x4128) + FIELD(RB_DW8_REGISTER_1, DATA_BYTES32, 24, 8) + FIELD(RB_DW8_REGISTER_1, DATA_BYTES33, 16, 8) + FIELD(RB_DW8_REGISTER_1, DATA_BYTES34, 8, 8) + FIELD(RB_DW8_REGISTER_1, DATA_BYTES35, 0, 8) +REG32(RB_DW9_REGISTER_1, 0x412c) + FIELD(RB_DW9_REGISTER_1, DATA_BYTES36, 24, 8) + FIELD(RB_DW9_REGISTER_1, DATA_BYTES37, 16, 8) + FIELD(RB_DW9_REGISTER_1, DATA_BYTES38, 8, 8) + FIELD(RB_DW9_REGISTER_1, DATA_BYTES39, 0, 8) +REG32(RB_DW10_REGISTER_1, 0x4130) + FIELD(RB_DW10_REGISTER_1, DATA_BYTES40, 24, 8) + FIELD(RB_DW10_REGISTER_1, DATA_BYTES41, 16, 8) + FIELD(RB_DW10_REGISTER_1, DATA_BYTES42, 8, 8) + FIELD(RB_DW10_REGISTER_1, DATA_BYTES43, 0, 8) +REG32(RB_DW11_REGISTER_1, 0x4134) + FIELD(RB_DW11_REGISTER_1, DATA_BYTES44, 24, 8) + FIELD(RB_DW11_REGISTER_1, DATA_BYTES45, 16, 8) + FIELD(RB_DW11_REGISTER_1, DATA_BYTES46, 8, 8) + FIELD(RB_DW11_REGISTER_1, DATA_BYTES47, 0, 8) +REG32(RB_DW12_REGISTER_1, 0x4138) + FIELD(RB_DW12_REGISTER_1, DATA_BYTES48, 24, 8) + FIELD(RB_DW12_REGISTER_1, DATA_BYTES49, 16, 8) + FIELD(RB_DW12_REGISTER_1, DATA_BYTES50, 8, 8) + FIELD(RB_DW12_REGISTER_1, DATA_BYTES51, 0, 8) +REG32(RB_DW13_REGISTER_1, 0x413c) + FIELD(RB_DW13_REGISTER_1, DATA_BYTES52, 24, 8) + FIELD(RB_DW13_REGISTER_1, DATA_BYTES53, 16, 8) + FIELD(RB_DW13_REGISTER_1, DATA_BYTES54, 8, 8) + FIELD(RB_DW13_REGISTER_1, DATA_BYTES55, 0, 8) +REG32(RB_DW14_REGISTER_1, 0x4140) + FIELD(RB_DW14_REGISTER_1, DATA_BYTES56, 24, 8) + FIELD(RB_DW14_REGISTER_1, DATA_BYTES57, 16, 8) + FIELD(RB_DW14_REGISTER_1, DATA_BYTES58, 8, 8) + FIELD(RB_DW14_REGISTER_1, DATA_BYTES59, 0, 8) +REG32(RB_DW15_REGISTER_1, 0x4144) + FIELD(RB_DW15_REGISTER_1, DATA_BYTES60, 24, 8) + FIELD(RB_DW15_REGISTER_1, DATA_BYTES61, 16, 8) + FIELD(RB_DW15_REGISTER_1, DATA_BYTES62, 8, 8) + FIELD(RB_DW15_REGISTER_1, DATA_BYTES63, 0, 8) + +static uint8_t canfd_dlc_array[8] =3D {8, 12, 16, 20, 24, 32, 48, 64}; + +static void canfd_update_irq(XlnxVersalCANFDState *s) +{ + unsigned int irq =3D s->regs[R_INTERRUPT_STATUS_REGISTER] & + s->regs[R_INTERRUPT_ENABLE_REGISTER]; + g_autofree char *path =3D object_get_canonical_path(OBJECT(s)); + + /* RX watermark interrupts. */ + if (ARRAY_FIELD_EX32(s->regs, RX_FIFO_STATUS_REGISTER, FL) > + ARRAY_FIELD_EX32(s->regs, RX_FIFO_WATERMARK_REGISTER, RXFWM)) { + ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXFWMFLL, 1); + } + + if (ARRAY_FIELD_EX32(s->regs, RX_FIFO_STATUS_REGISTER, FL_1) > + ARRAY_FIELD_EX32(s->regs, RX_FIFO_WATERMARK_REGISTER, RXFWM_1)) { + ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXFWMFLL_1, 1= ); + } + + /* TX watermark interrupt. */ + if (ARRAY_FIELD_EX32(s->regs, TX_EVENT_FIFO_STATUS_REGISTER, TXE_FL) > + ARRAY_FIELD_EX32(s->regs, TX_EVENT_FIFO_WATERMARK_REGISTER, TXE_FW= M)) { + ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXEWMFLL, 1); + } + + trace_xlnx_canfd_update_irq(path, s->regs[R_INTERRUPT_STATUS_REGISTER], + s->regs[R_INTERRUPT_ENABLE_REGISTER], irq); + + qemu_set_irq(s->irq_canfd_int, irq); +} + +static void canfd_ier_post_write(RegisterInfo *reg, uint64_t val64) +{ + XlnxVersalCANFDState *s =3D XILINX_CANFD(reg->opaque); + + canfd_update_irq(s); +} + +static uint64_t canfd_icr_pre_write(RegisterInfo *reg, uint64_t val64) +{ + XlnxVersalCANFDState *s =3D XILINX_CANFD(reg->opaque); + uint32_t val =3D val64; + + s->regs[R_INTERRUPT_STATUS_REGISTER] &=3D ~val; + + /* + * RXBOFLW_BI field is automatically cleared to default if RXBOFLW bit= is + * cleared in ISR. + */ + if (ARRAY_FIELD_EX32(s->regs, INTERRUPT_STATUS_REGISTER, RXFWMFLL_1)) { + ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXBOFLW_BI, 0= ); + } + + canfd_update_irq(s); + + return 0; +} + +static void canfd_config_reset(XlnxVersalCANFDState *s) +{ + + unsigned int i; + + /* Reset all the configuration register. */ + for (i =3D 0; i < R_RX_FIFO_WATERMARK_REGISTER; ++i) { + register_reset(&s->reg_info[i]); + } + + canfd_update_irq(s); +} + +static void canfd_config_mode(XlnxVersalCANFDState *s) +{ + register_reset(&s->reg_info[R_ERROR_COUNTER_REGISTER]); + register_reset(&s->reg_info[R_ERROR_STATUS_REGISTER]); + register_reset(&s->reg_info[R_STATUS_REGISTER]); + + /* Put XlnxVersalCANFDState in configuration mode. */ + ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, CONFIG, 1); + ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, WKUP, 0); + ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, SLP, 0); + ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, BSOFF, 0); + ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, ERROR, 0); + ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXFOFLW, 0); + ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXFOFLW_1, 0); + ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOK, 0); + ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXOK, 0); + ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, ARBLST, 0); + + /* Clear the time stamp. */ + ptimer_transaction_begin(s->canfd_timer); + ptimer_set_count(s->canfd_timer, 0); + ptimer_transaction_commit(s->canfd_timer); + + canfd_update_irq(s); +} + +static void update_status_register_mode_bits(XlnxVersalCANFDState *s) +{ + bool sleep_status =3D ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SLEEP= ); + bool sleep_mode =3D ARRAY_FIELD_EX32(s->regs, MODE_SELECT_REGISTER, SL= EEP); + /* Wake up interrupt bit. */ + bool wakeup_irq_val =3D !sleep_mode && sleep_status; + /* Sleep interrupt bit. */ + bool sleep_irq_val =3D sleep_mode && !sleep_status; + + /* Clear previous core mode status bits. */ + ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, LBACK, 0); + ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, SLEEP, 0); + ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, SNOOP, 0); + ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, NORMAL, 0); + + /* set current mode bit and generate irqs accordingly. */ + if (ARRAY_FIELD_EX32(s->regs, MODE_SELECT_REGISTER, LBACK)) { + ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, LBACK, 1); + } else if (ARRAY_FIELD_EX32(s->regs, MODE_SELECT_REGISTER, SLEEP)) { + ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, SLEEP, 1); + ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, SLP, + sleep_irq_val); + } else if (ARRAY_FIELD_EX32(s->regs, MODE_SELECT_REGISTER, SNOOP)) { + ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, SNOOP, 1); + } else { + /* If all bits are zero, XlnxVersalCANFDState is set in normal mod= e. */ + ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, NORMAL, 1); + /* Set wakeup interrupt bit. */ + ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, WKUP, + wakeup_irq_val); + } + + /* Put the CANFD in error active state. */ + ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, ESTAT, 1); + + canfd_update_irq(s); +} + +static uint64_t canfd_msr_pre_write(RegisterInfo *reg, uint64_t val64) +{ + XlnxVersalCANFDState *s =3D XILINX_CANFD(reg->opaque); + uint32_t val =3D val64; + uint8_t multi_mode =3D 0; + + /* + * Multiple mode set check. This is done to make sure user doesn't set + * multiple modes. + */ + multi_mode =3D FIELD_EX32(val, MODE_SELECT_REGISTER, LBACK) + + FIELD_EX32(val, MODE_SELECT_REGISTER, SLEEP) + + FIELD_EX32(val, MODE_SELECT_REGISTER, SNOOP); + + if (multi_mode > 1) { + qemu_log_mask(LOG_GUEST_ERROR, "Attempting to configure several mo= des" + " simultaneously. One mode will be selected accordin= g to" + " their priority: LBACK > SLEEP > SNOOP.\n"); + } + + if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN) =3D=3D 0) { + /* In configuration mode, any mode can be selected. */ + s->regs[R_MODE_SELECT_REGISTER] =3D val; + } else { + bool sleep_mode_bit =3D FIELD_EX32(val, MODE_SELECT_REGISTER, SLEE= P); + + ARRAY_FIELD_DP32(s->regs, MODE_SELECT_REGISTER, SLEEP, sleep_mode_= bit); + + if (FIELD_EX32(val, MODE_SELECT_REGISTER, LBACK)) { + qemu_log_mask(LOG_GUEST_ERROR, "Attempting to set LBACK mode" + " without setting CEN bit as 0\n"); + } else if (FIELD_EX32(val, MODE_SELECT_REGISTER, SNOOP)) { + qemu_log_mask(LOG_GUEST_ERROR, "Attempting to set SNOOP mode" + " without setting CEN bit as 0\n"); + } + + update_status_register_mode_bits(s); + } + + return s->regs[R_MODE_SELECT_REGISTER]; +} + +static void canfd_exit_sleep_mode(XlnxVersalCANFDState *s) +{ + ARRAY_FIELD_DP32(s->regs, MODE_SELECT_REGISTER, SLEEP, 0); + update_status_register_mode_bits(s); +} + +static void regs2frame(XlnxVersalCANFDState *s, qemu_can_frame *frame, + uint32_t reg_num) +{ + uint32_t i =3D 0; + uint32_t j =3D 0; + uint32_t val =3D 0; + uint32_t dlc_reg_val =3D 0; + uint32_t dlc_value =3D 0; + + /* Check that reg_num should be within TX register space. */ + assert(reg_num <=3D R_TB_ID_REGISTER + (NUM_REGS_PER_MSG_SPACE * + s->cfg.tx_fifo)); + + dlc_reg_val =3D s->regs[reg_num + 1]; + dlc_value =3D FIELD_EX32(dlc_reg_val, TB0_DLC_REGISTER, DLC); + + frame->can_id =3D s->regs[reg_num]; + + if (FIELD_EX32(dlc_reg_val, TB0_DLC_REGISTER, FDF)) { + /* + * CANFD frame. + * Converting dlc(0 to 15) 4 Byte data to plain length(i.e. 0 to 6= 4) + * 1 Byte data. This is done to make it work with SocketCAN. + * On actual CANFD frame, this value can't be more than 0xF. + * Conversion table for DLC to plain length: + * + * DLC Plain Length + * 0 - 8 0 - 8 + * 9 9 - 12 + * 10 13 - 16 + * 11 17 - 20 + * 12 21 - 24 + * 13 25 - 32 + * 14 33 - 48 + * 15 49 - 64 + */ + + frame->flags =3D QEMU_CAN_FRMF_TYPE_FD; + + if (dlc_value < 8) { + frame->can_dlc =3D dlc_value; + } else { + assert((dlc_value - 8) < ARRAY_SIZE(canfd_dlc_array)); + frame->can_dlc =3D canfd_dlc_array[dlc_value - 8]; + } + } else { + /* + * FD Format bit not set that means it is a CAN Frame. + * Conversion table for classic CAN: + * + * DLC Plain Length + * 0 - 7 0 - 7 + * 8 - 15 8 + */ + + if (dlc_value > 8) { + frame->can_dlc =3D 8; + qemu_log_mask(LOG_GUEST_ERROR, "Maximum DLC value for Classic = CAN" + " frame is 8. Only 8 byte data will be sent.\n"); + } else { + frame->can_dlc =3D dlc_value; + } + } + + for (j =3D 0; j < frame->can_dlc; j++) { + val =3D 8 * i; + + frame->data[j] =3D extract32(s->regs[reg_num + 2 + (j / 4)], val, = 8); + i++; + + if (i % 4 =3D=3D 0) { + i =3D 0; + } + } +} + +static void process_cancellation_requests(XlnxVersalCANFDState *s) +{ + uint32_t clear_mask =3D s->regs[R_TX_BUFFER_READY_REQUEST_REGISTER] & + s->regs[R_TX_BUFFER_CANCEL_REQUEST_REGIST= ER]; + + s->regs[R_TX_BUFFER_READY_REQUEST_REGISTER] &=3D ~clear_mask; + s->regs[R_TX_BUFFER_CANCEL_REQUEST_REGISTER] &=3D ~clear_mask; + + canfd_update_irq(s); +} + +static void store_rx_sequential(XlnxVersalCANFDState *s, + const qemu_can_frame *frame, + uint32_t fill_level, uint32_t read_index, + uint32_t store_location, uint8_t rx_fifo, + bool rx_fifo_id, uint8_t filter_index) +{ + int i; + bool is_canfd_frame; + uint8_t dlc =3D frame->can_dlc; + uint32_t dlc_reg_val =3D 0; + uint32_t data_reg_val =3D 0; + + /* Getting RX0/1 fill level */ + if ((fill_level) > rx_fifo - 1) { + g_autofree char *path =3D object_get_canonical_path(OBJECT(s)); + + qemu_log_mask(LOG_GUEST_ERROR, "%s: RX%d Buffer is full. Discardin= g the" + " message\n", path, rx_fifo_id); + + /* Set the corresponding RF buffer overflow interrupt. */ + if (rx_fifo_id =3D=3D 0) { + ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXFOFLW, = 1); + } else { + ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXFOFLW_1= , 1); + } + } else { + uint16_t rx_timestamp =3D CANFD_TIMER_MAX - + ptimer_get_count(s->canfd_timer); + + if (rx_timestamp =3D=3D 0xFFFF) { + ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TSCNT_OFL= W, 1); + } else { + ARRAY_FIELD_DP32(s->regs, TIMESTAMP_REGISTER, TIMESTAMP_CNT, + rx_timestamp); + } + + if (rx_fifo_id =3D=3D 0) { + ARRAY_FIELD_DP32(s->regs, RX_FIFO_STATUS_REGISTER, FL, + fill_level + 1); + assert(store_location <=3D + R_RB_ID_REGISTER + (s->cfg.rx0_fifo * + NUM_REGS_PER_MSG_SPACE)); + } else { + ARRAY_FIELD_DP32(s->regs, RX_FIFO_STATUS_REGISTER, FL_1, + fill_level + 1); + assert(store_location <=3D + R_RB_ID_REGISTER_1 + (s->cfg.rx1_fifo * + NUM_REGS_PER_MSG_SPACE= )); + } + + s->regs[store_location] =3D frame->can_id; + + if (frame->flags =3D=3D QEMU_CAN_FRMF_TYPE_FD) { + is_canfd_frame =3D true; + + for (i =3D 0; i < ARRAY_SIZE(canfd_dlc_array); i++) { + if (canfd_dlc_array[i] =3D=3D frame->can_dlc) { + dlc =3D 8 + i; + } + + dlc_reg_val =3D FIELD_DP32(0, RB_DLC_REGISTER, DLC, dlc); + } + } else { + is_canfd_frame =3D false; + if (frame->can_dlc > 8) { + dlc =3D 8; + } + + dlc_reg_val =3D FIELD_DP32(0, RB_DLC_REGISTER, DLC, frame->can= _dlc); + } + + dlc_reg_val |=3D FIELD_DP32(0, RB_DLC_REGISTER, FDF, is_canfd_fram= e); + dlc_reg_val |=3D FIELD_DP32(0, RB_DLC_REGISTER, TIMESTAMP, rx_time= stamp); + dlc_reg_val |=3D FIELD_DP32(0, RB_DLC_REGISTER, MATCHED_FILTER_IND= EX, + filter_index); + s->regs[store_location + 1] =3D dlc_reg_val; + + for (i =3D 0; i <=3D dlc; i++) { + data_reg_val =3D FIELD_DP32(0, RB_DW0_REGISTER, DATA_BYTES3, + frame->data[4 * i]); + data_reg_val |=3D FIELD_DP32(0, RB_DW0_REGISTER, DATA_BYTES2, + frame->data[4 * i + 1]); + data_reg_val |=3D FIELD_DP32(0, RB_DW0_REGISTER, DATA_BYTES1, + frame->data[4 * i + 2]); + data_reg_val |=3D FIELD_DP32(0, RB_DW0_REGISTER, DATA_BYTES0, + frame->data[4 * i + 3]); + s->regs[store_location + i + 2] =3D data_reg_val; + } + /* set the interrupt as RXOK. */ + ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOK, 1); + } +} + +static void update_rx_sequential(XlnxVersalCANFDState *s, + const qemu_can_frame *frame) +{ + bool filter_pass =3D false; + uint8_t filter_index =3D 0; + int i; + int filter_partition =3D ARRAY_FIELD_EX32(s->regs, + RX_FIFO_WATERMARK_REGISTER, RX= FP); + uint32_t store_location; + uint32_t fill_level; + uint32_t read_index; + uint8_t store_index =3D 0; + g_autofree char *path =3D NULL; + /* + * If all UAF bits are set to 0, then received messages are not stored + * in the RX buffers. + */ + if (!s->regs[R_ACCEPTANCE_FILTER_CONTROL_REGISTER]) { + qemu_log_mask(LOG_GUEST_ERROR, "No acceptance filter is set. Recei= ved" + " messages will not be stored.\n"); + } else { + uint32_t acceptance_filter_status =3D + s->regs[R_ACCEPTANCE_FILTER_CONTROL_REGIST= ER]; + + for (i =3D 0; i < 32; i++) { + if (acceptance_filter_status & 0x1) { + uint32_t msg_id_masked =3D s->regs[R_AFMR_REGISTER + 2 * i= ] & + frame->can_id; + uint32_t afir_id_masked =3D s->regs[R_AFIR_REGISTER + 2 * = i] & + s->regs[R_AFMR_REGISTER + 2 * i]; + uint16_t std_msg_id_masked =3D FIELD_EX32(msg_id_masked, + AFIR_REGISTER, AII= D); + uint16_t std_afir_id_masked =3D FIELD_EX32(afir_id_masked, + AFIR_REGISTER, AI= ID); + uint32_t ext_msg_id_masked =3D FIELD_EX32(msg_id_masked, + AFIR_REGISTER, + AIID_EXT); + uint32_t ext_afir_id_masked =3D FIELD_EX32(afir_id_masked, + AFIR_REGISTER, + AIID_EXT); + bool ext_ide =3D FIELD_EX32(s->regs[R_AFMR_REGISTER + 2 * = i], + AFMR_REGISTER, AMIDE); + + if (std_msg_id_masked =3D=3D std_afir_id_masked) { + if (ext_ide) { + /* Extended message ID message. */ + if (ext_msg_id_masked =3D=3D ext_afir_id_masked) { + filter_pass =3D true; + filter_index =3D i; + + break; + } + } else { + /* Standard message ID. */ + filter_pass =3D true; + filter_index =3D i; + + break; + } + } + } + acceptance_filter_status >>=3D 1; + } + } + + if (!filter_pass) { + path =3D object_get_canonical_path(OBJECT(s)); + + trace_xlnx_canfd_rx_fifo_filter_reject(path, frame->can_id, + frame->can_dlc); + } else { + if (filter_index <=3D filter_partition) { + fill_level =3D ARRAY_FIELD_EX32(s->regs, RX_FIFO_STATUS_REGIST= ER, FL); + read_index =3D ARRAY_FIELD_EX32(s->regs, RX_FIFO_STATUS_REGIST= ER, RI); + store_index =3D read_index + fill_level; + + if (read_index =3D=3D s->cfg.rx0_fifo - 1) { + /* + * When ri is s->cfg.rx0_fifo - 1 i.e. max, it goes cyclic= that + * means we reset the ri to 0x0. + */ + read_index =3D 0; + ARRAY_FIELD_DP32(s->regs, RX_FIFO_STATUS_REGISTER, RI, + read_index); + } + + if (store_index > s->cfg.rx0_fifo - 1) { + store_index -=3D s->cfg.rx0_fifo - 1; + } + + store_location =3D R_RB_ID_REGISTER + + (store_index * NUM_REGS_PER_MSG_SPACE); + + store_rx_sequential(s, frame, fill_level, read_index, + store_location, s->cfg.rx0_fifo, 0, + filter_index); + } else { + /* RX 1 fill level message */ + fill_level =3D ARRAY_FIELD_EX32(s->regs, RX_FIFO_STATUS_REGIST= ER, + FL_1); + read_index =3D ARRAY_FIELD_EX32(s->regs, RX_FIFO_STATUS_REGIST= ER, + RI_1); + store_index =3D read_index + fill_level; + + if (read_index =3D=3D s->cfg.rx1_fifo - 1) { + /* + * When ri is s->cfg.rx1_fifo - 1 i.e. max, it goes cyclic= that + * means we reset the ri to 0x0. + */ + read_index =3D 0; + ARRAY_FIELD_DP32(s->regs, RX_FIFO_STATUS_REGISTER, RI_1, + read_index); + } + + if (store_index > s->cfg.rx1_fifo - 1) { + store_index -=3D s->cfg.rx1_fifo - 1; + } + + store_location =3D R_RB_ID_REGISTER_1 + + (store_index * NUM_REGS_PER_MSG_SPACE); + + store_rx_sequential(s, frame, fill_level, read_index, + store_location, s->cfg.rx1_fifo, 1, + filter_index); + } + + path =3D object_get_canonical_path(OBJECT(s)); + + trace_xlnx_canfd_rx_data(path, frame->can_id, frame->can_dlc, + frame->flags); + canfd_update_irq(s); + } +} + +static bool tx_ready_check(XlnxVersalCANFDState *s) +{ + if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, SRST)) { + g_autofree char *path =3D object_get_canonical_path(OBJECT(s)); + + qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to transfer data wh= ile" + " XlnxVersalCANFDState is in reset mode\n", path); + + return false; + } + + if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN) =3D=3D 0) { + g_autofree char *path =3D object_get_canonical_path(OBJECT(s)); + + qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to transfer data wh= ile" + " XlnxVersalCANFDState is in configuration mode." + " Reset the core so operations can start fresh\n", + path); + return false; + } + + if (ARRAY_FIELD_EX32(s->regs, MODE_SELECT_REGISTER, SNOOP)) { + g_autofree char *path =3D object_get_canonical_path(OBJECT(s)); + + qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to transfer data wh= ile" + " XlnxVersalCANFDState is in SNOOP MODE\n", + path); + return false; + } + + return true; +} + +static void tx_fifo_stamp(XlnxVersalCANFDState *s, uint32_t tb0_regid) +{ + /* + * If EFC bit in DLC message is set, this means we will store the + * event of this transmitted message with time stamp. + */ + uint32_t dlc_reg_val =3D 0; + + if (FIELD_EX32(s->regs[tb0_regid + 1], TB0_DLC_REGISTER, EFC)) { + uint8_t dlc_val =3D FIELD_EX32(s->regs[tb0_regid + 1], TB0_DLC_REG= ISTER, + DLC); + bool fdf_val =3D FIELD_EX32(s->regs[tb0_regid + 1], TB0_DLC_REGIST= ER, + FDF); + bool brs_val =3D FIELD_EX32(s->regs[tb0_regid + 1], TB0_DLC_REGIST= ER, + BRS); + uint8_t mm_val =3D FIELD_EX32(s->regs[tb0_regid + 1], TB0_DLC_REGI= STER, + MM); + uint8_t fill_level =3D ARRAY_FIELD_EX32(s->regs, + TX_EVENT_FIFO_STATUS_REGISTE= R, + TXE_FL); + uint8_t read_index =3D ARRAY_FIELD_EX32(s->regs, + TX_EVENT_FIFO_STATUS_REGISTE= R, + TXE_RI); + uint8_t store_index =3D fill_level + read_index; + + if ((fill_level) > s->cfg.tx_fifo - 1) { + qemu_log_mask(LOG_GUEST_ERROR, "TX Event Buffer is full." + " Discarding the message\n"); + ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXEOFLW, = 1); + } else { + if (read_index =3D=3D s->cfg.tx_fifo - 1) { + /* + * When ri is s->cfg.tx_fifo - 1 i.e. max, it goes cyclic = that + * means we reset the ri to 0x0. + */ + read_index =3D 0; + ARRAY_FIELD_DP32(s->regs, TX_EVENT_FIFO_STATUS_REGISTER, T= XE_RI, + read_index); + } + + if (store_index > s->cfg.tx_fifo - 1) { + store_index -=3D s->cfg.tx_fifo - 1; + } + + assert(store_index < s->cfg.tx_fifo); + + uint32_t tx_event_reg0_id =3D R_TXE_FIFO_TB_ID_REGISTER + + (store_index * 2); + + /* Store message ID in TX event register. */ + s->regs[tx_event_reg0_id] =3D s->regs[tb0_regid]; + + uint16_t tx_timestamp =3D CANFD_TIMER_MAX - + ptimer_get_count(s->canfd_time= r); + + /* Store DLC with time stamp in DLC regs. */ + dlc_reg_val =3D FIELD_DP32(0, TXE_FIFO_TB_DLC_REGISTER, DLC, d= lc_val); + dlc_reg_val |=3D FIELD_DP32(0, TXE_FIFO_TB_DLC_REGISTER, FDF, + fdf_val); + dlc_reg_val |=3D FIELD_DP32(0, TXE_FIFO_TB_DLC_REGISTER, BRS, + brs_val); + dlc_reg_val |=3D FIELD_DP32(0, TXE_FIFO_TB_DLC_REGISTER, ET, 0= x3); + dlc_reg_val |=3D FIELD_DP32(0, TXE_FIFO_TB_DLC_REGISTER, MM, m= m_val); + dlc_reg_val |=3D FIELD_DP32(0, TXE_FIFO_TB_DLC_REGISTER, TIMES= TAMP, + tx_timestamp); + s->regs[tx_event_reg0_id + 1] =3D dlc_reg_val; + + ARRAY_FIELD_DP32(s->regs, TX_EVENT_FIFO_STATUS_REGISTER, TXE_F= L, + fill_level + 1); + } + } +} + +static gint g_cmp_ids(gconstpointer data1, gconstpointer data2) +{ + tx_ready_reg_info *tx_reg_1 =3D (tx_ready_reg_info *) data1; + tx_ready_reg_info *tx_reg_2 =3D (tx_ready_reg_info *) data2; + + return tx_reg_1->can_id - tx_reg_2->can_id; +} + +static void free_list(GSList *list) +{ + GSList *iterator =3D NULL; + + for (iterator =3D list; iterator !=3D NULL; iterator =3D iterator->nex= t) { + g_free((tx_ready_reg_info *)iterator->data); + } + + g_slist_free(list); + + return; +} + +static GSList *prepare_tx_data(XlnxVersalCANFDState *s) +{ + uint8_t i =3D 0; + GSList *list =3D NULL; + uint32_t reg_num =3D 0; + uint32_t reg_ready =3D s->regs[R_TX_BUFFER_READY_REQUEST_REGISTER]; + + /* First find the messages which are ready for transaction. */ + for (i =3D 0; i < s->cfg.tx_fifo; i++) { + if (reg_ready) { + reg_num =3D R_TB_ID_REGISTER + (NUM_REGS_PER_MSG_SPACE * i); + tx_ready_reg_info *temp =3D g_new(tx_ready_reg_info, 1); + if (temp =3D=3D NULL) { + qemu_log_mask(LOG_GUEST_ERROR, "%s: Couldn't allocate memo= ry\n", + __func__); + free_list(list); + return NULL; + } + + temp->can_id =3D s->regs[reg_num]; + temp->reg_num =3D reg_num; + list =3D g_slist_append(list, temp); + } + + list =3D g_slist_sort(list, g_cmp_ids); + reg_ready >>=3D 1; + s->regs[R_TX_BUFFER_READY_REQUEST_REGISTER] &=3D ~(1 << i); + s->regs[R_TX_BUFFER_CANCEL_REQUEST_REGISTER] &=3D ~(1 << i); + } + + return list; +} + +static void transfer_data(XlnxVersalCANFDState *s) +{ + bool canfd_tx =3D tx_ready_check(s); + GSList *list, *iterator =3D NULL; + + if (canfd_tx) { + qemu_can_frame frame; + + list =3D prepare_tx_data(s); + if (list =3D=3D NULL) { + return; + } + + for (iterator =3D list; iterator !=3D NULL; iterator =3D iterator-= >next) { + regs2frame(s, &frame, + ((tx_ready_reg_info *)iterator->data)->reg_num); + + if (ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, LBACK)) { + update_rx_sequential(s, &frame); + tx_fifo_stamp(s, + ((tx_ready_reg_info *)iterator->data)->reg_n= um); + + ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOK,= 1); + } else { + g_autofree char *path =3D object_get_canonical_path(OBJECT= (s)); + + trace_xlnx_canfd_tx_data(path, frame.can_id, frame.can_dlc, + frame.flags); + can_bus_client_send(&s->bus_client, &frame, 1); + tx_fifo_stamp(s, + ((tx_ready_reg_info *)iterator->data)->reg_n= um); + + ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXRRS= , 1); + + if (ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SLEEP)) { + canfd_exit_sleep_mode(s); + } + } + } + + s->tx_busy_bit =3D 0; + + ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXOK, 1); + free_list(list); + } else { + g_autofree char *path =3D object_get_canonical_path(OBJECT(s)); + + qemu_log_mask(LOG_GUEST_ERROR, "%s: Controller not enabled for" + " data transfer\n", path); + } + + canfd_update_irq(s); +} + +static uint64_t canfd_srr_pre_write(RegisterInfo *reg, uint64_t val64) +{ + XlnxVersalCANFDState *s =3D XILINX_CANFD(reg->opaque); + uint32_t val =3D val64; + + ARRAY_FIELD_DP32(s->regs, SOFTWARE_RESET_REGISTER, CEN, + FIELD_EX32(val, SOFTWARE_RESET_REGISTER, CEN)); + + if (FIELD_EX32(val, SOFTWARE_RESET_REGISTER, SRST)) { + g_autofree char *path =3D object_get_canonical_path(OBJECT(s)); + + trace_xlnx_canfd_reset(path, val64); + + /* First, core will do software reset then will enter in config mo= de. */ + canfd_config_reset(s); + } else if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN) =3D= =3D 0) { + canfd_config_mode(s); + } else { + /* + * Leave config mode. Now XlnxVersalCANFD core will enter Normal, = Sleep, + * snoop or Loopback mode depending upon LBACK, SLEEP, SNOOP regis= ter + * states. + */ + ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, CONFIG, 0); + + ptimer_transaction_begin(s->canfd_timer); + ptimer_set_count(s->canfd_timer, 0); + ptimer_transaction_commit(s->canfd_timer); + update_status_register_mode_bits(s); + transfer_data(s); + } + + return s->regs[R_SOFTWARE_RESET_REGISTER]; +} + +static uint64_t filter_mask(RegisterInfo *reg, uint64_t val64) +{ + XlnxVersalCANFDState *s =3D XILINX_CANFD(reg->opaque); + uint32_t reg_idx =3D (reg->access->addr) / 4; + uint32_t val =3D val64; + uint32_t filter_offset =3D (reg_idx - R_AFMR_REGISTER) / 2; + + if (!(s->regs[R_ACCEPTANCE_FILTER_CONTROL_REGISTER] & + (1 << filter_offset))) { + s->regs[reg_idx] =3D val; + } else { + g_autofree char *path =3D object_get_canonical_path(OBJECT(s)); + + qemu_log_mask(LOG_GUEST_ERROR, "%s: Acceptance filter %d not enabl= ed\n", + path, filter_offset + 1); + } + + return s->regs[reg_idx]; +} + +static uint64_t filter_id(RegisterInfo *reg, uint64_t val64) +{ + XlnxVersalCANFDState *s =3D XILINX_CANFD(reg->opaque); + hwaddr reg_idx =3D (reg->access->addr) / 4; + uint32_t val =3D val64; + uint32_t filter_offset =3D (reg_idx - R_AFIR_REGISTER) / 2; + + if (!(s->regs[R_ACCEPTANCE_FILTER_CONTROL_REGISTER] & + (1 << filter_offset))) { + s->regs[reg_idx] =3D val; + } else { + g_autofree char *path =3D object_get_canonical_path(OBJECT(s)); + + qemu_log_mask(LOG_GUEST_ERROR, "%s: Acceptance filter %d not enabl= ed\n", + path, filter_offset + 1); + } + + return s->regs[reg_idx]; +} + +static uint64_t canfd_tx_fifo_status_prew(RegisterInfo *reg, uint64_t val6= 4) +{ + XlnxVersalCANFDState *s =3D XILINX_CANFD(reg->opaque); + uint32_t val =3D val64; + uint8_t read_ind =3D 0; + uint8_t fill_ind =3D ARRAY_FIELD_EX32(s->regs, TX_EVENT_FIFO_STATUS_RE= GISTER, + TXE_FL); + + if (FIELD_EX32(val, TX_EVENT_FIFO_STATUS_REGISTER, TXE_IRI) && fill_in= d) { + read_ind =3D ARRAY_FIELD_EX32(s->regs, TX_EVENT_FIFO_STATUS_REGIST= ER, + TXE_RI) + 1; + + if (read_ind > s->cfg.tx_fifo - 1) { + read_ind =3D 0; + } + + /* + * Increase the read index by 1 and decrease the fill level by 1. + */ + ARRAY_FIELD_DP32(s->regs, TX_EVENT_FIFO_STATUS_REGISTER, TXE_RI, + read_ind); + ARRAY_FIELD_DP32(s->regs, TX_EVENT_FIFO_STATUS_REGISTER, TXE_FL, + fill_ind - 1); + } + + return s->regs[R_TX_EVENT_FIFO_STATUS_REGISTER]; +} + +static uint64_t canfd_rx_fifo_status_prew(RegisterInfo *reg, uint64_t val6= 4) +{ + XlnxVersalCANFDState *s =3D XILINX_CANFD(reg->opaque); + uint32_t val =3D val64; + uint8_t read_ind =3D 0; + uint8_t fill_ind =3D 0; + + if (FIELD_EX32(val, RX_FIFO_STATUS_REGISTER, IRI)) { + /* FL index is zero, setting IRI bit has no effect. */ + if (FIELD_EX32(val, RX_FIFO_STATUS_REGISTER, FL) !=3D 0) { + read_ind =3D FIELD_EX32(val, RX_FIFO_STATUS_REGISTER, RI) + 1; + + if (read_ind > s->cfg.rx0_fifo - 1) { + read_ind =3D 0; + } + + fill_ind =3D FIELD_EX32(val, RX_FIFO_STATUS_REGISTER, FL) - 1; + + ARRAY_FIELD_DP32(s->regs, RX_FIFO_STATUS_REGISTER, RI, read_in= d); + ARRAY_FIELD_DP32(s->regs, RX_FIFO_STATUS_REGISTER, FL, fill_in= d); + } + } + + if (FIELD_EX32(val, RX_FIFO_STATUS_REGISTER, IRI_1)) { + /* FL_1 index is zero, setting IRI_1 bit has no effect. */ + if (FIELD_EX32(val, RX_FIFO_STATUS_REGISTER, FL_1) !=3D 0) { + read_ind =3D FIELD_EX32(val, RX_FIFO_STATUS_REGISTER, RI_1) + = 1; + + if (read_ind > s->cfg.rx1_fifo - 1) { + read_ind =3D 0; + } + + fill_ind =3D FIELD_EX32(val, RX_FIFO_STATUS_REGISTER, FL_1) - = 1; + + ARRAY_FIELD_DP32(s->regs, RX_FIFO_STATUS_REGISTER, RI_1, read_= ind); + ARRAY_FIELD_DP32(s->regs, RX_FIFO_STATUS_REGISTER, FL_1, fill_= ind); + } + } + + return s->regs[R_RX_FIFO_STATUS_REGISTER]; +} + +static uint64_t canfd_tsr_pre_write(RegisterInfo *reg, uint64_t val64) +{ + XlnxVersalCANFDState *s =3D XILINX_CANFD(reg->opaque); + uint32_t val =3D val64; + + if (FIELD_EX32(val, TIMESTAMP_REGISTER, CTS)) { + ARRAY_FIELD_DP32(s->regs, TIMESTAMP_REGISTER, TIMESTAMP_CNT, 0); + ptimer_transaction_begin(s->canfd_timer); + ptimer_set_count(s->canfd_timer, 0); + ptimer_transaction_commit(s->canfd_timer); + } + + return 0; +} + +static uint64_t canfd_trr_reg_prew(RegisterInfo *reg, uint64_t val64) +{ + XlnxVersalCANFDState *s =3D XILINX_CANFD(reg->opaque); + + if (ARRAY_FIELD_EX32(s->regs, MODE_SELECT_REGISTER, SNOOP)) { + g_autofree char *path =3D object_get_canonical_path(OBJECT(s)); + + qemu_log_mask(LOG_GUEST_ERROR, "%s: Controller is in SNOOP mode." + " tx_ready_register will stay in reset mode\n", path= ); + return 0; + } else { + return val64; + } +} + +static void canfd_trr_reg_postw(RegisterInfo *reg, uint64_t val64) +{ + XlnxVersalCANFDState *s =3D XILINX_CANFD(reg->opaque); + + transfer_data(s); +} + +static void canfd_cancel_reg_postw(RegisterInfo *reg, uint64_t val64) +{ + XlnxVersalCANFDState *s =3D XILINX_CANFD(reg->opaque); + + process_cancellation_requests(s); +} + +static uint64_t canfd_write_check_prew(RegisterInfo *reg, uint64_t val64) +{ + XlnxVersalCANFDState *s =3D XILINX_CANFD(reg->opaque); + uint32_t val =3D val64; + + if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN) =3D=3D 0) { + return val; + } + return 0; +} + +static const RegisterAccessInfo canfd_tx_regs[] =3D { + { .name =3D "TB_ID_REGISTER", .addr =3D A_TB_ID_REGISTER, + },{ .name =3D "TB0_DLC_REGISTER", .addr =3D A_TB0_DLC_REGISTER, + },{ .name =3D "TB_DW0_REGISTER", .addr =3D A_TB_DW0_REGISTER, + },{ .name =3D "TB_DW1_REGISTER", .addr =3D A_TB_DW1_REGISTER, + },{ .name =3D "TB_DW2_REGISTER", .addr =3D A_TB_DW2_REGISTER, + },{ .name =3D "TB_DW3_REGISTER", .addr =3D A_TB_DW3_REGISTER, + },{ .name =3D "TB_DW4_REGISTER", .addr =3D A_TB_DW4_REGISTER, + },{ .name =3D "TB_DW5_REGISTER", .addr =3D A_TB_DW5_REGISTER, + },{ .name =3D "TB_DW6_REGISTER", .addr =3D A_TB_DW6_REGISTER, + },{ .name =3D "TB_DW7_REGISTER", .addr =3D A_TB_DW7_REGISTER, + },{ .name =3D "TB_DW8_REGISTER", .addr =3D A_TB_DW8_REGISTER, + },{ .name =3D "TB_DW9_REGISTER", .addr =3D A_TB_DW9_REGISTER, + },{ .name =3D "TB_DW10_REGISTER", .addr =3D A_TB_DW10_REGISTER, + },{ .name =3D "TB_DW11_REGISTER", .addr =3D A_TB_DW11_REGISTER, + },{ .name =3D "TB_DW12_REGISTER", .addr =3D A_TB_DW12_REGISTER, + },{ .name =3D "TB_DW13_REGISTER", .addr =3D A_TB_DW13_REGISTER, + },{ .name =3D "TB_DW14_REGISTER", .addr =3D A_TB_DW14_REGISTER, + },{ .name =3D "TB_DW15_REGISTER", .addr =3D A_TB_DW15_REGISTER, + } +}; + +static const RegisterAccessInfo canfd_rx0_regs[] =3D { + { .name =3D "RB_ID_REGISTER", .addr =3D A_RB_ID_REGISTER, + .ro =3D 0xffffffff, + },{ .name =3D "RB_DLC_REGISTER", .addr =3D A_RB_DLC_REGISTER, + .ro =3D 0xfe1fffff, + },{ .name =3D "RB_DW0_REGISTER", .addr =3D A_RB_DW0_REGISTER, + .ro =3D 0xffffffff, + },{ .name =3D "RB_DW1_REGISTER", .addr =3D A_RB_DW1_REGISTER, + .ro =3D 0xffffffff, + },{ .name =3D "RB_DW2_REGISTER", .addr =3D A_RB_DW2_REGISTER, + .ro =3D 0xffffffff, + },{ .name =3D "RB_DW3_REGISTER", .addr =3D A_RB_DW3_REGISTER, + .ro =3D 0xffffffff, + },{ .name =3D "RB_DW4_REGISTER", .addr =3D A_RB_DW4_REGISTER, + .ro =3D 0xffffffff, + },{ .name =3D "RB_DW5_REGISTER", .addr =3D A_RB_DW5_REGISTER, + .ro =3D 0xffffffff, + },{ .name =3D "RB_DW6_REGISTER", .addr =3D A_RB_DW6_REGISTER, + .ro =3D 0xffffffff, + },{ .name =3D "RB_DW7_REGISTER", .addr =3D A_RB_DW7_REGISTER, + .ro =3D 0xffffffff, + },{ .name =3D "RB_DW8_REGISTER", .addr =3D A_RB_DW8_REGISTER, + .ro =3D 0xffffffff, + },{ .name =3D "RB_DW9_REGISTER", .addr =3D A_RB_DW9_REGISTER, + .ro =3D 0xffffffff, + },{ .name =3D "RB_DW10_REGISTER", .addr =3D A_RB_DW10_REGISTER, + .ro =3D 0xffffffff, + },{ .name =3D "RB_DW11_REGISTER", .addr =3D A_RB_DW11_REGISTER, + .ro =3D 0xffffffff, + },{ .name =3D "RB_DW12_REGISTER", .addr =3D A_RB_DW12_REGISTER, + .ro =3D 0xffffffff, + },{ .name =3D "RB_DW13_REGISTER", .addr =3D A_RB_DW13_REGISTER, + .ro =3D 0xffffffff, + },{ .name =3D "RB_DW14_REGISTER", .addr =3D A_RB_DW14_REGISTER, + .ro =3D 0xffffffff, + },{ .name =3D "RB_DW15_REGISTER", .addr =3D A_RB_DW15_REGISTER, + .ro =3D 0xffffffff, + } +}; + +static const RegisterAccessInfo canfd_rx1_regs[] =3D { + { .name =3D "RB_ID_REGISTER_1", .addr =3D A_RB_ID_REGISTER_1, + .ro =3D 0xffffffff, + },{ .name =3D "RB_DLC_REGISTER_1", .addr =3D A_RB_DLC_REGISTER_1, + .ro =3D 0xfe1fffff, + },{ .name =3D "RB0_DW0_REGISTER_1", .addr =3D A_RB0_DW0_REGISTER_1, + .ro =3D 0xffffffff, + },{ .name =3D "RB_DW1_REGISTER_1", .addr =3D A_RB_DW1_REGISTER_1, + .ro =3D 0xffffffff, + },{ .name =3D "RB_DW2_REGISTER_1", .addr =3D A_RB_DW2_REGISTER_1, + .ro =3D 0xffffffff, + },{ .name =3D "RB_DW3_REGISTER_1", .addr =3D A_RB_DW3_REGISTER_1, + .ro =3D 0xffffffff, + },{ .name =3D "RB_DW4_REGISTER_1", .addr =3D A_RB_DW4_REGISTER_1, + .ro =3D 0xffffffff, + },{ .name =3D "RB_DW5_REGISTER_1", .addr =3D A_RB_DW5_REGISTER_1, + .ro =3D 0xffffffff, + },{ .name =3D "RB_DW6_REGISTER_1", .addr =3D A_RB_DW6_REGISTER_1, + .ro =3D 0xffffffff, + },{ .name =3D "RB_DW7_REGISTER_1", .addr =3D A_RB_DW7_REGISTER_1, + .ro =3D 0xffffffff, + },{ .name =3D "RB_DW8_REGISTER_1", .addr =3D A_RB_DW8_REGISTER_1, + .ro =3D 0xffffffff, + },{ .name =3D "RB_DW9_REGISTER_1", .addr =3D A_RB_DW9_REGISTER_1, + .ro =3D 0xffffffff, + },{ .name =3D "RB_DW10_REGISTER_1", .addr =3D A_RB_DW10_REGISTER_1, + .ro =3D 0xffffffff, + },{ .name =3D "RB_DW11_REGISTER_1", .addr =3D A_RB_DW11_REGISTER_1, + .ro =3D 0xffffffff, + },{ .name =3D "RB_DW12_REGISTER_1", .addr =3D A_RB_DW12_REGISTER_1, + .ro =3D 0xffffffff, + },{ .name =3D "RB_DW13_REGISTER_1", .addr =3D A_RB_DW13_REGISTER_1, + .ro =3D 0xffffffff, + },{ .name =3D "RB_DW14_REGISTER_1", .addr =3D A_RB_DW14_REGISTER_1, + .ro =3D 0xffffffff, + },{ .name =3D "RB_DW15_REGISTER_1", .addr =3D A_RB_DW15_REGISTER_1, + .ro =3D 0xffffffff, + } +}; + +/* Acceptance filter registers. */ +static const RegisterAccessInfo canfd_af_regs[] =3D { + { .name =3D "AFMR_REGISTER", .addr =3D A_AFMR_REGISTER, + .pre_write =3D filter_mask, + },{ .name =3D "AFIR_REGISTER", .addr =3D A_AFIR_REGISTER, + .pre_write =3D filter_id, + } +}; + +static const RegisterAccessInfo canfd_txe_regs[] =3D { + { .name =3D "TXE_FIFO_TB_ID_REGISTER", .addr =3D A_TXE_FIFO_TB_ID_R= EGISTER, + .ro =3D 0xffffffff, + },{ .name =3D "TXE_FIFO_TB_DLC_REGISTER", .addr =3D A_TXE_FIFO_TB_DLC= _REGISTER, + .ro =3D 0xffffffff, + } +}; + +static const RegisterAccessInfo canfd_regs_info[] =3D { + { .name =3D "SOFTWARE_RESET_REGISTER", .addr =3D A_SOFTWARE_RESET_R= EGISTER, + .pre_write =3D canfd_srr_pre_write, + },{ .name =3D "MODE_SELECT_REGISTER", .addr =3D A_MODE_SELECT_REGISTE= R, + .pre_write =3D canfd_msr_pre_write, + },{ .name =3D "ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER", + .addr =3D A_ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER, + .pre_write =3D canfd_write_check_prew, + },{ .name =3D "ARBITRATION_PHASE_BIT_TIMING_REGISTER", + .addr =3D A_ARBITRATION_PHASE_BIT_TIMING_REGISTER, + .pre_write =3D canfd_write_check_prew, + },{ .name =3D "ERROR_COUNTER_REGISTER", .addr =3D A_ERROR_COUNTER_REG= ISTER, + .ro =3D 0xffff, + },{ .name =3D "ERROR_STATUS_REGISTER", .addr =3D A_ERROR_STATUS_REGIS= TER, + .w1c =3D 0xf1f, + },{ .name =3D "STATUS_REGISTER", .addr =3D A_STATUS_REGISTER, + .reset =3D 0x1, + .ro =3D 0x7f17ff, + },{ .name =3D "INTERRUPT_STATUS_REGISTER", + .addr =3D A_INTERRUPT_STATUS_REGISTER, + .ro =3D 0xffffff7f, + },{ .name =3D "INTERRUPT_ENABLE_REGISTER", + .addr =3D A_INTERRUPT_ENABLE_REGISTER, + .post_write =3D canfd_ier_post_write, + },{ .name =3D "INTERRUPT_CLEAR_REGISTER", + .addr =3D A_INTERRUPT_CLEAR_REGISTER, .pre_write =3D canfd_icr_pre= _write, + },{ .name =3D "TIMESTAMP_REGISTER", .addr =3D A_TIMESTAMP_REGISTER, + .ro =3D 0xffff0000, + .pre_write =3D canfd_tsr_pre_write, + },{ .name =3D "DATA_PHASE_BAUD_RATE_PRESCALER_REGISTER", + .addr =3D A_DATA_PHASE_BAUD_RATE_PRESCALER_REGISTER, + .pre_write =3D canfd_write_check_prew, + },{ .name =3D "DATA_PHASE_BIT_TIMING_REGISTER", + .addr =3D A_DATA_PHASE_BIT_TIMING_REGISTER, + .pre_write =3D canfd_write_check_prew, + },{ .name =3D "TX_BUFFER_READY_REQUEST_REGISTER", + .addr =3D A_TX_BUFFER_READY_REQUEST_REGISTER, + .pre_write =3D canfd_trr_reg_prew, + .post_write =3D canfd_trr_reg_postw, + },{ .name =3D "INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER", + .addr =3D A_INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, + },{ .name =3D "TX_BUFFER_CANCEL_REQUEST_REGISTER", + .addr =3D A_TX_BUFFER_CANCEL_REQUEST_REGISTER, + .post_write =3D canfd_cancel_reg_postw, + },{ .name =3D "INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTE= R", + .addr =3D A_INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGIST= ER, + },{ .name =3D "TX_EVENT_FIFO_STATUS_REGISTER", + .addr =3D A_TX_EVENT_FIFO_STATUS_REGISTER, + .ro =3D 0x3f1f, .pre_write =3D canfd_tx_fifo_status_prew, + },{ .name =3D "TX_EVENT_FIFO_WATERMARK_REGISTER", + .addr =3D A_TX_EVENT_FIFO_WATERMARK_REGISTER, + .reset =3D 0xf, + .pre_write =3D canfd_write_check_prew, + },{ .name =3D "ACCEPTANCE_FILTER_CONTROL_REGISTER", + .addr =3D A_ACCEPTANCE_FILTER_CONTROL_REGISTER, + },{ .name =3D "RX_FIFO_STATUS_REGISTER", .addr =3D A_RX_FIFO_STATUS_R= EGISTER, + .ro =3D 0x7f3f7f3f, .pre_write =3D canfd_rx_fifo_status_prew, + },{ .name =3D "RX_FIFO_WATERMARK_REGISTER", + .addr =3D A_RX_FIFO_WATERMARK_REGISTER, + .reset =3D 0x1f0f0f, + .pre_write =3D canfd_write_check_prew, + } +}; + +static void xlnx_versal_canfd_ptimer_cb(void *opaque) +{ + /* No action required on the timer rollover. */ +} + +static const MemoryRegionOps canfd_ops =3D { + .read =3D register_read_memory, + .write =3D register_write_memory, + .endianness =3D DEVICE_LITTLE_ENDIAN, + .valid =3D { + .min_access_size =3D 4, + .max_access_size =3D 4, + }, +}; + +static void canfd_reset(DeviceState *dev) +{ + XlnxVersalCANFDState *s =3D XILINX_CANFD(dev); + unsigned int i; + + for (i =3D 0; i < ARRAY_SIZE(s->reg_info); ++i) { + register_reset(&s->reg_info[i]); + } + + ptimer_transaction_begin(s->canfd_timer); + ptimer_set_count(s->canfd_timer, 0); + ptimer_transaction_commit(s->canfd_timer); +} + +static bool can_xilinx_canfd_receive(CanBusClientState *client) +{ + XlnxVersalCANFDState *s =3D container_of(client, XlnxVersalCANFDState, + bus_client); + + bool reset_state =3D ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER= , SRST); + bool can_enabled =3D ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER= , CEN); + + if (reset_state || !can_enabled) { + return false; + } else { + return true; + } +} + +static ssize_t canfd_xilinx_receive(CanBusClientState *client, + const qemu_can_frame *buf, + size_t buf_size) +{ + XlnxVersalCANFDState *s =3D container_of(client, XlnxVersalCANFDState, + bus_client); + const qemu_can_frame *frame =3D buf; + + /* Update the status register that we are receiving message. */ + ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, BBSY, 1); + + if (buf_size <=3D 0) { + g_autofree char *path =3D object_get_canonical_path(OBJECT(s)); + + qemu_log_mask(LOG_GUEST_ERROR, "%s: Error in the data received.\n", + path); + return 0; + } + + if (ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, LBACK)) { + /* + * XlnxVersalCANFDState will not participate in normal bus communi= cation + * and does not receive any messages transmitted by other CAN node= s. + */ + g_autofree char *path =3D object_get_canonical_path(OBJECT(s)); + + qemu_log_mask(LOG_GUEST_ERROR, "%s: Controller is in loopback mod= e." + " It will not receive data.\n", path); + } else if (ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SNOOP)) { + /* Snoop Mode: Just keep the data. no response back. */ + update_rx_sequential(s, frame); + } else { + if ((ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SLEEP))) { + /* + * XlnxVersalCANFDState is in sleep mode. Any data on bus will= bring + * it to the wake up state. + */ + canfd_exit_sleep_mode(s); + } + + update_rx_sequential(s, frame); + } + + /* Message processing done. Update the status back to !busy */ + ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, BBSY, 0); + return 1; +} + +static CanBusClientInfo canfd_xilinx_bus_client_info =3D { + .can_receive =3D can_xilinx_canfd_receive, + .receive =3D canfd_xilinx_receive, +}; + +static int xlnx_canfd_connect_to_bus(XlnxVersalCANFDState *s, + CanBusState *bus) +{ + s->bus_client.info =3D &canfd_xilinx_bus_client_info; + + if (can_bus_insert_client(bus, &s->bus_client) < 0) { + return -1; + } + return 0; +} + +#define NUM_REG_PER_AF ARRAY_SIZE(canfd_af_regs) +#define NUM_AF 32 +#define NUM_REG_PER_TXE ARRAY_SIZE(canfd_txe_regs) +#define NUM_TXE 32 + +static int canfd_populate_regarray(XlnxVersalCANFDState *s, + RegisterInfoArray *r_array, int pos, + const RegisterAccessInfo *rae, + int num_rae) +{ + int i; + + for (i =3D 0; i < num_rae; i++) { + int index =3D rae[i].addr / 4; + RegisterInfo *r =3D &s->reg_info[index]; + + object_initialize((void *)r, sizeof(*r), TYPE_REGISTER); + + *r =3D (RegisterInfo) { + .data =3D &s->regs[index], + .data_size =3D sizeof(uint32_t), + .access =3D &rae[i], + .opaque =3D OBJECT(s), + }; + + r_array->r[i + pos] =3D r; + } + return i + pos; +} + +static void canfd_create_rai(RegisterAccessInfo *rai_array, + const RegisterAccessInfo *canfd_regs, + int template_rai_array_sz, + int num_template_to_copy) +{ + int i; + int reg_num; + + for (reg_num =3D 0; reg_num < num_template_to_copy; reg_num++) { + int pos =3D reg_num * template_rai_array_sz; + + memcpy(rai_array + pos, canfd_regs, + template_rai_array_sz * sizeof(RegisterAccessInfo)); + + for (i =3D 0; i < template_rai_array_sz; i++) { + const char *name =3D canfd_regs[i].name; + uint64_t addr =3D canfd_regs[i].addr; + rai_array[i + pos].name =3D g_strdup_printf("%s%d", name, reg_= num); + rai_array[i + pos].addr =3D addr + pos * 4; + } + } +} + +static void canfd_finalize(Object *obj) +{ + XlnxVersalCANFDState *s =3D XILINX_CANFD(obj); + g_free(s->tx_regs); + g_free(s->rx0_regs); + g_free(s->af_regs); + g_free(s->txe_regs); + g_free(s->rx1_regs); +} + +static RegisterInfoArray *canfd_create_regarray(XlnxVersalCANFDState *s) +{ + const char *device_prefix =3D object_get_typename(OBJECT(s)); + uint64_t memory_size =3D XLNX_VERSAL_CANFD_R_MAX * 4; + int num_regs; + int pos =3D 0; + RegisterInfoArray *r_array; + + num_regs =3D ARRAY_SIZE(canfd_regs_info) + + s->cfg.tx_fifo * NUM_REGS_PER_MSG_SPACE + + s->cfg.rx0_fifo * NUM_REGS_PER_MSG_SPACE + + NUM_AF * NUM_REG_PER_AF + + NUM_TXE * NUM_REG_PER_TXE; + + s->tx_regs =3D g_new0(RegisterAccessInfo, + s->cfg.tx_fifo * ARRAY_SIZE(canfd_tx_regs)); + + canfd_create_rai(s->tx_regs, canfd_tx_regs, + ARRAY_SIZE(canfd_tx_regs), s->cfg.tx_fifo); + + s->rx0_regs =3D g_new0(RegisterAccessInfo, + s->cfg.rx0_fifo * ARRAY_SIZE(canfd_rx0_regs)); + + canfd_create_rai(s->rx0_regs, canfd_rx0_regs, + ARRAY_SIZE(canfd_rx0_regs), s->cfg.rx0_fifo); + + s->af_regs =3D g_new0(RegisterAccessInfo, + NUM_AF * ARRAY_SIZE(canfd_af_regs)); + + canfd_create_rai(s->af_regs, canfd_af_regs, + ARRAY_SIZE(canfd_af_regs), NUM_AF); + + s->txe_regs =3D g_new0(RegisterAccessInfo, + NUM_TXE * ARRAY_SIZE(canfd_txe_regs)); + + canfd_create_rai(s->txe_regs, canfd_txe_regs, + ARRAY_SIZE(canfd_txe_regs), NUM_TXE); + + if (s->cfg.enable_rx_fifo1) { + num_regs +=3D s->cfg.rx1_fifo * NUM_REGS_PER_MSG_SPACE; + + s->rx1_regs =3D g_new0(RegisterAccessInfo, + s->cfg.rx1_fifo * ARRAY_SIZE(canfd_rx1_regs)); + + canfd_create_rai(s->rx1_regs, canfd_rx1_regs, + ARRAY_SIZE(canfd_rx1_regs), s->cfg.rx1_fifo); + } + + r_array =3D g_new0(RegisterInfoArray, 1); + r_array->r =3D g_new0(RegisterInfo * , num_regs); + r_array->num_elements =3D num_regs; + r_array->prefix =3D device_prefix; + + pos =3D canfd_populate_regarray(s, r_array, pos, + canfd_regs_info, + ARRAY_SIZE(canfd_regs_info)); + pos =3D canfd_populate_regarray(s, r_array, pos, + s->tx_regs, s->cfg.tx_fifo * + NUM_REGS_PER_MSG_SPACE); + pos =3D canfd_populate_regarray(s, r_array, pos, + s->rx0_regs, s->cfg.rx0_fifo * + NUM_REGS_PER_MSG_SPACE); + if (s->cfg.enable_rx_fifo1) { + pos =3D canfd_populate_regarray(s, r_array, pos, + s->rx1_regs, s->cfg.rx1_fifo * + NUM_REGS_PER_MSG_SPACE); + } + pos =3D canfd_populate_regarray(s, r_array, pos, + s->af_regs, NUM_AF * NUM_REG_PER_AF); + pos =3D canfd_populate_regarray(s, r_array, pos, + s->txe_regs, NUM_TXE * NUM_REG_PER_TXE); + + memory_region_init_io(&r_array->mem, OBJECT(s), &canfd_ops, r_array, + device_prefix, memory_size); + return r_array; +} + +static void canfd_realize(DeviceState *dev, Error **errp) +{ + XlnxVersalCANFDState *s =3D XILINX_CANFD(dev); + RegisterInfoArray *reg_array; + + reg_array =3D canfd_create_regarray(s); + memory_region_add_subregion(&s->iomem, 0x00, ®_array->mem); + sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem); + sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq_canfd_int); + + if (s->canfdbus) { + if (xlnx_canfd_connect_to_bus(s, s->canfdbus) < 0) { + g_autofree char *path =3D object_get_canonical_path(OBJECT(s)); + + error_setg(errp, "%s: xlnx_canfd_connect_to_bus failed", path); + return; + } + + } else { + /* If no bus is set. */ + g_autofree char *path =3D object_get_canonical_path(OBJECT(s)); + + qemu_log_mask(LOG_GUEST_ERROR, "%s: canfdbus property not set\n", = path); + } + + /* Allocate a new timer. */ + s->canfd_timer =3D ptimer_init(xlnx_versal_canfd_ptimer_cb, s, + PTIMER_POLICY_WRAP_AFTER_ONE_PERIOD | + PTIMER_POLICY_TRIGGER_ONLY_ON_DECREMENT | + PTIMER_POLICY_NO_IMMEDIATE_RELOAD); + + ptimer_transaction_begin(s->canfd_timer); + + ptimer_set_freq(s->canfd_timer, s->cfg.ext_clk_freq); + ptimer_set_limit(s->canfd_timer, CANFD_TIMER_MAX, 1); + ptimer_run(s->canfd_timer, 0); + ptimer_transaction_commit(s->canfd_timer); +} + +static void canfd_init(Object *obj) +{ + XlnxVersalCANFDState *s =3D XILINX_CANFD(obj); + + memory_region_init(&s->iomem, obj, TYPE_XILINX_CANFD, + XLNX_VERSAL_CANFD_R_MAX * 4); +} + +static const VMStateDescription vmstate_canfd =3D { + .name =3D TYPE_XILINX_CANFD, + .version_id =3D 1, + .minimum_version_id =3D 1, + .fields =3D (VMStateField[]) { + VMSTATE_UINT32_ARRAY(regs, XlnxVersalCANFDState, + XLNX_VERSAL_CANFD_R_MAX), + VMSTATE_PTIMER(canfd_timer, XlnxVersalCANFDState), + VMSTATE_END_OF_LIST(), + } +}; + +static Property canfd_core_properties[] =3D { + DEFINE_PROP_UINT8("rx-fifo0", XlnxVersalCANFDState, cfg.rx0_fifo, 0x40= ), + DEFINE_PROP_UINT8("rx-fifo1", XlnxVersalCANFDState, cfg.rx1_fifo, 0x40= ), + DEFINE_PROP_UINT8("tx-fifo", XlnxVersalCANFDState, cfg.tx_fifo, 0x20), + DEFINE_PROP_BOOL("enable-rx-fifo1", XlnxVersalCANFDState, + cfg.enable_rx_fifo1, true), + DEFINE_PROP_UINT32("ext_clk_freq", XlnxVersalCANFDState, cfg.ext_clk_f= req, + CANFD_DEFAULT_CLOCK), + DEFINE_PROP_LINK("canfdbus", XlnxVersalCANFDState, canfdbus, TYPE_CAN_= BUS, + CanBusState *), + DEFINE_PROP_END_OF_LIST(), +}; + +static void canfd_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(klass); + + dc->reset =3D canfd_reset; + dc->realize =3D canfd_realize; + device_class_set_props(dc, canfd_core_properties); + dc->vmsd =3D &vmstate_canfd; +} + +static const TypeInfo canfd_info =3D { + .name =3D TYPE_XILINX_CANFD, + .parent =3D TYPE_SYS_BUS_DEVICE, + .instance_size =3D sizeof(XlnxVersalCANFDState), + .class_init =3D canfd_class_init, + .instance_init =3D canfd_init, + .instance_finalize =3D canfd_finalize, +}; + +static void canfd_register_types(void) +{ + type_register_static(&canfd_info); +} + +type_init(canfd_register_types) diff --git a/include/hw/net/xlnx-versal-canfd.h b/include/hw/net/xlnx-versa= l-canfd.h new file mode 100644 index 0000000000..18dd026388 --- /dev/null +++ b/include/hw/net/xlnx-versal-canfd.h @@ -0,0 +1,90 @@ +/* + * QEMU model of the Xilinx Versal CANFD Controller. + * + * Copyright (c) 2022 AMD Inc. + * + * Written-by: Vikram Garhwal + * Based on QEMU CANFD Device emulation implemented by Jin Yang, Deniz Ere= n and + * Pavel Pisa. + * Permission is hereby granted, free of charge, to any person obtaining a= copy + * of this software and associated documentation files (the "Software"), t= o deal + * in the Software without restriction, including without limitation the r= ights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or se= ll + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included= in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS= OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OT= HER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING= FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS = IN + * THE SOFTWARE. + */ + +#ifndef HW_CANFD_XILINX_H +#define HW_CANFD_XILINX_H + +#include "hw/register.h" +#include "hw/ptimer.h" +#include "net/can_emu.h" +#include "hw/qdev-clock.h" + +#define TYPE_XILINX_CANFD "xlnx.versal-canfd" + +OBJECT_DECLARE_SIMPLE_TYPE(XlnxVersalCANFDState, XILINX_CANFD) + +#define NUM_REGS_PER_MSG_SPACE 18 /* 1 ID + 1 DLC + 16 Data(DW0 - DW15) re= gs. */ +#define MAX_NUM_RX 64 +#define OFFSET_RX1_DW15 (0x4144 / 4) +#define CANFD_TIMER_MAX 0xFFFFUL +#define CANFD_DEFAULT_CLOCK (24 * 1000 * 1000) + +#define XLNX_VERSAL_CANFD_R_MAX (OFFSET_RX1_DW15 + \ + ((MAX_NUM_RX - 1) * NUM_REGS_PER_MSG_SPACE) + 1) + +typedef struct XlnxVersalCANFDState { + SysBusDevice parent_obj; + MemoryRegion iomem; + + qemu_irq irq_canfd_int; + qemu_irq irq_addr_err; + + RegisterInfo reg_info[XLNX_VERSAL_CANFD_R_MAX]; + RegisterAccessInfo *tx_regs; + RegisterAccessInfo *rx0_regs; + RegisterAccessInfo *rx1_regs; + RegisterAccessInfo *af_regs; + RegisterAccessInfo *txe_regs; + RegisterAccessInfo *rx_mailbox_regs; + RegisterAccessInfo *af_mask_regs_mailbox; + + uint32_t regs[XLNX_VERSAL_CANFD_R_MAX]; + uint8_t tx_busy_bit; + uint8_t modes; + + ptimer_state *canfd_timer; + + CanBusClientState bus_client; + CanBusState *canfdbus; + + struct { + uint8_t ctrl_idx; + uint8_t rx0_fifo; + uint8_t rx1_fifo; + uint8_t tx_fifo; + bool enable_rx_fifo1; + uint32_t ext_clk_freq; + } cfg; + +} XlnxVersalCANFDState; + +typedef struct tx_ready_reg_info { + uint32_t can_id; + uint32_t reg_num; +} tx_ready_reg_info; + +#endif --=20 2.17.1 From nobody Fri May 17 22:23:27 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; arc=pass (i=1 dmarc=pass fromdomain=amd.com); dmarc=pass(p=quarantine dis=none) header.from=amd.com ARC-Seal: i=2; a=rsa-sha256; t=1670379354; cv=pass; d=zohomail.com; s=zohoarc; b=PkIVQmygXAM6j1nBbE9xUbA0z/2PzA31TJiXalxleXogXpwfPNHJtt/3bcuWDIrGY78CNzFKm1hsE+upfoDZNhZ6h0/TI8E0HG6LRPjqcsiI8jGp0eOit133d7g3/S0pnvw767WBFQJHy9gFxbHlVxxLTc0NzqhJaqp8vEGnGO4= ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1670379354; h=Content-Type:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=rD+0ciH7TjjgpwMFM/ZqnTOFSYmEFzGkAum1rmsd560=; b=SRNFVOU5L1RBLVgs2R+vfNrIrQuW6XNmHJ5Jis91isbAgy9DJqjmt14uGKjPR1MbFdgPY+EjqZnbknKj0NbF29P3KyMZQspwRCBk3BOlLF/iQYy/ce0PxdezC9wQ2i8pOWMWwdWBdCZk7k4aE3Qzo0AQ+cAlH0Bt20YMI2gDG3M= ARC-Authentication-Results: i=2; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; arc=pass (i=1 dmarc=pass fromdomain=amd.com); dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 167037935451931.1284530136071; Tue, 6 Dec 2022 18:15:54 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1p2jwX-0000NI-Ag; Tue, 06 Dec 2022 21:13:53 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1p2jwV-0000Mi-QL; Tue, 06 Dec 2022 21:13:51 -0500 Received: from mail-dm6nam11on2061f.outbound.protection.outlook.com ([2a01:111:f400:7eaa::61f] helo=NAM11-DM6-obe.outbound.protection.outlook.com) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1p2jwS-000893-VS; Tue, 06 Dec 2022 21:13:51 -0500 Received: from DS7PR03CA0200.namprd03.prod.outlook.com (2603:10b6:5:3b6::25) by BL3PR12MB6596.namprd12.prod.outlook.com (2603:10b6:208:38f::11) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5880.14; Wed, 7 Dec 2022 02:13:43 +0000 Received: from DM6NAM11FT039.eop-nam11.prod.protection.outlook.com (2603:10b6:5:3b6:cafe::69) by DS7PR03CA0200.outlook.office365.com (2603:10b6:5:3b6::25) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5880.14 via Frontend Transport; Wed, 7 Dec 2022 02:13:42 +0000 Received: from SATLEXMB04.amd.com (165.204.84.17) by DM6NAM11FT039.mail.protection.outlook.com (10.13.172.83) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.5901.14 via Frontend Transport; Wed, 7 Dec 2022 02:13:42 +0000 Received: from SATLEXMB03.amd.com (10.181.40.144) by SATLEXMB04.amd.com (10.181.40.145) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2375.34; Tue, 6 Dec 2022 20:13:42 -0600 Received: from xsjfnuv50.xilinx.com (10.180.168.240) by SATLEXMB03.amd.com (10.181.40.144) with Microsoft SMTP Server id 15.1.2375.34 via Frontend Transport; Tue, 6 Dec 2022 20:13:41 -0600 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=T1R2jdIUDVzDRhg1D7DJnuX0VJX7cykn55/ShpYnv9YEQbMgHYj7yNeKfA0Fmbz+/Fm/FF6d6TGx8sa2//KRzKwuRkHrdnX1OnY0vpqJWc9CVcEsXQXAqfPHh/t56fQH2ZS1Oq49TMzy0zdtZ4Q6cnXOjWlY2/Lx8hcm+EvR9XyowoteMYT1h64Bja4xgQU0mTXbU0dmMRAa+xANAoYbKXNQiO0M/lS6sNhyMK2H8RTd6KZF955niEuv+NJpbSaxOmtlSpye9LWbWRTMeGPoCwMoci3cZNTrqsZn09gMGbwAFayR+dIT0I5Y88eBT8G8+dpC8Nc67nfxy0JRIDU10w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=rD+0ciH7TjjgpwMFM/ZqnTOFSYmEFzGkAum1rmsd560=; b=f7bRJYzF7ldg6KRYlMwqHd4Vj5rRlqu2WODZRHubrXPfYHHT/po2bZsrBrg+678kMd+tsKPZi7j1qIcEHfsFh99qcRaGMTASjXV1rfhnOwscoFfIm5NcVLbCF+ChGha7icFuc+ucbJU7kyvz0+uTygS6BM/MluSq5jDG6gwrEF1r/6ysIHgXMIrJzMebFgg0uGj7XWII5riHOwJJqZf551Yj6dnu8IjAblNH2ygAPQ2wy+UhCiBx0QpdaK/lBGEGvtGzBnOpuaMeHEZzmMRTHRbWXd4IlPXYk6YnokXP02zcr0MpbNnku9UYfHkb3ibFNFR41QKyIBZlViwl6ZnSVg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 165.204.84.17) smtp.rcpttodomain=nongnu.org smtp.mailfrom=amd.com; dmarc=pass (p=quarantine sp=quarantine pct=100) action=none header.from=amd.com; dkim=none (message not signed); arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amd.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=rD+0ciH7TjjgpwMFM/ZqnTOFSYmEFzGkAum1rmsd560=; b=wLI1Yjhk77vjD6G5wMeesR1mxCXSvWAfQrMjp3zi5iq7jod1uR0PFW8zPkgtB1hVG1sx+PRVufjpAZHwZy71ixB0Q3hatPXfzSkEC5c7/MMUVJVKgNTcL6XQm62WpN6Z57E7V9E/Vb9HQB0QAD5c9aeevzEAorRzeA9EobBLmwg= X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 165.204.84.17) smtp.mailfrom=amd.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=amd.com; Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: Pass (protection.outlook.com: domain of amd.com designates 165.204.84.17 as permitted sender) receiver=protection.outlook.com; client-ip=165.204.84.17; helo=SATLEXMB04.amd.com; pr=C From: Vikram Garhwal To: CC: , , , Alistair Francis , "Edgar E. Iglesias" , "open list:Xilinx ZynqMP and..." Subject: [QEMU][PATCH v3 3/4] xlnx-zynqmp: Connect Xilinx VERSAL CANFD controllers Date: Tue, 6 Dec 2022 18:13:21 -0800 Message-ID: <20221207021322.16165-5-vikram.garhwal@amd.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20221207021322.16165-1-vikram.garhwal@amd.com> References: <20221207021322.16165-1-vikram.garhwal@amd.com> MIME-Version: 1.0 X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: DM6NAM11FT039:EE_|BL3PR12MB6596:EE_ X-MS-Office365-Filtering-Correlation-Id: b910fafe-6da6-4958-2fc8-08dad7f8a9f7 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: 60WXxExGVcQW867wfBMuRH9t22wC1nRHrotImWqef9GIVzA9JoTqXjiJe+tvXjr7M0MK+ZyIi66T68NtWk5bsjPZDgUtE9HlsrUOShv790iivVPNv42mADrXH6YVDVlpmkMQvjbdDsYogKAIgq1boRhWypZgmee0VPrlUbPtYrEfQsfFy6vONxwXlkqUgFkTF57KVlekrWWEoUFyydxpXUwk6e4o2DFCafwY/4II1J1/UwRriCs09eNmc//IGcSPoew/1t3koEUECV3h65E7TYWWDUM31TCaNi5Z35H5oL/kLJ3ktdSUbdVrWYom8NG8cG6urEeBmHjwAxAv6/gFLk4uQHIs1/uwja5lERpNakyfaVeht5ARCBjYZTS2q+F9IsGR7zMP92Jmq52ke5+q+1XAOL3GKfBF02S02qJA9Vv3xw8wiBt2i05QFVZlE6uZFFIklCroikouSJmu+60FGKHdppEbnNkTj9jfFqIJRaAwxEmQ6/AipLman7SBm/HIlCFHbZiALJ4Ikpo89cx8TO2XLXzJ7qvzb5doCbal4zDZ+bUuPQTnYvKFO+I+FrhWJiw/PnQZ0XvEEEs2M8PzbisXr5hixBe2PJmdFzYv+fNgYjYIXClFrw/UT/02AtnhjKHInI9phlouRPdap1Wq3R8CvOQEy/t07eHKQCxjKGxJfRd0lYaMPd3zP/fDqW77AdhQzR6uj4czPSuvZMcUr/yPRu4RgoLAyjvjcfNpz2E= X-Forefront-Antispam-Report: CIP:165.204.84.17; CTRY:US; LANG:en; SCL:1; SRV:; IPV:CAL; SFV:NSPM; H:SATLEXMB04.amd.com; PTR:InfoDomainNonexistent; CAT:NONE; SFS:(13230022)(4636009)(396003)(376002)(136003)(346002)(39860400002)(451199015)(46966006)(36840700001)(40470700004)(82310400005)(86362001)(36756003)(40480700001)(40460700003)(336012)(41300700001)(1076003)(2616005)(70206006)(70586007)(186003)(4326008)(8936002)(47076005)(5660300002)(44832011)(8676002)(426003)(478600001)(54906003)(6916009)(6666004)(316002)(356005)(81166007)(26005)(82740400003)(2906002)(36860700001)(83380400001)(36900700001); DIR:OUT; SFP:1101; X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 07 Dec 2022 02:13:42.9131 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: b910fafe-6da6-4958-2fc8-08dad7f8a9f7 X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=3dd8961f-e488-4e60-8e11-a82d994e183d; Ip=[165.204.84.17]; Helo=[SATLEXMB04.amd.com] X-MS-Exchange-CrossTenant-AuthSource: DM6NAM11FT039.eop-nam11.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: BL3PR12MB6596 Received-SPF: softfail client-ip=2a01:111:f400:7eaa::61f; envelope-from=vikram.garhwal@amd.com; helo=NAM11-DM6-obe.outbound.protection.outlook.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001, WEIRD_QUOTING=0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @amd.com) X-ZM-MESSAGEID: 1670379355128100001 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Connect CANFD0 and CANFD1 on the Versal-virt machine and update xlnx-versal= -virt document with CANFD command line examples. Signed-off-by: Vikram Garhwal --- docs/system/arm/xlnx-versal-virt.rst | 31 ++++++++++++++++++ hw/arm/xlnx-versal-virt.c | 48 ++++++++++++++++++++++++++++ hw/arm/xlnx-versal.c | 37 +++++++++++++++++++++ include/hw/arm/xlnx-versal.h | 12 +++++++ 4 files changed, 128 insertions(+) diff --git a/docs/system/arm/xlnx-versal-virt.rst b/docs/system/arm/xlnx-ve= rsal-virt.rst index 92ad10d2da..372e4249f0 100644 --- a/docs/system/arm/xlnx-versal-virt.rst +++ b/docs/system/arm/xlnx-versal-virt.rst @@ -34,6 +34,7 @@ Implemented devices: - DDR memory - BBRAM (36 bytes of Battery-backed RAM) - eFUSE (3072 bytes of one-time field-programmable bit array) +- 2 CANFDs =20 QEMU does not yet model any other devices, including the PL and the AI Eng= ine. =20 @@ -224,3 +225,33 @@ To use a different index value, N, from default of 1, = add: =20 Better yet, do not use actual product data when running guest image on this Xilinx Versal Virt board. + +Using CANFDs for Versal Virt +"""""""""""""""""""""""""""" +Versal CANFD controller is developed based on SocketCAN and QEMU CAN bus +implementation. Bus connection and socketCAN connection for each CAN module +can be set through command lines. + +To connect both CANFD0 and CANFD1 on the same bus: + +.. code-block:: bash + + -object can-bus,id=3Dcanbus -machine canbus0=3Dcanbus -machine canbus1= =3Dcanbus + +To connect CANFD0 and CANFD1 to separate buses: + +.. code-block:: bash + + -object can-bus,id=3Dcanbus0 -object can-bus,id=3Dcanbus1 \ + -machine canbus0=3Dcanbus0 -machine canbus1=3Dcanbus1 + +SocketCAN interface can connect to a Physical or a Virtual CAN interfaces = on +host machine. Please check this document to learn about CAN interface on L= inux: +docs/system/devices/can.rst + +To connect CANFD0 and CANFD1 to host machine's CAN interface can0: + +.. code-block:: bash + + -object can-bus,id=3Dcanbus -machine canbus0=3Dcanbus -machine canbus1= =3Dcanbus + -object can-host-socketcan,id=3Dcanhost0,if=3Dcan0,canbus=3Dcanbus diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c index 37fc9b919c..963ace861e 100644 --- a/hw/arm/xlnx-versal-virt.c +++ b/hw/arm/xlnx-versal-virt.c @@ -40,9 +40,11 @@ struct VersalVirt { uint32_t clk_25Mhz; uint32_t usb; uint32_t dwc; + uint32_t canfd[2]; } phandle; struct arm_boot_info binfo; =20 + CanBusState *canbus[XLNX_VERSAL_NR_CANFD]; struct { bool secure; } cfg; @@ -235,6 +237,33 @@ static void fdt_add_uart_nodes(VersalVirt *s) } } =20 +static void fdt_add_canfd_nodes(VersalVirt *s) +{ + uint64_t addrs[] =3D { MM_CANFD0, MM_CANFD1 }; + uint32_t size[] =3D { MM_CANFD0_SIZE, MM_CANFD1_SIZE }; + unsigned int irqs[] =3D { VERSAL_CANFD0_IRQ_0, VERSAL_CANFD1_IRQ_0 }; + int i; + + /* Create and connect CANFD0 and CANFD1 nodes to canbus0. */ + for (i =3D 0; i < ARRAY_SIZE(addrs); i++) { + char *name =3D g_strdup_printf("/canfd@%" PRIx64, addrs[i]); + qemu_fdt_add_subnode(s->fdt, name); + qemu_fdt_setprop_cell(s->fdt, name, "rx-fifo0", 0x40); + qemu_fdt_setprop_cell(s->fdt, name, "enable-rx-fifo1", 0x1); + qemu_fdt_setprop_cell(s->fdt, name, "rx-fifo1", 0x40); + + qemu_fdt_setprop_cells(s->fdt, name, "interrupts", + GIC_FDT_IRQ_TYPE_SPI, irqs[i], + GIC_FDT_IRQ_FLAGS_LEVEL_HI); + qemu_fdt_setprop_sized_cells(s->fdt, name, "reg", + 2, addrs[i], 2, size[i]); + qemu_fdt_setprop_string(s->fdt, name, "compatible", + "xlnx,versal-canfd"); + + g_free(name); + } +} + static void fdt_add_fixed_link_nodes(VersalVirt *s, char *gemname, uint32_t phandle) { @@ -639,12 +668,17 @@ static void versal_virt_init(MachineState *machine) TYPE_XLNX_VERSAL); object_property_set_link(OBJECT(&s->soc), "ddr", OBJECT(machine->ram), &error_abort); + object_property_set_link(OBJECT(&s->soc), "canbus0", OBJECT(s->canbus[= 0]), + &error_abort); + object_property_set_link(OBJECT(&s->soc), "canbus1", OBJECT(s->canbus[= 1]), + &error_abort); sysbus_realize(SYS_BUS_DEVICE(&s->soc), &error_fatal); =20 fdt_create(s); create_virtio_regions(s); fdt_add_gem_nodes(s); fdt_add_uart_nodes(s); + fdt_add_canfd_nodes(s); fdt_add_gic_nodes(s); fdt_add_timer_nodes(s); fdt_add_zdma_nodes(s); @@ -712,6 +746,20 @@ static void versal_virt_init(MachineState *machine) =20 static void versal_virt_machine_instance_init(Object *obj) { + VersalVirt *s =3D XLNX_VERSAL_VIRT_MACHINE(obj); + + /* + * User can set canbus0 and canbus1 properties to can-bus object and c= onnect + * to socketcan(optional) interface via command line. + */ + object_property_add_link(obj, "canbus0", TYPE_CAN_BUS, + (Object **)&s->canbus[0], + object_property_allow_set_link, + 0); + object_property_add_link(obj, "canbus1", TYPE_CAN_BUS, + (Object **)&s->canbus[1], + object_property_allow_set_link, + 0); } =20 static void versal_virt_machine_class_init(ObjectClass *oc, void *data) diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c index 57276e1506..44b0eaf0c8 100644 --- a/hw/arm/xlnx-versal.c +++ b/hw/arm/xlnx-versal.c @@ -185,6 +185,38 @@ static void versal_create_uarts(Versal *s, qemu_irq *p= ic) } } =20 +static void versal_create_canfds(Versal *s, qemu_irq *pic) +{ + int i; + + for (i =3D 0; i < ARRAY_SIZE(s->lpd.iou.canfd); i++) { + static const int irqs[] =3D { VERSAL_CANFD0_IRQ_0, VERSAL_CANFD1_I= RQ_0}; + static const uint64_t addrs[] =3D { MM_CANFD0, MM_CANFD1 }; + char *name =3D g_strdup_printf("canfd%d", i); + SysBusDevice *sbd; + MemoryRegion *mr; + + object_initialize_child(OBJECT(s), name, &s->lpd.iou.canfd[i], + TYPE_XILINX_CANFD); + sbd =3D SYS_BUS_DEVICE(&s->lpd.iou.canfd[i]); + + object_property_set_int(OBJECT(&s->lpd.iou.canfd[i]), "ext_clk_fre= q", + XLNX_VERSAL_CANFD_REF_CLK , &error_abort); + + object_property_set_link(OBJECT(&s->lpd.iou.canfd[i]), "canfdbus", + OBJECT(s->lpd.iou.canbus[i]), + &error_abort); + + sysbus_realize(sbd, &error_fatal); + + mr =3D sysbus_mmio_get_region(sbd, 0); + memory_region_add_subregion(&s->mr_ps, addrs[i], mr); + + sysbus_connect_irq(sbd, 0, pic[irqs[i]]); + g_free(name); + } +} + static void versal_create_usbs(Versal *s, qemu_irq *pic) { DeviceState *dev; @@ -719,6 +751,7 @@ static void versal_realize(DeviceState *dev, Error **er= rp) versal_create_apu_gic(s, pic); versal_create_rpu_cpus(s); versal_create_uarts(s, pic); + versal_create_canfds(s, pic); versal_create_usbs(s, pic); versal_create_gems(s, pic); versal_create_admas(s, pic); @@ -758,6 +791,10 @@ static void versal_init(Object *obj) static Property versal_properties[] =3D { DEFINE_PROP_LINK("ddr", Versal, cfg.mr_ddr, TYPE_MEMORY_REGION, MemoryRegion *), + DEFINE_PROP_LINK("canbus0", Versal, lpd.iou.canbus[0], + TYPE_CAN_BUS, CanBusState *), + DEFINE_PROP_LINK("canbus1", Versal, lpd.iou.canbus[1], + TYPE_CAN_BUS, CanBusState *), DEFINE_PROP_END_OF_LIST() }; =20 diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h index cbe8a19c10..97e63a1b0e 100644 --- a/include/hw/arm/xlnx-versal.h +++ b/include/hw/arm/xlnx-versal.h @@ -31,6 +31,7 @@ #include "hw/dma/xlnx_csu_dma.h" #include "hw/misc/xlnx-versal-crl.h" #include "hw/misc/xlnx-versal-pmc-iou-slcr.h" +#include "hw/net/xlnx-versal-canfd.h" =20 #define TYPE_XLNX_VERSAL "xlnx-versal" OBJECT_DECLARE_SIMPLE_TYPE(Versal, XLNX_VERSAL) @@ -43,6 +44,8 @@ OBJECT_DECLARE_SIMPLE_TYPE(Versal, XLNX_VERSAL) #define XLNX_VERSAL_NR_SDS 2 #define XLNX_VERSAL_NR_XRAM 4 #define XLNX_VERSAL_NR_IRQS 192 +#define XLNX_VERSAL_NR_CANFD 2 +#define XLNX_VERSAL_CANFD_REF_CLK (24 * 1000 * 1000) =20 struct Versal { /*< private >*/ @@ -73,6 +76,8 @@ struct Versal { CadenceGEMState gem[XLNX_VERSAL_NR_GEMS]; XlnxZDMA adma[XLNX_VERSAL_NR_ADMAS]; VersalUsb2 usb; + CanBusState *canbus[XLNX_VERSAL_NR_CANFD]; + XlnxVersalCANFDState canfd[XLNX_VERSAL_NR_CANFD]; } iou; =20 /* Real-time Processing Unit. */ @@ -133,6 +138,8 @@ struct Versal { #define VERSAL_CRL_IRQ 10 #define VERSAL_UART0_IRQ_0 18 #define VERSAL_UART1_IRQ_0 19 +#define VERSAL_CANFD0_IRQ_0 20 +#define VERSAL_CANFD1_IRQ_0 21 #define VERSAL_USB0_IRQ_0 22 #define VERSAL_GEM0_IRQ_0 56 #define VERSAL_GEM0_WAKE_IRQ_0 57 @@ -163,6 +170,11 @@ struct Versal { #define MM_UART1 0xff010000U #define MM_UART1_SIZE 0x10000 =20 +#define MM_CANFD0 0xff060000 +#define MM_CANFD0_SIZE 0x10000 +#define MM_CANFD1 0xff070000 +#define MM_CANFD1_SIZE 0x10000 + #define MM_GEM0 0xff0c0000U #define MM_GEM0_SIZE 0x10000 #define MM_GEM1 0xff0d0000U --=20 2.17.1 From nobody Fri May 17 22:23:27 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; arc=pass (i=1 dmarc=pass fromdomain=amd.com); dmarc=pass(p=quarantine dis=none) header.from=amd.com ARC-Seal: i=2; a=rsa-sha256; t=1670379290; cv=pass; d=zohomail.com; s=zohoarc; b=BbpFPR5GSaBT4HZJwpc6yrdU17MPP8GCi605RWP1GH+PJgRk55lFueWrOe4X7tTQ0mwr/IFos4n8F26Gdjag9kIXkUvcQ9Tq+EuHVvJWnpRn2ClzAuk2Kk7SyjpEEPGfR7bQ9Fco82PqWPIFBJ/cM8Q5oeu3YEm8O8NYjtIx7XE= ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1670379290; h=Content-Type:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=zdmrY+wNsYHvcI7dLQdbHmGBXXz7HJVvR1XR7ka+bOc=; b=Mr+CwHBIRSjdWVlylytjp9ELUKMtp0Wy1vXCxfgwWJEOKsApQQMwqs/yYi3vqNgTdU/RzzuJMxefilBlOvP697KjxXqAt/3fqyRwvy1npt8pH1tEJjcRSUrH2+2R95ZNrPNoZenMHXEAB6uuXqNaJPIJUouKRIKTWzQ3FsffPgg= ARC-Authentication-Results: i=2; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; arc=pass (i=1 dmarc=pass fromdomain=amd.com); dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1670379290504793.4430020604456; Tue, 6 Dec 2022 18:14:50 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1p2jwk-0000Rg-AQ; Tue, 06 Dec 2022 21:14:06 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1p2jwh-0000PR-T4; Tue, 06 Dec 2022 21:14:04 -0500 Received: from mail-bn1nam02on20631.outbound.protection.outlook.com ([2a01:111:f400:7eb2::631] helo=NAM02-BN1-obe.outbound.protection.outlook.com) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1p2jwR-00087f-2P; Tue, 06 Dec 2022 21:14:02 -0500 Received: from DS7PR03CA0188.namprd03.prod.outlook.com (2603:10b6:5:3b6::13) by MW3PR12MB4556.namprd12.prod.outlook.com (2603:10b6:303:52::20) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5880.14; Wed, 7 Dec 2022 02:13:42 +0000 Received: from DM6NAM11FT039.eop-nam11.prod.protection.outlook.com (2603:10b6:5:3b6:cafe::42) by DS7PR03CA0188.outlook.office365.com (2603:10b6:5:3b6::13) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5880.14 via Frontend Transport; Wed, 7 Dec 2022 02:13:42 +0000 Received: from SATLEXMB04.amd.com (165.204.84.17) by DM6NAM11FT039.mail.protection.outlook.com (10.13.172.83) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.5901.14 via Frontend Transport; Wed, 7 Dec 2022 02:13:41 +0000 Received: from SATLEXMB03.amd.com (10.181.40.144) by SATLEXMB04.amd.com (10.181.40.145) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2375.34; Tue, 6 Dec 2022 20:13:41 -0600 Received: from xsjfnuv50.xilinx.com (10.180.168.240) by SATLEXMB03.amd.com (10.181.40.144) with Microsoft SMTP Server id 15.1.2375.34 via Frontend Transport; Tue, 6 Dec 2022 20:13:40 -0600 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=kAJUvrsIn9O4RO9O7uA3TMrdnIymX6MiL1vdlGl9kWXJMm/3QsPMCohrFFO9qwEs+oXmZuEJY9hxJ3ApY1U8xd1G6p6xZZRUQVbjXdOeiab/P1suHqbBvgI9HTp2nRBdHSi7gLiSn42yLwlF5ZKYL+U3whvJsWlKSN+GbmMjMg1pW4JkPYXsyGvbCCKWxarIy9FUAONxl6ysbGEEZADMK8alIBJ40/TLNrM8EhU3yEyjGx2PLAHloMpXEGns1D/dDufSjV0c30Ji7CNR6BBVsaaxqyOMhuzXebcUuyoUhij7ndW1nc5BsnMV3cLSqi5olQ/TjldfQE+VAQX8s44Org== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=zdmrY+wNsYHvcI7dLQdbHmGBXXz7HJVvR1XR7ka+bOc=; b=D5MZ+T+oFw5zLBjnSgd5mkTHnMllZcI48cPlICs9BjKwMBSFuIGGGG3h+N6GD/7sndjLQ22v36jZkynURcWso3Kc9ykFwjITWsniIJtD74b79ltlxVVYcrbOjfP9TUI3oRwp8ZkbbXYn8JNWTmJ0k82Rn517+PoqVZ3G2S3+rvnXqimaeK0kXLU7lebC5eTBHH38HIuAvSQDoJRoqw8jDm8yg1t5yuWsg+5+QeoGJrLlUmQQpQwSheCVie2crQ8M2xZklMnP/A0FvTDYKk10RSeWtII5DrA/W/XIpyeT8S+9jANoP718X/EOcf9BY83triKJwVOqhf3KMCzIzUy/rg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 165.204.84.17) smtp.rcpttodomain=nongnu.org smtp.mailfrom=amd.com; dmarc=pass (p=quarantine sp=quarantine pct=100) action=none header.from=amd.com; dkim=none (message not signed); arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amd.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=zdmrY+wNsYHvcI7dLQdbHmGBXXz7HJVvR1XR7ka+bOc=; b=QjxpJUVEI1Ai0G5ZvO3HPYTjNdunnJZ/oeznFKCMRYkHAYRwGDvL78adKSIG9w9yaqiFl5gpz6YtDcRkRM2FDk8YlFXX574AVSqUq6C2EtfWBB1Lc5Yk0QqNVSauXfQ8O8BihDWsGhNc06mYkuqRijgcBOB9qSOTNGG9U6o++fo= X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 165.204.84.17) smtp.mailfrom=amd.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=amd.com; Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: Pass (protection.outlook.com: domain of amd.com designates 165.204.84.17 as permitted sender) receiver=protection.outlook.com; client-ip=165.204.84.17; helo=SATLEXMB04.amd.com; pr=C From: Vikram Garhwal To: CC: , , , Alistair Francis , "Edgar E. Iglesias" , "open list:Xilinx ZynqMP and..." Subject: [QEMU][PATCH v3 3/4] xlnx-versal: Connect Xilinx VERSAL CANFD controllers Date: Tue, 6 Dec 2022 18:13:20 -0800 Message-ID: <20221207021322.16165-4-vikram.garhwal@amd.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20221207021322.16165-1-vikram.garhwal@amd.com> References: <20221207021322.16165-1-vikram.garhwal@amd.com> MIME-Version: 1.0 X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: DM6NAM11FT039:EE_|MW3PR12MB4556:EE_ X-MS-Office365-Filtering-Correlation-Id: 8d4512a6-7905-4f45-87a0-08dad7f8a96a X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: eCC+CApNVcKaPnUpJdGScNC5qPJISiQw6qZAY4a8FDoFhXufzumlu8ZBmYxScjAZZ2m8TSbOf90UJLr+9sexVL+sWGHtehkT6jI+QXW/2/+hc1UeCN5I1jjg3c2skbn1Sn2AjTWYvA6eumIk8rav7kBjfpy70FBl5qUhkjpdxEILhsOGwlLycGWmmxbqFPNDFnE1Esh2oSuuUqYdlGzwI2cXgVFcJTabo183reuA1l/o6ZzQxsp0RsRMvYFcfz8BtscnetQCmTqqi5WJjP95GO+SmT8DrHEa/or3K45q405c5rOhq/R8gCBb4BNp7dU+r2ZV51PoWCwuXq1zRG7I4V4yoDn7CuiUiEQuilLBqGgFx3CduRdI5A2SSpRoFkCHMWVd8rR+ZrqiySNNc5CPpfNlNcf4Df9QEswF/4/a/JpXd4MjfWIMXQoEdsfjmdzG4jUNLzIxRVNuAMo5r0PFsBhcD0GDD3ExXF6RwFX2N/WtknRFnJfiugWyKjg8oxhbQqVdnKPVqHsNOb7Z9tGLU9suSq9r5BCTtmNCpobQYXTy+18LxzXaVDdQR32NYwaM7KwbtAZAGuosjCzp7lPLl+9iyGVdkdgGs+LIeeA3MFRvatH5yBauX2lEc8oFsa7ocTnd/EIV90P7RD3uxoDtKm2fIcahnu7jQikYrK3D9mg8Iy4XTpOtRRVpZOfb8t/l60rXDv7SjA/PYNjmN/CMC4BmAaKg7dD0tqLD6UW8gL8= X-Forefront-Antispam-Report: CIP:165.204.84.17; CTRY:US; LANG:en; SCL:1; SRV:; IPV:CAL; SFV:NSPM; H:SATLEXMB04.amd.com; PTR:InfoDomainNonexistent; CAT:NONE; SFS:(13230022)(4636009)(39860400002)(136003)(346002)(376002)(396003)(451199015)(40470700004)(46966006)(36840700001)(36860700001)(70206006)(70586007)(40480700001)(478600001)(356005)(4326008)(8676002)(6666004)(82740400003)(81166007)(2906002)(186003)(336012)(26005)(86362001)(6916009)(54906003)(83380400001)(5660300002)(8936002)(36756003)(316002)(47076005)(426003)(41300700001)(2616005)(44832011)(40460700003)(1076003)(82310400005)(36900700001); DIR:OUT; SFP:1101; X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 07 Dec 2022 02:13:41.9757 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 8d4512a6-7905-4f45-87a0-08dad7f8a96a X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=3dd8961f-e488-4e60-8e11-a82d994e183d; Ip=[165.204.84.17]; Helo=[SATLEXMB04.amd.com] X-MS-Exchange-CrossTenant-AuthSource: DM6NAM11FT039.eop-nam11.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: MW3PR12MB4556 Received-SPF: softfail client-ip=2a01:111:f400:7eb2::631; envelope-from=vikram.garhwal@amd.com; helo=NAM02-BN1-obe.outbound.protection.outlook.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001, WEIRD_QUOTING=0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @amd.com) X-ZM-MESSAGEID: 1670379292854100007 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Connect CANFD0 and CANFD1 on the Versal-virt machine and update xlnx-versal= -virt document with CANFD command line examples. Signed-off-by: Vikram Garhwal Reviewed-by: Peter Maydell --- docs/system/arm/xlnx-versal-virt.rst | 31 ++++++++++++++++++ hw/arm/xlnx-versal-virt.c | 48 ++++++++++++++++++++++++++++ hw/arm/xlnx-versal.c | 37 +++++++++++++++++++++ include/hw/arm/xlnx-versal.h | 12 +++++++ 4 files changed, 128 insertions(+) diff --git a/docs/system/arm/xlnx-versal-virt.rst b/docs/system/arm/xlnx-ve= rsal-virt.rst index 92ad10d2da..d2d1b26692 100644 --- a/docs/system/arm/xlnx-versal-virt.rst +++ b/docs/system/arm/xlnx-versal-virt.rst @@ -34,6 +34,7 @@ Implemented devices: - DDR memory - BBRAM (36 bytes of Battery-backed RAM) - eFUSE (3072 bytes of one-time field-programmable bit array) +- 2 CANFDs =20 QEMU does not yet model any other devices, including the PL and the AI Eng= ine. =20 @@ -224,3 +225,33 @@ To use a different index value, N, from default of 1, = add: =20 Better yet, do not use actual product data when running guest image on this Xilinx Versal Virt board. + +Using CANFDs for Versal Virt +"""""""""""""""""""""""""""" +Versal CANFD controller is developed based on SocketCAN and QEMU CAN bus +implementation. Bus connection and socketCAN connection for each CAN module +can be set through command lines. + +To connect both CANFD0 and CANFD1 on the same bus: + +.. code-block:: bash + + -object can-bus,id=3Dcanbus -machine canbus0=3Dcanbus -machine canbus1= =3Dcanbus + +To connect CANFD0 and CANFD1 to separate buses: + +.. code-block:: bash + + -object can-bus,id=3Dcanbus0 -object can-bus,id=3Dcanbus1 \ + -machine canbus0=3Dcanbus0 -machine canbus1=3Dcanbus1 + +The SocketCAN interface can connect to a Physical or a Virtual CAN interfa= ces on +the host machine. Please check this document to learn about CAN interface = on +Linux: docs/system/devices/can.rst + +To connect CANFD0 and CANFD1 to host machine's CAN interface can0: + +.. code-block:: bash + + -object can-bus,id=3Dcanbus -machine canbus0=3Dcanbus -machine canbus1= =3Dcanbus + -object can-host-socketcan,id=3Dcanhost0,if=3Dcan0,canbus=3Dcanbus diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c index 37fc9b919c..963ace861e 100644 --- a/hw/arm/xlnx-versal-virt.c +++ b/hw/arm/xlnx-versal-virt.c @@ -40,9 +40,11 @@ struct VersalVirt { uint32_t clk_25Mhz; uint32_t usb; uint32_t dwc; + uint32_t canfd[2]; } phandle; struct arm_boot_info binfo; =20 + CanBusState *canbus[XLNX_VERSAL_NR_CANFD]; struct { bool secure; } cfg; @@ -235,6 +237,33 @@ static void fdt_add_uart_nodes(VersalVirt *s) } } =20 +static void fdt_add_canfd_nodes(VersalVirt *s) +{ + uint64_t addrs[] =3D { MM_CANFD0, MM_CANFD1 }; + uint32_t size[] =3D { MM_CANFD0_SIZE, MM_CANFD1_SIZE }; + unsigned int irqs[] =3D { VERSAL_CANFD0_IRQ_0, VERSAL_CANFD1_IRQ_0 }; + int i; + + /* Create and connect CANFD0 and CANFD1 nodes to canbus0. */ + for (i =3D 0; i < ARRAY_SIZE(addrs); i++) { + char *name =3D g_strdup_printf("/canfd@%" PRIx64, addrs[i]); + qemu_fdt_add_subnode(s->fdt, name); + qemu_fdt_setprop_cell(s->fdt, name, "rx-fifo0", 0x40); + qemu_fdt_setprop_cell(s->fdt, name, "enable-rx-fifo1", 0x1); + qemu_fdt_setprop_cell(s->fdt, name, "rx-fifo1", 0x40); + + qemu_fdt_setprop_cells(s->fdt, name, "interrupts", + GIC_FDT_IRQ_TYPE_SPI, irqs[i], + GIC_FDT_IRQ_FLAGS_LEVEL_HI); + qemu_fdt_setprop_sized_cells(s->fdt, name, "reg", + 2, addrs[i], 2, size[i]); + qemu_fdt_setprop_string(s->fdt, name, "compatible", + "xlnx,versal-canfd"); + + g_free(name); + } +} + static void fdt_add_fixed_link_nodes(VersalVirt *s, char *gemname, uint32_t phandle) { @@ -639,12 +668,17 @@ static void versal_virt_init(MachineState *machine) TYPE_XLNX_VERSAL); object_property_set_link(OBJECT(&s->soc), "ddr", OBJECT(machine->ram), &error_abort); + object_property_set_link(OBJECT(&s->soc), "canbus0", OBJECT(s->canbus[= 0]), + &error_abort); + object_property_set_link(OBJECT(&s->soc), "canbus1", OBJECT(s->canbus[= 1]), + &error_abort); sysbus_realize(SYS_BUS_DEVICE(&s->soc), &error_fatal); =20 fdt_create(s); create_virtio_regions(s); fdt_add_gem_nodes(s); fdt_add_uart_nodes(s); + fdt_add_canfd_nodes(s); fdt_add_gic_nodes(s); fdt_add_timer_nodes(s); fdt_add_zdma_nodes(s); @@ -712,6 +746,20 @@ static void versal_virt_init(MachineState *machine) =20 static void versal_virt_machine_instance_init(Object *obj) { + VersalVirt *s =3D XLNX_VERSAL_VIRT_MACHINE(obj); + + /* + * User can set canbus0 and canbus1 properties to can-bus object and c= onnect + * to socketcan(optional) interface via command line. + */ + object_property_add_link(obj, "canbus0", TYPE_CAN_BUS, + (Object **)&s->canbus[0], + object_property_allow_set_link, + 0); + object_property_add_link(obj, "canbus1", TYPE_CAN_BUS, + (Object **)&s->canbus[1], + object_property_allow_set_link, + 0); } =20 static void versal_virt_machine_class_init(ObjectClass *oc, void *data) diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c index 57276e1506..ff76d5ee3c 100644 --- a/hw/arm/xlnx-versal.c +++ b/hw/arm/xlnx-versal.c @@ -185,6 +185,38 @@ static void versal_create_uarts(Versal *s, qemu_irq *p= ic) } } =20 +static void versal_create_canfds(Versal *s, qemu_irq *pic) +{ + int i; + uint32_t irqs[] =3D { VERSAL_CANFD0_IRQ_0, VERSAL_CANFD1_IRQ_0}; + uint64_t addrs[] =3D { MM_CANFD0, MM_CANFD1 }; + + for (i =3D 0; i < ARRAY_SIZE(s->lpd.iou.canfd); i++) { + char *name =3D g_strdup_printf("canfd%d", i); + SysBusDevice *sbd; + MemoryRegion *mr; + + object_initialize_child(OBJECT(s), name, &s->lpd.iou.canfd[i], + TYPE_XILINX_CANFD); + sbd =3D SYS_BUS_DEVICE(&s->lpd.iou.canfd[i]); + + object_property_set_int(OBJECT(&s->lpd.iou.canfd[i]), "ext_clk_fre= q", + XLNX_VERSAL_CANFD_REF_CLK , &error_abort); + + object_property_set_link(OBJECT(&s->lpd.iou.canfd[i]), "canfdbus", + OBJECT(s->lpd.iou.canbus[i]), + &error_abort); + + sysbus_realize(sbd, &error_fatal); + + mr =3D sysbus_mmio_get_region(sbd, 0); + memory_region_add_subregion(&s->mr_ps, addrs[i], mr); + + sysbus_connect_irq(sbd, 0, pic[irqs[i]]); + g_free(name); + } +} + static void versal_create_usbs(Versal *s, qemu_irq *pic) { DeviceState *dev; @@ -719,6 +751,7 @@ static void versal_realize(DeviceState *dev, Error **er= rp) versal_create_apu_gic(s, pic); versal_create_rpu_cpus(s); versal_create_uarts(s, pic); + versal_create_canfds(s, pic); versal_create_usbs(s, pic); versal_create_gems(s, pic); versal_create_admas(s, pic); @@ -758,6 +791,10 @@ static void versal_init(Object *obj) static Property versal_properties[] =3D { DEFINE_PROP_LINK("ddr", Versal, cfg.mr_ddr, TYPE_MEMORY_REGION, MemoryRegion *), + DEFINE_PROP_LINK("canbus0", Versal, lpd.iou.canbus[0], + TYPE_CAN_BUS, CanBusState *), + DEFINE_PROP_LINK("canbus1", Versal, lpd.iou.canbus[1], + TYPE_CAN_BUS, CanBusState *), DEFINE_PROP_END_OF_LIST() }; =20 diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h index cbe8a19c10..97e63a1b0e 100644 --- a/include/hw/arm/xlnx-versal.h +++ b/include/hw/arm/xlnx-versal.h @@ -31,6 +31,7 @@ #include "hw/dma/xlnx_csu_dma.h" #include "hw/misc/xlnx-versal-crl.h" #include "hw/misc/xlnx-versal-pmc-iou-slcr.h" +#include "hw/net/xlnx-versal-canfd.h" =20 #define TYPE_XLNX_VERSAL "xlnx-versal" OBJECT_DECLARE_SIMPLE_TYPE(Versal, XLNX_VERSAL) @@ -43,6 +44,8 @@ OBJECT_DECLARE_SIMPLE_TYPE(Versal, XLNX_VERSAL) #define XLNX_VERSAL_NR_SDS 2 #define XLNX_VERSAL_NR_XRAM 4 #define XLNX_VERSAL_NR_IRQS 192 +#define XLNX_VERSAL_NR_CANFD 2 +#define XLNX_VERSAL_CANFD_REF_CLK (24 * 1000 * 1000) =20 struct Versal { /*< private >*/ @@ -73,6 +76,8 @@ struct Versal { CadenceGEMState gem[XLNX_VERSAL_NR_GEMS]; XlnxZDMA adma[XLNX_VERSAL_NR_ADMAS]; VersalUsb2 usb; + CanBusState *canbus[XLNX_VERSAL_NR_CANFD]; + XlnxVersalCANFDState canfd[XLNX_VERSAL_NR_CANFD]; } iou; =20 /* Real-time Processing Unit. */ @@ -133,6 +138,8 @@ struct Versal { #define VERSAL_CRL_IRQ 10 #define VERSAL_UART0_IRQ_0 18 #define VERSAL_UART1_IRQ_0 19 +#define VERSAL_CANFD0_IRQ_0 20 +#define VERSAL_CANFD1_IRQ_0 21 #define VERSAL_USB0_IRQ_0 22 #define VERSAL_GEM0_IRQ_0 56 #define VERSAL_GEM0_WAKE_IRQ_0 57 @@ -163,6 +170,11 @@ struct Versal { #define MM_UART1 0xff010000U #define MM_UART1_SIZE 0x10000 =20 +#define MM_CANFD0 0xff060000 +#define MM_CANFD0_SIZE 0x10000 +#define MM_CANFD1 0xff070000 +#define MM_CANFD1_SIZE 0x10000 + #define MM_GEM0 0xff0c0000U #define MM_GEM0_SIZE 0x10000 #define MM_GEM1 0xff0d0000U --=20 2.17.1 From nobody Fri May 17 22:23:27 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; arc=pass (i=1 dmarc=pass fromdomain=amd.com); dmarc=pass(p=quarantine dis=none) header.from=amd.com ARC-Seal: i=2; a=rsa-sha256; t=1670379290; cv=pass; d=zohomail.com; s=zohoarc; b=Ub9LrVMFp3NwxxnoEdDugsVIu4CYxioJwkCDyKjO+/moW/kl3g1rQ+sS3bsVK4WmdUcsIz8BP2D0cWWLMT9auCLLxnZrR3JuiS4W0pBRqwiR2kC8VElO3M2kHRo60aT839Kt6LhUuFr6kcbdjD+V4FbrzE6LhgAmGoQbXl1dAJY= ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1670379290; h=Content-Type:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=onrecn6/JEbUYP/rdo3UabBqv0FzJ/fpvuC1y3iqRiQ=; b=WOwfQarlORArvoj1ViqHx4MD0hlifRA/CVYHBWN4iElAdVEx6GqsYO6xHo21gebMSJ0AUm4pALNPV4DYHLV6V62N2s92T1ybeRGWfDYsHsVAQYwTOTGo38DhRv89S4F0KF98jyjDcZ3qfVO1diA/SFgvVZTVWxn10Dy9lqWwsTg= ARC-Authentication-Results: i=2; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; arc=pass (i=1 dmarc=pass fromdomain=amd.com); dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1670379289975915.7344683189597; Tue, 6 Dec 2022 18:14:49 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1p2jwY-0000Nm-KF; Tue, 06 Dec 2022 21:13:54 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1p2jwW-0000Mw-T5 for qemu-devel@nongnu.org; Tue, 06 Dec 2022 21:13:52 -0500 Received: from mail-mw2nam12on2062f.outbound.protection.outlook.com ([2a01:111:f400:fe5a::62f] helo=NAM12-MW2-obe.outbound.protection.outlook.com) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1p2jwU-00089E-3S for qemu-devel@nongnu.org; Tue, 06 Dec 2022 21:13:52 -0500 Received: from DS7PR03CA0191.namprd03.prod.outlook.com (2603:10b6:5:3b6::16) by MN2PR12MB4096.namprd12.prod.outlook.com (2603:10b6:208:1dc::13) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5880.14; Wed, 7 Dec 2022 02:13:46 +0000 Received: from DM6NAM11FT039.eop-nam11.prod.protection.outlook.com (2603:10b6:5:3b6:cafe::bb) by DS7PR03CA0191.outlook.office365.com (2603:10b6:5:3b6::16) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5880.14 via Frontend Transport; Wed, 7 Dec 2022 02:13:45 +0000 Received: from SATLEXMB04.amd.com (165.204.84.17) by DM6NAM11FT039.mail.protection.outlook.com (10.13.172.83) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.5901.14 via Frontend Transport; Wed, 7 Dec 2022 02:13:45 +0000 Received: from SATLEXMB03.amd.com (10.181.40.144) by SATLEXMB04.amd.com (10.181.40.145) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2375.34; Tue, 6 Dec 2022 20:13:43 -0600 Received: from xsjfnuv50.xilinx.com (10.180.168.240) by SATLEXMB03.amd.com (10.181.40.144) with Microsoft SMTP Server id 15.1.2375.34 via Frontend Transport; Tue, 6 Dec 2022 20:13:42 -0600 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=B7+sFBobzxpFfxGJZADplZssI807imYrQgpV/Vc4E4Y0P4VCiCLzL4p1aSobgI5rLYUMovg93yZJ5aRf9A6rZE0UuD4DOyGh9yv5DTPBm7KgVzOUHXLZXT+AzRVoM8TazkTN+V9k4+bMz4KXSlYT2n7cseuekHPPfjWr/kIbTRBRCnK4yjs3ILEvPvqLLf6NenJgwLcngDjPLykO0GMvHilG4J3oEs3qVSUxquRb8wzh2Dqw3f+OKDOUEPpG1zQP+ZfIyiHfEtwotHIBcyhxZae6/98R5fcUp0UIsIJ+o0tRTZsszgV/Wf0rbAOLJ3BVm4Bih2od2YVzwx4rYweMiA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=onrecn6/JEbUYP/rdo3UabBqv0FzJ/fpvuC1y3iqRiQ=; b=nsyzkrkCmKZlHm3N7XB9ENnXPWYqJGMkUZuAoQv8rPePeIUmnz5ESx2gULc3X+P71h5z8EooE8ITJggvdTBVjin/CSoTQDELDPnJNB8OAixiFOxdddmH8X5hfptbgciVeRfv55+Mg9yt8XoOXlOcOGSuF9cvqhGhIn8giGXhjh8A1gaV+C1NpWQvoevGHq/gKVLgHszCYlyv/cXP+9yxDdX0mXgzv+tgbnDTsZWuD4nmiaOUQQc56/mivHOvkt6M++v4MbSZv7ScpvAlmG+MYkbbNzLgYLVurUpGxA2ZKVr3FUzr5krdII0tbxeoxZbAR9cLjcKo/erpcbEkQ4NVSw== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 165.204.84.17) smtp.rcpttodomain=nongnu.org smtp.mailfrom=amd.com; dmarc=pass (p=quarantine sp=quarantine pct=100) action=none header.from=amd.com; dkim=none (message not signed); arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amd.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=onrecn6/JEbUYP/rdo3UabBqv0FzJ/fpvuC1y3iqRiQ=; b=e0qHCRoTy8izmEAJLQ4gDlXEJzdFHJOiFfpDbZhlS+fj/9Al870E2B7Oq/xra0RGJRPuy6DLi9Jl6YoZxyotIw4BvM57HiQ3D5y9+1o8CywFlgRSJsFplH9CG7H06WkaE5iaEbv33yr7KoNLUZsyJjVQVAWKMovCce+yVCXDXAs= X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 165.204.84.17) smtp.mailfrom=amd.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=amd.com; Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: Pass (protection.outlook.com: domain of amd.com designates 165.204.84.17 as permitted sender) receiver=protection.outlook.com; client-ip=165.204.84.17; helo=SATLEXMB04.amd.com; pr=C From: Vikram Garhwal To: CC: , , , Thomas Huth , Laurent Vivier , Paolo Bonzini Subject: [QEMU][PATCH v3 4/4] tests/qtest: Introduce tests for Xilinx VERSAL CANFD controller Date: Tue, 6 Dec 2022 18:13:22 -0800 Message-ID: <20221207021322.16165-6-vikram.garhwal@amd.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20221207021322.16165-1-vikram.garhwal@amd.com> References: <20221207021322.16165-1-vikram.garhwal@amd.com> MIME-Version: 1.0 X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: DM6NAM11FT039:EE_|MN2PR12MB4096:EE_ X-MS-Office365-Filtering-Correlation-Id: 1ed8c46b-b553-4110-b16e-08dad7f8aba6 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: 7zhlF4Ok63jsis2ZYbuTkBpjguvghef+yL3gDnuaP7+MPED+9253Ge752bMJE8kIOQ8ZYlxpxnMopzfOVxJCTLTiAqtBqv1DujlufUZIvYn/yHbDEI8wjm2ESuMB2AmFqzdba15+Aux9ykeJQNVSlbGtT0dld3U+xalFcrswisysBFc43OrYjEt5Z2CQWtNaRRmus057AX5iH4G4BvJhKm2tgz0XStMIX3QTIn7pKBesBKq2ERP25SaDMxAPBYVErRuG0lTu0MvIGBtg5Lj4vfOazIi5QlFF6ipsJ6r9zAZr2gi+iVkZBTDG7rFieQAhOEuDGeekvIqDqPiHcTeEBfnor9cP/cL+6t0i0Ir6e/WrIYPn9z1/T0KTz0Mu5+lxEQHiyi9t/ZVpE1dxdKkTDvMJBfwDgD/SIGO2u/I4ffES8a85ME9453TbJBO/dhaOCofU2r7rMI9dei7koB2ONh0omyGuQZnAFYS/Hz2k2hC70jHPhDYj3tVq2EwyD8f/qnoOK2LXAnN7p/tkSpzpdzThIXi3RkfXg5BKeECBlyoqv7VMVjxw1N2qeC+bfHO3FP81ZIhfhrsDcTGtHi9/F0KV5U9AAtv/m3OC6Hks96JXdXfJafYzoffS8sm+nDf1dkpo5arV2eTiFXYuwQFQmy2Zs6VJKsSF/NjH775EKluuvk53KxyGIUxoLitZ9xR4/2Bzr4vybeCrjEQjtJEltNv2MpQDi4FWyhXt361jVhw= X-Forefront-Antispam-Report: CIP:165.204.84.17; CTRY:US; LANG:en; SCL:1; SRV:; IPV:CAL; SFV:NSPM; H:SATLEXMB04.amd.com; PTR:InfoDomainNonexistent; CAT:NONE; SFS:(13230022)(4636009)(39860400002)(136003)(396003)(346002)(376002)(451199015)(46966006)(36840700001)(40470700004)(83380400001)(6916009)(54906003)(70206006)(6666004)(70586007)(478600001)(41300700001)(2616005)(316002)(82310400005)(40480700001)(40460700003)(36860700001)(36756003)(186003)(26005)(4326008)(1076003)(8676002)(2906002)(86362001)(356005)(81166007)(66899015)(47076005)(5660300002)(426003)(82740400003)(8936002)(30864003)(336012)(44832011)(36900700001); DIR:OUT; SFP:1101; X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 07 Dec 2022 02:13:45.7254 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 1ed8c46b-b553-4110-b16e-08dad7f8aba6 X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=3dd8961f-e488-4e60-8e11-a82d994e183d; Ip=[165.204.84.17]; Helo=[SATLEXMB04.amd.com] X-MS-Exchange-CrossTenant-AuthSource: DM6NAM11FT039.eop-nam11.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: MN2PR12MB4096 Received-SPF: softfail client-ip=2a01:111:f400:fe5a::62f; envelope-from=vikram.garhwal@amd.com; helo=NAM12-MW2-obe.outbound.protection.outlook.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @amd.com) X-ZM-MESSAGEID: 1670379291217100001 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The QTests perform three tests on the Xilinx VERSAL CANFD controller: Tests the CANFD controllers in loopback. Tests the CANFD controllers in normal mode with CAN frame. Tests the CANFD controllers in normal mode with CANFD frame. Signed-off-by: Vikram Garhwal Acked-by: Thomas Huth Reviewed-by: Francisco Iglesias Reviewed-by: Peter Maydell --- tests/qtest/meson.build | 1 + tests/qtest/xlnx-canfd-test.c | 422 ++++++++++++++++++++++++++++++++++ 2 files changed, 423 insertions(+) create mode 100644 tests/qtest/xlnx-canfd-test.c diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build index c07a5b1a5f..9486ebee24 100644 --- a/tests/qtest/meson.build +++ b/tests/qtest/meson.build @@ -213,6 +213,7 @@ qtests_aarch64 =3D \ (config_all_devices.has_key('CONFIG_TPM_TIS_SYSBUS') ? ['tpm-tis-device-= test'] : []) + \ (config_all_devices.has_key('CONFIG_TPM_TIS_SYSBUS') ? ['tpm-tis-device-= swtpm-test'] : []) + \ (config_all_devices.has_key('CONFIG_XLNX_ZYNQMP_ARM') ? ['xlnx-can-test'= , 'fuzz-xlnx-dp-test'] : []) + \ + (config_all_devices.has_key('CONFIG_XLNX_VERSAL') ? ['xlnx-canfd-test'] = : []) + \ ['arm-cpu-features', 'numa-test', 'boot-serial-test', diff --git a/tests/qtest/xlnx-canfd-test.c b/tests/qtest/xlnx-canfd-test.c new file mode 100644 index 0000000000..4ccc0267d4 --- /dev/null +++ b/tests/qtest/xlnx-canfd-test.c @@ -0,0 +1,422 @@ +/* SPDX-License-Identifier: MIT + * + * QTests for the Xilinx Versal CANFD controller. + * + * Copyright (c) 2022 AMD Inc. + * + * Written-by: Vikram Garhwal + * + * Permission is hereby granted, free of charge, to any person obtaining a= copy + * of this software and associated documentation files (the "Software"), t= o deal + * in the Software without restriction, including without limitation the r= ights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or se= ll + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included= in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS= OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OT= HER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING= FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS = IN + * THE SOFTWARE. + */ + +#include "qemu/osdep.h" +#include "libqtest.h" + +/* Base address. */ +#define CANFD0_BASE_ADDR 0xff060000 +#define CANFD1_BASE_ADDR 0xff070000 + +/* Register addresses. */ +#define R_SRR_OFFSET 0x00 +#define R_MSR_OFFSET 0x04 +#define R_FILTER_CONTROL_REGISTER 0xe0 +#define R_SR_OFFSET 0x18 +#define R_ISR_OFFSET 0x1c +#define R_IER_OFFSET 0x20 +#define R_ICR_OFFSET 0x24 +#define R_TX_READY_REQ_REGISTER 0x90 +#define RX_FIFO_STATUS_REGISTER 0xe8 +#define R_TXID_OFFSET 0x100 +#define R_TXDLC_OFFSET 0x104 +#define R_TXDATA1_OFFSET 0x108 +#define R_TXDATA2_OFFSET 0x10c +#define R_AFMR_REGISTER0 0xa00 +#define R_AFIR_REGISTER0 0xa04 +#define R_RX0_ID_OFFSET 0x2100 +#define R_RX0_DLC_OFFSET 0x2104 +#define R_RX0_DATA1_OFFSET 0x2108 +#define R_RX0_DATA2_OFFSET 0x210c + +/* CANFD modes. */ +#define SRR_CONFIG_MODE 0x00 +#define MSR_NORMAL_MODE 0x00 +#define MSR_LOOPBACK_MODE (1 << 1) +#define ENABLE_CANFD (1 << 1) + +/* CANFD status. */ +#define STATUS_CONFIG_MODE (1 << 0) +#define STATUS_NORMAL_MODE (1 << 3) +#define STATUS_LOOPBACK_MODE (1 << 1) +#define ISR_TXOK (1 << 1) +#define ISR_RXOK (1 << 4) + +#define ENABLE_ALL_FILTERS 0xffffffff +#define ENABLE_ALL_INTERRUPTS 0xffffffff + +/* We are sending one canfd message. */ +#define TX_READY_REG_VAL 0x1 + +#define FIRST_RX_STORE_INDEX 0x1 +#define STATUS_REG_MASK 0xf +#define DLC_FD_BIT_SHIFT 0x1b +#define DLC_FD_BIT_MASK 0xf8000000 +#define FIFO_STATUS_READ_INDEX_MASK 0x3f +#define FIFO_STATUS_FILL_LEVEL_MASK 0x7f00 +#define FILL_LEVEL_SHIFT 0x8 + +/* CANFD frame size ID, DLC and 16 DATA word. */ +#define CANFD_FRAME_SIZE 18 +/* CAN frame size ID, DLC and 2 DATA word. */ +#define CAN_FRAME_SIZE 4 + +/* Set the filters for CANFD controller. */ +static void enable_filters(QTestState *qts) +{ + const uint32_t arr_afmr[32] =3D { 0xb423deaa, 0xa2a40bdc, 0x1b64f486, + 0x95c0d4ee, 0xe0c44528, 0x4b407904, + 0xd2673f46, 0x9fc638d6, 0x8844f3d8, + 0xa607d1e8, 0x67871bf4, 0xc2557dc, + 0x9ea5b53e, 0x3643c0cc, 0x5a05ea8e, + 0x83a46d84, 0x4a25c2b8, 0x93a66008, + 0x2e467470, 0xedc66118, 0x9086f9f2, + 0xfa23dd36, 0xb6654b90, 0xb221b8ca, + 0x3467d1e2, 0xa3a55542, 0x5b26a012, + 0x2281ea7e, 0xcea0ece8, 0xdc61e588, + 0x2e5676a, 0x16821320 }; + + const uint32_t arr_afir[32] =3D { 0xa833dfa1, 0x255a477e, 0x3a4bb1c5, + 0x8f560a6c, 0x27f38903, 0x2fecec4d, + 0xa014c66d, 0xec289b8, 0x7e52dead, + 0x82e94f3c, 0xcf3e3c5c, 0x66059871, + 0x3f213df4, 0x25ac3959, 0xa12e9bef, + 0xa3ad3af, 0xbafd7fe, 0xb3cb40fd, + 0x5d9caa81, 0x2ed61902, 0x7cd64a0, + 0x4b1fa538, 0x9b5ced8c, 0x150de059, + 0xd2794227, 0x635e820a, 0xbb6b02cf, + 0xbb58176, 0x570025bb, 0xa78d9658, + 0x49d735df, 0xe5399d2f }; + + /* Passing the respective array values to all the AFMR and AFIR pairs.= */ + for (int i =3D 0; i < 32; i++) { + /* For CANFD0. */ + qtest_writel(qts, CANFD0_BASE_ADDR + R_AFMR_REGISTER0 + 8 * i, + arr_afmr[i]); + qtest_writel(qts, CANFD0_BASE_ADDR + R_AFIR_REGISTER0 + 8 * i, + arr_afir[i]); + + /* For CANFD1. */ + qtest_writel(qts, CANFD1_BASE_ADDR + R_AFMR_REGISTER0 + 8 * i, + arr_afmr[i]); + qtest_writel(qts, CANFD1_BASE_ADDR + R_AFIR_REGISTER0 + 8 * i, + arr_afir[i]); + } + + /* Enable all the pairs from AFR register. */ + qtest_writel(qts, CANFD0_BASE_ADDR + R_FILTER_CONTROL_REGISTER, + ENABLE_ALL_FILTERS); + qtest_writel(qts, CANFD1_BASE_ADDR + R_FILTER_CONTROL_REGISTER, + ENABLE_ALL_FILTERS); +} + +static void configure_canfd(QTestState *qts, uint8_t mode) +{ + uint32_t status =3D 0; + + /* Put CANFD0 and CANFD1 in config mode. */ + qtest_writel(qts, CANFD0_BASE_ADDR + R_SRR_OFFSET, SRR_CONFIG_MODE); + qtest_writel(qts, CANFD1_BASE_ADDR + R_SRR_OFFSET, SRR_CONFIG_MODE); + + /* Write mode of operation in Mode select register. */ + qtest_writel(qts, CANFD0_BASE_ADDR + R_MSR_OFFSET, mode); + qtest_writel(qts, CANFD1_BASE_ADDR + R_MSR_OFFSET, mode); + + enable_filters(qts); + + /* Check here if CANFD0 and CANFD1 are in config mode. */ + status =3D qtest_readl(qts, CANFD0_BASE_ADDR + R_SR_OFFSET); + status =3D status & STATUS_REG_MASK; + g_assert_cmpint(status, =3D=3D, STATUS_CONFIG_MODE); + + status =3D qtest_readl(qts, CANFD1_BASE_ADDR + R_SR_OFFSET); + status =3D status & STATUS_REG_MASK; + g_assert_cmpint(status, =3D=3D, STATUS_CONFIG_MODE); + + qtest_writel(qts, CANFD1_BASE_ADDR + R_IER_OFFSET, ENABLE_ALL_INTERRUP= TS); + qtest_writel(qts, CANFD1_BASE_ADDR + R_IER_OFFSET, ENABLE_ALL_INTERRUP= TS); + + qtest_writel(qts, CANFD0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CANFD); + qtest_writel(qts, CANFD1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CANFD); +} + +static void generate_random_data(uint32_t *buf_tx, bool is_canfd_frame) +{ + /* Generate random TX data for CANFD frame. */ + if (is_canfd_frame) { + for (int i =3D 0; i < CANFD_FRAME_SIZE - 2; i++) { + buf_tx[2 + i] =3D rand(); + } + } else { + /* Generate random TX data for CAN frame. */ + for (int i =3D 0; i < CAN_FRAME_SIZE - 2; i++) { + buf_tx[2 + i] =3D rand(); + } + } +} + +static void read_data(QTestState *qts, uint64_t can_base_addr, uint32_t *b= uf_rx) +{ + uint32_t int_status; + uint32_t fifo_status_reg_value; + /* At which RX FIFO the received data is stored. */ + uint8_t store_ind =3D 0; + bool is_canfd_frame =3D false; + + /* Read the interrupt on CANFD rx. */ + int_status =3D qtest_readl(qts, can_base_addr + R_ISR_OFFSET) & ISR_RX= OK; + + g_assert_cmpint(int_status, =3D=3D, ISR_RXOK); + + /* Find the fill level and read index. */ + fifo_status_reg_value =3D qtest_readl(qts, can_base_addr + + RX_FIFO_STATUS_REGISTER); + + store_ind =3D (fifo_status_reg_value & FIFO_STATUS_READ_INDEX_MASK) + + ((fifo_status_reg_value & FIFO_STATUS_FILL_LEVEL_MASK) >> + FILL_LEVEL_SHIFT); + + g_assert_cmpint(store_ind, =3D=3D, FIRST_RX_STORE_INDEX); + + /* Read the RX register data for CANFD. */ + buf_rx[0] =3D qtest_readl(qts, can_base_addr + R_RX0_ID_OFFSET); + buf_rx[1] =3D qtest_readl(qts, can_base_addr + R_RX0_DLC_OFFSET); + + is_canfd_frame =3D (buf_rx[1] >> DLC_FD_BIT_SHIFT) & 1; + + if (is_canfd_frame) { + for (int i =3D 0; i < CANFD_FRAME_SIZE - 2; i++) { + buf_rx[i + 2] =3D qtest_readl(qts, + can_base_addr + R_RX0_DATA1_OFFSET + 4= * i); + } + } else { + buf_rx[2] =3D qtest_readl(qts, can_base_addr + R_RX0_DATA1_OFFSET); + buf_rx[3] =3D qtest_readl(qts, can_base_addr + R_RX0_DATA2_OFFSET); + } + + /* Clear the RX interrupt. */ + qtest_writel(qts, CANFD1_BASE_ADDR + R_ICR_OFFSET, ISR_RXOK); +} + +static void write_data(QTestState *qts, uint64_t can_base_addr, + const uint32_t *buf_tx, bool is_canfd_frame) +{ + /* Write the TX register data for CANFD. */ + qtest_writel(qts, can_base_addr + R_TXID_OFFSET, buf_tx[0]); + qtest_writel(qts, can_base_addr + R_TXDLC_OFFSET, buf_tx[1]); + + if (is_canfd_frame) { + for (int i =3D 0; i < CANFD_FRAME_SIZE - 2; i++) { + qtest_writel(qts, can_base_addr + R_TXDATA1_OFFSET + 4 * i, + buf_tx[2 + i]); + } + } else { + qtest_writel(qts, can_base_addr + R_TXDATA1_OFFSET, buf_tx[2]); + qtest_writel(qts, can_base_addr + R_TXDATA2_OFFSET, buf_tx[3]); + } +} + +static void send_data(QTestState *qts, uint64_t can_base_addr) +{ + uint32_t int_status; + + qtest_writel(qts, can_base_addr + R_TX_READY_REQ_REGISTER, + TX_READY_REG_VAL); + + /* Read the interrupt on CANFD for tx. */ + int_status =3D qtest_readl(qts, can_base_addr + R_ISR_OFFSET) & ISR_TX= OK; + + g_assert_cmpint(int_status, =3D=3D, ISR_TXOK); + + /* Clear the interrupt for tx. */ + qtest_writel(qts, CANFD0_BASE_ADDR + R_ICR_OFFSET, ISR_TXOK); +} + +static void match_rx_tx_data(const uint32_t *buf_tx, const uint32_t *buf_r= x, + bool is_canfd_frame) +{ + uint16_t size =3D 0; + uint8_t len =3D CAN_FRAME_SIZE; + + if (is_canfd_frame) { + len =3D CANFD_FRAME_SIZE; + } + + while (size < len) { + if (R_RX0_ID_OFFSET + 4 * size =3D=3D R_RX0_DLC_OFFSET) { + g_assert_cmpint((buf_rx[size] & DLC_FD_BIT_MASK), =3D=3D, + (buf_tx[size] & DLC_FD_BIT_MASK)); + } else { + if (!is_canfd_frame && size =3D=3D 4) { + break; + } + + g_assert_cmpint(buf_rx[size], =3D=3D, buf_tx[size]); + } + + size++; + } +} +/* + * Xilinx CANFD supports both CAN and CANFD frames. This test will be + * transferring CAN frame i.e. 8 bytes of data from CANFD0 and CANFD1 thro= ugh + * canbus. CANFD0 initiate the data transfer to can-bus, CANFD1 receives t= he + * data. Test compares the can frame data sent from CANFD0 and received on + * CANFD1. + */ +static void test_can_data_transfer(void) +{ + uint32_t buf_tx[CAN_FRAME_SIZE] =3D { 0x5a5bb9a4, 0x80000000, + 0x12345678, 0x87654321 }; + uint32_t buf_rx[CAN_FRAME_SIZE] =3D { 0x00, 0x00, 0x00, 0x00 }; + uint32_t status =3D 0; + + generate_random_data(buf_tx, false); + + QTestState *qts =3D qtest_init("-machine xlnx-versal-virt" + " -object can-bus,id=3Dcanbus" + " -machine canbus0=3Dcanbus" + " -machine canbus1=3Dcanbus" + ); + + configure_canfd(qts, MSR_NORMAL_MODE); + + /* Check if CANFD0 and CANFD1 are in Normal mode. */ + status =3D qtest_readl(qts, CANFD0_BASE_ADDR + R_SR_OFFSET); + status =3D status & STATUS_REG_MASK; + g_assert_cmpint(status, =3D=3D, STATUS_NORMAL_MODE); + + status =3D qtest_readl(qts, CANFD1_BASE_ADDR + R_SR_OFFSET); + status =3D status & STATUS_REG_MASK; + g_assert_cmpint(status, =3D=3D, STATUS_NORMAL_MODE); + + write_data(qts, CANFD0_BASE_ADDR, buf_tx, false); + + send_data(qts, CANFD0_BASE_ADDR); + read_data(qts, CANFD1_BASE_ADDR, buf_rx); + match_rx_tx_data(buf_tx, buf_rx, false); + + qtest_quit(qts); +} + +/* + * This test will be transferring CANFD frame i.e. 64 bytes of data from C= ANFD0 + * and CANFD1 through canbus. CANFD0 initiate the data transfer to can-bus, + * CANFD1 receives the data. Test compares the CANFD frame data sent from = CANFD0 + * with received on CANFD1. + */ +static void test_canfd_data_transfer(void) +{ + uint32_t buf_tx[CANFD_FRAME_SIZE] =3D { 0x5a5bb9a4, 0xf8000000 }; + uint32_t buf_rx[CANFD_FRAME_SIZE] =3D { 0x00, 0x00, 0x00, 0x00 }; + uint32_t status =3D 0; + + generate_random_data(buf_tx, true); + + QTestState *qts =3D qtest_init("-machine xlnx-versal-virt" + " -object can-bus,id=3Dcanbus" + " -machine canbus0=3Dcanbus" + " -machine canbus1=3Dcanbus" + ); + + configure_canfd(qts, MSR_NORMAL_MODE); + + /* Check if CANFD0 and CANFD1 are in Normal mode. */ + status =3D qtest_readl(qts, CANFD0_BASE_ADDR + R_SR_OFFSET); + status =3D status & STATUS_REG_MASK; + g_assert_cmpint(status, =3D=3D, STATUS_NORMAL_MODE); + + status =3D qtest_readl(qts, CANFD1_BASE_ADDR + R_SR_OFFSET); + status =3D status & STATUS_REG_MASK; + g_assert_cmpint(status, =3D=3D, STATUS_NORMAL_MODE); + + write_data(qts, CANFD0_BASE_ADDR, buf_tx, true); + + send_data(qts, CANFD0_BASE_ADDR); + read_data(qts, CANFD1_BASE_ADDR, buf_rx); + match_rx_tx_data(buf_tx, buf_rx, true); + + qtest_quit(qts); +} + +/* + * This test is performing loopback mode on CANFD0 and CANFD1. Data sent f= rom + * TX of each CANFD0 and CANFD1 are compared with RX register data for + * respective CANFD Controller. + */ +static void test_can_loopback(void) +{ + uint32_t buf_tx[CANFD_FRAME_SIZE] =3D { 0x5a5bb9a4, 0xf8000000 }; + uint32_t buf_rx[CANFD_FRAME_SIZE] =3D { 0x00, 0x00, 0x00, 0x00 }; + uint32_t status =3D 0; + + generate_random_data(buf_tx, true); + + QTestState *qts =3D qtest_init("-machine xlnx-versal-virt" + " -object can-bus,id=3Dcanbus" + " -machine canbus0=3Dcanbus" + " -machine canbus1=3Dcanbus" + ); + + configure_canfd(qts, MSR_LOOPBACK_MODE); + + /* Check if CANFD0 and CANFD1 are set in correct loopback mode. */ + status =3D qtest_readl(qts, CANFD0_BASE_ADDR + R_SR_OFFSET); + status =3D status & STATUS_REG_MASK; + g_assert_cmpint(status, =3D=3D, STATUS_LOOPBACK_MODE); + + status =3D qtest_readl(qts, CANFD1_BASE_ADDR + R_SR_OFFSET); + status =3D status & STATUS_REG_MASK; + g_assert_cmpint(status, =3D=3D, STATUS_LOOPBACK_MODE); + + write_data(qts, CANFD0_BASE_ADDR, buf_tx, true); + + send_data(qts, CANFD0_BASE_ADDR); + read_data(qts, CANFD0_BASE_ADDR, buf_rx); + match_rx_tx_data(buf_tx, buf_rx, true); + + generate_random_data(buf_tx, true); + + write_data(qts, CANFD1_BASE_ADDR, buf_tx, true); + + send_data(qts, CANFD1_BASE_ADDR); + read_data(qts, CANFD1_BASE_ADDR, buf_rx); + match_rx_tx_data(buf_tx, buf_rx, true); + + qtest_quit(qts); +} + +int main(int argc, char **argv) +{ + g_test_init(&argc, &argv, NULL); + + qtest_add_func("/net/canfd/can_data_transfer", test_can_data_transfer); + qtest_add_func("/net/canfd/canfd_data_transfer", test_canfd_data_trans= fer); + qtest_add_func("/net/canfd/can_loopback", test_can_loopback); + + return g_test_run(); +} --=20 2.17.1