From nobody Fri May 3 14:37:10 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=1dmarc=pass fromdomain=xilinx.com) ARC-Seal: i=2; a=rsa-sha256; t=1605729248; cv=pass; d=zohomail.com; s=zohoarc; b=gpwCzbeAVIoPvY7x0UciCkNN5Eg0iWneS/kvYgqW2eNATb5OmbHJy+zXcLmVdms4MkmvdbVrZgaZymHCQLqw48aae7KaxQyFWF+UY5Mvex8TDFUCqnLrh+R+Tu/CXO2hXfx57JGb34L8iXIQnPrIuBp+rGsxijQxxQSXbXqtYfY= ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1605729248; 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=Uq9Y/6GYSHRGXA6S/QSGpoPssE3coaxwHZTp8TA5eXw=; b=hWB733HYxEEFww3IOQzKcIsHwg0cmWC03Whjm8B7qa78dD+DVZOe72ad35i9m2otzvbKJg+C/8YEO2yQDmjSmZe6M9YJ3bV+2HIHutgDkUZ4xOe7y/IydluoGeeEExx07pPn93Ca7ko6DH14SI2Ecy7Lq2t299VHgdoJOhmYqt4= 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=1dmarc=pass fromdomain=xilinx.com) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1605729248858687.1744701840804; Wed, 18 Nov 2020 11:54:08 -0800 (PST) Received: from localhost ([::1]:58064 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kfTWp-0000B4-Gy for importer@patchew.org; Wed, 18 Nov 2020 14:54:07 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:48942) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kfTS5-0004U0-VG; Wed, 18 Nov 2020 14:49:17 -0500 Received: from mail-eopbgr750075.outbound.protection.outlook.com ([40.107.75.75]:61410 helo=NAM02-BL2-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 1kfTRy-0005YY-Vk; Wed, 18 Nov 2020 14:49:13 -0500 Received: from BL1PR13CA0205.namprd13.prod.outlook.com (2603:10b6:208:2be::30) by MW4PR02MB7105.namprd02.prod.outlook.com (2603:10b6:303:70::19) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3564.25; Wed, 18 Nov 2020 19:49:02 +0000 Received: from BL2NAM02FT056.eop-nam02.prod.protection.outlook.com (2603:10b6:208:2be:cafe::72) by BL1PR13CA0205.outlook.office365.com (2603:10b6:208:2be::30) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3564.21 via Frontend Transport; Wed, 18 Nov 2020 19:49:01 +0000 Received: from xsj-pvapexch01.xlnx.xilinx.com (149.199.62.198) by BL2NAM02FT056.mail.protection.outlook.com (10.152.77.221) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.3564.22 via Frontend Transport; Wed, 18 Nov 2020 19:49:01 +0000 Received: from xsj-pvapexch02.xlnx.xilinx.com (172.19.86.41) by xsj-pvapexch01.xlnx.xilinx.com (172.19.86.40) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.1913.5; Wed, 18 Nov 2020 11:48:59 -0800 Received: from smtp.xilinx.com (172.19.127.96) by xsj-pvapexch02.xlnx.xilinx.com (172.19.86.41) with Microsoft SMTP Server id 15.1.1913.5 via Frontend Transport; Wed, 18 Nov 2020 11:48:59 -0800 Received: from [172.19.2.115] (port=52002 helo=xsjfnuv50.xilinx.com) by smtp.xilinx.com with esmtp (Exim 4.90) (envelope-from ) id 1kfTRr-0003iK-Tb; Wed, 18 Nov 2020 11:48:59 -0800 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=fWtJjO/Ucv/gDGdaLVxNlSi4bnJsvumHbzmW6CMeNoM99aO2v2UHw3Qz3cClDR3HEsjuJCIyqGEoeXw4Kc/j1pDSPCBVliL0EOy0rR5Mxcwp/G4jhwKbY0w5Q4gXSGfziVgQC2nuNrS+Ywivc4Mx1+KoOY2F+rRSQizg5S+7WJbyngUVKSXzYgr88lM5oNxcxFTDxR7mzuZ6qXgXB0rHXkY2oun0c06GyAiiG+SocqLmvXdsq6EhDb8XnJXYzqSfSzbXhqpiMRpkSo0/5hc3X4B38N93JX+rioxFjurh5c+0TGitodtP7Vvpc+kdBk+nXC/r/FqlhAZZWXc3gPhI0g== 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-SenderADCheck; bh=Uq9Y/6GYSHRGXA6S/QSGpoPssE3coaxwHZTp8TA5eXw=; b=lNs50Hmp68u12EpOUuTIpQdx8ORyvE2BijjvcbhRGqkq8q9GOus1KEYitFZnavRmO7D70/5Wd4hV1pmb28iXkJjzvfIxozUkXqniqttFNl6NpgxuSITgz4+M4OUTVK8/WxFaWxJ9Ti27PCx7JQJ7vgHsPm3vXZnK78rnX8iX+pFwXs497TLpgwA5MNbn01ZF/t+ceMpQ8gIsyXxIR0OtJndo3cdmlwRPYaVax0FqJuKYLYctxIScNRmRqqLYjugzQK665aGkmeHL/ytppqaE9IoctVdjyn/Zb0YzrMoIS4Y5zKQy0brk1bg36/j7MKZz1C8FYOaY6ksGZU5pYQIjQQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 149.199.62.198) smtp.rcpttodomain=nongnu.org smtp.mailfrom=xilinx.com; dmarc=bestguesspass action=none header.from=xilinx.com; dkim=none (message not signed); arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=xilinx.onmicrosoft.com; s=selector2-xilinx-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=Uq9Y/6GYSHRGXA6S/QSGpoPssE3coaxwHZTp8TA5eXw=; b=XUC5BV2oWxtzVk3TtlaibYWvXIg2fqjmsd+IRP0uEFkGB6muKnMOyizlkT5Z/+sF3HC2i1aJnB8FGk8c5/aaXVgf3T9rZ7DrL/R2BJKgv32Em0KLcDNFKjsiq1+shJvZVjuMFPvuwoBszgyMZgLhIFBo8TdS+iUw2nAK8LBfIEE= X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 149.199.62.198) smtp.mailfrom=xilinx.com; nongnu.org; dkim=none (message not signed) header.d=none;nongnu.org; dmarc=bestguesspass action=none header.from=xilinx.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 xilinx.com designates 149.199.62.198 as permitted sender) receiver=protection.outlook.com; client-ip=149.199.62.198; helo=xsj-pvapexch01.xlnx.xilinx.com; From: Vikram Garhwal To: Subject: [PATCH v12 1/4] hw/net/can: Introduce Xilinx ZynqMP CAN controller Date: Wed, 18 Nov 2020 11:48:43 -0800 Message-ID: <1605728926-352690-2-git-send-email-fnu.vikram@xilinx.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1605728926-352690-1-git-send-email-fnu.vikram@xilinx.com> References: <1605728926-352690-1-git-send-email-fnu.vikram@xilinx.com> MIME-Version: 1.0 X-EOPAttributedMessage: 0 X-MS-Office365-Filtering-HT: Tenant X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 163d9875-a724-456f-a12a-08d88bfaff82 X-MS-TrafficTypeDiagnostic: MW4PR02MB7105: X-Microsoft-Antispam-PRVS: X-Auto-Response-Suppress: DR, RN, NRN, OOF, AutoReply X-MS-Oob-TLC-OOBClassifiers: OLM:3044; X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: SOnKDyYnlVJOVrzI9PCkRkOTkTyEU5RGODv1W6i5/PstsqwOTnZ8zYbdWS2cYavxk58G6O+dWtfI4pwEm8qnFuY9jcxVWXrglDVzJagTzpgMbjlQhT0B/DzaCHS9M9yLJ3baxGwLC6oWNuV0p5z9smhdH35qJZLJDJ7eCiSB86nSSp6vBgrzly/vFG/gwy5jPF5/idd6Do1d0SjjCZAUh5l7/XZtVo2/Rb1wFl4HOEEYo0RlhS5pT7SKkwzLAglXUaoG9ey9WD8f5Edsu4JfkbC/XnGhdzN5YnXBxFnBkG2Apd1e47NP0Nac7WVPokLAUMEfaGWVbv6wfd7M1WSGDR9r0BpJas9q4qK22Of57Q0IwTNwkvw8I/dPnteGpvyu0CNxqgHPZJQwReFWQ82qiFX7azjDQk5JJHzG9SepDWruwmU4GpPQg96bt+nCmfyNiRQ0LFEOsWL8lpSw75phcAEfTsrQ6J03DTKZLZJ5jnP9WTEO40Zoo4ybc4B6dNBx+A7E8G0Iqk5fpjETvqETeg== X-Forefront-Antispam-Report: CIP:149.199.62.198; CTRY:US; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:xsj-pvapexch01.xlnx.xilinx.com; PTR:unknown-62-198.xilinx.com; CAT:NONE; SFS:(4636009)(39860400002)(346002)(136003)(396003)(376002)(46966005)(26005)(356005)(47076004)(186003)(36906005)(70206006)(7636003)(83380400001)(426003)(336012)(2616005)(9786002)(4326008)(54906003)(30864003)(316002)(82310400003)(6666004)(6916009)(966005)(5660300002)(8676002)(478600001)(82740400003)(7696005)(70586007)(36756003)(8936002)(2906002)(102446001)(559001)(579004)(6606295002); DIR:OUT; SFP:1101; X-OriginatorOrg: xilinx.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 18 Nov 2020 19:49:01.6081 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 163d9875-a724-456f-a12a-08d88bfaff82 X-MS-Exchange-CrossTenant-Id: 657af505-d5df-48d0-8300-c31994686c5c X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=657af505-d5df-48d0-8300-c31994686c5c; Ip=[149.199.62.198]; Helo=[xsj-pvapexch01.xlnx.xilinx.com] X-MS-Exchange-CrossTenant-AuthSource: BL2NAM02FT056.eop-nam02.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: MW4PR02MB7105 Received-SPF: pass client-ip=40.107.75.75; envelope-from=fnuv@xilinx.com; helo=NAM02-BL2-obe.outbound.protection.outlook.com X-detected-operating-system: by eggs.gnu.org: First seen = 2020/11/18 14:49:04 X-ACL-Warn: Detected OS = Windows NT kernel [generic] [fuzzy] X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.001, 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.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, Vikram Garhwal , Jason Wang , Alistair Francis , francisco.iglesias@xilinx.com, "open list:Xilinx ZynqMP and..." , "Edgar E. Iglesias" , Pavel Pisa Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: pass (identity @xilinx.onmicrosoft.com) Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The Xilinx ZynqMP CAN controller is developed based on SocketCAN, QEMU CAN = bus implementation. Bus connection and socketCAN connection for each CAN module can be set through command lines. Example for using single CAN: -object can-bus,id=3Dcanbus0 \ -machine xlnx-zcu102.canbus0=3Dcanbus0 \ -object can-host-socketcan,id=3Dsocketcan0,if=3Dvcan0,canbus=3Dcanbus0 Example for connecting both CAN to same virtual CAN on host machine: -object can-bus,id=3Dcanbus0 -object can-bus,id=3Dcanbus1 \ -machine xlnx-zcu102.canbus0=3Dcanbus0 \ -machine xlnx-zcu102.canbus1=3Dcanbus1 \ -object can-host-socketcan,id=3Dsocketcan0,if=3Dvcan0,canbus=3Dcanbus0 \ -object can-host-socketcan,id=3Dsocketcan1,if=3Dvcan0,canbus=3Dcanbus1 To create virtual CAN on the host machine, please check the QEMU CAN docs: https://github.com/qemu/qemu/blob/master/docs/can.txt Signed-off-by: Vikram Garhwal --- meson.build | 1 + hw/net/can/trace.h | 1 + include/hw/net/xlnx-zynqmp-can.h | 78 +++ hw/net/can/xlnx-zynqmp-can.c | 1161 ++++++++++++++++++++++++++++++++++= ++++ hw/Kconfig | 1 + hw/net/can/meson.build | 1 + hw/net/can/trace-events | 9 + 7 files changed, 1252 insertions(+) create mode 100644 hw/net/can/trace.h create mode 100644 include/hw/net/xlnx-zynqmp-can.h create mode 100644 hw/net/can/xlnx-zynqmp-can.c create mode 100644 hw/net/can/trace-events diff --git a/meson.build b/meson.build index 39ac5cf..7eefedc 100644 --- a/meson.build +++ b/meson.build @@ -1408,6 +1408,7 @@ if have_system 'hw/misc', 'hw/misc/macio', 'hw/net', + 'hw/net/can', 'hw/nvram', 'hw/pci', 'hw/pci-host', diff --git a/hw/net/can/trace.h b/hw/net/can/trace.h new file mode 100644 index 0000000..d391c64 --- /dev/null +++ b/hw/net/can/trace.h @@ -0,0 +1 @@ +#include "trace/trace-hw_net_can.h" diff --git a/include/hw/net/xlnx-zynqmp-can.h b/include/hw/net/xlnx-zynqmp-= can.h new file mode 100644 index 0000000..eb15587 --- /dev/null +++ b/include/hw/net/xlnx-zynqmp-can.h @@ -0,0 +1,78 @@ +/* + * QEMU model of the Xilinx ZynqMP CAN controller. + * + * Copyright (c) 2020 Xilinx Inc. + * + * Written-by: Vikram Garhwal + * + * Based on QEMU CAN Device emulation implemented by Jin Yang, Deniz Eren = 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 XLNX_ZYNQMP_CAN_H +#define XLNX_ZYNQMP_CAN_H + +#include "hw/register.h" +#include "net/can_emu.h" +#include "net/can_host.h" +#include "qemu/fifo32.h" +#include "hw/ptimer.h" +#include "hw/qdev-clock.h" + +#define TYPE_XLNX_ZYNQMP_CAN "xlnx.zynqmp-can" + +#define XLNX_ZYNQMP_CAN(obj) \ + OBJECT_CHECK(XlnxZynqMPCANState, (obj), TYPE_XLNX_ZYNQMP_CAN) + +#define MAX_CAN_CTRLS 2 +#define XLNX_ZYNQMP_CAN_R_MAX (0x84 / 4) +#define MAILBOX_CAPACITY 64 +#define CAN_TIMER_MAX 0XFFFFUL +#define CAN_DEFAULT_CLOCK (24 * 1000 * 1000) + +/* Each CAN_FRAME will have 4 * 32bit size. */ +#define CAN_FRAME_SIZE 4 +#define RXFIFO_SIZE (MAILBOX_CAPACITY * CAN_FRAME_SIZE) + +typedef struct XlnxZynqMPCANState { + SysBusDevice parent_obj; + MemoryRegion iomem; + + qemu_irq irq; + + CanBusClientState bus_client; + CanBusState *canbus; + + struct { + uint32_t ext_clk_freq; + } cfg; + + RegisterInfo reg_info[XLNX_ZYNQMP_CAN_R_MAX]; + uint32_t regs[XLNX_ZYNQMP_CAN_R_MAX]; + + Fifo32 rx_fifo; + Fifo32 tx_fifo; + Fifo32 txhpb_fifo; + + ptimer_state *can_timer; +} XlnxZynqMPCANState; + +#endif diff --git a/hw/net/can/xlnx-zynqmp-can.c b/hw/net/can/xlnx-zynqmp-can.c new file mode 100644 index 0000000..affa21a --- /dev/null +++ b/hw/net/can/xlnx-zynqmp-can.c @@ -0,0 +1,1161 @@ +/* + * QEMU model of the Xilinx ZynqMP CAN controller. + * This implementation is based on the following datasheet: + * https://www.xilinx.com/support/documentation/user_guides/ug1085-zynq-ul= trascale-trm.pdf + * + * Copyright (c) 2020 Xilinx Inc. + * + * Written-by: Vikram Garhwal + * + * Based on QEMU CAN Device emulation implemented by Jin Yang, Deniz Eren = 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/register.h" +#include "hw/irq.h" +#include "qapi/error.h" +#include "qemu/bitops.h" +#include "qemu/log.h" +#include "qemu/cutils.h" +#include "sysemu/sysemu.h" +#include "migration/vmstate.h" +#include "hw/qdev-properties.h" +#include "net/can_emu.h" +#include "net/can_host.h" +#include "qemu/event_notifier.h" +#include "qom/object_interfaces.h" +#include "hw/net/xlnx-zynqmp-can.h" +#include "trace.h" + +#ifndef XLNX_ZYNQMP_CAN_ERR_DEBUG +#define XLNX_ZYNQMP_CAN_ERR_DEBUG 0 +#endif + +#define MAX_DLC 8 +#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, 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, 7, 2) + FIELD(ARBITRATION_PHASE_BIT_TIMING_REGISTER, TS2, 4, 3) + FIELD(ARBITRATION_PHASE_BIT_TIMING_REGISTER, TS1, 0, 4) +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, 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, SNOOP, 12, 1) + FIELD(STATUS_REGISTER, ACFBSY, 11, 1) + FIELD(STATUS_REGISTER, TXFLL, 10, 1) + FIELD(STATUS_REGISTER, TXBFLL, 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, TXFEMP, 14, 1) + FIELD(INTERRUPT_STATUS_REGISTER, TXFWMEMP, 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, RXNEMP, 7, 1) + FIELD(INTERRUPT_STATUS_REGISTER, RXOFLW, 6, 1) + FIELD(INTERRUPT_STATUS_REGISTER, RXUFLW, 5, 1) + FIELD(INTERRUPT_STATUS_REGISTER, RXOK, 4, 1) + FIELD(INTERRUPT_STATUS_REGISTER, TXBFLL, 3, 1) + FIELD(INTERRUPT_STATUS_REGISTER, TXFLL, 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, ETXFEMP, 14, 1) + FIELD(INTERRUPT_ENABLE_REGISTER, ETXFWMEMP, 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, ERXNEMP, 7, 1) + FIELD(INTERRUPT_ENABLE_REGISTER, ERXOFLW, 6, 1) + FIELD(INTERRUPT_ENABLE_REGISTER, ERXUFLW, 5, 1) + FIELD(INTERRUPT_ENABLE_REGISTER, ERXOK, 4, 1) + FIELD(INTERRUPT_ENABLE_REGISTER, ETXBFLL, 3, 1) + FIELD(INTERRUPT_ENABLE_REGISTER, ETXFLL, 2, 1) + FIELD(INTERRUPT_ENABLE_REGISTER, ETXOK, 1, 1) + FIELD(INTERRUPT_ENABLE_REGISTER, EARBLST, 0, 1) +REG32(INTERRUPT_CLEAR_REGISTER, 0x24) + FIELD(INTERRUPT_CLEAR_REGISTER, CTXFEMP, 14, 1) + FIELD(INTERRUPT_CLEAR_REGISTER, CTXFWMEMP, 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, CRXNEMP, 7, 1) + FIELD(INTERRUPT_CLEAR_REGISTER, CRXOFLW, 6, 1) + FIELD(INTERRUPT_CLEAR_REGISTER, CRXUFLW, 5, 1) + FIELD(INTERRUPT_CLEAR_REGISTER, CRXOK, 4, 1) + FIELD(INTERRUPT_CLEAR_REGISTER, CTXBFLL, 3, 1) + FIELD(INTERRUPT_CLEAR_REGISTER, CTXFLL, 2, 1) + FIELD(INTERRUPT_CLEAR_REGISTER, CTXOK, 1, 1) + FIELD(INTERRUPT_CLEAR_REGISTER, CARBLST, 0, 1) +REG32(TIMESTAMP_REGISTER, 0x28) + FIELD(TIMESTAMP_REGISTER, CTS, 0, 1) +REG32(WIR, 0x2c) + FIELD(WIR, EW, 8, 8) + FIELD(WIR, FW, 0, 8) +REG32(TXFIFO_ID, 0x30) + FIELD(TXFIFO_ID, IDH, 21, 11) + FIELD(TXFIFO_ID, SRRRTR, 20, 1) + FIELD(TXFIFO_ID, IDE, 19, 1) + FIELD(TXFIFO_ID, IDL, 1, 18) + FIELD(TXFIFO_ID, RTR, 0, 1) +REG32(TXFIFO_DLC, 0x34) + FIELD(TXFIFO_DLC, DLC, 28, 4) +REG32(TXFIFO_DATA1, 0x38) + FIELD(TXFIFO_DATA1, DB0, 24, 8) + FIELD(TXFIFO_DATA1, DB1, 16, 8) + FIELD(TXFIFO_DATA1, DB2, 8, 8) + FIELD(TXFIFO_DATA1, DB3, 0, 8) +REG32(TXFIFO_DATA2, 0x3c) + FIELD(TXFIFO_DATA2, DB4, 24, 8) + FIELD(TXFIFO_DATA2, DB5, 16, 8) + FIELD(TXFIFO_DATA2, DB6, 8, 8) + FIELD(TXFIFO_DATA2, DB7, 0, 8) +REG32(TXHPB_ID, 0x40) + FIELD(TXHPB_ID, IDH, 21, 11) + FIELD(TXHPB_ID, SRRRTR, 20, 1) + FIELD(TXHPB_ID, IDE, 19, 1) + FIELD(TXHPB_ID, IDL, 1, 18) + FIELD(TXHPB_ID, RTR, 0, 1) +REG32(TXHPB_DLC, 0x44) + FIELD(TXHPB_DLC, DLC, 28, 4) +REG32(TXHPB_DATA1, 0x48) + FIELD(TXHPB_DATA1, DB0, 24, 8) + FIELD(TXHPB_DATA1, DB1, 16, 8) + FIELD(TXHPB_DATA1, DB2, 8, 8) + FIELD(TXHPB_DATA1, DB3, 0, 8) +REG32(TXHPB_DATA2, 0x4c) + FIELD(TXHPB_DATA2, DB4, 24, 8) + FIELD(TXHPB_DATA2, DB5, 16, 8) + FIELD(TXHPB_DATA2, DB6, 8, 8) + FIELD(TXHPB_DATA2, DB7, 0, 8) +REG32(RXFIFO_ID, 0x50) + FIELD(RXFIFO_ID, IDH, 21, 11) + FIELD(RXFIFO_ID, SRRRTR, 20, 1) + FIELD(RXFIFO_ID, IDE, 19, 1) + FIELD(RXFIFO_ID, IDL, 1, 18) + FIELD(RXFIFO_ID, RTR, 0, 1) +REG32(RXFIFO_DLC, 0x54) + FIELD(RXFIFO_DLC, DLC, 28, 4) + FIELD(RXFIFO_DLC, RXT, 0, 16) +REG32(RXFIFO_DATA1, 0x58) + FIELD(RXFIFO_DATA1, DB0, 24, 8) + FIELD(RXFIFO_DATA1, DB1, 16, 8) + FIELD(RXFIFO_DATA1, DB2, 8, 8) + FIELD(RXFIFO_DATA1, DB3, 0, 8) +REG32(RXFIFO_DATA2, 0x5c) + FIELD(RXFIFO_DATA2, DB4, 24, 8) + FIELD(RXFIFO_DATA2, DB5, 16, 8) + FIELD(RXFIFO_DATA2, DB6, 8, 8) + FIELD(RXFIFO_DATA2, DB7, 0, 8) +REG32(AFR, 0x60) + FIELD(AFR, UAF4, 3, 1) + FIELD(AFR, UAF3, 2, 1) + FIELD(AFR, UAF2, 1, 1) + FIELD(AFR, UAF1, 0, 1) +REG32(AFMR1, 0x64) + FIELD(AFMR1, AMIDH, 21, 11) + FIELD(AFMR1, AMSRR, 20, 1) + FIELD(AFMR1, AMIDE, 19, 1) + FIELD(AFMR1, AMIDL, 1, 18) + FIELD(AFMR1, AMRTR, 0, 1) +REG32(AFIR1, 0x68) + FIELD(AFIR1, AIIDH, 21, 11) + FIELD(AFIR1, AISRR, 20, 1) + FIELD(AFIR1, AIIDE, 19, 1) + FIELD(AFIR1, AIIDL, 1, 18) + FIELD(AFIR1, AIRTR, 0, 1) +REG32(AFMR2, 0x6c) + FIELD(AFMR2, AMIDH, 21, 11) + FIELD(AFMR2, AMSRR, 20, 1) + FIELD(AFMR2, AMIDE, 19, 1) + FIELD(AFMR2, AMIDL, 1, 18) + FIELD(AFMR2, AMRTR, 0, 1) +REG32(AFIR2, 0x70) + FIELD(AFIR2, AIIDH, 21, 11) + FIELD(AFIR2, AISRR, 20, 1) + FIELD(AFIR2, AIIDE, 19, 1) + FIELD(AFIR2, AIIDL, 1, 18) + FIELD(AFIR2, AIRTR, 0, 1) +REG32(AFMR3, 0x74) + FIELD(AFMR3, AMIDH, 21, 11) + FIELD(AFMR3, AMSRR, 20, 1) + FIELD(AFMR3, AMIDE, 19, 1) + FIELD(AFMR3, AMIDL, 1, 18) + FIELD(AFMR3, AMRTR, 0, 1) +REG32(AFIR3, 0x78) + FIELD(AFIR3, AIIDH, 21, 11) + FIELD(AFIR3, AISRR, 20, 1) + FIELD(AFIR3, AIIDE, 19, 1) + FIELD(AFIR3, AIIDL, 1, 18) + FIELD(AFIR3, AIRTR, 0, 1) +REG32(AFMR4, 0x7c) + FIELD(AFMR4, AMIDH, 21, 11) + FIELD(AFMR4, AMSRR, 20, 1) + FIELD(AFMR4, AMIDE, 19, 1) + FIELD(AFMR4, AMIDL, 1, 18) + FIELD(AFMR4, AMRTR, 0, 1) +REG32(AFIR4, 0x80) + FIELD(AFIR4, AIIDH, 21, 11) + FIELD(AFIR4, AISRR, 20, 1) + FIELD(AFIR4, AIIDE, 19, 1) + FIELD(AFIR4, AIIDL, 1, 18) + FIELD(AFIR4, AIRTR, 0, 1) + +static void can_update_irq(XlnxZynqMPCANState *s) +{ + uint32_t irq; + + /* Watermark register interrupts. */ + if ((fifo32_num_free(&s->tx_fifo) / CAN_FRAME_SIZE) > + ARRAY_FIELD_EX32(s->regs, WIR, EW)) { + ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXFWMEMP, 1); + } + + if ((fifo32_num_used(&s->rx_fifo) / CAN_FRAME_SIZE) > + ARRAY_FIELD_EX32(s->regs, WIR, FW)) { + ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXFWMFLL, 1); + } + + /* RX Interrupts. */ + if (fifo32_num_used(&s->rx_fifo) >=3D CAN_FRAME_SIZE) { + ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXNEMP, 1); + } + + /* TX interrupts. */ + if (fifo32_is_empty(&s->tx_fifo)) { + ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXFEMP, 1); + } + + if (fifo32_is_full(&s->tx_fifo)) { + ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXFLL, 1); + } + + if (fifo32_is_full(&s->txhpb_fifo)) { + ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXBFLL, 1); + } + + irq =3D s->regs[R_INTERRUPT_STATUS_REGISTER]; + irq &=3D s->regs[R_INTERRUPT_ENABLE_REGISTER]; + + trace_xlnx_can_update_irq(s->regs[R_INTERRUPT_STATUS_REGISTER], + s->regs[R_INTERRUPT_ENABLE_REGISTER], irq); + qemu_set_irq(s->irq, irq); +} + +static void can_ier_post_write(RegisterInfo *reg, uint64_t val) +{ + XlnxZynqMPCANState *s =3D XLNX_ZYNQMP_CAN(reg->opaque); + + can_update_irq(s); +} + +static uint64_t can_icr_pre_write(RegisterInfo *reg, uint64_t val) +{ + XlnxZynqMPCANState *s =3D XLNX_ZYNQMP_CAN(reg->opaque); + + s->regs[R_INTERRUPT_STATUS_REGISTER] &=3D ~val; + can_update_irq(s); + + return 0; +} + +static void can_config_reset(XlnxZynqMPCANState *s) +{ + /* Reset all the configuration registers. */ + register_reset(&s->reg_info[R_SOFTWARE_RESET_REGISTER]); + register_reset(&s->reg_info[R_MODE_SELECT_REGISTER]); + register_reset( + &s->reg_info[R_ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTE= R]); + register_reset(&s->reg_info[R_ARBITRATION_PHASE_BIT_TIMING_REGISTER]); + register_reset(&s->reg_info[R_STATUS_REGISTER]); + register_reset(&s->reg_info[R_INTERRUPT_STATUS_REGISTER]); + register_reset(&s->reg_info[R_INTERRUPT_ENABLE_REGISTER]); + register_reset(&s->reg_info[R_INTERRUPT_CLEAR_REGISTER]); + register_reset(&s->reg_info[R_WIR]); +} + +static void can_config_mode(XlnxZynqMPCANState *s) +{ + register_reset(&s->reg_info[R_ERROR_COUNTER_REGISTER]); + register_reset(&s->reg_info[R_ERROR_STATUS_REGISTER]); + + /* Put XlnxZynqMPCAN 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, RXOFLW, 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); + + can_update_irq(s); +} + +static void update_status_register_mode_bits(XlnxZynqMPCANState *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_status && (sleep_mode =3D=3D 0); + /* Sleep interrupt bit. */ + bool sleep_irq_val =3D sleep_mode && (sleep_status =3D=3D 0); + + /* 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 then XlnxZynqMPCAN is set in normal mode. + */ + 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); + } + + can_update_irq(s); +} + +static void can_exit_sleep_mode(XlnxZynqMPCANState *s) +{ + ARRAY_FIELD_DP32(s->regs, MODE_SELECT_REGISTER, SLEEP, 0); + update_status_register_mode_bits(s); +} + +static void generate_frame(qemu_can_frame *frame, uint32_t *data) +{ + frame->can_id =3D data[0]; + frame->can_dlc =3D FIELD_EX32(data[1], TXFIFO_DLC, DLC); + + frame->data[0] =3D FIELD_EX32(data[2], TXFIFO_DATA1, DB3); + frame->data[1] =3D FIELD_EX32(data[2], TXFIFO_DATA1, DB2); + frame->data[2] =3D FIELD_EX32(data[2], TXFIFO_DATA1, DB1); + frame->data[3] =3D FIELD_EX32(data[2], TXFIFO_DATA1, DB0); + + frame->data[4] =3D FIELD_EX32(data[3], TXFIFO_DATA2, DB7); + frame->data[5] =3D FIELD_EX32(data[3], TXFIFO_DATA2, DB6); + frame->data[6] =3D FIELD_EX32(data[3], TXFIFO_DATA2, DB5); + frame->data[7] =3D FIELD_EX32(data[3], TXFIFO_DATA2, DB4); +} + +static bool tx_ready_check(XlnxZynqMPCANState *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" + " data while controller 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 while controller is in configuration mode. Re= set" + " the core so operations can start fresh.\n", + path); + return false; + } + + if (ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SNOOP)) { + g_autofree char *path =3D object_get_canonical_path(OBJECT(s)); + + qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to transfer" + " data while controller is in SNOOP MODE.\n", + path); + return false; + } + + return true; +} + +static void transfer_fifo(XlnxZynqMPCANState *s, Fifo32 *fifo) +{ + qemu_can_frame frame; + uint32_t data[CAN_FRAME_SIZE]; + int i; + bool can_tx =3D tx_ready_check(s); + + if (!can_tx) { + g_autofree char *path =3D object_get_canonical_path(OBJECT(s)); + + qemu_log_mask(LOG_GUEST_ERROR, "%s: Controller is not enabled for = data" + " transfer.\n", path); + can_update_irq(s); + return; + } + + while (!fifo32_is_empty(fifo)) { + for (i =3D 0; i < CAN_FRAME_SIZE; i++) { + data[i] =3D fifo32_pop(fifo); + } + + if (ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, LBACK)) { + /* + * Controller is in loopback. In Loopback mode, the CAN core + * transmits a recessive bitstream on to the XlnxZynqMPCAN Bus. + * Any message transmitted is looped back to the RX line and + * acknowledged. The XlnxZynqMPCAN core receives any message + * that it transmits. + */ + if (fifo32_is_full(&s->rx_fifo)) { + ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOFL= W, 1); + } else { + for (i =3D 0; i < CAN_FRAME_SIZE; i++) { + fifo32_push(&s->rx_fifo, data[i]); + } + + ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOK,= 1); + } + } else { + /* Normal mode Tx. */ + generate_frame(&frame, data); + + trace_xlnx_can_tx_data(frame.can_id, frame.can_dlc, + frame.data[0], frame.data[1], + frame.data[2], frame.data[3], + frame.data[4], frame.data[5], + frame.data[6], frame.data[7]); + can_bus_client_send(&s->bus_client, &frame, 1); + } + } + + ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXOK, 1); + ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, TXBFLL, 0); + + if (ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SLEEP)) { + can_exit_sleep_mode(s); + } + + can_update_irq(s); +} + +static uint64_t can_srr_pre_write(RegisterInfo *reg, uint64_t val) +{ + XlnxZynqMPCANState *s =3D XLNX_ZYNQMP_CAN(reg->opaque); + + ARRAY_FIELD_DP32(s->regs, SOFTWARE_RESET_REGISTER, CEN, + FIELD_EX32(val, SOFTWARE_RESET_REGISTER, CEN)); + + if (FIELD_EX32(val, SOFTWARE_RESET_REGISTER, SRST)) { + trace_xlnx_can_reset(val); + + /* First, core will do software reset then will enter in config mo= de. */ + can_config_reset(s); + } + + if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN) =3D=3D 0) { + can_config_mode(s); + } else { + /* + * Leave config mode. Now XlnxZynqMPCAN core will enter normal, + * sleep, snoop or loopback mode depending upon LBACK, SLEEP, SNOOP + * register states. + */ + ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, CONFIG, 0); + + ptimer_transaction_begin(s->can_timer); + ptimer_set_count(s->can_timer, 0); + ptimer_transaction_commit(s->can_timer); + + /* XlnxZynqMPCAN is out of config mode. It will send pending data.= */ + transfer_fifo(s, &s->txhpb_fifo); + transfer_fifo(s, &s->tx_fifo); + } + + update_status_register_mode_bits(s); + + return s->regs[R_SOFTWARE_RESET_REGISTER]; +} + +static uint64_t can_msr_pre_write(RegisterInfo *reg, uint64_t val) +{ + XlnxZynqMPCANState *s =3D XLNX_ZYNQMP_CAN(reg->opaque); + uint8_t multi_mode; + + /* + * 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) { + g_autofree char *path =3D object_get_canonical_path(OBJECT(s)); + + qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to config" + " several modes simultaneously. One mode will be sel= ected" + " according to their priority: LBACK > SLEEP > SNOOP= .\n", + path); + } + + if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN) =3D=3D 0) { + /* We are 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)) { + g_autofree char *path =3D object_get_canonical_path(OBJECT(s)); + + qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to set" + " LBACK mode without setting CEN bit as 0.\n", + path); + } else if (FIELD_EX32(val, MODE_SELECT_REGISTER, SNOOP)) { + g_autofree char *path =3D object_get_canonical_path(OBJECT(s)); + + qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to set" + " SNOOP mode without setting CEN bit as 0.\n", + path); + } + + update_status_register_mode_bits(s); + } + + return s->regs[R_MODE_SELECT_REGISTER]; +} + +static uint64_t can_brpr_pre_write(RegisterInfo *reg, uint64_t val) +{ + XlnxZynqMPCANState *s =3D XLNX_ZYNQMP_CAN(reg->opaque); + + /* Only allow writes when in config mode. */ + if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN)) { + return s->regs[R_ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER]; + } + + return val; +} + +static uint64_t can_btr_pre_write(RegisterInfo *reg, uint64_t val) +{ + XlnxZynqMPCANState *s =3D XLNX_ZYNQMP_CAN(reg->opaque); + + /* Only allow writes when in config mode. */ + if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN)) { + return s->regs[R_ARBITRATION_PHASE_BIT_TIMING_REGISTER]; + } + + return val; +} + +static uint64_t can_tcr_pre_write(RegisterInfo *reg, uint64_t val) +{ + XlnxZynqMPCANState *s =3D XLNX_ZYNQMP_CAN(reg->opaque); + + if (FIELD_EX32(val, TIMESTAMP_REGISTER, CTS)) { + ptimer_transaction_begin(s->can_timer); + ptimer_set_count(s->can_timer, 0); + ptimer_transaction_commit(s->can_timer); + } + + return 0; +} + +static void update_rx_fifo(XlnxZynqMPCANState *s, const qemu_can_frame *fr= ame) +{ + bool filter_pass =3D false; + uint16_t timestamp =3D 0; + + /* If no filter is enabled. Message will be stored in FIFO. */ + if (!((ARRAY_FIELD_EX32(s->regs, AFR, UAF1)) | + (ARRAY_FIELD_EX32(s->regs, AFR, UAF2)) | + (ARRAY_FIELD_EX32(s->regs, AFR, UAF3)) | + (ARRAY_FIELD_EX32(s->regs, AFR, UAF4)))) { + filter_pass =3D true; + } + + /* + * Messages that pass any of the acceptance filters will be stored in + * the RX FIFO. + */ + if (ARRAY_FIELD_EX32(s->regs, AFR, UAF1)) { + uint32_t id_masked =3D s->regs[R_AFMR1] & frame->can_id; + uint32_t filter_id_masked =3D s->regs[R_AFMR1] & s->regs[R_AFIR1]; + + if (filter_id_masked =3D=3D id_masked) { + filter_pass =3D true; + } + } + + if (ARRAY_FIELD_EX32(s->regs, AFR, UAF2)) { + uint32_t id_masked =3D s->regs[R_AFMR2] & frame->can_id; + uint32_t filter_id_masked =3D s->regs[R_AFMR2] & s->regs[R_AFIR2]; + + if (filter_id_masked =3D=3D id_masked) { + filter_pass =3D true; + } + } + + if (ARRAY_FIELD_EX32(s->regs, AFR, UAF3)) { + uint32_t id_masked =3D s->regs[R_AFMR3] & frame->can_id; + uint32_t filter_id_masked =3D s->regs[R_AFMR3] & s->regs[R_AFIR3]; + + if (filter_id_masked =3D=3D id_masked) { + filter_pass =3D true; + } + } + + if (ARRAY_FIELD_EX32(s->regs, AFR, UAF4)) { + uint32_t id_masked =3D s->regs[R_AFMR4] & frame->can_id; + uint32_t filter_id_masked =3D s->regs[R_AFMR4] & s->regs[R_AFIR4]; + + if (filter_id_masked =3D=3D id_masked) { + filter_pass =3D true; + } + } + + if (!filter_pass) { + trace_xlnx_can_rx_fifo_filter_reject(frame->can_id, frame->can_dlc= ); + return; + } + + /* Store the message in fifo if it passed through any of the filters. = */ + if (filter_pass && frame->can_dlc <=3D MAX_DLC) { + + if (fifo32_is_full(&s->rx_fifo)) { + ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOFLW, 1= ); + } else { + timestamp =3D CAN_TIMER_MAX - ptimer_get_count(s->can_timer); + + fifo32_push(&s->rx_fifo, frame->can_id); + + fifo32_push(&s->rx_fifo, deposit32(0, R_RXFIFO_DLC_DLC_SHIFT, + R_RXFIFO_DLC_DLC_LENGTH, + frame->can_dlc) | + deposit32(0, R_RXFIFO_DLC_RXT_SHIFT, + R_RXFIFO_DLC_RXT_LENGTH, + timestamp)); + + /* First 32 bit of the data. */ + fifo32_push(&s->rx_fifo, deposit32(0, R_TXFIFO_DATA1_DB3_SHIFT, + R_TXFIFO_DATA1_DB3_LENGTH, + frame->data[0]) | + deposit32(0, R_TXFIFO_DATA1_DB2_SHIFT, + R_TXFIFO_DATA1_DB2_LENGTH, + frame->data[1]) | + deposit32(0, R_TXFIFO_DATA1_DB1_SHIFT, + R_TXFIFO_DATA1_DB1_LENGTH, + frame->data[2]) | + deposit32(0, R_TXFIFO_DATA1_DB0_SHIFT, + R_TXFIFO_DATA1_DB0_LENGTH, + frame->data[3])); + /* Last 32 bit of the data. */ + fifo32_push(&s->rx_fifo, deposit32(0, R_TXFIFO_DATA2_DB7_SHIFT, + R_TXFIFO_DATA2_DB7_LENGTH, + frame->data[4]) | + deposit32(0, R_TXFIFO_DATA2_DB6_SHIFT, + R_TXFIFO_DATA2_DB6_LENGTH, + frame->data[5]) | + deposit32(0, R_TXFIFO_DATA2_DB5_SHIFT, + R_TXFIFO_DATA2_DB5_LENGTH, + frame->data[6]) | + deposit32(0, R_TXFIFO_DATA2_DB4_SHIFT, + R_TXFIFO_DATA2_DB4_LENGTH, + frame->data[7])); + + ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOK, 1); + trace_xlnx_can_rx_data(frame->can_id, frame->can_dlc, + frame->data[0], frame->data[1], + frame->data[2], frame->data[3], + frame->data[4], frame->data[5], + frame->data[6], frame->data[7]); + } + + can_update_irq(s); + } +} + +static uint64_t can_rxfifo_pre_read(RegisterInfo *reg, uint64_t val) +{ + XlnxZynqMPCANState *s =3D XLNX_ZYNQMP_CAN(reg->opaque); + + if (!fifo32_is_empty(&s->rx_fifo)) { + val =3D fifo32_pop(&s->rx_fifo); + } else { + ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXUFLW, 1); + } + + can_update_irq(s); + return val; +} + +static void can_filter_enable_post_write(RegisterInfo *reg, uint64_t val) +{ + XlnxZynqMPCANState *s =3D XLNX_ZYNQMP_CAN(reg->opaque); + + if (ARRAY_FIELD_EX32(s->regs, AFR, UAF1) && + ARRAY_FIELD_EX32(s->regs, AFR, UAF2) && + ARRAY_FIELD_EX32(s->regs, AFR, UAF3) && + ARRAY_FIELD_EX32(s->regs, AFR, UAF4)) { + ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, ACFBSY, 1); + } else { + ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, ACFBSY, 0); + } +} + +static uint64_t can_filter_mask_pre_write(RegisterInfo *reg, uint64_t val) +{ + XlnxZynqMPCANState *s =3D XLNX_ZYNQMP_CAN(reg->opaque); + uint32_t reg_idx =3D (reg->access->addr) / 4; + uint32_t filter_number =3D (reg_idx - R_AFMR1) / 2; + + /* modify an acceptance filter, the corresponding UAF bit should be '0= '. */ + if (!(s->regs[R_AFR] & (1 << filter_number))) { + s->regs[reg_idx] =3D val; + + trace_xlnx_can_filter_mask_pre_write(filter_number, s->regs[reg_id= x]); + } else { + g_autofree char *path =3D object_get_canonical_path(OBJECT(s)); + + qemu_log_mask(LOG_GUEST_ERROR, "%s: Acceptance filter %d" + " mask is not set as corresponding UAF bit is not 0.= \n", + path, filter_number + 1); + } + + return s->regs[reg_idx]; +} + +static uint64_t can_filter_id_pre_write(RegisterInfo *reg, uint64_t val) +{ + XlnxZynqMPCANState *s =3D XLNX_ZYNQMP_CAN(reg->opaque); + uint32_t reg_idx =3D (reg->access->addr) / 4; + uint32_t filter_number =3D (reg_idx - R_AFIR1) / 2; + + if (!(s->regs[R_AFR] & (1 << filter_number))) { + s->regs[reg_idx] =3D val; + + trace_xlnx_can_filter_id_pre_write(filter_number, s->regs[reg_idx]= ); + } else { + g_autofree char *path =3D object_get_canonical_path(OBJECT(s)); + + qemu_log_mask(LOG_GUEST_ERROR, "%s: Acceptance filter %d" + " id is not set as corresponding UAF bit is not 0.\n= ", + path, filter_number + 1); + } + + return s->regs[reg_idx]; +} + +static void can_tx_post_write(RegisterInfo *reg, uint64_t val) +{ + XlnxZynqMPCANState *s =3D XLNX_ZYNQMP_CAN(reg->opaque); + + bool is_txhpb =3D reg->access->addr > A_TXFIFO_DATA2; + + bool initiate_transfer =3D (reg->access->addr =3D=3D A_TXFIFO_DATA2) || + (reg->access->addr =3D=3D A_TXHPB_DATA2); + + Fifo32 *f =3D is_txhpb ? &s->txhpb_fifo : &s->tx_fifo; + + if (!fifo32_is_full(f)) { + fifo32_push(f, val); + } else { + g_autofree char *path =3D object_get_canonical_path(OBJECT(s)); + + qemu_log_mask(LOG_GUEST_ERROR, "%s: TX FIFO is full.\n", path); + } + + /* Initiate the message send if TX register is written. */ + if (initiate_transfer && + ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN)) { + transfer_fifo(s, f); + } + + can_update_irq(s); +} + +static const RegisterAccessInfo can_regs_info[] =3D { + { .name =3D "SOFTWARE_RESET_REGISTER", + .addr =3D A_SOFTWARE_RESET_REGISTER, + .rsvd =3D 0xfffffffc, + .pre_write =3D can_srr_pre_write, + },{ .name =3D "MODE_SELECT_REGISTER", + .addr =3D A_MODE_SELECT_REGISTER, + .rsvd =3D 0xfffffff8, + .pre_write =3D can_msr_pre_write, + },{ .name =3D "ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER", + .addr =3D A_ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER, + .rsvd =3D 0xffffff00, + .pre_write =3D can_brpr_pre_write, + },{ .name =3D "ARBITRATION_PHASE_BIT_TIMING_REGISTER", + .addr =3D A_ARBITRATION_PHASE_BIT_TIMING_REGISTER, + .rsvd =3D 0xfffffe00, + .pre_write =3D can_btr_pre_write, + },{ .name =3D "ERROR_COUNTER_REGISTER", + .addr =3D A_ERROR_COUNTER_REGISTER, + .rsvd =3D 0xffff0000, + .ro =3D 0xffffffff, + },{ .name =3D "ERROR_STATUS_REGISTER", + .addr =3D A_ERROR_STATUS_REGISTER, + .rsvd =3D 0xffffffe0, + .w1c =3D 0x1f, + },{ .name =3D "STATUS_REGISTER", .addr =3D A_STATUS_REGISTER, + .reset =3D 0x1, + .rsvd =3D 0xffffe000, + .ro =3D 0x1fff, + },{ .name =3D "INTERRUPT_STATUS_REGISTER", + .addr =3D A_INTERRUPT_STATUS_REGISTER, + .reset =3D 0x6000, + .rsvd =3D 0xffff8000, + .ro =3D 0x7fff, + },{ .name =3D "INTERRUPT_ENABLE_REGISTER", + .addr =3D A_INTERRUPT_ENABLE_REGISTER, + .rsvd =3D 0xffff8000, + .post_write =3D can_ier_post_write, + },{ .name =3D "INTERRUPT_CLEAR_REGISTER", + .addr =3D A_INTERRUPT_CLEAR_REGISTER, + .rsvd =3D 0xffff8000, + .pre_write =3D can_icr_pre_write, + },{ .name =3D "TIMESTAMP_REGISTER", + .addr =3D A_TIMESTAMP_REGISTER, + .rsvd =3D 0xfffffffe, + .pre_write =3D can_tcr_pre_write, + },{ .name =3D "WIR", .addr =3D A_WIR, + .reset =3D 0x3f3f, + .rsvd =3D 0xffff0000, + },{ .name =3D "TXFIFO_ID", .addr =3D A_TXFIFO_ID, + .post_write =3D can_tx_post_write, + },{ .name =3D "TXFIFO_DLC", .addr =3D A_TXFIFO_DLC, + .rsvd =3D 0xfffffff, + .post_write =3D can_tx_post_write, + },{ .name =3D "TXFIFO_DATA1", .addr =3D A_TXFIFO_DATA1, + .post_write =3D can_tx_post_write, + },{ .name =3D "TXFIFO_DATA2", .addr =3D A_TXFIFO_DATA2, + .post_write =3D can_tx_post_write, + },{ .name =3D "TXHPB_ID", .addr =3D A_TXHPB_ID, + .post_write =3D can_tx_post_write, + },{ .name =3D "TXHPB_DLC", .addr =3D A_TXHPB_DLC, + .rsvd =3D 0xfffffff, + .post_write =3D can_tx_post_write, + },{ .name =3D "TXHPB_DATA1", .addr =3D A_TXHPB_DATA1, + .post_write =3D can_tx_post_write, + },{ .name =3D "TXHPB_DATA2", .addr =3D A_TXHPB_DATA2, + .post_write =3D can_tx_post_write, + },{ .name =3D "RXFIFO_ID", .addr =3D A_RXFIFO_ID, + .ro =3D 0xffffffff, + .post_read =3D can_rxfifo_pre_read, + },{ .name =3D "RXFIFO_DLC", .addr =3D A_RXFIFO_DLC, + .rsvd =3D 0xfff0000, + .post_read =3D can_rxfifo_pre_read, + },{ .name =3D "RXFIFO_DATA1", .addr =3D A_RXFIFO_DATA1, + .post_read =3D can_rxfifo_pre_read, + },{ .name =3D "RXFIFO_DATA2", .addr =3D A_RXFIFO_DATA2, + .post_read =3D can_rxfifo_pre_read, + },{ .name =3D "AFR", .addr =3D A_AFR, + .rsvd =3D 0xfffffff0, + .post_write =3D can_filter_enable_post_write, + },{ .name =3D "AFMR1", .addr =3D A_AFMR1, + .pre_write =3D can_filter_mask_pre_write, + },{ .name =3D "AFIR1", .addr =3D A_AFIR1, + .pre_write =3D can_filter_id_pre_write, + },{ .name =3D "AFMR2", .addr =3D A_AFMR2, + .pre_write =3D can_filter_mask_pre_write, + },{ .name =3D "AFIR2", .addr =3D A_AFIR2, + .pre_write =3D can_filter_id_pre_write, + },{ .name =3D "AFMR3", .addr =3D A_AFMR3, + .pre_write =3D can_filter_mask_pre_write, + },{ .name =3D "AFIR3", .addr =3D A_AFIR3, + .pre_write =3D can_filter_id_pre_write, + },{ .name =3D "AFMR4", .addr =3D A_AFMR4, + .pre_write =3D can_filter_mask_pre_write, + },{ .name =3D "AFIR4", .addr =3D A_AFIR4, + .pre_write =3D can_filter_id_pre_write, + } +}; + +static void xlnx_zynqmp_can_ptimer_cb(void *opaque) +{ + /* No action required on the timer rollover. */ +} + +static const MemoryRegionOps can_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 xlnx_zynqmp_can_reset_init(Object *obj, ResetType type) +{ + XlnxZynqMPCANState *s =3D XLNX_ZYNQMP_CAN(obj); + unsigned int i; + + for (i =3D R_RXFIFO_ID; i < ARRAY_SIZE(s->reg_info); ++i) { + register_reset(&s->reg_info[i]); + } + + ptimer_transaction_begin(s->can_timer); + ptimer_set_count(s->can_timer, 0); + ptimer_transaction_commit(s->can_timer); +} + +static void xlnx_zynqmp_can_reset_hold(Object *obj) +{ + XlnxZynqMPCANState *s =3D XLNX_ZYNQMP_CAN(obj); + unsigned int i; + + for (i =3D 0; i < R_RXFIFO_ID; ++i) { + register_reset(&s->reg_info[i]); + } + + /* + * Reset FIFOs when CAN model is reset. This will clear the fifo writes + * done by post_write which gets called from register_reset function, + * post_write handle will not be able to trigger tx because CAN will be + * disabled when software_reset_register is cleared first. + */ + fifo32_reset(&s->rx_fifo); + fifo32_reset(&s->tx_fifo); + fifo32_reset(&s->txhpb_fifo); +} + +static bool xlnx_zynqmp_can_can_receive(CanBusClientState *client) +{ + XlnxZynqMPCANState *s =3D container_of(client, XlnxZynqMPCANState, + bus_client); + + 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: Controller is in reset state.\= 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: Controller is disabled. Incomi= ng" + " messages will be discarded.\n", path); + return false; + } + + return true; +} + +static ssize_t xlnx_zynqmp_can_receive(CanBusClientState *client, + const qemu_can_frame *buf, size_t buf_size)= { + XlnxZynqMPCANState *s =3D container_of(client, XlnxZynqMPCANState, + bus_client); + const qemu_can_frame *frame =3D buf; + + 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, SNOOP)) { + /* Snoop Mode: Just keep the data. no response back. */ + update_rx_fifo(s, frame); + } else if ((ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SLEEP))) { + /* + * XlnxZynqMPCAN is in sleep mode. Any data on bus will bring it t= o wake + * up state. + */ + can_exit_sleep_mode(s); + update_rx_fifo(s, frame); + } else if ((ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SLEEP)) =3D=3D = 0) { + update_rx_fifo(s, frame); + } else { + /* + * XlnxZynqMPCAN will not participate in normal bus communication + * and will not receive any messages transmitted by other CAN node= s. + */ + trace_xlnx_can_rx_discard(s->regs[R_STATUS_REGISTER]); + } + + return 1; +} + +static CanBusClientInfo can_xilinx_bus_client_info =3D { + .can_receive =3D xlnx_zynqmp_can_can_receive, + .receive =3D xlnx_zynqmp_can_receive, +}; + +static int xlnx_zynqmp_can_connect_to_bus(XlnxZynqMPCANState *s, + CanBusState *bus) +{ + s->bus_client.info =3D &can_xilinx_bus_client_info; + + if (can_bus_insert_client(bus, &s->bus_client) < 0) { + return -1; + } + return 0; +} + +static void xlnx_zynqmp_can_realize(DeviceState *dev, Error **errp) +{ + XlnxZynqMPCANState *s =3D XLNX_ZYNQMP_CAN(dev); + + if (s->canbus) { + if (xlnx_zynqmp_can_connect_to_bus(s, s->canbus) < 0) { + g_autofree char *path =3D object_get_canonical_path(OBJECT(s)); + + error_setg(errp, "%s: xlnx_zynqmp_can_connect_to_bus" + " failed.", path); + return; + } + } + + /* Create RX FIFO, TXFIFO, TXHPB storage. */ + fifo32_create(&s->rx_fifo, RXFIFO_SIZE); + fifo32_create(&s->tx_fifo, RXFIFO_SIZE); + fifo32_create(&s->txhpb_fifo, CAN_FRAME_SIZE); + + /* Allocate a new timer. */ + s->can_timer =3D ptimer_init(xlnx_zynqmp_can_ptimer_cb, s, + PTIMER_POLICY_DEFAULT); + + ptimer_transaction_begin(s->can_timer); + + ptimer_set_freq(s->can_timer, s->cfg.ext_clk_freq); + ptimer_set_limit(s->can_timer, CAN_TIMER_MAX, 1); + ptimer_run(s->can_timer, 0); + ptimer_transaction_commit(s->can_timer); +} + +static void xlnx_zynqmp_can_init(Object *obj) +{ + XlnxZynqMPCANState *s =3D XLNX_ZYNQMP_CAN(obj); + SysBusDevice *sbd =3D SYS_BUS_DEVICE(obj); + + RegisterInfoArray *reg_array; + + memory_region_init(&s->iomem, obj, TYPE_XLNX_ZYNQMP_CAN, + XLNX_ZYNQMP_CAN_R_MAX * 4); + reg_array =3D register_init_block32(DEVICE(obj), can_regs_info, + ARRAY_SIZE(can_regs_info), + s->reg_info, s->regs, + &can_ops, + XLNX_ZYNQMP_CAN_ERR_DEBUG, + XLNX_ZYNQMP_CAN_R_MAX * 4); + + memory_region_add_subregion(&s->iomem, 0x00, ®_array->mem); + sysbus_init_mmio(sbd, &s->iomem); + sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq); +} + +static const VMStateDescription vmstate_can =3D { + .name =3D TYPE_XLNX_ZYNQMP_CAN, + .version_id =3D 1, + .minimum_version_id =3D 1, + .fields =3D (VMStateField[]) { + VMSTATE_FIFO32(rx_fifo, XlnxZynqMPCANState), + VMSTATE_FIFO32(tx_fifo, XlnxZynqMPCANState), + VMSTATE_FIFO32(txhpb_fifo, XlnxZynqMPCANState), + VMSTATE_UINT32_ARRAY(regs, XlnxZynqMPCANState, XLNX_ZYNQMP_CAN_R_M= AX), + VMSTATE_PTIMER(can_timer, XlnxZynqMPCANState), + VMSTATE_END_OF_LIST(), + } +}; + +static Property xlnx_zynqmp_can_properties[] =3D { + DEFINE_PROP_UINT32("ext_clk_freq", XlnxZynqMPCANState, cfg.ext_clk_fre= q, + CAN_DEFAULT_CLOCK), + DEFINE_PROP_LINK("canbus", XlnxZynqMPCANState, canbus, TYPE_CAN_BUS, + CanBusState *), + DEFINE_PROP_END_OF_LIST(), +}; + +static void xlnx_zynqmp_can_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(klass); + ResettableClass *rc =3D RESETTABLE_CLASS(klass); + + rc->phases.enter =3D xlnx_zynqmp_can_reset_init; + rc->phases.hold =3D xlnx_zynqmp_can_reset_hold; + dc->realize =3D xlnx_zynqmp_can_realize; + device_class_set_props(dc, xlnx_zynqmp_can_properties); + dc->vmsd =3D &vmstate_can; +} + +static const TypeInfo can_info =3D { + .name =3D TYPE_XLNX_ZYNQMP_CAN, + .parent =3D TYPE_SYS_BUS_DEVICE, + .instance_size =3D sizeof(XlnxZynqMPCANState), + .class_init =3D xlnx_zynqmp_can_class_init, + .instance_init =3D xlnx_zynqmp_can_init, +}; + +static void can_register_types(void) +{ + type_register_static(&can_info); +} + +type_init(can_register_types) diff --git a/hw/Kconfig b/hw/Kconfig index 4de1797..5ad3c6b 100644 --- a/hw/Kconfig +++ b/hw/Kconfig @@ -80,3 +80,4 @@ config XILINX_AXI config XLNX_ZYNQMP bool select REGISTER + select CAN_BUS diff --git a/hw/net/can/meson.build b/hw/net/can/meson.build index 714951f..8fabbd9 100644 --- a/hw/net/can/meson.build +++ b/hw/net/can/meson.build @@ -4,3 +4,4 @@ softmmu_ss.add(when: 'CONFIG_CAN_PCI', if_true: files('can_= pcm3680_pci.c')) 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')) diff --git a/hw/net/can/trace-events b/hw/net/can/trace-events new file mode 100644 index 0000000..8346a98 --- /dev/null +++ b/hw/net/can/trace-events @@ -0,0 +1,9 @@ +# xlnx-zynqmp-can.c +xlnx_can_update_irq(uint32_t isr, uint32_t ier, uint32_t irq) "ISR: 0x%08x= IER: 0x%08x IRQ: 0x%08x" +xlnx_can_reset(uint32_t val) "Resetting controller with value =3D 0x%08x" +xlnx_can_rx_fifo_filter_reject(uint32_t id, uint8_t dlc) "Frame: ID: 0x%08= x DLC: 0x%02x" +xlnx_can_filter_id_pre_write(uint8_t filter_num, uint32_t value) "Filter%d= ID: 0x%08x" +xlnx_can_filter_mask_pre_write(uint8_t filter_num, uint32_t value) "Filter= %d MASK: 0x%08x" +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" --=20 2.7.4 From nobody Fri May 3 14:37:10 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=1dmarc=pass fromdomain=xilinx.com) ARC-Seal: i=2; a=rsa-sha256; t=1605729059; cv=pass; d=zohomail.com; s=zohoarc; b=fEZ7zDYpTfbUGywiHIMLVgDTlavECtzPHNUSxMH4saZPKSsNlLBeG4I3GmSwdWFzDLbYSWbtcgZeJBC50qhZooXq1B81tY3hDCvbvojSQ4BStaZYLz9rp3XzswNcR0SuyNmIXNbDc/db/kr7wYqQoIH2XgX1v9lm9fiVJ7wfG5E= ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1605729059; 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=JlEP77TEb8SF9MAjy5QJ6aGzR5r/P/0aoihL9r+yD6E=; b=gkOBKP4zxCr9YsT7cS5xH94JSmNJ8CaqhcuS2Z+OU/F9JvuFO1eYLYMqh3KmCB3L1rFqICx5bXr99VAVeiLCtTRavuBYEPfeSwjbYIZF2IjKcHMuMAV4zqpxqURn6cnKg+5/6x5xS/ssdsOtuHPkwsJQHsHKJ4rbCZ3Vjdpz4sY= 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=1dmarc=pass fromdomain=xilinx.com) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 160572905931452.94087874208117; Wed, 18 Nov 2020 11:50:59 -0800 (PST) Received: from localhost ([::1]:51532 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kfTTl-0005rv-VL for importer@patchew.org; Wed, 18 Nov 2020 14:50:58 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:48896) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kfTS2-0004Nv-2V; Wed, 18 Nov 2020 14:49:10 -0500 Received: from mail-mw2nam10on2080.outbound.protection.outlook.com ([40.107.94.80]:5761 helo=NAM10-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 1kfTRz-0005YX-1W; Wed, 18 Nov 2020 14:49:09 -0500 Received: from DM3PR12CA0121.namprd12.prod.outlook.com (2603:10b6:0:51::17) by BY5PR02MB7041.namprd02.prod.outlook.com (2603:10b6:a03:237::10) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3589.20; Wed, 18 Nov 2020 19:49:02 +0000 Received: from CY1NAM02FT064.eop-nam02.prod.protection.outlook.com (2603:10b6:0:51:cafe::7b) by DM3PR12CA0121.outlook.office365.com (2603:10b6:0:51::17) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3589.20 via Frontend Transport; Wed, 18 Nov 2020 19:49:02 +0000 Received: from xsj-pvapexch02.xlnx.xilinx.com (149.199.62.198) by CY1NAM02FT064.mail.protection.outlook.com (10.152.74.64) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.3589.20 via Frontend Transport; Wed, 18 Nov 2020 19:49:02 +0000 Received: from xsj-pvapexch02.xlnx.xilinx.com (172.19.86.41) by xsj-pvapexch02.xlnx.xilinx.com (172.19.86.41) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.1913.5; Wed, 18 Nov 2020 11:49:00 -0800 Received: from smtp.xilinx.com (172.19.127.96) by xsj-pvapexch02.xlnx.xilinx.com (172.19.86.41) with Microsoft SMTP Server id 15.1.1913.5 via Frontend Transport; Wed, 18 Nov 2020 11:49:00 -0800 Received: from [172.19.2.115] (port=52002 helo=xsjfnuv50.xilinx.com) by smtp.xilinx.com with esmtp (Exim 4.90) (envelope-from ) id 1kfTRs-0003iK-Nl; Wed, 18 Nov 2020 11:49:00 -0800 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=HGZjauiJkAziQ3FrmMdQCSqVQ8lRxlkFvJouiHsHg6gM63QRWIrb6fF84rxNodK7npf/K0Gc/4fIjx+hJJjxOCR+t4bBI6rmQxWR2DF3WEFqbcmc05zBm3pGc2n6Y77Y9ZfhuGFHNIFrMuoFpnIPg/NQKqfoNlp/C7V0fnKDqOs7TyDP6sMZER0ZImougS2YB/VoPYJKSdNYNkBzqrfFyFZcqyAtCf1VwoHClvCWJdJa/fdS0dqDuX8RMPm4GR+5EpHgh8JagVK8CeKa2x6z7+8WmNn0N7gnUFPI21DT0cZGXDzcHkl5RqbiqQk0u6Zoax0ntwPM7bzo7gSBuPDzrw== 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-SenderADCheck; bh=JlEP77TEb8SF9MAjy5QJ6aGzR5r/P/0aoihL9r+yD6E=; b=kkuba6jsxVu+Ln0dCTLNkj2esaGKhjg2TNxTWLspuOGWbiHjDjSa+TF8+kW8d9cXO8Bzm3dYlcAn0GJWjUYr5XHjolCQSUrpzq0QjtMuHK/C1CL40p3/3uUVZv1n+aAOAIsWN2Me/i7w+gimvZ+n8FFIUxlyatKURxhmAhr7CFgLkrr1MIzA5Ay9v6Z0pnOiZsRw2yvjopXobejq+JrJTE210frxet9/aMXhZlogrxrhmE8fFSTRbiF+z0P419CYKwn9Wnl9J9sOxkYtmZQE9XMzsBTyeTg5gweVbc58yIxPNemgeMNxSPunUkDUUhv2ferfDWMl6iZlWrDhwPWJSg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 149.199.62.198) smtp.rcpttodomain=nongnu.org smtp.mailfrom=xilinx.com; dmarc=bestguesspass action=none header.from=xilinx.com; dkim=none (message not signed); arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=xilinx.onmicrosoft.com; s=selector2-xilinx-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=JlEP77TEb8SF9MAjy5QJ6aGzR5r/P/0aoihL9r+yD6E=; b=TaZTO3WrsLX2AjM9nd0qGYBKvuHPcGIDQJXSiq3N/9xweXV1/b4JFrkjOjJ6sE48Xuwb4DaeAxDlymHe3WZzhHmG3AyRYE+SNi+JbF/j4YjYykzUt8xzm9HGN+8DvPK1j+gl7QBaqXmDTZCUoReF7BHGVEwzo7WGayWSWp/YZts= X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 149.199.62.198) smtp.mailfrom=xilinx.com; nongnu.org; dkim=none (message not signed) header.d=none;nongnu.org; dmarc=bestguesspass action=none header.from=xilinx.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 xilinx.com designates 149.199.62.198 as permitted sender) receiver=protection.outlook.com; client-ip=149.199.62.198; helo=xsj-pvapexch02.xlnx.xilinx.com; From: Vikram Garhwal To: Subject: [PATCH v12 2/4] xlnx-zynqmp: Connect Xilinx ZynqMP CAN controllers Date: Wed, 18 Nov 2020 11:48:44 -0800 Message-ID: <1605728926-352690-3-git-send-email-fnu.vikram@xilinx.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1605728926-352690-1-git-send-email-fnu.vikram@xilinx.com> References: <1605728926-352690-1-git-send-email-fnu.vikram@xilinx.com> MIME-Version: 1.0 X-EOPAttributedMessage: 0 X-MS-Office365-Filtering-HT: Tenant X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 13e7f7f5-7bb2-44eb-7570-08d88bfaffc6 X-MS-TrafficTypeDiagnostic: BY5PR02MB7041: X-Microsoft-Antispam-PRVS: X-Auto-Response-Suppress: DR, RN, NRN, OOF, AutoReply X-MS-Oob-TLC-OOBClassifiers: OLM:114; X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: hJsGCaT80nrjrQkH0xZv/G91l26Fb95JkCetXJFhP4sliCIELd5NVLhC3y8SiJ87C9KScKfQaxtQBZFTnYWO7CgJyv4+ZH5oM+Z+2HmgblwFE3CiqBL6XOzwJpb23M7lYJE733wdYJX/iesWtUSl4JJpb31rFdnZ6FK8vyxvZuFDD+uRafhZKJI5E8EUPBSG8/O/W6xZmeK6tl2tWMeNFb25Yk1zgnXQ4jiLWFsQiQeOpfP26FxXYVFaj9wZ6G3cIdCloMHIuVrDg1hhPugcj+QwYqoI2up6hIsXbZUTGYZCINM86XUBhkPfxJAnPPjXjHOcUfEH7FlzSFq71S2T65SFqvoVq/2PelMaZb7Ls9CdZfmIqoEEi9IFIDMxBaWr+oYUDAPSoMkoSFUeEhbad/pdNdzRVV7iY+XVJ/wawqw= X-Forefront-Antispam-Report: CIP:149.199.62.198; CTRY:US; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:xsj-pvapexch02.xlnx.xilinx.com; PTR:unknown-62-198.xilinx.com; CAT:NONE; SFS:(4636009)(396003)(136003)(39860400002)(346002)(376002)(46966005)(9786002)(47076004)(7636003)(6916009)(7696005)(356005)(82740400003)(8936002)(4326008)(83380400001)(70206006)(70586007)(6666004)(5660300002)(8676002)(36756003)(54906003)(316002)(478600001)(426003)(336012)(186003)(82310400003)(36906005)(26005)(2616005)(2906002)(102446001); DIR:OUT; SFP:1101; X-OriginatorOrg: xilinx.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 18 Nov 2020 19:49:02.1576 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 13e7f7f5-7bb2-44eb-7570-08d88bfaffc6 X-MS-Exchange-CrossTenant-Id: 657af505-d5df-48d0-8300-c31994686c5c X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=657af505-d5df-48d0-8300-c31994686c5c; Ip=[149.199.62.198]; Helo=[xsj-pvapexch02.xlnx.xilinx.com] X-MS-Exchange-CrossTenant-AuthSource: CY1NAM02FT064.eop-nam02.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: BY5PR02MB7041 Received-SPF: pass client-ip=40.107.94.80; envelope-from=fnuv@xilinx.com; helo=NAM10-MW2-obe.outbound.protection.outlook.com X-detected-operating-system: by eggs.gnu.org: First seen = 2020/11/18 14:49:04 X-ACL-Warn: Detected OS = Windows NT kernel [generic] [fuzzy] X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.001, 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.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, Vikram Garhwal , Alistair Francis , francisco.iglesias@xilinx.com, "open list:Xilinx ZynqMP and..." , "Edgar E. Iglesias" Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: pass (identity @xilinx.onmicrosoft.com) Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Connect CAN0 and CAN1 on the ZynqMP. Reviewed-by: Francisco Iglesias Reviewed-by: Edgar E. Iglesias Signed-off-by: Vikram Garhwal --- include/hw/arm/xlnx-zynqmp.h | 8 ++++++++ hw/arm/xlnx-zcu102.c | 20 ++++++++++++++++++++ hw/arm/xlnx-zynqmp.c | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 62 insertions(+) diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h index 567d0db..6f45387 100644 --- a/include/hw/arm/xlnx-zynqmp.h +++ b/include/hw/arm/xlnx-zynqmp.h @@ -22,6 +22,7 @@ #include "hw/intc/arm_gic.h" #include "hw/net/cadence_gem.h" #include "hw/char/cadence_uart.h" +#include "hw/net/xlnx-zynqmp-can.h" #include "hw/ide/ahci.h" #include "hw/sd/sdhci.h" #include "hw/ssi/xilinx_spips.h" @@ -33,6 +34,7 @@ #include "hw/cpu/cluster.h" #include "target/arm/cpu.h" #include "qom/object.h" +#include "net/can_emu.h" =20 #define TYPE_XLNX_ZYNQMP "xlnx,zynqmp" OBJECT_DECLARE_SIMPLE_TYPE(XlnxZynqMPState, XLNX_ZYNQMP) @@ -41,6 +43,8 @@ OBJECT_DECLARE_SIMPLE_TYPE(XlnxZynqMPState, XLNX_ZYNQMP) #define XLNX_ZYNQMP_NUM_RPU_CPUS 2 #define XLNX_ZYNQMP_NUM_GEMS 4 #define XLNX_ZYNQMP_NUM_UARTS 2 +#define XLNX_ZYNQMP_NUM_CAN 2 +#define XLNX_ZYNQMP_CAN_REF_CLK (24 * 1000 * 1000) #define XLNX_ZYNQMP_NUM_SDHCI 2 #define XLNX_ZYNQMP_NUM_SPIS 2 #define XLNX_ZYNQMP_NUM_GDMA_CH 8 @@ -92,6 +96,7 @@ struct XlnxZynqMPState { =20 CadenceGEMState gem[XLNX_ZYNQMP_NUM_GEMS]; CadenceUARTState uart[XLNX_ZYNQMP_NUM_UARTS]; + XlnxZynqMPCANState can[XLNX_ZYNQMP_NUM_CAN]; SysbusAHCIState sata; SDHCIState sdhci[XLNX_ZYNQMP_NUM_SDHCI]; XilinxSPIPS spi[XLNX_ZYNQMP_NUM_SPIS]; @@ -112,6 +117,9 @@ struct XlnxZynqMPState { bool virt; /* Has the RPU subsystem? */ bool has_rpu; + + /* CAN bus. */ + CanBusState *canbus[XLNX_ZYNQMP_NUM_CAN]; }; =20 #endif diff --git a/hw/arm/xlnx-zcu102.c b/hw/arm/xlnx-zcu102.c index ad7fff9..4ef0c51 100644 --- a/hw/arm/xlnx-zcu102.c +++ b/hw/arm/xlnx-zcu102.c @@ -25,6 +25,7 @@ #include "sysemu/qtest.h" #include "sysemu/device_tree.h" #include "qom/object.h" +#include "net/can_emu.h" =20 struct XlnxZCU102 { MachineState parent_obj; @@ -34,6 +35,8 @@ struct XlnxZCU102 { bool secure; bool virt; =20 + CanBusState *canbus[XLNX_ZYNQMP_NUM_CAN]; + struct arm_boot_info binfo; }; =20 @@ -125,6 +128,14 @@ static void xlnx_zcu102_init(MachineState *machine) object_property_set_bool(OBJECT(&s->soc), "virtualization", s->virt, &error_fatal); =20 + for (i =3D 0; i < XLNX_ZYNQMP_NUM_CAN; i++) { + gchar *bus_name =3D g_strdup_printf("canbus%d", i); + + object_property_set_link(OBJECT(&s->soc), bus_name, + OBJECT(s->canbus[i]), &error_fatal); + g_free(bus_name); + } + qdev_realize(DEVICE(&s->soc), NULL, &error_fatal); =20 /* Create and plug in the SD cards */ @@ -208,6 +219,15 @@ static void xlnx_zcu102_machine_instance_init(Object *= obj) s->secure =3D false; /* Default to virt (EL2) being disabled */ s->virt =3D false; + object_property_add_link(obj, "xlnx-zcu102.canbus0", TYPE_CAN_BUS, + (Object **)&s->canbus[0], + object_property_allow_set_link, + 0); + + object_property_add_link(obj, "xlnx-zcu102.canbus1", TYPE_CAN_BUS, + (Object **)&s->canbus[1], + object_property_allow_set_link, + 0); } =20 static void xlnx_zcu102_machine_class_init(ObjectClass *oc, void *data) diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c index 7885bb1..8818472 100644 --- a/hw/arm/xlnx-zynqmp.c +++ b/hw/arm/xlnx-zynqmp.c @@ -81,6 +81,14 @@ static const int uart_intr[XLNX_ZYNQMP_NUM_UARTS] =3D { 21, 22, }; =20 +static const uint64_t can_addr[XLNX_ZYNQMP_NUM_CAN] =3D { + 0xFF060000, 0xFF070000, +}; + +static const int can_intr[XLNX_ZYNQMP_NUM_CAN] =3D { + 23, 24, +}; + static const uint64_t sdhci_addr[XLNX_ZYNQMP_NUM_SDHCI] =3D { 0xFF160000, 0xFF170000, }; @@ -243,6 +251,11 @@ static void xlnx_zynqmp_init(Object *obj) TYPE_CADENCE_UART); } =20 + for (i =3D 0; i < XLNX_ZYNQMP_NUM_CAN; i++) { + object_initialize_child(obj, "can[*]", &s->can[i], + TYPE_XLNX_ZYNQMP_CAN); + } + object_initialize_child(obj, "sata", &s->sata, TYPE_SYSBUS_AHCI); =20 for (i =3D 0; i < XLNX_ZYNQMP_NUM_SDHCI; i++) { @@ -482,6 +495,23 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Erro= r **errp) gic_spi[uart_intr[i]]); } =20 + for (i =3D 0; i < XLNX_ZYNQMP_NUM_CAN; i++) { + object_property_set_int(OBJECT(&s->can[i]), "ext_clk_freq", + XLNX_ZYNQMP_CAN_REF_CLK, &error_abort); + + object_property_set_link(OBJECT(&s->can[i]), "canbus", + OBJECT(s->canbus[i]), &error_fatal); + + sysbus_realize(SYS_BUS_DEVICE(&s->can[i]), &err); + if (err) { + error_propagate(errp, err); + return; + } + sysbus_mmio_map(SYS_BUS_DEVICE(&s->can[i]), 0, can_addr[i]); + sysbus_connect_irq(SYS_BUS_DEVICE(&s->can[i]), 0, + gic_spi[can_intr[i]]); + } + object_property_set_int(OBJECT(&s->sata), "num-ports", SATA_NUM_PORTS, &error_abort); if (!sysbus_realize(SYS_BUS_DEVICE(&s->sata), errp)) { @@ -619,6 +649,10 @@ static Property xlnx_zynqmp_props[] =3D { DEFINE_PROP_BOOL("has_rpu", XlnxZynqMPState, has_rpu, false), DEFINE_PROP_LINK("ddr-ram", XlnxZynqMPState, ddr_ram, TYPE_MEMORY_REGI= ON, MemoryRegion *), + DEFINE_PROP_LINK("canbus0", XlnxZynqMPState, canbus[0], TYPE_CAN_BUS, + CanBusState *), + DEFINE_PROP_LINK("canbus1", XlnxZynqMPState, canbus[1], TYPE_CAN_BUS, + CanBusState *), DEFINE_PROP_END_OF_LIST() }; =20 --=20 2.7.4 From nobody Fri May 3 14:37:10 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=1dmarc=pass fromdomain=xilinx.com) ARC-Seal: i=2; a=rsa-sha256; t=1605729201; cv=pass; d=zohomail.com; s=zohoarc; b=aSNEn5K1U7rA2Te+7aogewgmlI/b/g1KLyUh/ZOsuGbezV0B03higvPOki83RkhJ7sNWv4FxZZ8GHD3ibegA0jsfvOZ+NE4RTL4gcNPun1zPc9oS07PDsDQopw3VG0208rPPzayU1ZgO21W/rSvGEDHyMDm8XOwVrMoXAqbrZiw= ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1605729201; h=Content-Type:Content-Transfer-Encoding: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=QWPS3Vfe1IEKxtHteenfX9mQuxXZq4soCN9C9yL6zQ8=; b=Vz6Has4HFBZtXpyN2xPyN0ruRTB6xBKQ5rXZQkBbFkkzAwxBjbBEmKfMBA1PEkciWb2xWrKrrfaA2+CR4Hf9vGsMhiBhc1SASVVqi9X+J1Ul2xLV1YRqNTbFvkbmGpzAVGrkeFJLggxPMK3Rh222eZ/9lWNy1YwFaHiPkltwuMY= 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=1dmarc=pass fromdomain=xilinx.com) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1605729201864692.3946046128909; Wed, 18 Nov 2020 11:53:21 -0800 (PST) Received: from localhost ([::1]:56900 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kfTW4-00089W-NY for importer@patchew.org; Wed, 18 Nov 2020 14:53:20 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:48936) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kfTS4-0004RT-D1 for qemu-devel@nongnu.org; Wed, 18 Nov 2020 14:49:12 -0500 Received: from mail-dm6nam12on2048.outbound.protection.outlook.com ([40.107.243.48]:45032 helo=NAM12-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 1kfTS1-0005Z4-JL for qemu-devel@nongnu.org; Wed, 18 Nov 2020 14:49:12 -0500 Received: from DM3PR12CA0132.namprd12.prod.outlook.com (2603:10b6:0:51::28) by SN6PR02MB4765.namprd02.prod.outlook.com (2603:10b6:805:9b::25) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3589.20; Wed, 18 Nov 2020 19:49:03 +0000 Received: from CY1NAM02FT064.eop-nam02.prod.protection.outlook.com (2603:10b6:0:51:cafe::3) by DM3PR12CA0132.outlook.office365.com (2603:10b6:0:51::28) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3589.20 via Frontend Transport; Wed, 18 Nov 2020 19:49:03 +0000 Received: from xsj-pvapexch02.xlnx.xilinx.com (149.199.62.198) by CY1NAM02FT064.mail.protection.outlook.com (10.152.74.64) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.3589.20 via Frontend Transport; Wed, 18 Nov 2020 19:49:03 +0000 Received: from xsj-pvapexch01.xlnx.xilinx.com (172.19.86.40) by xsj-pvapexch02.xlnx.xilinx.com (172.19.86.41) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.1913.5; Wed, 18 Nov 2020 11:49:01 -0800 Received: from smtp.xilinx.com (172.19.127.96) by xsj-pvapexch01.xlnx.xilinx.com (172.19.86.40) with Microsoft SMTP Server id 15.1.1913.5 via Frontend Transport; Wed, 18 Nov 2020 11:49:01 -0800 Received: from [172.19.2.115] (port=52002 helo=xsjfnuv50.xilinx.com) by smtp.xilinx.com with esmtp (Exim 4.90) (envelope-from ) id 1kfTRt-0003iK-Bv; Wed, 18 Nov 2020 11:49:01 -0800 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=aG4wPKyidU2XPAQy3f1sco27SHpOR+49s5Lb0YEsvAlnx19W21oTaLv7ybd5Mum6TWLqnuYy7dL6C98491nQQe9jpDod/MykKIPu477RoCeyoOK//Z6G4QJEHuyXPoGfvkk7Qnww3Mf5qnfevnhF2LfeHxbH/zfN3/8TSsfXyyXL/QBPG2qxVWAtzYznbxoKg3Lgqa96+VU6W0Yx1DHSR/e8nKuFZLriJUYU31A0O2iFuQiE/t3kDggaPY6D7n3sSf1RtArCM5rfvWanlUPTBXQEQSZYE7q/VyHuibIwUG7KVA3eZbGjTXlVKRrSc1yDZOceH7pVSxMx4E9NTKDtCg== 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-SenderADCheck; bh=QWPS3Vfe1IEKxtHteenfX9mQuxXZq4soCN9C9yL6zQ8=; b=QXaPVNu3VzPBpKh/OavKEcTUDwH7x62pid0E7KmF1RYTBjUrHlofL1mLdl/4RC0teDYFFwqkS8Lo7jQEnxlBOi/8Z9NHTCcYdPyIIMz/yffT+nyZbjU9CPsjbqUf14qKco4bYThnEuH4OCU1dERR122ZzYrgyvhAVNelQe2Cm64LtSIHHfE4lQ19iO8sFeQwrl6rx0CJz2tjzEK+6n5bAgyKC23wGwrt4c8hrygEm2yowKkpeQhCzaJCZ22kxZVCwkd2jy10vNsXfMecD3oLBq8yWFmHnVWy/btfIz2SlaStTKqgCniPRPZqEEVxW8SatoSCSlJ2FHLT7rUQycmMkQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 149.199.62.198) smtp.rcpttodomain=nongnu.org smtp.mailfrom=xilinx.com; dmarc=bestguesspass action=none header.from=xilinx.com; dkim=none (message not signed); arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=xilinx.onmicrosoft.com; s=selector2-xilinx-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=QWPS3Vfe1IEKxtHteenfX9mQuxXZq4soCN9C9yL6zQ8=; b=Yn0lXzt+43c43r5J6LAriyTeZx0otxJBl+Z11yUHFWusILHIraWFIziqiI3GeBaY3rC9ILA162wsR9pFn3jDlsZ6g1AS/2tqARGGCpTAB2edkMOgASZvFNgSDWlYsmh0gZJOXM9jG7+gTguYoOcr56C21uteqsfN3D5mV53HJhM= X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 149.199.62.198) smtp.mailfrom=xilinx.com; nongnu.org; dkim=none (message not signed) header.d=none;nongnu.org; dmarc=bestguesspass action=none header.from=xilinx.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 xilinx.com designates 149.199.62.198 as permitted sender) receiver=protection.outlook.com; client-ip=149.199.62.198; helo=xsj-pvapexch02.xlnx.xilinx.com; From: Vikram Garhwal To: Subject: [PATCH v12 3/4] tests/qtest: Introduce tests for Xilinx ZynqMP CAN controller Date: Wed, 18 Nov 2020 11:48:45 -0800 Message-ID: <1605728926-352690-4-git-send-email-fnu.vikram@xilinx.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1605728926-352690-1-git-send-email-fnu.vikram@xilinx.com> References: <1605728926-352690-1-git-send-email-fnu.vikram@xilinx.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-EOPAttributedMessage: 0 X-MS-Office365-Filtering-HT: Tenant X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 7564dab4-f6c6-4153-1414-08d88bfb004a X-MS-TrafficTypeDiagnostic: SN6PR02MB4765: X-Microsoft-Antispam-PRVS: X-Auto-Response-Suppress: DR, RN, NRN, OOF, AutoReply X-MS-Oob-TLC-OOBClassifiers: OLM:7691; X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: sfkq/vU+QR2EEi1mvEnaMywOgXv2Yz0QisPU5KkpEz0Sd+WTesZf7e0sbnWvMtxoC4+w1J8KiWI1aAOrb/uNJ1sjN9bMRxvqbacfDhtXmJg3Sh/WItQT1LXCNo+/Mch3YI+xjDWqzDN7SpEKcZbCMY57vRosqmFntpdxEVdl7LTIi6jTLrtYGmoEMN+r1xl20kFkz46cBAhHY96gK7MWJqC3V8xqICgNDD3LkVQaPvi5lY9t9KM7o0pDwiuHPA8AD+81pYS+DIq5DA0Oejdy/rLk59dDuJo8Go/SOCO6//9ebs7fcm59H+t6HhLFv51zcHdT7g7r8JbhC4WeHWtJgA8jQMgZodvuAU16g+/KeSwy0rbFPIyycOOHCdZK2nZumKNTLISQStWdhgQNBQbJTZskMI7vMUqDc8JAZgjFnCM= X-Forefront-Antispam-Report: CIP:149.199.62.198; CTRY:US; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:xsj-pvapexch02.xlnx.xilinx.com; PTR:unknown-62-198.xilinx.com; CAT:NONE; SFS:(4636009)(376002)(346002)(39860400002)(396003)(136003)(46966005)(83380400001)(82740400003)(9786002)(7696005)(82310400003)(26005)(8676002)(426003)(8936002)(336012)(6916009)(47076004)(7636003)(356005)(2616005)(5660300002)(36906005)(2906002)(316002)(36756003)(54906003)(478600001)(30864003)(6666004)(186003)(4326008)(70586007)(70206006)(102446001); DIR:OUT; SFP:1101; X-OriginatorOrg: xilinx.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 18 Nov 2020 19:49:03.0202 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 7564dab4-f6c6-4153-1414-08d88bfb004a X-MS-Exchange-CrossTenant-Id: 657af505-d5df-48d0-8300-c31994686c5c X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=657af505-d5df-48d0-8300-c31994686c5c; Ip=[149.199.62.198]; Helo=[xsj-pvapexch02.xlnx.xilinx.com] X-MS-Exchange-CrossTenant-AuthSource: CY1NAM02FT064.eop-nam02.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: SN6PR02MB4765 Received-SPF: pass client-ip=40.107.243.48; envelope-from=fnuv@xilinx.com; helo=NAM12-DM6-obe.outbound.protection.outlook.com X-detected-operating-system: by eggs.gnu.org: First seen = 2020/11/18 14:49:08 X-ACL-Warn: Detected OS = Windows NT kernel [generic] [fuzzy] X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.001, 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.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Laurent Vivier , peter.maydell@linaro.org, Thomas Huth , Vikram Garhwal , francisco.iglesias@xilinx.com, Paolo Bonzini Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: pass (identity @xilinx.onmicrosoft.com) The QTests perform five tests on the Xilinx ZynqMP CAN controller: Tests the CAN controller in loopback, sleep and snoop mode. Tests filtering of incoming CAN messages. Reviewed-by: Philippe Mathieu-Daud=C3=A9 Reviewed-by: Francisco Iglesias Signed-off-by: Vikram Garhwal --- tests/qtest/xlnx-can-test.c | 360 ++++++++++++++++++++++++++++++++++++++++= ++++ tests/qtest/meson.build | 1 + 2 files changed, 361 insertions(+) create mode 100644 tests/qtest/xlnx-can-test.c diff --git a/tests/qtest/xlnx-can-test.c b/tests/qtest/xlnx-can-test.c new file mode 100644 index 0000000..3d11200 --- /dev/null +++ b/tests/qtest/xlnx-can-test.c @@ -0,0 +1,360 @@ +/* + * QTests for the Xilinx ZynqMP CAN controller. + * + * Copyright (c) 2020 Xilinx 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 "libqos/libqtest.h" + +/* Base address. */ +#define CAN0_BASE_ADDR 0xFF060000 +#define CAN1_BASE_ADDR 0xFF070000 + +/* Register addresses. */ +#define R_SRR_OFFSET 0x00 +#define R_MSR_OFFSET 0x04 +#define R_SR_OFFSET 0x18 +#define R_ISR_OFFSET 0x1C +#define R_ICR_OFFSET 0x24 +#define R_TXID_OFFSET 0x30 +#define R_TXDLC_OFFSET 0x34 +#define R_TXDATA1_OFFSET 0x38 +#define R_TXDATA2_OFFSET 0x3C +#define R_RXID_OFFSET 0x50 +#define R_RXDLC_OFFSET 0x54 +#define R_RXDATA1_OFFSET 0x58 +#define R_RXDATA2_OFFSET 0x5C +#define R_AFR 0x60 +#define R_AFMR1 0x64 +#define R_AFIR1 0x68 +#define R_AFMR2 0x6C +#define R_AFIR2 0x70 +#define R_AFMR3 0x74 +#define R_AFIR3 0x78 +#define R_AFMR4 0x7C +#define R_AFIR4 0x80 + +/* CAN modes. */ +#define CONFIG_MODE 0x00 +#define NORMAL_MODE 0x00 +#define LOOPBACK_MODE 0x02 +#define SNOOP_MODE 0x04 +#define SLEEP_MODE 0x01 +#define ENABLE_CAN (1 << 1) +#define STATUS_NORMAL_MODE (1 << 3) +#define STATUS_LOOPBACK_MODE (1 << 1) +#define STATUS_SNOOP_MODE (1 << 12) +#define STATUS_SLEEP_MODE (1 << 2) +#define ISR_TXOK (1 << 1) +#define ISR_RXOK (1 << 4) + +static void match_rx_tx_data(const uint32_t *buf_tx, const uint32_t *buf_r= x, + uint8_t can_timestamp) +{ + uint16_t size =3D 0; + uint8_t len =3D 4; + + while (size < len) { + if (R_RXID_OFFSET + 4 * size =3D=3D R_RXDLC_OFFSET) { + g_assert_cmpint(buf_rx[size], =3D=3D, buf_tx[size] + can_times= tamp); + } else { + g_assert_cmpint(buf_rx[size], =3D=3D, buf_tx[size]); + } + + size++; + } +} + +static void read_data(QTestState *qts, uint64_t can_base_addr, uint32_t *b= uf_rx) +{ + uint32_t int_status; + + /* Read the interrupt on CAN 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); + + /* Read the RX register data for CAN. */ + buf_rx[0] =3D qtest_readl(qts, can_base_addr + R_RXID_OFFSET); + buf_rx[1] =3D qtest_readl(qts, can_base_addr + R_RXDLC_OFFSET); + buf_rx[2] =3D qtest_readl(qts, can_base_addr + R_RXDATA1_OFFSET); + buf_rx[3] =3D qtest_readl(qts, can_base_addr + R_RXDATA2_OFFSET); + + /* Clear the RX interrupt. */ + qtest_writel(qts, CAN1_BASE_ADDR + R_ICR_OFFSET, ISR_RXOK); +} + +static void send_data(QTestState *qts, uint64_t can_base_addr, + const uint32_t *buf_tx) +{ + uint32_t int_status; + + /* Write the TX register data for CAN. */ + qtest_writel(qts, can_base_addr + R_TXID_OFFSET, buf_tx[0]); + qtest_writel(qts, can_base_addr + R_TXDLC_OFFSET, buf_tx[1]); + qtest_writel(qts, can_base_addr + R_TXDATA1_OFFSET, buf_tx[2]); + qtest_writel(qts, can_base_addr + R_TXDATA2_OFFSET, buf_tx[3]); + + /* Read the interrupt on CAN 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, CAN0_BASE_ADDR + R_ICR_OFFSET, ISR_TXOK); +} + +/* + * This test will be transferring data from CAN0 and CAN1 through canbus. = CAN0 + * initiate the data transfer to can-bus, CAN1 receives the data. Test com= pares + * the data sent from CAN0 with received on CAN1. + */ +static void test_can_bus(void) +{ + const uint32_t buf_tx[4] =3D { 0xFF, 0x80000000, 0x12345678, 0x8765432= 1 }; + uint32_t buf_rx[4] =3D { 0x00, 0x00, 0x00, 0x00 }; + uint32_t status =3D 0; + uint8_t can_timestamp =3D 1; + + QTestState *qts =3D qtest_init("-machine xlnx-zcu102" + " -object can-bus,id=3Dcanbus0" + " -machine xlnx-zcu102.canbus0=3Dcanbus0" + " -machine xlnx-zcu102.canbus1=3Dcanbus0" + ); + + /* Configure the CAN0 and CAN1. */ + qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN); + qtest_writel(qts, CAN0_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE); + qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN); + qtest_writel(qts, CAN1_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE); + + /* Check here if CAN0 and CAN1 are in normal mode. */ + status =3D qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET); + g_assert_cmpint(status, =3D=3D, STATUS_NORMAL_MODE); + + status =3D qtest_readl(qts, CAN1_BASE_ADDR + R_SR_OFFSET); + g_assert_cmpint(status, =3D=3D, STATUS_NORMAL_MODE); + + send_data(qts, CAN0_BASE_ADDR, buf_tx); + + read_data(qts, CAN1_BASE_ADDR, buf_rx); + match_rx_tx_data(buf_tx, buf_rx, can_timestamp); + + qtest_quit(qts); +} + +/* + * This test is performing loopback mode on CAN0 and CAN1. Data sent from = TX of + * each CAN0 and CAN1 are compared with RX register data for respective CA= N. + */ +static void test_can_loopback(void) +{ + uint32_t buf_tx[4] =3D { 0xFF, 0x80000000, 0x12345678, 0x87654321 }; + uint32_t buf_rx[4] =3D { 0x00, 0x00, 0x00, 0x00 }; + uint32_t status =3D 0; + + QTestState *qts =3D qtest_init("-machine xlnx-zcu102" + " -object can-bus,id=3Dcanbus0" + " -machine xlnx-zcu102.canbus0=3Dcanbus0" + " -machine xlnx-zcu102.canbus1=3Dcanbus0" + ); + + /* Configure the CAN0 in loopback mode. */ + qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, CONFIG_MODE); + qtest_writel(qts, CAN0_BASE_ADDR + R_MSR_OFFSET, LOOPBACK_MODE); + qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN); + + /* Check here if CAN0 is set in loopback mode. */ + status =3D qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET); + + g_assert_cmpint(status, =3D=3D, STATUS_LOOPBACK_MODE); + + send_data(qts, CAN0_BASE_ADDR, buf_tx); + read_data(qts, CAN0_BASE_ADDR, buf_rx); + match_rx_tx_data(buf_tx, buf_rx, 0); + + /* Configure the CAN1 in loopback mode. */ + qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, CONFIG_MODE); + qtest_writel(qts, CAN1_BASE_ADDR + R_MSR_OFFSET, LOOPBACK_MODE); + qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN); + + /* Check here if CAN1 is set in loopback mode. */ + status =3D qtest_readl(qts, CAN1_BASE_ADDR + R_SR_OFFSET); + + g_assert_cmpint(status, =3D=3D, STATUS_LOOPBACK_MODE); + + send_data(qts, CAN1_BASE_ADDR, buf_tx); + read_data(qts, CAN1_BASE_ADDR, buf_rx); + match_rx_tx_data(buf_tx, buf_rx, 0); + + qtest_quit(qts); +} + +/* + * Enable filters for CAN1. This will filter incoming messages with ID. In= this + * test message will pass through filter 2. + */ +static void test_can_filter(void) +{ + uint32_t buf_tx[4] =3D { 0x14, 0x80000000, 0x12345678, 0x87654321 }; + uint32_t buf_rx[4] =3D { 0x00, 0x00, 0x00, 0x00 }; + uint32_t status =3D 0; + uint8_t can_timestamp =3D 1; + + QTestState *qts =3D qtest_init("-machine xlnx-zcu102" + " -object can-bus,id=3Dcanbus0" + " -machine xlnx-zcu102.canbus0=3Dcanbus0" + " -machine xlnx-zcu102.canbus1=3Dcanbus0" + ); + + /* Configure the CAN0 and CAN1. */ + qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN); + qtest_writel(qts, CAN0_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE); + qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN); + qtest_writel(qts, CAN1_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE); + + /* Check here if CAN0 and CAN1 are in normal mode. */ + status =3D qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET); + g_assert_cmpint(status, =3D=3D, STATUS_NORMAL_MODE); + + status =3D qtest_readl(qts, CAN1_BASE_ADDR + R_SR_OFFSET); + g_assert_cmpint(status, =3D=3D, STATUS_NORMAL_MODE); + + /* Set filter for CAN1 for incoming messages. */ + qtest_writel(qts, CAN1_BASE_ADDR + R_AFR, 0x0); + qtest_writel(qts, CAN1_BASE_ADDR + R_AFMR1, 0xF7); + qtest_writel(qts, CAN1_BASE_ADDR + R_AFIR1, 0x121F); + qtest_writel(qts, CAN1_BASE_ADDR + R_AFMR2, 0x5431); + qtest_writel(qts, CAN1_BASE_ADDR + R_AFIR2, 0x14); + qtest_writel(qts, CAN1_BASE_ADDR + R_AFMR3, 0x1234); + qtest_writel(qts, CAN1_BASE_ADDR + R_AFIR3, 0x5431); + qtest_writel(qts, CAN1_BASE_ADDR + R_AFMR4, 0xFFF); + qtest_writel(qts, CAN1_BASE_ADDR + R_AFIR4, 0x1234); + + qtest_writel(qts, CAN1_BASE_ADDR + R_AFR, 0xF); + + send_data(qts, CAN0_BASE_ADDR, buf_tx); + + read_data(qts, CAN1_BASE_ADDR, buf_rx); + match_rx_tx_data(buf_tx, buf_rx, can_timestamp); + + qtest_quit(qts); +} + +/* Testing sleep mode on CAN0 while CAN1 is in normal mode. */ +static void test_can_sleepmode(void) +{ + uint32_t buf_tx[4] =3D { 0x14, 0x80000000, 0x12345678, 0x87654321 }; + uint32_t buf_rx[4] =3D { 0x00, 0x00, 0x00, 0x00 }; + uint32_t status =3D 0; + uint8_t can_timestamp =3D 1; + + QTestState *qts =3D qtest_init("-machine xlnx-zcu102" + " -object can-bus,id=3Dcanbus0" + " -machine xlnx-zcu102.canbus0=3Dcanbus0" + " -machine xlnx-zcu102.canbus1=3Dcanbus0" + ); + + /* Configure the CAN0. */ + qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, CONFIG_MODE); + qtest_writel(qts, CAN0_BASE_ADDR + R_MSR_OFFSET, SLEEP_MODE); + qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN); + + qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN); + qtest_writel(qts, CAN1_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE); + + /* Check here if CAN0 is in SLEEP mode and CAN1 in normal mode. */ + status =3D qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET); + g_assert_cmpint(status, =3D=3D, STATUS_SLEEP_MODE); + + status =3D qtest_readl(qts, CAN1_BASE_ADDR + R_SR_OFFSET); + g_assert_cmpint(status, =3D=3D, STATUS_NORMAL_MODE); + + send_data(qts, CAN1_BASE_ADDR, buf_tx); + + /* + * Once CAN1 sends data on can-bus. CAN0 should exit sleep mode. + * Check the CAN0 status now. It should exit the sleep mode and receiv= e the + * incoming data. + */ + status =3D qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET); + g_assert_cmpint(status, =3D=3D, STATUS_NORMAL_MODE); + + read_data(qts, CAN0_BASE_ADDR, buf_rx); + + match_rx_tx_data(buf_tx, buf_rx, can_timestamp); + + qtest_quit(qts); +} + +/* Testing Snoop mode on CAN0 while CAN1 is in normal mode. */ +static void test_can_snoopmode(void) +{ + uint32_t buf_tx[4] =3D { 0x14, 0x80000000, 0x12345678, 0x87654321 }; + uint32_t buf_rx[4] =3D { 0x00, 0x00, 0x00, 0x00 }; + uint32_t status =3D 0; + uint8_t can_timestamp =3D 1; + + QTestState *qts =3D qtest_init("-machine xlnx-zcu102" + " -object can-bus,id=3Dcanbus0" + " -machine xlnx-zcu102.canbus0=3Dcanbus0" + " -machine xlnx-zcu102.canbus1=3Dcanbus0" + ); + + /* Configure the CAN0. */ + qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, CONFIG_MODE); + qtest_writel(qts, CAN0_BASE_ADDR + R_MSR_OFFSET, SNOOP_MODE); + qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN); + + qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN); + qtest_writel(qts, CAN1_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE); + + /* Check here if CAN0 is in SNOOP mode and CAN1 in normal mode. */ + status =3D qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET); + g_assert_cmpint(status, =3D=3D, STATUS_SNOOP_MODE); + + status =3D qtest_readl(qts, CAN1_BASE_ADDR + R_SR_OFFSET); + g_assert_cmpint(status, =3D=3D, STATUS_NORMAL_MODE); + + send_data(qts, CAN1_BASE_ADDR, buf_tx); + + read_data(qts, CAN0_BASE_ADDR, buf_rx); + + match_rx_tx_data(buf_tx, buf_rx, can_timestamp); + + qtest_quit(qts); +} + +int main(int argc, char **argv) +{ + g_test_init(&argc, &argv, NULL); + + qtest_add_func("/net/can/can_bus", test_can_bus); + qtest_add_func("/net/can/can_loopback", test_can_loopback); + qtest_add_func("/net/can/can_filter", test_can_filter); + qtest_add_func("/net/can/can_test_snoopmode", test_can_snoopmode); + qtest_add_func("/net/can/can_test_sleepmode", test_can_sleepmode); + + return g_test_run(); +} diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build index c19f1c8..4ca83ce 100644 --- a/tests/qtest/meson.build +++ b/tests/qtest/meson.build @@ -156,6 +156,7 @@ qtests_aarch64 =3D \ ['arm-cpu-features', 'numa-test', 'boot-serial-test', + 'xlnx-can-test', 'migration-test'] =20 qtests_s390x =3D \ --=20 2.7.4 From nobody Fri May 3 14:37:10 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=1dmarc=pass fromdomain=xilinx.com) ARC-Seal: i=2; a=rsa-sha256; t=1605729057; cv=pass; d=zohomail.com; s=zohoarc; b=H/cDK2JegKgpOmyLM24SWclWK6TA3sMM0vPivwXcDs+i78IS8VgGNzlPB/2GH9nwVZJSzlPIW54VrQQgJmpfJlC+IK69wnQDCe36XmgKl9S6YlZVqIwMJ0TsenPhe1kIVKexNFV20STLezlTgp4vYzpplZT/186Fw4Himx3BpZQ= ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1605729057; 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=nzXBABBh3RN7rpqsrFWWBz9hU1S7g1JHE8nFHCOo798=; b=TN8SU8GEGzZw91QvaBkQuhCBfEjlHP+9ec4YdQXrFMKbX/np4yGBZn6ljtDZWeENZE27RZmeORXeKyMpJamtzDY/V4gClDwW8a11CfoCRGk2P8YKRc4ToYMY0mRUbXypR35ZUN8Ixl9DoNWT6Rz6VKXiA7IN+2fuDCJapqr4VoQ= 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=1dmarc=pass fromdomain=xilinx.com) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1605729057837754.1812264721987; Wed, 18 Nov 2020 11:50:57 -0800 (PST) Received: from localhost ([::1]:51464 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kfTTk-0005q9-JS for importer@patchew.org; Wed, 18 Nov 2020 14:50:56 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:48886) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kfTS2-0004NW-2J for qemu-devel@nongnu.org; Wed, 18 Nov 2020 14:49:10 -0500 Received: from mail-mw2nam12on2080.outbound.protection.outlook.com ([40.107.244.80]:49467 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 1kfTRy-0005Ya-W2 for qemu-devel@nongnu.org; Wed, 18 Nov 2020 14:49:08 -0500 Received: from BL1PR13CA0190.namprd13.prod.outlook.com (2603:10b6:208:2be::15) by MN2PR02MB6784.namprd02.prod.outlook.com (2603:10b6:208:15f::20) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3564.28; Wed, 18 Nov 2020 19:49:03 +0000 Received: from BL2NAM02FT056.eop-nam02.prod.protection.outlook.com (2603:10b6:208:2be:cafe::1c) by BL1PR13CA0190.outlook.office365.com (2603:10b6:208:2be::15) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3564.14 via Frontend Transport; Wed, 18 Nov 2020 19:49:03 +0000 Received: from xsj-pvapexch01.xlnx.xilinx.com (149.199.62.198) by BL2NAM02FT056.mail.protection.outlook.com (10.152.77.221) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.3564.22 via Frontend Transport; Wed, 18 Nov 2020 19:49:03 +0000 Received: from xsj-pvapexch02.xlnx.xilinx.com (172.19.86.41) by xsj-pvapexch01.xlnx.xilinx.com (172.19.86.40) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.1913.5; Wed, 18 Nov 2020 11:49:01 -0800 Received: from smtp.xilinx.com (172.19.127.96) by xsj-pvapexch02.xlnx.xilinx.com (172.19.86.41) with Microsoft SMTP Server id 15.1.1913.5 via Frontend Transport; Wed, 18 Nov 2020 11:49:01 -0800 Received: from [172.19.2.115] (port=52002 helo=xsjfnuv50.xilinx.com) by smtp.xilinx.com with esmtp (Exim 4.90) (envelope-from ) id 1kfTRt-0003iK-Sg; Wed, 18 Nov 2020 11:49:01 -0800 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=c9x975oHg5b9khGl1uIgER79QnCsYcID7K/AMO7yRlV3TBRUr+fFMNk/lN4z2D9GuF+PhxlcdvH4VE3WuiC80sSJqvU5xuJpJk42c5OKh7UkJ6sp9J6K67ajJJ1FdmlbhqsKgTta8+lxA9cw/mmK0M1xxyQ6e6pUT3acyzT7qYzm2AqLOdXNM40Ua3KhTiUnWEXpzGZKClodohltly4/YoYTnnBHlFVnZHauq/WJvPFN68sXoLmUAwWp1JoU9tT9alFHvmbbQ14xNM1Ce0cCEwlpsH56hI8mTPX2xFYe0vJtu3c1jIOTwJvAs/jFMmVDdURJ0sApPmZMe32cGaeLjg== 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-SenderADCheck; bh=nzXBABBh3RN7rpqsrFWWBz9hU1S7g1JHE8nFHCOo798=; b=huCvsrphI37j8WX4ZqVLbd6wLaoB4Q4gRT2K7i8x47nZWrYkY7JM8EpoVhLKxZ2gFjE9X4zoglrCQ/HuEtjwElYYJS/rBelF/XHIyThcKTx69o09HZRkjpwnfY4iD1ErmpEt3b5L6+s8EMpuHMXOHcq8d4fmiqCGcub0XHzF0ga3XbVyWvwdgTLxA9IQxi4RcBf/Fvx2u+ZVy5DXDnO9WgBZ6F0jARawK/yGzXIPa0uW2x8gtzcdFp47mcXFQitwrD7FN/xptl4PJ7HpWu9MfjkvUEVM/jcxR5NneV1nTY1KYtdt4f8d9wT1PI6b7rAhAu4xUID4YQMZ4u2YwCEa2g== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 149.199.62.198) smtp.rcpttodomain=nongnu.org smtp.mailfrom=xilinx.com; dmarc=bestguesspass action=none header.from=xilinx.com; dkim=none (message not signed); arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=xilinx.onmicrosoft.com; s=selector2-xilinx-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=nzXBABBh3RN7rpqsrFWWBz9hU1S7g1JHE8nFHCOo798=; b=oH4BAhvZVZd/c9gucF5LzL159NL9RTEnmmJuy4oVAjSS0Q5WFZENDldMrIXBhIJSYUgx3QRqi+632zT0fzB/v/vfPsP19le2j9fQ9XEjyUd91TyPd9i/n4z8erY6W5/iUBWnQWfykeqy51byHSG6xuMJ4GtNm9n3HYSVFoCiM7w= X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 149.199.62.198) smtp.mailfrom=xilinx.com; nongnu.org; dkim=none (message not signed) header.d=none;nongnu.org; dmarc=bestguesspass action=none header.from=xilinx.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 xilinx.com designates 149.199.62.198 as permitted sender) receiver=protection.outlook.com; client-ip=149.199.62.198; helo=xsj-pvapexch01.xlnx.xilinx.com; From: Vikram Garhwal To: Subject: [PATCH v12 4/4] MAINTAINERS: Add maintainer entry for Xilinx ZynqMP CAN controller Date: Wed, 18 Nov 2020 11:48:46 -0800 Message-ID: <1605728926-352690-5-git-send-email-fnu.vikram@xilinx.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1605728926-352690-1-git-send-email-fnu.vikram@xilinx.com> References: <1605728926-352690-1-git-send-email-fnu.vikram@xilinx.com> MIME-Version: 1.0 X-EOPAttributedMessage: 0 X-MS-Office365-Filtering-HT: Tenant X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 713a3140-7ea7-4d44-5731-08d88bfb00b5 X-MS-TrafficTypeDiagnostic: MN2PR02MB6784: X-Microsoft-Antispam-PRVS: X-Auto-Response-Suppress: DR, RN, NRN, OOF, AutoReply X-MS-Oob-TLC-OOBClassifiers: OLM:331; X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: 0uQpFnpkdzYhQiNp684SzSCg+X7uzSMNJ8T/spBIr7+ZrDty3H6WsdQABhzs2cytE7/P4URgvs0OdC8BZlZa5W1vlJ1BzmnmNsKNEX3PBJJC+GaTpZr1SCg46nlMVdlo2mGuZKcSpcwrMrmJDK8nMpzj9vEa31XIKELJLd0tQOesCvme/Y5gef8n4t6qgTsStZlZNdlFQ9VUIyvVGTZNtlsP+2JQ4Hjch/q6fEgGOpALFyeDUe7j7BbGmKlHdd0FjlcDU9y0PeB+ZQMUnwDmWaWqp1ptUwV8NkQTur+OnAJdgo0EOOXIB01IXxpy8hQc7MbCcFEnM+Ru8h3/2CMZl757eRz6auxFWqxihirzt9ux6fyt7Zesm7Th2VtQd+nGh10Mbuh8lGM6ogy9+kdk95VXilbqgOU7QCztXsOxrHQ= X-Forefront-Antispam-Report: CIP:149.199.62.198; CTRY:US; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:xsj-pvapexch01.xlnx.xilinx.com; PTR:unknown-62-198.xilinx.com; CAT:NONE; SFS:(4636009)(136003)(346002)(39860400002)(396003)(376002)(46966005)(5660300002)(316002)(478600001)(54906003)(6666004)(36906005)(186003)(426003)(8936002)(7696005)(107886003)(2616005)(36756003)(70586007)(70206006)(82310400003)(26005)(4744005)(82740400003)(6916009)(336012)(2906002)(7636003)(8676002)(9786002)(4326008)(356005)(47076004)(102446001); DIR:OUT; SFP:1101; X-OriginatorOrg: xilinx.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 18 Nov 2020 19:49:03.6442 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 713a3140-7ea7-4d44-5731-08d88bfb00b5 X-MS-Exchange-CrossTenant-Id: 657af505-d5df-48d0-8300-c31994686c5c X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=657af505-d5df-48d0-8300-c31994686c5c; Ip=[149.199.62.198]; Helo=[xsj-pvapexch01.xlnx.xilinx.com] X-MS-Exchange-CrossTenant-AuthSource: BL2NAM02FT056.eop-nam02.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: MN2PR02MB6784 Received-SPF: pass client-ip=40.107.244.80; envelope-from=fnuv@xilinx.com; helo=NAM12-MW2-obe.outbound.protection.outlook.com X-detected-operating-system: by eggs.gnu.org: First seen = 2020/11/18 14:49:05 X-ACL-Warn: Detected OS = Windows NT kernel [generic] [fuzzy] X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.001, 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.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: francisco.iglesias@xilinx.com, Vikram Garhwal , peter.maydell@linaro.org Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: pass (identity @xilinx.onmicrosoft.com) Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Reviewed-by: Francisco Iglesias Reviewed-by: Edgar E. Iglesias Signed-off-by: Vikram Garhwal --- MAINTAINERS | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 63223e1..447b7f2 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1554,6 +1554,14 @@ F: hw/net/opencores_eth.c =20 Devices ------- +Xilinx CAN +M: Vikram Garhwal +M: Francisco Iglesias +S: Maintained +F: hw/net/can/xlnx-* +F: include/hw/net/xlnx-* +F: tests/qtest/xlnx-can-test* + EDU M: Jiri Slaby S: Maintained --=20 2.7.4