From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 983A944111; Thu, 30 May 2024 16:52:46 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 3454042DD5; Thu, 30 May 2024 16:50:23 +0200 (CEST) Received: from egress-ip42b.ess.de.barracuda.com (egress-ip42b.ess.de.barracuda.com [18.185.115.246]) by mails.dpdk.org (Postfix) with ESMTP id F0BE042DC7 for ; Thu, 30 May 2024 16:50:19 +0200 (CEST) Received: from EUR04-VI1-obe.outbound.protection.outlook.com (mail-vi1eur04lp2048.outbound.protection.outlook.com [104.47.14.48]) by mx-outbound40-151.eu-central-1c.ess.aws.cudaops.com (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Thu, 30 May 2024 14:50:11 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=gfekM3AOnw8VwBrfz8WEEjixy5iDjcivWITsswuOh3Aq/NC7wzP62zZcVC5Kntj5beTMSTW820eQFA6TMHrhmxAF1eOamC7V4cRG/7s7lrwe1chL4UHpEQBr+w57fyKRNn80SzAHNEOIQaWwuAqj+RUTkJLaM91fmxfmhC3x2mmvZgJqOg+34gDYGUPHe1r+9d1FPyXLfCOTiswDzDFe3bdCvuNteuAqbws0UMVdKgXmnSPnPRMUrakZ2Iobajm2BevMHCz1COwqRg8LidRVEOsO1mVhAR3JxI8Vcglsahe4s/yIoLC6gybMardbWmUetYKEjlS2kkimP1mxgkzqzA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=03p8MYGSnllvCXcRz3LW0vpb/wohd6D0uxYwoLzQWWg=; b=PBkJGAGVR1+64FKJJn9nH/WpPRaYzQOYP+mvUI2sKvjHsBYZYI0HNvrUG4S03HJf8rZMSfPrU0x22LgkJzecDcCDrd1glWdvJgsckWVGtKStqGx9BVb8zFrkRYkhbcnJWjgtADEe/jnU0yf74bd4xV8yT7x4edCtaCo7sZbHtBFh9SFCtC/jhzqcwdP/2vFwdtsi/RCgtvgOTuQCM7GyXLKlKduWviPWu5UyKWDgqyRyZLG5nANp3YUslXHA6RtFJNSBNsBpC7lho6HhWverlBRKm/B2yOqZSquPwTRk7Tl7McUIjILyy29pdyCYHJ1pg6ezf7qdtHBi1D8YOuS6Ww== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=fail (sender ip is 178.72.21.4) smtp.rcpttodomain=dpdk.org smtp.mailfrom=napatech.com; dmarc=fail (p=reject sp=reject pct=100) action=oreject header.from=napatech.com; dkim=none (message not signed); arc=none (0) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=napatech.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=03p8MYGSnllvCXcRz3LW0vpb/wohd6D0uxYwoLzQWWg=; b=YsoRb1ENz+E4AX7AZeoTZ7zXmEwW2eP8/nxtLMlCYjStNDlDLPtKPpnMHaL1W66Ed5GDeBZojkwm9FFqzYWFmNK4yN+0PRC3sTxH8IShG0Yl7PYP6yWoFD6AY8Yn1zLDjLvMo8dLo5fWb031WS4f8CFQW6TsMOnK9dSlFFhrXvo= Received: from DU6P191CA0047.EURP191.PROD.OUTLOOK.COM (2603:10a6:10:53f::12) by DB8P190MB0666.EURP190.PROD.OUTLOOK.COM (2603:10a6:10:127::20) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7633.21; Thu, 30 May 2024 14:50:02 +0000 Received: from DB1PEPF000509EB.eurprd03.prod.outlook.com (2603:10a6:10:53f:cafe::21) by DU6P191CA0047.outlook.office365.com (2603:10a6:10:53f::12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7633.21 via Frontend Transport; Thu, 30 May 2024 14:50:02 +0000 X-MS-Exchange-Authentication-Results: spf=fail (sender IP is 178.72.21.4) smtp.mailfrom=napatech.com; dkim=none (message not signed) header.d=none;dmarc=fail action=oreject header.from=napatech.com; Received-SPF: Fail (protection.outlook.com: domain of napatech.com does not designate 178.72.21.4 as permitted sender) receiver=protection.outlook.com; client-ip=178.72.21.4; helo=localhost.localdomain; Received: from localhost.localdomain (178.72.21.4) by DB1PEPF000509EB.mail.protection.outlook.com (10.167.242.69) with Microsoft SMTP Server id 15.20.7633.15 via Frontend Transport; Thu, 30 May 2024 14:50:01 +0000 From: Serhii Iliushyk To: dev@dpdk.org Cc: mko-plv@napatech.com, ckm@napatech.com, andrew.rybchenko@oktetlabs.ru, ferruh.yigit@amd.com Subject: [PATCH v1 12/17] net/ntnic: add support of the NT200A0X smartNIC Date: Thu, 30 May 2024 16:49:09 +0200 Message-ID: <20240530144929.4127931-12-sil-plv@napatech.com> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240530144929.4127931-1-sil-plv@napatech.com> References: <20240530144929.4127931-1-sil-plv@napatech.com> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: DB1PEPF000509EB:EE_|DB8P190MB0666:EE_ X-MS-Office365-Filtering-Correlation-Id: f88d0fd8-07f8-474b-f7a2-08dc80b7c929 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; ARA:13230031|1800799015|82310400017|36860700004|376005; X-Microsoft-Antispam-Message-Info: =?utf-8?B?WTdtNEtsc3hXMVN0Y20yeXhmMGdYdlcvTWYvU1BOU2VkZGFVWXQ2QVlsamd0?= =?utf-8?B?UmoweGdEa05JUWQ3elVCdDBJVGQyWjNPRmQ2VjNPOW9vOGJOZGpCN0VIbmly?= =?utf-8?B?Q0MvNU9jaFJZdVhQQ240M2pDREQ5WHJ4Y3YyTDI5V3YvZ3EyV0Y1VWt2Umtj?= =?utf-8?B?YlNVRG9kanAyQ0FhYlhRTE56ME0xZE5jRDVlV2Fod3h2V2pBWGlSWGZRV1Ar?= =?utf-8?B?bnNpYzl1OW1oM2xIc0I1am15Njg3T3Y0bHgvamc0ZjdJdjRaTVhCWG5Ia0hr?= =?utf-8?B?bDRyanF1bHAwa28zR2lEbS83WTFsTmpJc2xvQ0tQRXNxTmluOGZ4VXlQL0tG?= =?utf-8?B?L2FPYU9ldnVGZmV5YVMrRzI1MS9CT3AwMlUwTWhpZEdEOExpcGw4UUpZaUZX?= =?utf-8?B?SUh5RTMrS3hIajZFRjB6SStXN3RDV2VsNGR4VkVIZVYxZVJ1WnJsK29nU011?= =?utf-8?B?MjJYTGJGRjh2QkZTNFJMZmo2TTJzYXhVNVM4YVZtN2pSVVppZ2RwM1Y2Wnha?= =?utf-8?B?LytXQnJIMXpIZUFrcGdvdkJMdDR6b3ovMm5oVTEyNWU5QldsK2t5Z2MxQ241?= =?utf-8?B?UWxmTEVuREhDdHBuUUF5M2dJb09jWHFvSmJjMjVML3lFU1JUaGNIb2pBVFZw?= =?utf-8?B?VG5OM0Nwc0VpWmdINkM2cDE4S3hkMW1Zb3hVV1p3TnBoQmgyeHVlbzV0RGFp?= =?utf-8?B?YURiZmJDTlNaNTJoZUR0UEgzOWk2Zi9JMnJCTUw2WURBSjdpWmM0Vm9qZmdm?= =?utf-8?B?NzQ1eG9CREJKWlFZN0FqUDVxamVBcmsvK3pVUXVkSzhPdEdxMUFLMFBCczU1?= =?utf-8?B?aGhYVmlsVGNPRWlRckdwejFHSk4xZVZWdTZlNEZydkQ5RS9jYnI4eitOaktr?= =?utf-8?B?Q25pZ1RoYmVVenJqSytuTE1ZeDV2SmVtZVBPN2FTL3pjSVBRNjNkNUtPWlcw?= =?utf-8?B?MlcyOU9ibGtXdGJMV3V4SkwwR0dHV2JMQ1VBVy9pV2JlKzF0QXlCd0x0MFNF?= =?utf-8?B?VFNJc0FMVThFZ21wc3JjOVNIZHdJODMyY2NTR3FWclUxcU9ZaDFPQkhqNVR2?= =?utf-8?B?UGUzeFhFRThsRmNCVEp1eWRDbmxPczhnM1ZUNFlaWng4TGpmcUNiVjdGcDhR?= =?utf-8?B?UldvN0RyU1RHbG1GbzBHZkxvanpCMXN3bTA3UjREY2hGUllybXJ2ZjBEeWQ3?= =?utf-8?B?V3F2VENwck45amlGMnNtWlMvR1NJNEhuVTFwaGNMNmEvc2xFR21Kemh0SGpu?= =?utf-8?B?SWR0WjlMT2s1YjlDNjVoNm1DOEsxb2JmODAwMzdqN0hGb1FkSytOUkZYdGs1?= =?utf-8?B?TTBoT0w5Z3JKMUtrSEhydzYwbUhDcmFYMlo1QmtVTi92cEhqMmtDQXNjNVFs?= =?utf-8?B?WFNHUnlRZ1FmTHlLaDlDTjIvQUdkN3ZSajhsbHNKLzNUTGYvODg2eDZ0VURF?= =?utf-8?B?dWhWN2FkeWZONW92NUJWaU00Z3J3M0ZGcUt0dkttNnNkSGRaaVFENVB5d0tO?= =?utf-8?B?UU1PV2I5aFlNV09GOERkbUhJWnBQcUpVVCtvL1pHMnVrKzh5RlEvVWNPeURm?= =?utf-8?B?YjhKUjlqN3diRCtEQWRNUjU0Qm9YM1JTNkIyZ3BtZnVIMmp0RCtVRzN3bXVx?= =?utf-8?B?V2RRUGpnUlFkZkpQOTJ3L1djOVBOc3FCVi9TR1I1bEhBTWZYeEpiK2o3K1ND?= =?utf-8?B?Nm1QYTBTZTRVWW50R1c1RXNzU2lQRU5EM0x1T2hQeEZtWEFKNkJyKzVzZU9S?= =?utf-8?B?N3k0bGZEaHFVN3dUQ0FweDlSbzhsdDJQdnIvUUdtZEl4ampiN0pIaXBLaG5j?= =?utf-8?Q?/9UMzt2TTBRoevwttvnBn25ywDQoeeecuN5bU=3D?= X-Forefront-Antispam-Report: CIP:178.72.21.4; CTRY:DK; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:localhost.localdomain; PTR:InfoDomainNonexistent; CAT:NONE; SFS:(13230031)(1800799015)(82310400017)(36860700004)(376005); DIR:OUT; SFP:1102; X-MS-Exchange-AntiSpam-ExternalHop-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-ExternalHop-MessageData-0: NYuZM+HAD1aDfKe4Z/70h+eKeR0swl3tE7z6Ugnx6MiRdI+oSrJNhYKOW9Jerx1Q/u6HZiXmwfNhgIE+piDej4cvQ6tMxmq8uwMmxMkUJAENI5PWkx1N8DxQHeBmk82fL0uIGsrRtlJC6YFpqOlaDbGRfeEtf72Ly73nBjBLV6NuOLSUC69JxiIFS5coE932E3PKkBarsWmKnbhFKEsVhTTH2nu5ol1on4xpQ4YA53fBUTF7VHhimceEFaU0D6j3Di6PzuBJpId8VQ5S8VnfP7Oh2b3hpaUNRNwEkLsIw3exYf8vKy77bitBpqVUYggVKNd5UpmvWD7f9pY3g+1yygQAjcVXd/m/1Yxl4e6luLB0spXgypbUzSdgKwjeAgQ27zSSDKZxP1kG6kI2IBRx5rDYrh7QKYpHnHB/EFhTJl1u6N/nFMPXSoXqqwfhGnUaE3+qTMNDfsscmzVdhWkrub8n/bjfBN+Jns5Vu4eoc0bybzAbNBoDfynPiH7vv9uymwPj87w+X5IxVOTc3nmmj+EAevppO0ms5WGaoyqul9V9SoAe+sPbjhFiNc+svwXm6Noyd4qLC8gOE+8Brn1gVYYm4Zzm3I2E547Y5CcV+/kZVQWRND33yNyqV1BoOLbQ0jXHeibHTCYeM+jC/lOSOQ== X-OriginatorOrg: napatech.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 30 May 2024 14:50:01.9609 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: f88d0fd8-07f8-474b-f7a2-08dc80b7c929 X-MS-Exchange-CrossTenant-Id: c4540d0b-728a-4233-9da5-9ea30c7ec3ed X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=c4540d0b-728a-4233-9da5-9ea30c7ec3ed; Ip=[178.72.21.4]; Helo=[localhost.localdomain] X-MS-Exchange-CrossTenant-AuthSource: DB1PEPF000509EB.eurprd03.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: DB8P190MB0666 X-BESS-ID: 1717080606-310391-12727-18675-2 X-BESS-VER: 2019.1_20240429.2309 X-BESS-Apparent-Source-IP: 104.47.14.48 X-BESS-Parts: H4sIAAAAAAACA4uuVkqtKFGyUioBkjpK+cVKVkaGloaG5kB2BlDYyNzI0iTRxD jVxDTJ2MwwOS01Kc3U2NLSKMnEJMkoLUmpNhYAH8FsiUMAAAA= X-BESS-Outbound-Spam-Score: 0.70 X-BESS-Outbound-Spam-Report: Code version 3.2, rules version 3.2.2.256603 [from cloudscan11-245.eu-central-1a.ess.aws.cudaops.com] Rule breakdown below pts rule name description ---- ---------------------- -------------------------------- 0.50 BSF_RULE7568M META: Custom Rule 7568M 0.00 BSF_BESS_OUTBOUND META: BESS Outbound 0.20 PR0N_SUBJECT META: Subject has letters around special characters (pr0n) X-BESS-Outbound-Spam-Status: SCORE=0.70 using account:ESS113687 scores of KILL_LEVEL=7.0 tests=BSF_RULE7568M, BSF_BESS_OUTBOUND, PR0N_SUBJECT X-BESS-BRTS-Status: 1 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Add ntnic support for NT200A0X NIC * Reset * Clock profiles * FPGA Registers * API for FPGA registers Signed-off-by: Serhii Iliushyk --- .../NT200A02_U23_Si5340_adr0_v5-Registers.h | 752 +++++++++++ drivers/net/ntnic/meson.build | 16 + .../clock_profiles/nthw_fpga_clk9563.c | 51 + .../clock_profiles/nthw_fpga_clk9563.h | 9 + .../nthw/core/nt200a0x/nthw_fpga_nt200a0x.c | 107 ++ .../nthw/core/nt200a0x/nthw_fpga_nt200a0x.h | 9 + .../core/nt200a0x/reset/nthw_fpga_rst9563.c | 258 ++++ .../core/nt200a0x/reset/nthw_fpga_rst9563.h | 9 + .../nt200a0x/reset/nthw_fpga_rst_nt200a0x.c | 729 ++++++++++ .../nt200a0x/reset/nthw_fpga_rst_nt200a0x.h | 9 + drivers/net/ntnic/nthw/core/nthw_fpga.c | 888 +++++++++++++ drivers/net/ntnic/nthw/core/nthw_fpga_rst.c | 10 + drivers/net/ntnic/nthw/core/nthw_hif.c | 312 +++++ drivers/net/ntnic/nthw/core/nthw_iic.c | 529 ++++++++ .../net/ntnic/nthw/core/nthw_mac_pcs_xxv.c | 1169 +++++++++++++++++ drivers/net/ntnic/nthw/core/nthw_pcie3.c | 270 ++++ drivers/net/ntnic/nthw/core/nthw_sdc.c | 176 +++ drivers/net/ntnic/nthw/core/nthw_si5340.c | 205 +++ drivers/net/ntnic/nthw/core/nthw_spi_v3.c | 356 +++++ drivers/net/ntnic/nthw/core/nthw_spim.c | 121 ++ drivers/net/ntnic/nthw/core/nthw_spis.c | 129 ++ drivers/net/ntnic/nthw/core/nthw_tsm.c | 167 +++ 22 files changed, 6281 insertions(+) create mode 100644 drivers/net/ntnic/include/NT200A02_U23_Si5340_adr0_v5-Registers.h create mode 100644 drivers/net/ntnic/nthw/core/nt200a0x/clock_profiles/nthw_fpga_clk9563.c create mode 100644 drivers/net/ntnic/nthw/core/nt200a0x/clock_profiles/nthw_fpga_clk9563.h create mode 100644 drivers/net/ntnic/nthw/core/nt200a0x/nthw_fpga_nt200a0x.c create mode 100644 drivers/net/ntnic/nthw/core/nt200a0x/nthw_fpga_nt200a0x.h create mode 100644 drivers/net/ntnic/nthw/core/nt200a0x/reset/nthw_fpga_rst9563.c create mode 100644 drivers/net/ntnic/nthw/core/nt200a0x/reset/nthw_fpga_rst9563.h create mode 100644 drivers/net/ntnic/nthw/core/nt200a0x/reset/nthw_fpga_rst_nt200a0x.c create mode 100644 drivers/net/ntnic/nthw/core/nt200a0x/reset/nthw_fpga_rst_nt200a0x.h create mode 100644 drivers/net/ntnic/nthw/core/nthw_fpga.c create mode 100644 drivers/net/ntnic/nthw/core/nthw_fpga_rst.c create mode 100644 drivers/net/ntnic/nthw/core/nthw_hif.c create mode 100644 drivers/net/ntnic/nthw/core/nthw_iic.c create mode 100644 drivers/net/ntnic/nthw/core/nthw_mac_pcs_xxv.c create mode 100644 drivers/net/ntnic/nthw/core/nthw_pcie3.c create mode 100644 drivers/net/ntnic/nthw/core/nthw_sdc.c create mode 100644 drivers/net/ntnic/nthw/core/nthw_si5340.c create mode 100644 drivers/net/ntnic/nthw/core/nthw_spi_v3.c create mode 100644 drivers/net/ntnic/nthw/core/nthw_spim.c create mode 100644 drivers/net/ntnic/nthw/core/nthw_spis.c create mode 100644 drivers/net/ntnic/nthw/core/nthw_tsm.c diff --git a/drivers/net/ntnic/include/NT200A02_U23_Si5340_adr0_v5-Registers.h b/drivers/net/ntnic/include/NT200A02_U23_Si5340_adr0_v5-Registers.h new file mode 100644 index 0000000000..c4185c77ff --- /dev/null +++ b/drivers/net/ntnic/include/NT200A02_U23_Si5340_adr0_v5-Registers.h @@ -0,0 +1,752 @@ +/* + * Si5340 Rev D Configuration Register Export Header File + * + * This file represents a series of Silicon Labs Si5340 Rev D + * register writes that can be performed to load a single configuration + * on a device. It was created by a Silicon Labs ClockBuilder Pro + * export tool. + * + * Part: Si5340 Rev D + * Design ID: 05 + * Includes Pre/Post Download Control Register Writes: Yes + * Created By: ClockBuilder Pro v2.28.1 [2018-09-24] + * Timestamp: 2018-11-14 16:20:29 GMT+01:00 + * + * A complete design report corresponding to this export is included at the end + * of this header file. + * + */ + +#ifndef SI5340_REVD_REG_CONFIG_HEADER +#define SI5340_REVD_REG_CONFIG_HEADER + +#define SI5340_REVD_REG_CONFIG_NUM_REGS 326 + +typedef struct { + unsigned int address; /* 16-bit register address */ + unsigned char value; /* 8-bit register data */ + +} si5340_revd_register_t; + +static const si5340_revd_register_t si5340_revd_registers[SI5340_REVD_REG_CONFIG_NUM_REGS] = { + /* Start configuration preamble */ + { 0x0B24, 0xC0 }, + { 0x0B25, 0x00 }, + /* Rev D stuck divider fix */ + { 0x0502, 0x01 }, + { 0x0505, 0x03 }, + { 0x0957, 0x17 }, + { 0x0B4E, 0x1A }, + /* End configuration preamble */ + + /* Delay 300 msec */ + /* Delay is worst case time for device to complete any calibration */ + /* that is running due to device state change previous to this script */ + /* being processed. */ + + /* Start configuration registers */ + { 0x0006, 0x00 }, + { 0x0007, 0x00 }, + { 0x0008, 0x00 }, + { 0x000B, 0x74 }, + { 0x0017, 0xF0 }, + { 0x0018, 0xFF }, + { 0x0021, 0x0F }, + { 0x0022, 0x00 }, + { 0x002B, 0x0A }, + { 0x002C, 0x20 }, + { 0x002D, 0x00 }, + { 0x002E, 0x00 }, + { 0x002F, 0x00 }, + { 0x0030, 0x00 }, + { 0x0031, 0x00 }, + { 0x0032, 0x00 }, + { 0x0033, 0x00 }, + { 0x0034, 0x00 }, + { 0x0035, 0x00 }, + { 0x0036, 0x00 }, + { 0x0037, 0x00 }, + { 0x0038, 0x00 }, + { 0x0039, 0x00 }, + { 0x003A, 0x00 }, + { 0x003B, 0x00 }, + { 0x003C, 0x00 }, + { 0x003D, 0x00 }, + { 0x0041, 0x00 }, + { 0x0042, 0x00 }, + { 0x0043, 0x00 }, + { 0x0044, 0x00 }, + { 0x009E, 0x00 }, + { 0x0102, 0x01 }, + { 0x0112, 0x02 }, + { 0x0113, 0x09 }, + { 0x0114, 0x3E }, + { 0x0115, 0x19 }, + { 0x0117, 0x06 }, + { 0x0118, 0x09 }, + { 0x0119, 0x3E }, + { 0x011A, 0x18 }, + { 0x0126, 0x06 }, + { 0x0127, 0x09 }, + { 0x0128, 0x3E }, + { 0x0129, 0x18 }, + { 0x012B, 0x06 }, + { 0x012C, 0x09 }, + { 0x012D, 0x3E }, + { 0x012E, 0x1A }, + { 0x013F, 0x00 }, + { 0x0140, 0x00 }, + { 0x0141, 0x40 }, + { 0x0206, 0x00 }, + { 0x0208, 0x00 }, + { 0x0209, 0x00 }, + { 0x020A, 0x00 }, + { 0x020B, 0x00 }, + { 0x020C, 0x00 }, + { 0x020D, 0x00 }, + { 0x020E, 0x00 }, + { 0x020F, 0x00 }, + { 0x0210, 0x00 }, + { 0x0211, 0x00 }, + { 0x0212, 0x00 }, + { 0x0213, 0x00 }, + { 0x0214, 0x00 }, + { 0x0215, 0x00 }, + { 0x0216, 0x00 }, + { 0x0217, 0x00 }, + { 0x0218, 0x00 }, + { 0x0219, 0x00 }, + { 0x021A, 0x00 }, + { 0x021B, 0x00 }, + { 0x021C, 0x00 }, + { 0x021D, 0x00 }, + { 0x021E, 0x00 }, + { 0x021F, 0x00 }, + { 0x0220, 0x00 }, + { 0x0221, 0x00 }, + { 0x0222, 0x00 }, + { 0x0223, 0x00 }, + { 0x0224, 0x00 }, + { 0x0225, 0x00 }, + { 0x0226, 0x00 }, + { 0x0227, 0x00 }, + { 0x0228, 0x00 }, + { 0x0229, 0x00 }, + { 0x022A, 0x00 }, + { 0x022B, 0x00 }, + { 0x022C, 0x00 }, + { 0x022D, 0x00 }, + { 0x022E, 0x00 }, + { 0x022F, 0x00 }, + { 0x0235, 0x00 }, + { 0x0236, 0x00 }, + { 0x0237, 0x00 }, + { 0x0238, 0xA6 }, + { 0x0239, 0x8B }, + { 0x023A, 0x00 }, + { 0x023B, 0x00 }, + { 0x023C, 0x00 }, + { 0x023D, 0x00 }, + { 0x023E, 0x80 }, + { 0x0250, 0x03 }, + { 0x0251, 0x00 }, + { 0x0252, 0x00 }, + { 0x0253, 0x00 }, + { 0x0254, 0x00 }, + { 0x0255, 0x00 }, + { 0x025C, 0x00 }, + { 0x025D, 0x00 }, + { 0x025E, 0x00 }, + { 0x025F, 0x00 }, + { 0x0260, 0x00 }, + { 0x0261, 0x00 }, + { 0x026B, 0x30 }, + { 0x026C, 0x35 }, + { 0x026D, 0x00 }, + { 0x026E, 0x00 }, + { 0x026F, 0x00 }, + { 0x0270, 0x00 }, + { 0x0271, 0x00 }, + { 0x0272, 0x00 }, + { 0x0302, 0x00 }, + { 0x0303, 0x00 }, + { 0x0304, 0x00 }, + { 0x0305, 0x00 }, + { 0x0306, 0x0D }, + { 0x0307, 0x00 }, + { 0x0308, 0x00 }, + { 0x0309, 0x00 }, + { 0x030A, 0x00 }, + { 0x030B, 0x80 }, + { 0x030C, 0x00 }, + { 0x030D, 0x00 }, + { 0x030E, 0x00 }, + { 0x030F, 0x00 }, + { 0x0310, 0x61 }, + { 0x0311, 0x08 }, + { 0x0312, 0x00 }, + { 0x0313, 0x00 }, + { 0x0314, 0x00 }, + { 0x0315, 0x00 }, + { 0x0316, 0x80 }, + { 0x0317, 0x00 }, + { 0x0318, 0x00 }, + { 0x0319, 0x00 }, + { 0x031A, 0x00 }, + { 0x031B, 0xD0 }, + { 0x031C, 0x1A }, + { 0x031D, 0x00 }, + { 0x031E, 0x00 }, + { 0x031F, 0x00 }, + { 0x0320, 0x00 }, + { 0x0321, 0xA0 }, + { 0x0322, 0x00 }, + { 0x0323, 0x00 }, + { 0x0324, 0x00 }, + { 0x0325, 0x00 }, + { 0x0326, 0x00 }, + { 0x0327, 0x00 }, + { 0x0328, 0x00 }, + { 0x0329, 0x00 }, + { 0x032A, 0x00 }, + { 0x032B, 0x00 }, + { 0x032C, 0x00 }, + { 0x032D, 0x00 }, + { 0x0338, 0x00 }, + { 0x0339, 0x1F }, + { 0x033B, 0x00 }, + { 0x033C, 0x00 }, + { 0x033D, 0x00 }, + { 0x033E, 0x00 }, + { 0x033F, 0x00 }, + { 0x0340, 0x00 }, + { 0x0341, 0x00 }, + { 0x0342, 0x00 }, + { 0x0343, 0x00 }, + { 0x0344, 0x00 }, + { 0x0345, 0x00 }, + { 0x0346, 0x00 }, + { 0x0347, 0x00 }, + { 0x0348, 0x00 }, + { 0x0349, 0x00 }, + { 0x034A, 0x00 }, + { 0x034B, 0x00 }, + { 0x034C, 0x00 }, + { 0x034D, 0x00 }, + { 0x034E, 0x00 }, + { 0x034F, 0x00 }, + { 0x0350, 0x00 }, + { 0x0351, 0x00 }, + { 0x0352, 0x00 }, + { 0x0359, 0x00 }, + { 0x035A, 0x00 }, + { 0x035B, 0x00 }, + { 0x035C, 0x00 }, + { 0x035D, 0x00 }, + { 0x035E, 0x00 }, + { 0x035F, 0x00 }, + { 0x0360, 0x00 }, + { 0x0802, 0x00 }, + { 0x0803, 0x00 }, + { 0x0804, 0x00 }, + { 0x0805, 0x00 }, + { 0x0806, 0x00 }, + { 0x0807, 0x00 }, + { 0x0808, 0x00 }, + { 0x0809, 0x00 }, + { 0x080A, 0x00 }, + { 0x080B, 0x00 }, + { 0x080C, 0x00 }, + { 0x080D, 0x00 }, + { 0x080E, 0x00 }, + { 0x080F, 0x00 }, + { 0x0810, 0x00 }, + { 0x0811, 0x00 }, + { 0x0812, 0x00 }, + { 0x0813, 0x00 }, + { 0x0814, 0x00 }, + { 0x0815, 0x00 }, + { 0x0816, 0x00 }, + { 0x0817, 0x00 }, + { 0x0818, 0x00 }, + { 0x0819, 0x00 }, + { 0x081A, 0x00 }, + { 0x081B, 0x00 }, + { 0x081C, 0x00 }, + { 0x081D, 0x00 }, + { 0x081E, 0x00 }, + { 0x081F, 0x00 }, + { 0x0820, 0x00 }, + { 0x0821, 0x00 }, + { 0x0822, 0x00 }, + { 0x0823, 0x00 }, + { 0x0824, 0x00 }, + { 0x0825, 0x00 }, + { 0x0826, 0x00 }, + { 0x0827, 0x00 }, + { 0x0828, 0x00 }, + { 0x0829, 0x00 }, + { 0x082A, 0x00 }, + { 0x082B, 0x00 }, + { 0x082C, 0x00 }, + { 0x082D, 0x00 }, + { 0x082E, 0x00 }, + { 0x082F, 0x00 }, + { 0x0830, 0x00 }, + { 0x0831, 0x00 }, + { 0x0832, 0x00 }, + { 0x0833, 0x00 }, + { 0x0834, 0x00 }, + { 0x0835, 0x00 }, + { 0x0836, 0x00 }, + { 0x0837, 0x00 }, + { 0x0838, 0x00 }, + { 0x0839, 0x00 }, + { 0x083A, 0x00 }, + { 0x083B, 0x00 }, + { 0x083C, 0x00 }, + { 0x083D, 0x00 }, + { 0x083E, 0x00 }, + { 0x083F, 0x00 }, + { 0x0840, 0x00 }, + { 0x0841, 0x00 }, + { 0x0842, 0x00 }, + { 0x0843, 0x00 }, + { 0x0844, 0x00 }, + { 0x0845, 0x00 }, + { 0x0846, 0x00 }, + { 0x0847, 0x00 }, + { 0x0848, 0x00 }, + { 0x0849, 0x00 }, + { 0x084A, 0x00 }, + { 0x084B, 0x00 }, + { 0x084C, 0x00 }, + { 0x084D, 0x00 }, + { 0x084E, 0x00 }, + { 0x084F, 0x00 }, + { 0x0850, 0x00 }, + { 0x0851, 0x00 }, + { 0x0852, 0x00 }, + { 0x0853, 0x00 }, + { 0x0854, 0x00 }, + { 0x0855, 0x00 }, + { 0x0856, 0x00 }, + { 0x0857, 0x00 }, + { 0x0858, 0x00 }, + { 0x0859, 0x00 }, + { 0x085A, 0x00 }, + { 0x085B, 0x00 }, + { 0x085C, 0x00 }, + { 0x085D, 0x00 }, + { 0x085E, 0x00 }, + { 0x085F, 0x00 }, + { 0x0860, 0x00 }, + { 0x0861, 0x00 }, + { 0x090E, 0x02 }, + { 0x091C, 0x04 }, + { 0x0943, 0x00 }, + { 0x0949, 0x00 }, + { 0x094A, 0x00 }, + { 0x094E, 0x49 }, + { 0x094F, 0x02 }, + { 0x095E, 0x00 }, + { 0x0A02, 0x00 }, + { 0x0A03, 0x07 }, + { 0x0A04, 0x01 }, + { 0x0A05, 0x07 }, + { 0x0A14, 0x00 }, + { 0x0A1A, 0x00 }, + { 0x0A20, 0x00 }, + { 0x0A26, 0x00 }, + { 0x0B44, 0x0F }, + { 0x0B4A, 0x08 }, + { 0x0B57, 0x0E }, + { 0x0B58, 0x01 }, + /* End configuration registers */ + + /* Start configuration postamble */ + { 0x001C, 0x01 }, + { 0x0B24, 0xC3 }, + { 0x0B25, 0x02 }, + /* End configuration postamble */ +}; + +/* + * Design Report + * + * Overview + * ======== + * Part: Si5340AB Rev D + * Project File: P:\Hardware\NT + * Adapters\NT200A02\design\Clock_syn_design\NT200A02_U23_Si5340_adr0_v5.slabtimeproj Design ID: 05 + * Created By: ClockBuilder Pro v2.28.1 [2018-09-24] + * Timestamp: 2018-11-14 16:20:29 GMT+01:00 + * + * Design Rule Check + * ================= + * Errors: + * - No errors + * + * Warnings: + * - No warnings + * + * Device Grade + * ============ + * Maximum Output Frequency: 257.8125 MHz + * Frequency Synthesis Mode: Fractional + * Frequency Plan Grade: B + * Minimum Base OPN: Si5340B* + * + * Base Output Clock Supported Frequency Synthesis Modes + * OPN Grade Frequency Range (Typical Jitter) + * --------- ------------------- -------------------------------------------- + * Si5340A 100 Hz to 1.028 GHz Integer (< 100 fs) and fractional (< 150 fs) + * Si5340B* 100 Hz to 350 MHz " + * Si5340C 100 Hz to 1.028 GHz Integer only (< 100 fs) + * Si5340D 100 Hz to 350 MHz " + * + * * Based on your calculated frequency plan, a Si5340B grade device is + * sufficient for your design. For more in-system configuration flexibility + * (higher frequencies and/or to enable fractional synthesis), consider + * selecting device grade Si5340A when specifying an ordering part number (OPN) + * for your application. See the datasheet Ordering Guide for more information. + * + * Design + * ====== + * Host Interface: + * I/O Power Supply: VDD (Core) + * SPI Mode: 3-Wire + * I2C Address Range: 116d to 119d / 0x74 to 0x77 (selected via A0/A1 pins) + * + * Inputs: + * XAXB: 48 MHz + * Crystal Mode + * IN0: Unused + * IN1: Unused + * IN2: Unused + * FB_IN: Unused + * + * Outputs: + * OUT0: 100 MHz + * Enabled, LVDS 1.8 V + * OUT1: 257.8125 MHz [ 257 + 13/16 MHz ] + * Enabled, LVDS 1.8 V + * OUT2: 257.8125 MHz [ 257 + 13/16 MHz ] + * Enabled, LVDS 1.8 V + * OUT3: 156.25 MHz [ 156 + 1/4 MHz ] + * Enabled, LVDS 1.8 V + * + * Frequency Plan + * ============== + * Priority: OUT1 is lowest jitter output + * + * Fpfd = 48 MHz + * Fvco = 13.40625 GHz [ 13 + 13/32 GHz ] + * Fms0 = 515.625 MHz [ 515 + 5/8 MHz ] + * Fms1 = 800 MHz + * Fms2 = 312.5 MHz [ 312 + 1/2 MHz ] + * + * P dividers: + * P0 = Unused + * P1 = Unused + * P2 = Unused + * P3 = Unused + * Pxaxb = 1 + * + * M = 279.296875 [ 279 + 19/64 ] + * N dividers: + * N0: + * Value: 26 + * Skew: 0.000 s + * OUT1: 257.8125 MHz [ 257 + 13/16 MHz ] + * OUT2: 257.8125 MHz [ 257 + 13/16 MHz ] + * N1: + * Value: 16.7578125 [ 16 + 97/128 ] + * Skew: 0.000 s + * OUT0: 100 MHz + * N2: + * Value: 42.9 [ 42 + 9/10 ] + * Skew: 0.000 s + * OUT3: 156.25 MHz [ 156 + 1/4 MHz ] + * N3: + * Unused + * + * R dividers: + * R0 = 8 + * R1 = 2 + * R2 = 2 + * R3 = 2 + * + * Dividers listed above show effective values. These values are translated to register settings by + * ClockBuilder Pro. For the actual register values, see below. Refer to the Family Reference + * Manual for information on registers related to frequency plan. + * + * Digitally Controlled Oscillator (DCO) + * ===================================== + * Mode: FINC/FDEC + * + * N0: DCO Disabled + * + * N1: DCO Disabled + * + * N2: DCO Disabled + * + * N3: DCO Disabled + * + * Estimated Power & Junction Temperature + * ====================================== + * Assumptions: + * + * Revision: D + * VDD: 1.8 V + * Ta: 70 °C + * Airflow: None + * + * Total Power: 767 mW, On Chip Power: 743 mW, Tj: 87 °C + * + * Frequency Format Voltage Current Power + * ------------ ------ -------- -------- -------- + * VDD 1.8 V 146.3 mA 263 mW + * VDDA 3.3 V 117.4 mA 387 mW + * VDDO0 100 MHz LVDS 1.8 V 15.6 mA 28 mW + * VDDO1 257.8125 MHz LVDS 1.8 V 16.6 mA 30 mW + * VDDO2 257.8125 MHz LVDS 1.8 V 16.6 mA 30 mW + * VDDO3 156.25 MHz LVDS 1.8 V 15.9 mA 29 mW + * -------- -------- + * Total 328.4 mA 767 mW + * + * Note: + * + * -Total power includes on- and off-chip power. This is a typical value and estimate only. + * -Use an EVB for a more exact power measurement + * -On-chip power excludes power dissipated in external terminations. + * -Tj is junction temperature. Tj must be less than 125 °C (on Si5340 Revision D) for device to + * comply with datasheet specifications. + * + * Settings + * ======== + * + * Location Setting Name Decimal Value Hex Value + * ------------ ------------------- ----------------- ----------------- + * 0x0006[23:0] TOOL_VERSION 0 0x000000 + * 0x000B[6:0] I2C_ADDR 116 0x74 + * 0x0017[0] SYSINCAL_INTR_MSK 0 0x0 + * 0x0017[1] LOSXAXB_INTR_MSK 0 0x0 + * 0x0017[2] LOSREF_INTR_MSK 0 0x0 + * 0x0017[3] LOL_INTR_MSK 0 0x0 + * 0x0017[5] SMB_TMOUT_INTR_MSK 1 0x1 + * 0x0018[3:0] LOSIN_INTR_MSK 15 0xF + * 0x0021[0] IN_SEL_REGCTRL 1 0x1 + * 0x0021[2:1] IN_SEL 3 0x3 + * 0x0022[1] OE 0 0x0 + * 0x002B[3] SPI_3WIRE 1 0x1 + * 0x002B[5] AUTO_NDIV_UPDATE 0 0x0 + * 0x002C[3:0] LOS_EN 0 0x0 + * 0x002C[4] LOSXAXB_DIS 0 0x0 + * 0x002D[1:0] LOS0_VAL_TIME 0 0x0 + * 0x002D[3:2] LOS1_VAL_TIME 0 0x0 + * 0x002D[5:4] LOS2_VAL_TIME 0 0x0 + * 0x002D[7:6] LOS3_VAL_TIME 0 0x0 + * 0x002E[15:0] LOS0_TRG_THR 0 0x0000 + * 0x0030[15:0] LOS1_TRG_THR 0 0x0000 + * 0x0032[15:0] LOS2_TRG_THR 0 0x0000 + * 0x0034[15:0] LOS3_TRG_THR 0 0x0000 + * 0x0036[15:0] LOS0_CLR_THR 0 0x0000 + * 0x0038[15:0] LOS1_CLR_THR 0 0x0000 + * 0x003A[15:0] LOS2_CLR_THR 0 0x0000 + * 0x003C[15:0] LOS3_CLR_THR 0 0x0000 + * 0x0041[4:0] LOS0_DIV_SEL 0 0x00 + * 0x0042[4:0] LOS1_DIV_SEL 0 0x00 + * 0x0043[4:0] LOS2_DIV_SEL 0 0x00 + * 0x0044[4:0] LOS3_DIV_SEL 0 0x00 + * 0x009E[7:4] LOL_SET_THR 0 0x0 + * 0x0102[0] OUTALL_DISABLE_LOW 1 0x1 + * 0x0112[0] OUT0_PDN 0 0x0 + * 0x0112[1] OUT0_OE 1 0x1 + * 0x0112[2] OUT0_RDIV_FORCE2 0 0x0 + * 0x0113[2:0] OUT0_FORMAT 1 0x1 + * 0x0113[3] OUT0_SYNC_EN 1 0x1 + * 0x0113[5:4] OUT0_DIS_STATE 0 0x0 + * 0x0113[7:6] OUT0_CMOS_DRV 0 0x0 + * 0x0114[3:0] OUT0_CM 14 0xE + * 0x0114[6:4] OUT0_AMPL 3 0x3 + * 0x0115[2:0] OUT0_MUX_SEL 1 0x1 + * 0x0115[5:4] OUT0_VDD_SEL 1 0x1 + * 0x0115[3] OUT0_VDD_SEL_EN 1 0x1 + * 0x0115[7:6] OUT0_INV 0 0x0 + * 0x0117[0] OUT1_PDN 0 0x0 + * 0x0117[1] OUT1_OE 1 0x1 + * 0x0117[2] OUT1_RDIV_FORCE2 1 0x1 + * 0x0118[2:0] OUT1_FORMAT 1 0x1 + * 0x0118[3] OUT1_SYNC_EN 1 0x1 + * 0x0118[5:4] OUT1_DIS_STATE 0 0x0 + * 0x0118[7:6] OUT1_CMOS_DRV 0 0x0 + * 0x0119[3:0] OUT1_CM 14 0xE + * 0x0119[6:4] OUT1_AMPL 3 0x3 + * 0x011A[2:0] OUT1_MUX_SEL 0 0x0 + * 0x011A[5:4] OUT1_VDD_SEL 1 0x1 + * 0x011A[3] OUT1_VDD_SEL_EN 1 0x1 + * 0x011A[7:6] OUT1_INV 0 0x0 + * 0x0126[0] OUT2_PDN 0 0x0 + * 0x0126[1] OUT2_OE 1 0x1 + * 0x0126[2] OUT2_RDIV_FORCE2 1 0x1 + * 0x0127[2:0] OUT2_FORMAT 1 0x1 + * 0x0127[3] OUT2_SYNC_EN 1 0x1 + * 0x0127[5:4] OUT2_DIS_STATE 0 0x0 + * 0x0127[7:6] OUT2_CMOS_DRV 0 0x0 + * 0x0128[3:0] OUT2_CM 14 0xE + * 0x0128[6:4] OUT2_AMPL 3 0x3 + * 0x0129[2:0] OUT2_MUX_SEL 0 0x0 + * 0x0129[5:4] OUT2_VDD_SEL 1 0x1 + * 0x0129[3] OUT2_VDD_SEL_EN 1 0x1 + * 0x0129[7:6] OUT2_INV 0 0x0 + * 0x012B[0] OUT3_PDN 0 0x0 + * 0x012B[1] OUT3_OE 1 0x1 + * 0x012B[2] OUT3_RDIV_FORCE2 1 0x1 + * 0x012C[2:0] OUT3_FORMAT 1 0x1 + * 0x012C[3] OUT3_SYNC_EN 1 0x1 + * 0x012C[5:4] OUT3_DIS_STATE 0 0x0 + * 0x012C[7:6] OUT3_CMOS_DRV 0 0x0 + * 0x012D[3:0] OUT3_CM 14 0xE + * 0x012D[6:4] OUT3_AMPL 3 0x3 + * 0x012E[2:0] OUT3_MUX_SEL 2 0x2 + * 0x012E[5:4] OUT3_VDD_SEL 1 0x1 + * 0x012E[3] OUT3_VDD_SEL_EN 1 0x1 + * 0x012E[7:6] OUT3_INV 0 0x0 + * 0x013F[11:0] OUTX_ALWAYS_ON 0 0x000 + * 0x0141[5] OUT_DIS_LOL_MSK 0 0x0 + * 0x0141[7] OUT_DIS_MSK_LOS_PFD 0 0x0 + * 0x0206[1:0] PXAXB 0 0x0 + * 0x0208[47:0] P0 0 0x000000000000 + * 0x020E[31:0] P0_SET 0 0x00000000 + * 0x0212[47:0] P1 0 0x000000000000 + * 0x0218[31:0] P1_SET 0 0x00000000 + * 0x021C[47:0] P2 0 0x000000000000 + * 0x0222[31:0] P2_SET 0 0x00000000 + * 0x0226[47:0] P3 0 0x000000000000 + * 0x022C[31:0] P3_SET 0 0x00000000 + * 0x0235[43:0] M_NUM 599785472000 0x08BA6000000 + * 0x023B[31:0] M_DEN 2147483648 0x80000000 + * 0x0250[23:0] R0_REG 3 0x000003 + * 0x0253[23:0] R1_REG 0 0x000000 + * 0x025C[23:0] R2_REG 0 0x000000 + * 0x025F[23:0] R3_REG 0 0x000000 + * 0x026B[7:0] DESIGN_ID0 48 0x30 + * 0x026C[7:0] DESIGN_ID1 53 0x35 + * 0x026D[7:0] DESIGN_ID2 0 0x00 + * 0x026E[7:0] DESIGN_ID3 0 0x00 + * 0x026F[7:0] DESIGN_ID4 0 0x00 + * 0x0270[7:0] DESIGN_ID5 0 0x00 + * 0x0271[7:0] DESIGN_ID6 0 0x00 + * 0x0272[7:0] DESIGN_ID7 0 0x00 + * 0x0302[43:0] N0_NUM 55834574848 0x00D00000000 + * 0x0308[31:0] N0_DEN 2147483648 0x80000000 + * 0x030C[0] N0_UPDATE 0 0x0 + * 0x030D[43:0] N1_NUM 35987128320 0x00861000000 + * 0x0313[31:0] N1_DEN 2147483648 0x80000000 + * 0x0317[0] N1_UPDATE 0 0x0 + * 0x0318[43:0] N2_NUM 115158810624 0x01AD0000000 + * 0x031E[31:0] N2_DEN 2684354560 0xA0000000 + * 0x0322[0] N2_UPDATE 0 0x0 + * 0x0323[43:0] N3_NUM 0 0x00000000000 + * 0x0329[31:0] N3_DEN 0 0x00000000 + * 0x032D[0] N3_UPDATE 0 0x0 + * 0x0338[1] N_UPDATE 0 0x0 + * 0x0339[4:0] N_FSTEP_MSK 31 0x1F + * 0x033B[43:0] N0_FSTEPW 0 0x00000000000 + * 0x0341[43:0] N1_FSTEPW 0 0x00000000000 + * 0x0347[43:0] N2_FSTEPW 0 0x00000000000 + * 0x034D[43:0] N3_FSTEPW 0 0x00000000000 + * 0x0359[15:0] N0_DELAY 0 0x0000 + * 0x035B[15:0] N1_DELAY 0 0x0000 + * 0x035D[15:0] N2_DELAY 0 0x0000 + * 0x035F[15:0] N3_DELAY 0 0x0000 + * 0x0802[15:0] FIXREGSA0 0 0x0000 + * 0x0804[7:0] FIXREGSD0 0 0x00 + * 0x0805[15:0] FIXREGSA1 0 0x0000 + * 0x0807[7:0] FIXREGSD1 0 0x00 + * 0x0808[15:0] FIXREGSA2 0 0x0000 + * 0x080A[7:0] FIXREGSD2 0 0x00 + * 0x080B[15:0] FIXREGSA3 0 0x0000 + * 0x080D[7:0] FIXREGSD3 0 0x00 + * 0x080E[15:0] FIXREGSA4 0 0x0000 + * 0x0810[7:0] FIXREGSD4 0 0x00 + * 0x0811[15:0] FIXREGSA5 0 0x0000 + * 0x0813[7:0] FIXREGSD5 0 0x00 + * 0x0814[15:0] FIXREGSA6 0 0x0000 + * 0x0816[7:0] FIXREGSD6 0 0x00 + * 0x0817[15:0] FIXREGSA7 0 0x0000 + * 0x0819[7:0] FIXREGSD7 0 0x00 + * 0x081A[15:0] FIXREGSA8 0 0x0000 + * 0x081C[7:0] FIXREGSD8 0 0x00 + * 0x081D[15:0] FIXREGSA9 0 0x0000 + * 0x081F[7:0] FIXREGSD9 0 0x00 + * 0x0820[15:0] FIXREGSA10 0 0x0000 + * 0x0822[7:0] FIXREGSD10 0 0x00 + * 0x0823[15:0] FIXREGSA11 0 0x0000 + * 0x0825[7:0] FIXREGSD11 0 0x00 + * 0x0826[15:0] FIXREGSA12 0 0x0000 + * 0x0828[7:0] FIXREGSD12 0 0x00 + * 0x0829[15:0] FIXREGSA13 0 0x0000 + * 0x082B[7:0] FIXREGSD13 0 0x00 + * 0x082C[15:0] FIXREGSA14 0 0x0000 + * 0x082E[7:0] FIXREGSD14 0 0x00 + * 0x082F[15:0] FIXREGSA15 0 0x0000 + * 0x0831[7:0] FIXREGSD15 0 0x00 + * 0x0832[15:0] FIXREGSA16 0 0x0000 + * 0x0834[7:0] FIXREGSD16 0 0x00 + * 0x0835[15:0] FIXREGSA17 0 0x0000 + * 0x0837[7:0] FIXREGSD17 0 0x00 + * 0x0838[15:0] FIXREGSA18 0 0x0000 + * 0x083A[7:0] FIXREGSD18 0 0x00 + * 0x083B[15:0] FIXREGSA19 0 0x0000 + * 0x083D[7:0] FIXREGSD19 0 0x00 + * 0x083E[15:0] FIXREGSA20 0 0x0000 + * 0x0840[7:0] FIXREGSD20 0 0x00 + * 0x0841[15:0] FIXREGSA21 0 0x0000 + * 0x0843[7:0] FIXREGSD21 0 0x00 + * 0x0844[15:0] FIXREGSA22 0 0x0000 + * 0x0846[7:0] FIXREGSD22 0 0x00 + * 0x0847[15:0] FIXREGSA23 0 0x0000 + * 0x0849[7:0] FIXREGSD23 0 0x00 + * 0x084A[15:0] FIXREGSA24 0 0x0000 + * 0x084C[7:0] FIXREGSD24 0 0x00 + * 0x084D[15:0] FIXREGSA25 0 0x0000 + * 0x084F[7:0] FIXREGSD25 0 0x00 + * 0x0850[15:0] FIXREGSA26 0 0x0000 + * 0x0852[7:0] FIXREGSD26 0 0x00 + * 0x0853[15:0] FIXREGSA27 0 0x0000 + * 0x0855[7:0] FIXREGSD27 0 0x00 + * 0x0856[15:0] FIXREGSA28 0 0x0000 + * 0x0858[7:0] FIXREGSD28 0 0x00 + * 0x0859[15:0] FIXREGSA29 0 0x0000 + * 0x085B[7:0] FIXREGSD29 0 0x00 + * 0x085C[15:0] FIXREGSA30 0 0x0000 + * 0x085E[7:0] FIXREGSD30 0 0x00 + * 0x085F[15:0] FIXREGSA31 0 0x0000 + * 0x0861[7:0] FIXREGSD31 0 0x00 + * 0x090E[0] XAXB_EXTCLK_EN 0 0x0 + * 0x090E[1] XAXB_PDNB 1 0x1 + * 0x091C[2:0] ZDM_EN 4 0x4 + * 0x0943[0] IO_VDD_SEL 0 0x0 + * 0x0949[3:0] IN_EN 0 0x0 + * 0x0949[7:4] IN_PULSED_CMOS_EN 0 0x0 + * 0x094A[7:4] INX_TO_PFD_EN 0 0x0 + * 0x094E[11:0] REFCLK_HYS_SEL 585 0x249 + * 0x095E[0] M_INTEGER 0 0x0 + * 0x0A02[4:0] N_ADD_0P5 0 0x00 + * 0x0A03[4:0] N_CLK_TO_OUTX_EN 7 0x07 + * 0x0A04[4:0] N_PIBYP 1 0x01 + * 0x0A05[4:0] N_PDNB 7 0x07 + * 0x0A14[3] N0_HIGH_FREQ 0 0x0 + * 0x0A1A[3] N1_HIGH_FREQ 0 0x0 + * 0x0A20[3] N2_HIGH_FREQ 0 0x0 + * 0x0A26[3] N3_HIGH_FREQ 0 0x0 + * 0x0B44[3:0] PDIV_ENB 15 0xF + * 0x0B4A[4:0] N_CLK_DIS 8 0x08 + * 0x0B57[11:0] VCO_RESET_CALCODE 270 0x10E + * + * + */ + +#endif diff --git a/drivers/net/ntnic/meson.build b/drivers/net/ntnic/meson.build index a9bf9b5906..14cd951d6d 100644 --- a/drivers/net/ntnic/meson.build +++ b/drivers/net/ntnic/meson.build @@ -87,6 +87,22 @@ sources = files( 'nthw/supported/nthw_fpga_9563_055_039_0000.c', 'nthw/supported/nthw_fpga_instances.c', 'nthw/supported/nthw_fpga_mod_str_map.c', + 'nthw/core/nt200a0x/clock_profiles/nthw_fpga_clk9563.c', + 'nthw/core/nt200a0x/nthw_fpga_nt200a0x.c', + 'nthw/core/nt200a0x/reset/nthw_fpga_rst9563.c', + 'nthw/core/nt200a0x/reset/nthw_fpga_rst_nt200a0x.c', + 'nthw/core/nthw_fpga.c', + 'nthw/core/nthw_fpga_rst.c', + 'nthw/core/nthw_hif.c', + 'nthw/core/nthw_iic.c', + 'nthw/core/nthw_mac_pcs_xxv.c', + 'nthw/core/nthw_pcie3.c', + 'nthw/core/nthw_sdc.c', + 'nthw/core/nthw_si5340.c', + 'nthw/core/nthw_spim.c', + 'nthw/core/nthw_spis.c', + 'nthw/core/nthw_spi_v3.c', + 'nthw/core/nthw_tsm.c', 'nthw/model/nthw_fpga_model.c', 'nthw/nthw_epp.c', 'nthw/nthw_platform.c', diff --git a/drivers/net/ntnic/nthw/core/nt200a0x/clock_profiles/nthw_fpga_clk9563.c b/drivers/net/ntnic/nthw/core/nt200a0x/clock_profiles/nthw_fpga_clk9563.c new file mode 100644 index 0000000000..f00e9ac053 --- /dev/null +++ b/drivers/net/ntnic/nthw/core/nt200a0x/clock_profiles/nthw_fpga_clk9563.c @@ -0,0 +1,51 @@ +/* + * SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include "nthw_clock_profiles.h" +#include "nthw_fpga_clk9563.h" +#include "ntnic_mod_reg.h" + +#define code /* Remove this word from the array definitions */ + +/* + * Clock profile for NT200A02 FPGA 9563 + */ +#define si5340_revd_register_t type_9563_si5340_nt200a02_u23_v5 +#define si5340_revd_registers data_9563_si5340_nt200a02_u23_v5 +#include "NT200A02_U23_Si5340_adr0_v5-Registers.h" +#ifdef __cplusplus +static_assert(sizeof(type_9563_si5340_nt200a02_u23_v5) == sizeof(clk_profile_data_fmt2_t), + clk_profile_size_error_msg); +#endif /* __cplusplus */ +static const int n_data_9563_si5340_nt200a02_u23_v5 = SI5340_REVD_REG_CONFIG_NUM_REGS; +static const clk_profile_data_fmt2_t *p_data_9563_si5340_nt200a02_u23_v5 = + (const clk_profile_data_fmt2_t *)&data_9563_si5340_nt200a02_u23_v5[0]; + +static const int *get_n_data_9563_si5340_nt200a02_u23_v5(void) +{ + return &n_data_9563_si5340_nt200a02_u23_v5; +} + +static const clk_profile_data_fmt2_t *get_p_data_9563_si5340_nt200a02_u23_v5(void) +{ + return p_data_9563_si5340_nt200a02_u23_v5; +} + +static struct clk9563_ops ops = { .get_n_data_9563_si5340_nt200a02_u23_v5 = + get_n_data_9563_si5340_nt200a02_u23_v5, + .get_p_data_9563_si5340_nt200a02_u23_v5 = + get_p_data_9563_si5340_nt200a02_u23_v5 +}; + +static void __attribute__((constructor(65535))) clk9563_ops_init(void) +{ + register_clk9563_ops(&ops); +} + +#undef si5340_revd_registers +#undef si5340_revd_register_t +#undef SI5340_REVD_REG_CONFIG_HEADER /* Disable the include once protection */ + +#undef code diff --git a/drivers/net/ntnic/nthw/core/nt200a0x/clock_profiles/nthw_fpga_clk9563.h b/drivers/net/ntnic/nthw/core/nt200a0x/clock_profiles/nthw_fpga_clk9563.h new file mode 100644 index 0000000000..88d72cd334 --- /dev/null +++ b/drivers/net/ntnic/nthw/core/nt200a0x/clock_profiles/nthw_fpga_clk9563.h @@ -0,0 +1,9 @@ +/* + * SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef _NTHW_FPGA_CLK_9563_H_ +#define _NTHW_FPGA_CLK_9563_H_ + +#endif /* _NTHW_FPGA_CLK_9563_H_ */ diff --git a/drivers/net/ntnic/nthw/core/nt200a0x/nthw_fpga_nt200a0x.c b/drivers/net/ntnic/nthw/core/nt200a0x/nthw_fpga_nt200a0x.c new file mode 100644 index 0000000000..0f358da346 --- /dev/null +++ b/drivers/net/ntnic/nthw/core/nt200a0x/nthw_fpga_nt200a0x.c @@ -0,0 +1,107 @@ +/* + * SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include "ntlog.h" + +#include "nthw_fpga.h" +#include "nthw_fpga_nt200a0x.h" +#include "ntnic_mod_reg.h" + +static int nthw_fpga_nt200a0x_init(struct fpga_info_s *p_fpga_info) +{ + assert(p_fpga_info); + + const char *const p_adapter_id_str = p_fpga_info->mp_adapter_id_str; + struct nthw_fpga_rst_nt200a0x rst; + int res = -1; + const struct rst_nt200a0x_ops *rst_nt200a0x_ops = get_rst_nt200a0x_ops(); + + if (rst_nt200a0x_ops == NULL) { + NT_LOG(ERR, NTHW, "RST NT200A0X NOT INCLUDED\n"); + return -1; + } + + /* reset common */ + res = rst_nt200a0x_ops->nthw_fpga_rst_nt200a0x_init(p_fpga_info, &rst); + + if (res) { + NT_LOG(ERR, NTHW, "%s: %s: loc=%u: FPGA=%04d res=%d\n", p_adapter_id_str, __func__, + __LINE__, p_fpga_info->n_fpga_prod_id, res); + return res; + } + + bool included = true; + struct rst9530_ops *rst9530_ops = get_rst9530_ops(); + struct rst9544_ops *rst9544_ops = get_rst9544_ops(); + struct rst9563_ops *rst9563_ops = get_rst9563_ops(); + struct rst9572_ops *rst9572_ops = get_rst9572_ops(); + + /* reset specific */ + switch (p_fpga_info->n_fpga_prod_id) { + case 9530: + if (rst9530_ops != NULL) + res = rst9530_ops->nthw_fpga_rst9530_init(p_fpga_info, &rst); + + else + included = false; + + break; + + case 9544: + if (rst9544_ops != NULL) + res = rst9544_ops->nthw_fpga_rst9544_init(p_fpga_info, &rst); + + else + included = false; + + break; + + case 9563: + if (rst9563_ops != NULL) + res = rst9563_ops->nthw_fpga_rst9563_init(p_fpga_info, &rst); + + else + included = false; + + break; + + case 9572: + if (rst9572_ops != NULL) + res = rst9572_ops->nthw_fpga_rst9572_init(p_fpga_info, &rst); + + else + included = false; + + break; + + default: + NT_LOG(ERR, NTHW, "%s: Unsupported FPGA product: %04d\n", p_adapter_id_str, + p_fpga_info->n_fpga_prod_id); + res = -1; + break; + } + + if (!included) { + NT_LOG(ERR, NTHW, "%s: NOT INCLUDED FPGA product: %04d\n", p_adapter_id_str, + p_fpga_info->n_fpga_prod_id); + res = -1; + } + + if (res) { + NT_LOG(ERR, NTHW, "%s: %s: loc=%u: FPGA=%04d res=%d\n", p_adapter_id_str, __func__, + __LINE__, p_fpga_info->n_fpga_prod_id, res); + return res; + } + + return res; +} + +static struct nt200a0x_ops nt200a0x_ops = { .nthw_fpga_nt200a0x_init = nthw_fpga_nt200a0x_init }; + +static void __attribute__((constructor(65535))) nt200a0x_ops_init(void) +{ + NT_LOG(INF, NTHW, "NT200A0X OPS INIT"); + register_nt200a0x_ops(&nt200a0x_ops); +} diff --git a/drivers/net/ntnic/nthw/core/nt200a0x/nthw_fpga_nt200a0x.h b/drivers/net/ntnic/nthw/core/nt200a0x/nthw_fpga_nt200a0x.h new file mode 100644 index 0000000000..26efe27e0f --- /dev/null +++ b/drivers/net/ntnic/nthw/core/nt200a0x/nthw_fpga_nt200a0x.h @@ -0,0 +1,9 @@ +/* + * SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2024 Napatech A/S + */ + +#ifndef __NTHW_FPGA_NT200A0X_H__ +#define __NTHW_FPGA_NT200A0X_H__ + +#endif /* __NTHW_FPGA_NT200A0X_H__ */ diff --git a/drivers/net/ntnic/nthw/core/nt200a0x/reset/nthw_fpga_rst9563.c b/drivers/net/ntnic/nthw/core/nt200a0x/reset/nthw_fpga_rst9563.c new file mode 100644 index 0000000000..c113bb04b7 --- /dev/null +++ b/drivers/net/ntnic/nthw/core/nt200a0x/reset/nthw_fpga_rst9563.c @@ -0,0 +1,258 @@ +/* + * SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include "ntlog.h" + +#include "nthw_drv.h" +#include "nthw_register.h" +#include "nthw_fpga.h" + +#include "nthw_fpga_rst9563.h" +#include "nthw_fpga_nt200a0x.h" +#include "nthw_fpga_rst_nt200a0x.h" +#include "ntnic_mod_reg.h" + +static int nthw_fpga_rst9563_setup(nthw_fpga_t *p_fpga, struct nthw_fpga_rst_nt200a0x *const p) +{ + const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str; + const int n_fpga_product_id = p_fpga->mn_product_id; + const int n_fpga_version = p_fpga->mn_fpga_version; + const int n_fpga_revision = p_fpga->mn_fpga_revision; + + nthw_module_t *p_mod_rst; + nthw_register_t *p_curr_reg; + + assert(p); + p->mn_fpga_product_id = n_fpga_product_id; + p->mn_fpga_version = n_fpga_version; + p->mn_fpga_revision = n_fpga_revision; + + NT_LOG(DBG, NTHW, "%s: %s: FPGA reset setup: FPGA %04d-%02d-%02d\n", p_adapter_id_str, + __func__, n_fpga_product_id, n_fpga_version, n_fpga_revision); + + p_mod_rst = nthw_fpga_query_module(p_fpga, MOD_RST9563, 0); + + if (p_mod_rst == NULL) { + NT_LOG(ERR, NTHW, "%s: RST %d: no such instance\n", p_adapter_id_str, 0); + return -1; + } + + p_mod_rst = nthw_fpga_query_module(p_fpga, MOD_RST9563, 0); + + if (p_mod_rst == NULL) { + NT_LOG(ERR, NTHW, "%s: RST %d: no such instance\n", p_adapter_id_str, 0); + return -1; + } + + /* RST register field pointers */ + p_curr_reg = nthw_module_get_register(p_mod_rst, RST9563_RST); + p->mp_fld_rst_sys = nthw_register_get_field(p_curr_reg, RST9563_RST_SYS); + p->mp_fld_rst_sys_mmcm = nthw_register_get_field(p_curr_reg, RST9563_RST_SYS_MMCM); + p->mp_fld_rst_core_mmcm = nthw_register_get_field(p_curr_reg, RST9563_RST_CORE_MMCM); + p->mp_fld_rst_rpp = nthw_register_get_field(p_curr_reg, RST9563_RST_RPP); + p->mp_fld_rst_ddr4 = nthw_register_get_field(p_curr_reg, RST9563_RST_DDR4); + p->mp_fld_rst_sdc = nthw_register_get_field(p_curr_reg, RST9563_RST_SDC); + p->mp_fld_rst_phy = nthw_register_get_field(p_curr_reg, RST9563_RST_PHY); + p->mp_fld_rst_serdes_rx = NULL; /* Field not present on 9563 */ + p->mp_fld_rst_serdes_tx = NULL; /* Field not present on 9563 */ + p->mp_fld_rst_serdes_rx_datapath = NULL;/* Field not present on 9563 */ + p->mp_fld_rst_pcs_rx = NULL; /* Field not present on 9563 */ + p->mp_fld_rst_mac_rx = nthw_register_get_field(p_curr_reg, RST9563_RST_MAC_RX); + p->mp_fld_rst_mac_tx = NULL; + p->mp_fld_rst_ptp = nthw_register_get_field(p_curr_reg, RST9563_RST_PTP); + p->mp_fld_rst_ptp = nthw_register_get_field(p_curr_reg, RST9563_RST_PTP); + p->mp_fld_rst_ts = nthw_register_get_field(p_curr_reg, RST9563_RST_TS); + p->mp_fld_rst_ptp_mmcm = nthw_register_get_field(p_curr_reg, RST9563_RST_PTP_MMCM); + p->mp_fld_rst_ts_mmcm = nthw_register_get_field(p_curr_reg, RST9563_RST_TS_MMCM); + /* referenced in separate function */ + p->mp_fld_rst_periph = nthw_register_get_field(p_curr_reg, RST9563_RST_PERIPH); + p->mp_fld_rst_tsm_ref_mmcm = + nthw_register_query_field(p_curr_reg, RST9563_RST_TSM_REF_MMCM); + p->mp_fld_rst_tmc = nthw_register_query_field(p_curr_reg, RST9563_RST_TMC); + + if (!p->mp_fld_rst_tsm_ref_mmcm) + NT_LOG(DBG, NTHW, "%s: No RST9563_RST_TSM_REF_MMCM found\n", p_adapter_id_str); + + if (!p->mp_fld_rst_tmc) + NT_LOG(DBG, NTHW, "%s: No RST9563_RST_TMC found\n", p_adapter_id_str); + + nthw_register_update(p_curr_reg); + + /* CTRL register field pointers */ + p_curr_reg = nthw_module_get_register(p_mod_rst, RST9563_CTRL); + p->mp_fld_ctrl_ts_clk_sel_override = + nthw_register_get_field(p_curr_reg, RST9563_CTRL_TS_CLKSEL_OVERRIDE); + /* Field not present on 9563 */ + p->mp_fld_ctrl_ts_clk_sel = nthw_register_get_field(p_curr_reg, RST9563_CTRL_TS_CLKSEL); + p->mp_fld_ctrl_ts_clk_sel_ref = NULL; /* Field not present on 9563 */ + p->mp_fld_ctrl_ptp_mmcm_clk_sel = + nthw_register_get_field(p_curr_reg, RST9563_CTRL_PTP_MMCM_CLKSEL); + nthw_register_update(p_curr_reg); + + /* STAT register field pointers */ + p_curr_reg = nthw_module_get_register(p_mod_rst, RST9563_STAT); + p->mp_fld_stat_ddr4_mmcm_locked = + nthw_register_get_field(p_curr_reg, RST9563_STAT_DDR4_MMCM_LOCKED); + p->mp_fld_stat_sys_mmcm_locked = + nthw_register_get_field(p_curr_reg, RST9563_STAT_SYS_MMCM_LOCKED); + p->mp_fld_stat_core_mmcm_locked = + nthw_register_get_field(p_curr_reg, RST9563_STAT_CORE_MMCM_LOCKED); + p->mp_fld_stat_ddr4_pll_locked = + nthw_register_get_field(p_curr_reg, RST9563_STAT_DDR4_PLL_LOCKED); + p->mp_fld_stat_ptp_mmcm_locked = + nthw_register_get_field(p_curr_reg, RST9563_STAT_PTP_MMCM_LOCKED); + p->mp_fld_stat_ts_mmcm_locked = + nthw_register_get_field(p_curr_reg, RST9563_STAT_TS_MMCM_LOCKED); + p->mp_fld_stat_tsm_ref_mmcm_locked = NULL; /* Field not present on 9563 */ + + if (!p->mp_fld_stat_tsm_ref_mmcm_locked) { + NT_LOG(DBG, NTHW, "%s: No RST9563_STAT_TSM_REF_MMCM_LOCKED found\n", + p_adapter_id_str); + } + + nthw_register_update(p_curr_reg); + + /* STICKY register field pointers */ + p_curr_reg = nthw_module_get_register(p_mod_rst, RST9563_STICKY); + p->mp_fld_sticky_ptp_mmcm_unlocked = + nthw_register_get_field(p_curr_reg, RST9563_STICKY_PTP_MMCM_UNLOCKED); + p->mp_fld_sticky_ts_mmcm_unlocked = + nthw_register_get_field(p_curr_reg, RST9563_STICKY_TS_MMCM_UNLOCKED); + p->mp_fld_sticky_ddr4_mmcm_unlocked = + nthw_register_get_field(p_curr_reg, RST9563_STICKY_DDR4_MMCM_UNLOCKED); + p->mp_fld_sticky_ddr4_pll_unlocked = + nthw_register_get_field(p_curr_reg, RST9563_STICKY_DDR4_PLL_UNLOCKED); + p->mp_fld_sticky_core_mmcm_unlocked = + nthw_register_get_field(p_curr_reg, RST9563_STICKY_CORE_MMCM_UNLOCKED); + p->mp_fld_sticky_pci_sys_mmcm_unlocked = NULL; /* Field not present on 9563 */ + p->mp_fld_sticky_tsm_ref_mmcm_unlocked = NULL; /* Field not present on 9563 */ + + if (!p->mp_fld_sticky_tsm_ref_mmcm_unlocked) { + NT_LOG(DBG, NTHW, "%s: No RST9563_STICKY_TSM_REF_MMCM_UNLOCKED found\n", + p_adapter_id_str); + } + + nthw_register_update(p_curr_reg); + + /* POWER register field pointers */ + p_curr_reg = nthw_module_get_register(p_mod_rst, RST9563_POWER); + p->mp_fld_power_pu_phy = nthw_register_get_field(p_curr_reg, RST9563_POWER_PU_PHY); + p->mp_fld_power_pu_nseb = nthw_register_get_field(p_curr_reg, RST9563_POWER_PU_NSEB); + nthw_register_update(p_curr_reg); + + return 0; +} + +static int nthw_fpga_rst9563_periph_reset(nthw_fpga_t *p_fpga) +{ + const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str; + (void)p_adapter_id_str; + nthw_module_t *p_mod_rst = nthw_fpga_query_module(p_fpga, MOD_RST9563, 0); + + if (p_mod_rst) { + nthw_register_t *p_reg_rst; + nthw_field_t *p_fld_rst_periph; + NT_LOG(DBG, NTHW, "%s: PERIPH RST\n", p_adapter_id_str); + p_reg_rst = nthw_module_get_register(p_mod_rst, RST9563_RST); + p_fld_rst_periph = nthw_register_get_field(p_reg_rst, RST9563_RST_PERIPH); + nthw_field_set_flush(p_fld_rst_periph); + nthw_field_clr_flush(p_fld_rst_periph); + + } else { + return -1; + } + + return 0; +} + +static int nthw_fpga_rst9563_clock_synth_init(nthw_fpga_t *p_fpga, + const int n_si_labs_clock_synth_model, + const uint8_t n_si_labs_clock_synth_i2c_addr) +{ + const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str; + const int n_fpga_product_id = p_fpga->mn_product_id; + int res; + const struct clk9563_ops *clk9563_ops = get_clk9563_ops(); + + if (clk9563_ops == NULL) { + NT_LOG(INF, ETHDEV, "CLK9563 module not included\n"); + return -1; + } + + if (n_si_labs_clock_synth_model == 5340) { + res = nthw_fpga_si5340_clock_synth_init_fmt2(p_fpga, n_si_labs_clock_synth_i2c_addr, + clk9563_ops->get_p_data_9563_si5340_nt200a02_u23_v5(), + *clk9563_ops->get_n_data_9563_si5340_nt200a02_u23_v5()); + + } else { + NT_LOG(ERR, NTHW, "%s: Fpga %d: Unsupported clock synth model (%d)\n", + p_adapter_id_str, n_fpga_product_id, n_si_labs_clock_synth_model); + res = -1; + } + + return res; +} + +static int nthw_fpga_rst9563_init(struct fpga_info_s *p_fpga_info, + struct nthw_fpga_rst_nt200a0x *p_rst) +{ + assert(p_fpga_info); + assert(p_rst); + + const char *const p_adapter_id_str = p_fpga_info->mp_adapter_id_str; + (void)p_adapter_id_str; + int res = -1; + int n_si_labs_clock_synth_model; + uint8_t n_si_labs_clock_synth_i2c_addr; + nthw_fpga_t *p_fpga = NULL; + + p_fpga = p_fpga_info->mp_fpga; + n_si_labs_clock_synth_model = p_rst->mn_si_labs_clock_synth_model; + n_si_labs_clock_synth_i2c_addr = p_rst->mn_si_labs_clock_synth_i2c_addr; + + res = nthw_fpga_rst9563_periph_reset(p_fpga); + + if (res) { + NT_LOG(DBG, NTHW, "%s: ERROR: res=%d [%s:%u]\n", p_adapter_id_str, res, __func__, + __LINE__); + return res; + } + + res = nthw_fpga_rst9563_clock_synth_init(p_fpga, n_si_labs_clock_synth_model, + n_si_labs_clock_synth_i2c_addr); + + if (res) { + NT_LOG(DBG, NTHW, "%s: ERROR: res=%d [%s:%u]\n", p_adapter_id_str, res, __func__, + __LINE__); + return res; + } + + res = nthw_fpga_rst9563_setup(p_fpga, p_rst); + + if (res) { + NT_LOG(DBG, NTHW, "%s: ERROR: res=%d [%s:%u]\n", p_adapter_id_str, res, __func__, + __LINE__); + return res; + } + + const struct rst_nt200a0x_ops *rst_ops = get_rst_nt200a0x_ops(); + res = rst_ops != NULL ? rst_ops->nthw_fpga_rst_nt200a0x_reset(p_fpga, p_rst) : -1; + + if (res) { + NT_LOG(DBG, NTHW, "%s: ERROR: res=%d [%s:%u]\n", p_adapter_id_str, res, __func__, + __LINE__); + return res; + } + + return res; +} + +static struct rst9563_ops rst9563_ops = { .nthw_fpga_rst9563_init = nthw_fpga_rst9563_init }; + +static void __attribute__((constructor(65535))) rst9563_ops_init(void) +{ + NT_LOG(INF, NTHW, "RST9563 OPS INIT"); + register_rst9563_ops(&rst9563_ops); +} diff --git a/drivers/net/ntnic/nthw/core/nt200a0x/reset/nthw_fpga_rst9563.h b/drivers/net/ntnic/nthw/core/nt200a0x/reset/nthw_fpga_rst9563.h new file mode 100644 index 0000000000..e61cd32954 --- /dev/null +++ b/drivers/net/ntnic/nthw/core/nt200a0x/reset/nthw_fpga_rst9563.h @@ -0,0 +1,9 @@ +/* + * SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef __NTHW_FPGA_RST9563_H__ +#define __NTHW_FPGA_RST9563_H__ + +#endif /* __NTHW_FPGA_RST9563_H__ */ diff --git a/drivers/net/ntnic/nthw/core/nt200a0x/reset/nthw_fpga_rst_nt200a0x.c b/drivers/net/ntnic/nthw/core/nt200a0x/reset/nthw_fpga_rst_nt200a0x.c new file mode 100644 index 0000000000..d323d9a93f --- /dev/null +++ b/drivers/net/ntnic/nthw/core/nt200a0x/reset/nthw_fpga_rst_nt200a0x.c @@ -0,0 +1,729 @@ +/* + * SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include "ntlog.h" + +#include "nthw_drv.h" +#include "nthw_register.h" +#include "nthw_fpga.h" + +#include "nthw_fpga_rst_nt200a0x.h" +#include "nthw_fpga_nt200a0x.h" +#include "ntnic_mod_reg.h" + +static const uint8_t si5338_u23_i2c_addr_7bit = 0x70; +static const uint8_t si5340_u23_i2c_addr_7bit = 0x74; + +/* + * Wait until DDR4 PLL LOCKED + */ +static int nthw_fpga_rst_nt200a0x_wait_ddr4_pll_locked(nthw_fpga_t *p_fpga, + const struct nthw_fpga_rst_nt200a0x *p) +{ + const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str; + uint32_t locked; + uint32_t retrycount = 5; + uint32_t timeout = 50000; /* initial timeout must be set to 5 sec. */ + /* 14: wait until DDR4 PLL LOCKED */ + NT_LOG(DBG, NTHW, "%s: Waiting for DDR4 PLL to lock\n", p_adapter_id_str); + + /* + * The following retry count gives a total timeout of 1 * 5 + 5 * 8 = 45sec + * It has been observed that at least 21sec can be necessary + */ + while (true) { + int locked = + nthw_field_wait_set_any32(p->mp_fld_stat_ddr4_pll_locked, timeout, 100); + + if (locked == 0) { + break; + + } else { + NT_LOG(DBG, NTHW, "%s: Waiting for DDR4 PLL to lock - timeout\n", + p_adapter_id_str); + + if (retrycount <= 0) { + NT_LOG(ERR, NTHW, "%s: Waiting for DDR4 PLL to lock failed (%d)\n", + p_adapter_id_str, locked); + break; + } + + nthw_field_set_flush(p->mp_fld_rst_ddr4); /* Reset DDR PLL */ + nthw_field_clr_flush(p->mp_fld_rst_ddr4); /* Reset DDR PLL */ + retrycount--; + timeout = 80000;/* Increase timeout for second attempt to 8 sec. */ + } + } + + NT_LOG(DBG, NTHW, "%s: Waiting for DDR4 MMCM to lock\n", p_adapter_id_str); + locked = nthw_field_wait_set_any32(p->mp_fld_stat_ddr4_mmcm_locked, -1, -1); + + if (locked != 0) { + NT_LOG(ERR, NTHW, "%s: Waiting for DDR4 MMCM to lock failed (%d)\n", + p_adapter_id_str, locked); + return -1; + } + + if (true && p->mp_fld_stat_tsm_ref_mmcm_locked) { + NT_LOG(DBG, NTHW, "%s: Waiting for TSM REF MMCM to lock\n", p_adapter_id_str); + locked = nthw_field_wait_set_any32(p->mp_fld_stat_tsm_ref_mmcm_locked, -1, -1); + + if (locked != 0) { + NT_LOG(ERR, NTHW, "%s: Waiting for TSM REF MMCM to lock failed (%d)\n", + p_adapter_id_str, locked); + return -1; + } + } + + /* 10: Clear all MMCM/PLL lock sticky bits before testing them */ + NT_LOG(DBG, NTHW, "%s: Clear sticky MMCM unlock bits\n", p_adapter_id_str); + nthw_field_update_register(p->mp_fld_sticky_ptp_mmcm_unlocked); + /* Clear all sticky bits */ + nthw_field_set_flush(p->mp_fld_sticky_ptp_mmcm_unlocked); + nthw_field_set_flush(p->mp_fld_sticky_ts_mmcm_unlocked); + nthw_field_set_flush(p->mp_fld_sticky_ddr4_mmcm_unlocked); + nthw_field_set_flush(p->mp_fld_sticky_ddr4_pll_unlocked); + nthw_field_set_flush(p->mp_fld_sticky_core_mmcm_unlocked); + + if (p->mp_fld_sticky_tsm_ref_mmcm_unlocked) + nthw_field_set_flush(p->mp_fld_sticky_tsm_ref_mmcm_unlocked); + + if (p->mp_fld_sticky_pci_sys_mmcm_unlocked) + nthw_field_set_flush(p->mp_fld_sticky_pci_sys_mmcm_unlocked); + + /* 11: Ensure sticky bits are not unlocked except PTP MMCM and TS MMCM */ + if (nthw_field_get_updated(p->mp_fld_sticky_ddr4_mmcm_unlocked)) { + NT_LOG(ERR, NTHW, "%s: get_sticky_ddr4_mmcm_unlocked() returned true\n", + p_adapter_id_str); + } + + if (nthw_field_get_updated(p->mp_fld_sticky_ddr4_pll_unlocked)) { + NT_LOG(ERR, NTHW, "%s: get_sticky_ddr4_pll_unlocked() returned true\n", + p_adapter_id_str); + } + + return 0; +} + +/* + * Wait for SDRAM controller has been calibrated - On some adapters we have seen + * calibration time of 2.3 seconds + */ +static int nthw_fpga_rst_nt200a0x_wait_sdc_calibrated(nthw_fpga_t *p_fpga, + const struct nthw_fpga_rst_nt200a0x *p) +{ + const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str; + nthw_sdc_t *p_nthw_sdc = NULL; + const int n_retry_cnt_max = 5; + int n_retry_cnt; + int res; + + res = nthw_sdc_init(NULL, p_fpga, 0); /* probe for module */ + + if (res == 0) { + p_nthw_sdc = nthw_sdc_new(); + + if (p_nthw_sdc) { + res = nthw_sdc_init(p_nthw_sdc, p_fpga, 0); + + if (res) { + NT_LOG(ERR, NTHW, "%s: SDC init failed: res=%d [%s:%d]\n", + p_adapter_id_str, res, __func__, __LINE__); + nthw_sdc_delete(p_nthw_sdc); + p_nthw_sdc = NULL; + return -1; + } + + } else { + nthw_sdc_delete(p_nthw_sdc); + p_nthw_sdc = NULL; + } + + } else { + NT_LOG(DBG, NTHW, "%s: No SDC found\n", p_adapter_id_str); + } + + n_retry_cnt = 0; + res = -1; + + while ((res != 0) && (n_retry_cnt <= n_retry_cnt_max)) { + /* wait until DDR4 PLL LOCKED */ + res = nthw_fpga_rst_nt200a0x_wait_ddr4_pll_locked(p_fpga, p); + + if (res == 0) { + if (p_nthw_sdc) { + /* + * Wait for SDRAM controller has been calibrated + * On some adapters we have seen calibration time of 2.3 seconds + */ + NT_LOG(DBG, NTHW, "%s: Waiting for SDRAM to calibrate\n", + p_adapter_id_str); + res = nthw_sdc_wait_states(p_nthw_sdc, 10000, 1000); + { + uint64_t n_result_mask; + int n_state_code = + nthw_sdc_get_states(p_nthw_sdc, &n_result_mask); + (void)n_state_code; + NT_LOG(DBG, NTHW, + "%s: SDRAM state=0x%08lX state_code=%d retry=%d code=%d\n", + p_adapter_id_str, n_result_mask, n_state_code, + n_retry_cnt, res); + } + + if (res == 0) + break; + } + + if (n_retry_cnt >= n_retry_cnt_max) { + uint64_t n_result_mask; + int n_state_code = nthw_sdc_get_states(p_nthw_sdc, &n_result_mask); + (void)n_state_code; + + NT_LOG(DBG, NTHW, + "%s: SDRAM state=0x%08lX state_code=%d retry=%d code=%d\n", + p_adapter_id_str, n_result_mask, n_state_code, n_retry_cnt, + res); + + if (res != 0) { + NT_LOG(ERR, NTHW, + "%s: Timeout waiting for SDRAM controller calibration\n", + p_adapter_id_str); + } + } + } + + /* + * SDRAM controller is not calibrated with DDR4 ram blocks: + * reset DDR and perform calibration retry + */ + nthw_field_set_flush(p->mp_fld_rst_ddr4); /* Reset DDR PLL */ + nt_os_wait_usec(100); + nthw_field_clr_flush(p->mp_fld_rst_ddr4); + + n_retry_cnt++; + } + + nthw_sdc_delete(p_nthw_sdc); + + return res; +} + +static int nthw_fpga_rst_nt200a0x_reset(nthw_fpga_t *p_fpga, + const struct nthw_fpga_rst_nt200a0x *p) +{ + const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str; + const fpga_info_t *const p_fpga_info = p_fpga->p_fpga_info; + + const int n_fpga_product_id = p->mn_fpga_product_id; + const int n_fpga_version = p->mn_fpga_version; + const int n_fpga_revision = p->mn_fpga_revision; + const int n_nthw_adapter_id = p_fpga_info->n_nthw_adapter_id; + const bool b_is_nt200a01 = (n_nthw_adapter_id == NT_HW_ADAPTER_ID_NT200A01); + const int n_hw_id = p_fpga_info->nthw_hw_info.hw_id; + const uint8_t index = 0; + int locked; + int res = -1; + + NT_LOG(DBG, NTHW, "%s: %s: FPGA reset sequence: FPGA %04d-%02d-%02d @ HWId%d\n", + p_adapter_id_str, __func__, n_fpga_product_id, n_fpga_version, n_fpga_revision, + n_hw_id); + assert(n_fpga_product_id == p_fpga->mn_product_id); + + /* + * Reset all domains / modules except peripherals + * Set default reset values to ensure that all modules are reset correctly + * no matter if nic has been powercycled or ntservice has been reloaded + */ + + /* + * reset to defaults + * 1: Reset all domains + */ + NT_LOG(DBG, NTHW, "%s: RST defaults\n", p_adapter_id_str); + + nthw_field_update_register(p->mp_fld_rst_sys); + nthw_field_set_flush(p->mp_fld_rst_sys); + + if (p->mp_fld_rst_tmc) + nthw_field_set_flush(p->mp_fld_rst_tmc); + + nthw_field_set_flush(p->mp_fld_rst_rpp); + nthw_field_set_flush(p->mp_fld_rst_ddr4); /* 0x07 3 banks */ + nthw_field_set_flush(p->mp_fld_rst_sdc); + + /* Reset port 0 and 1 in the following registers: */ + nthw_field_set_flush(p->mp_fld_rst_phy);/* 0x03 2 ports */ + + if (p->mp_fld_rst_mac_rx) + nthw_field_set_flush(p->mp_fld_rst_mac_rx); /* 0x03 2 ports */ + + if (p->mp_fld_rst_mac_tx) + nthw_field_set_flush(p->mp_fld_rst_mac_tx); /* 0x03 2 ports */ + + if (p->mp_fld_rst_pcs_rx) + nthw_field_set_flush(p->mp_fld_rst_pcs_rx); /* 0x03 2 ports */ + + if (p->mp_fld_rst_serdes_rx) + nthw_field_set_flush(p->mp_fld_rst_serdes_rx); /* 0x03 2 ports */ + + if (p->mp_fld_rst_serdes_rx_datapath) { + nthw_field_set_flush(p->mp_fld_rst_serdes_rx_datapath); + nthw_field_clr_flush(p->mp_fld_rst_serdes_rx); + } + + if (p->mp_fld_rst_serdes_tx) + nthw_field_set_flush(p->mp_fld_rst_serdes_tx); + + nthw_field_set_flush(p->mp_fld_rst_ptp); + nthw_field_set_flush(p->mp_fld_rst_ts); + nthw_field_set_flush(p->mp_fld_rst_sys_mmcm); + nthw_field_set_flush(p->mp_fld_rst_core_mmcm); + nthw_field_set_flush(p->mp_fld_rst_ptp_mmcm); + nthw_field_set_flush(p->mp_fld_rst_ts_mmcm); + + if (true && p->mp_fld_rst_tsm_ref_mmcm) + nthw_field_set_flush(p->mp_fld_rst_tsm_ref_mmcm); + + /* Write all changes to register */ + nthw_field_flush_register(p->mp_fld_rst_sys); + + if (b_is_nt200a01 && n_hw_id == 2) { /* Not relevant to NT200A02 */ + if (p->mp_fld_rst_tsm_ref_mmcm) { + nthw_field_update_register(p->mp_fld_rst_tsm_ref_mmcm); + nthw_field_set_flush(p->mp_fld_rst_tsm_ref_mmcm); + } + } + + /* + * 2: Force use of 50 MHz reference clock for timesync; + * NOTE: From 9508-05-18 this is a 20 MHz clock + */ + NT_LOG(DBG, NTHW, "%s: Setting TS CLK SEL OVERRIDE\n", p_adapter_id_str); + nthw_field_update_register(p->mp_fld_ctrl_ts_clk_sel_override); + nthw_field_set_flush(p->mp_fld_ctrl_ts_clk_sel_override); + + NT_LOG(DBG, NTHW, "%s: Setting TS CLK SEL\n", p_adapter_id_str); + nthw_field_update_register(p->mp_fld_ctrl_ts_clk_sel); + nthw_field_set_flush(p->mp_fld_ctrl_ts_clk_sel); + + if (b_is_nt200a01 && n_hw_id == 2) { /* Not relevant to NT200A02 */ + NT_LOG(DBG, NTHW, "%s: Selecting 20MHz TS CLK SEL REF\n", p_adapter_id_str); + + if (p->mp_fld_ctrl_ts_clk_sel_ref) { + nthw_field_update_register(p->mp_fld_ctrl_ts_clk_sel_ref); + nthw_field_clr_flush(p->mp_fld_ctrl_ts_clk_sel_ref); + } + } + + /* 4: De-assert sys reset, CORE and SYS MMCM resets */ + NT_LOG(DBG, NTHW, "%s: De-asserting SYS, CORE and SYS MMCM resets\n", p_adapter_id_str); + nthw_field_update_register(p->mp_fld_rst_sys); + nthw_field_clr_flush(p->mp_fld_rst_sys); + nthw_field_clr_flush(p->mp_fld_rst_sys_mmcm); + nthw_field_clr_flush(p->mp_fld_rst_core_mmcm); + + /* 5: wait until CORE MMCM and SYS MMCM are LOCKED */ + NT_LOG(DBG, NTHW, "%s: Waiting for SYS MMCM to lock\n", p_adapter_id_str); + locked = nthw_field_wait_set_any32(p->mp_fld_stat_sys_mmcm_locked, -1, -1); + + if (locked != 0) { + NT_LOG(ERR, NTHW, "%s: Waiting for SYS MMCM to lock failed (%d)\n", + p_adapter_id_str, locked); + } + + NT_LOG(DBG, NTHW, "%s: Waiting for CORE MMCM to lock\n", p_adapter_id_str); + locked = nthw_field_wait_set_any32(p->mp_fld_stat_core_mmcm_locked, -1, -1); + + if (locked != 0) { + NT_LOG(ERR, NTHW, "%s: Waiting for CORE MMCM to lock failed (%d)\n", + p_adapter_id_str, locked); + } + + /* + * RAC RAB bus "flip/flip" reset second stage - new impl (ref RMT#37020) + * RAC/RAB init - SYS/CORE MMCM is locked - pull the remaining RAB busses out of reset + */ + { + nthw_rac_t *p_nthw_rac = p_fpga_info->mp_nthw_rac; + NT_LOG(DBG, NTHW, "%s: De-asserting remaining RAB busses\n", p_adapter_id_str); + nthw_rac_rab_init(p_nthw_rac, 0); + } + + if (true && p->mp_fld_rst_tsm_ref_mmcm) { + NT_LOG(DBG, NTHW, "%s: De-asserting TSM REF MMCM\n", p_adapter_id_str); + nthw_field_clr_flush(p->mp_fld_rst_tsm_ref_mmcm); + + if (p->mp_fld_stat_tsm_ref_mmcm_locked) { + NT_LOG(DBG, NTHW, "%s: Waiting for TSM REF MMCM to lock\n", + p_adapter_id_str); + locked = nthw_field_wait_set_any32(p->mp_fld_stat_tsm_ref_mmcm_locked, -1, + -1); + + if (locked != 0) { + NT_LOG(ERR, NTHW, + "%s: Waiting for TSM REF MMCM to lock failed (%d)\n", + p_adapter_id_str, locked); + } + } + } + + /* + * 5.2: Having ensured CORE MMCM and SYS MMCM are LOCKED, + * we need to select the alternative 20 MHz reference clock, + * the external TSM reference clock + * on NT200A01 - build 2 HW only (see SSF00024 p.32) + */ + if (b_is_nt200a01 && n_hw_id == 2) { /* Not relevant to NT200A02 */ + NT_LOG(DBG, NTHW, "%s: Setting TS CLK SEL REF\n", p_adapter_id_str); + + if (p->mp_fld_ctrl_ts_clk_sel_ref) + nthw_field_set_flush(p->mp_fld_ctrl_ts_clk_sel_ref); + + if (p->mp_fld_rst_tsm_ref_mmcm) { + NT_LOG(DBG, NTHW, "%s: De-asserting TSM REF MMCM\n", p_adapter_id_str); + nthw_field_clr_flush(p->mp_fld_rst_tsm_ref_mmcm); + } + + NT_LOG(DBG, NTHW, "%s: Waiting for TSM REF MMCM to lock\n", p_adapter_id_str); + + if (p->mp_fld_stat_tsm_ref_mmcm_locked) { + locked = nthw_field_wait_set_any32(p->mp_fld_stat_tsm_ref_mmcm_locked, -1, + -1); + + if (locked != 0) { + NT_LOG(ERR, NTHW, + "%s: Waiting for TSM REF MMCM to lock failed (%d)\n", + p_adapter_id_str, locked); + } + } + } + + NT_LOG(DBG, NTHW, "%s: De-asserting all PHY resets\n", p_adapter_id_str); + nthw_field_update_register(p->mp_fld_rst_phy); + nthw_field_clr_flush(p->mp_fld_rst_phy); + + /* MAC_PCS_XXV 10G/25G: 9530 / 9544 */ + if (n_fpga_product_id == 9530 || n_fpga_product_id == 9544) { + { + /* Based on nt200e3_2_ptp.cpp My25GbPhy::resetRx */ + nthw_mac_pcs_xxv_t *p_nthw_mac_pcs_xxv0 = nthw_mac_pcs_xxv_new(); + assert(p_nthw_mac_pcs_xxv0); + nthw_mac_pcs_xxv_init(p_nthw_mac_pcs_xxv0, p_fpga, 0, 1, false); + + nthw_mac_pcs_xxv_reset_rx_gt_data(p_nthw_mac_pcs_xxv0, true, index); + nt_os_wait_usec(1000); + + nthw_mac_pcs_xxv_reset_rx_gt_data(p_nthw_mac_pcs_xxv0, false, index); + nt_os_wait_usec(1000); + + nthw_mac_pcs_xxv_delete(p_nthw_mac_pcs_xxv0); + } + + { + /* Based on nt200e3_2_ptp.cpp My25GbPhy::resetRx */ + nthw_mac_pcs_xxv_t *p_nthw_mac_pcs_xxv1 = nthw_mac_pcs_xxv_new(); + assert(p_nthw_mac_pcs_xxv1); + nthw_mac_pcs_xxv_init(p_nthw_mac_pcs_xxv1, p_fpga, 1, 1, false); + + nthw_mac_pcs_xxv_reset_rx_gt_data(p_nthw_mac_pcs_xxv1, true, index); + nt_os_wait_usec(1000); + + nthw_mac_pcs_xxv_reset_rx_gt_data(p_nthw_mac_pcs_xxv1, false, index); + nt_os_wait_usec(1000); + + nthw_mac_pcs_xxv_delete(p_nthw_mac_pcs_xxv1); + } + nt_os_wait_usec(3000); + } + + /* MAC_PCS_XXV 8x10G: 9572 */ + if (n_fpga_product_id == 9572) { + { + nthw_mac_pcs_xxv_t *p_nthw_mac_pcs_xxv0 = nthw_mac_pcs_xxv_new(); + assert(p_nthw_mac_pcs_xxv0); + nthw_mac_pcs_xxv_init(p_nthw_mac_pcs_xxv0, p_fpga, 0, 4, true); + + for (int i = 0; i < 4; i++) { + nthw_mac_pcs_xxv_reset_rx_gt_data(p_nthw_mac_pcs_xxv0, true, i); + nthw_mac_pcs_xxv_set_rx_mac_pcs_rst(p_nthw_mac_pcs_xxv0, true, i); + nt_os_wait_usec(1000); + + nthw_mac_pcs_xxv_reset_rx_gt_data(p_nthw_mac_pcs_xxv0, false, i); + nthw_mac_pcs_xxv_set_rx_mac_pcs_rst(p_nthw_mac_pcs_xxv0, false, i); + nt_os_wait_usec(1000); + } + + nthw_mac_pcs_xxv_delete(p_nthw_mac_pcs_xxv0); + } + + { + nthw_mac_pcs_xxv_t *p_nthw_mac_pcs_xxv1 = nthw_mac_pcs_xxv_new(); + assert(p_nthw_mac_pcs_xxv1); + nthw_mac_pcs_xxv_init(p_nthw_mac_pcs_xxv1, p_fpga, 1, 4, true); + + for (int i = 0; i < 4; i++) { + nthw_mac_pcs_xxv_reset_rx_gt_data(p_nthw_mac_pcs_xxv1, true, i); + nthw_mac_pcs_xxv_set_rx_mac_pcs_rst(p_nthw_mac_pcs_xxv1, true, i); + nt_os_wait_usec(1000); + + nthw_mac_pcs_xxv_reset_rx_gt_data(p_nthw_mac_pcs_xxv1, false, i); + nthw_mac_pcs_xxv_set_rx_mac_pcs_rst(p_nthw_mac_pcs_xxv1, false, i); + nt_os_wait_usec(1000); + } + + nthw_mac_pcs_xxv_delete(p_nthw_mac_pcs_xxv1); + } + nt_os_wait_usec(3000); + } + + /* + * 8: De-assert reset for remaining domains/modules resets except + * TS, PTP, PTP_MMCM and TS_MMCM + */ + NT_LOG(DBG, NTHW, "%s: De-asserting TMC RST\n", p_adapter_id_str); + + if (p->mp_fld_rst_tmc) { + nthw_field_update_register(p->mp_fld_rst_tmc); + nthw_field_clr_flush(p->mp_fld_rst_tmc); + } + + NT_LOG(DBG, NTHW, "%s: De-asserting RPP RST\n", p_adapter_id_str); + nthw_field_update_register(p->mp_fld_rst_rpp); + nthw_field_clr_flush(p->mp_fld_rst_rpp); + + NT_LOG(DBG, NTHW, "%s: De-asserting DDR4 RST\n", p_adapter_id_str); + nthw_field_update_register(p->mp_fld_rst_ddr4); + nthw_field_clr_flush(p->mp_fld_rst_ddr4); + + NT_LOG(DBG, NTHW, "%s: De-asserting SDC RST\n", p_adapter_id_str); + nthw_field_update_register(p->mp_fld_rst_sdc); + nthw_field_clr_flush(p->mp_fld_rst_sdc); + + /* NOTE: 9522 implements PHY10G_QPLL reset and lock at this stage in mac_rx_rst() */ + NT_LOG(DBG, NTHW, "%s: De-asserting MAC RX RST\n", p_adapter_id_str); + + if (p->mp_fld_rst_mac_rx) { + nthw_field_update_register(p->mp_fld_rst_mac_rx); + nthw_field_clr_flush(p->mp_fld_rst_mac_rx); + } + + /* await until DDR4 PLL LOCKED and SDRAM controller has been calibrated */ + res = nthw_fpga_rst_nt200a0x_wait_sdc_calibrated(p_fpga, p); + + if (res) { + NT_LOG(ERR, NTHW, + "%s: nthw_fpga_rst_nt200a0x_wait_sdc_calibrated() returned true\n", + p_adapter_id_str); + return -1; + } + + if (nthw_field_get_updated(p->mp_fld_sticky_core_mmcm_unlocked)) { + NT_LOG(ERR, NTHW, "%s: get_sticky_core_mmcm_unlocked() returned true\n", + p_adapter_id_str); + return -1; + } + + if (p->mp_fld_sticky_pci_sys_mmcm_unlocked && + nthw_field_get_updated(p->mp_fld_sticky_pci_sys_mmcm_unlocked)) { + NT_LOG(ERR, NTHW, "%s: get_sticky_pci_sys_mmcm_unlocked() returned true\n", + p_adapter_id_str); + return -1; + } + + if (b_is_nt200a01 && n_hw_id == 2) { /* Not relevant to NT200A02 */ + if (p->mp_fld_sticky_tsm_ref_mmcm_unlocked && + nthw_field_get_updated(p->mp_fld_sticky_tsm_ref_mmcm_unlocked)) { + NT_LOG(ERR, NTHW, "%s: get_sticky_tsm_ref_mmcm_unlocked returned true\n", + p_adapter_id_str); + return -1; + } + } + + /* + * Timesync/PTP reset sequence + * De-assert TS_MMCM reset + */ + NT_LOG(DBG, NTHW, "%s: De-asserting TS MMCM RST\n", p_adapter_id_str); + nthw_field_clr_flush(p->mp_fld_rst_ts_mmcm); + + /* Wait until TS_MMCM LOCKED (NT_RAB0_REG_P9508_RST9508_STAT_TS_MMCM_LOCKED=1); */ + NT_LOG(DBG, NTHW, "%s: Waiting for TS MMCM to lock\n", p_adapter_id_str); + locked = nthw_field_wait_set_any32(p->mp_fld_stat_ts_mmcm_locked, -1, -1); + + if (locked != 0) { + NT_LOG(ERR, NTHW, "%s: Waiting for TS MMCM to lock failed (%d)\n", + p_adapter_id_str, locked); + } + + NT_LOG(DBG, NTHW, "%s: Calling clear_sticky_mmcm_unlock_bits()\n", p_adapter_id_str); + nthw_field_update_register(p->mp_fld_sticky_ptp_mmcm_unlocked); + /* Clear all sticky bits */ + nthw_field_set_flush(p->mp_fld_sticky_ptp_mmcm_unlocked); + nthw_field_set_flush(p->mp_fld_sticky_ts_mmcm_unlocked); + nthw_field_set_flush(p->mp_fld_sticky_ddr4_mmcm_unlocked); + nthw_field_set_flush(p->mp_fld_sticky_ddr4_pll_unlocked); + nthw_field_set_flush(p->mp_fld_sticky_core_mmcm_unlocked); + + if (p->mp_fld_sticky_tsm_ref_mmcm_unlocked) + nthw_field_set_flush(p->mp_fld_sticky_tsm_ref_mmcm_unlocked); + + if (p->mp_fld_sticky_pci_sys_mmcm_unlocked) + nthw_field_set_flush(p->mp_fld_sticky_pci_sys_mmcm_unlocked); + + /* De-assert TS reset bit */ + NT_LOG(DBG, NTHW, "%s: De-asserting TS RST\n", p_adapter_id_str); + nthw_field_clr_flush(p->mp_fld_rst_ts); + + if (nthw_field_get_updated(p->mp_fld_sticky_ts_mmcm_unlocked)) { + NT_LOG(ERR, NTHW, "%s: get_sticky_ts_mmcm_unlocked() returned true\n", + p_adapter_id_str); + return -1; + } + + if (nthw_field_get_updated(p->mp_fld_sticky_ddr4_mmcm_unlocked)) { + NT_LOG(ERR, NTHW, "%s: get_sticky_ddr4_mmcm_unlocked() returned true\n", + p_adapter_id_str); + return -1; + } + + if (nthw_field_get_updated(p->mp_fld_sticky_ddr4_pll_unlocked)) { + NT_LOG(ERR, NTHW, "%s: get_sticky_ddr4_pll_unlocked() returned true\n", + p_adapter_id_str); + return -1; + } + + if (nthw_field_get_updated(p->mp_fld_sticky_core_mmcm_unlocked)) { + NT_LOG(ERR, NTHW, "%s: get_sticky_core_mmcm_unlocked() returned true\n", + p_adapter_id_str); + return -1; + } + + if (p->mp_fld_sticky_pci_sys_mmcm_unlocked && + nthw_field_get_updated(p->mp_fld_sticky_pci_sys_mmcm_unlocked)) { + NT_LOG(ERR, NTHW, "%s: get_sticky_pci_sys_mmcm_unlocked() returned true\n", + p_adapter_id_str); + return -1; + } + + if (b_is_nt200a01 && n_hw_id == 2) { /* Not relevant to NT200A02 */ + if (p->mp_fld_sticky_tsm_ref_mmcm_unlocked && + nthw_field_get_updated(p->mp_fld_sticky_tsm_ref_mmcm_unlocked)) { + NT_LOG(ERR, NTHW, "%s: get_sticky_tsm_ref_mmcm_unlocked() returned true\n", + p_adapter_id_str); + return -1; + } + } + + if (false) { + /* Deassert PTP_MMCM */ + NT_LOG(DBG, NTHW, "%s: De-asserting PTP MMCM RST\n", p_adapter_id_str); + nthw_field_clr_flush(p->mp_fld_rst_ptp_mmcm); + + if ((b_is_nt200a01 && n_fpga_version >= 9) || !b_is_nt200a01) { + /* Wait until PTP_MMCM LOCKED */ + NT_LOG(DBG, NTHW, "%s: Waiting for PTP MMCM to lock\n", p_adapter_id_str); + locked = nthw_field_wait_set_any32(p->mp_fld_stat_ptp_mmcm_locked, -1, -1); + + if (locked != 0) { + NT_LOG(ERR, NTHW, "%s: Waiting for PTP MMCM to lock failed (%d)\n", + p_adapter_id_str, locked); + } + } + + /* Switch PTP MMCM sel to use ptp clk */ + NT_LOG(DBG, NTHW, "%s: Setting PTP MMCM CLK SEL\n", p_adapter_id_str); + nthw_field_set_flush(p->mp_fld_ctrl_ptp_mmcm_clk_sel); + + /* Wait until TS_MMCM LOCKED (NT_RAB0_REG_P9508_RST9508_STAT_TS_MMCM_LOCKED=1); */ + NT_LOG(DBG, NTHW, "%s: Waiting for TS MMCM to re-lock\n", p_adapter_id_str); + locked = nthw_field_wait_set_any32(p->mp_fld_stat_ts_mmcm_locked, -1, -1); + + if (locked != 0) { + NT_LOG(ERR, NTHW, "%s: Waiting for TS MMCM to re-lock failed (%d)\n", + p_adapter_id_str, locked); + } + } + + NT_LOG(DBG, NTHW, "%s: De-asserting PTP RST\n", p_adapter_id_str); + nthw_field_clr_flush(p->mp_fld_rst_ptp); + + /* POWER staging introduced in 9508-05-09 and always for 9512 */ + if (n_fpga_product_id == 9508 && n_fpga_version <= 5 && n_fpga_revision <= 8) { + NT_LOG(DBG, NTHW, "%s: No power staging\n", p_adapter_id_str); + + } else { + NT_LOG(DBG, NTHW, "%s: Staging power\n", p_adapter_id_str); + nthw_field_set_flush(p->mp_fld_power_pu_phy); /* PHY power up */ + nthw_field_clr_flush(p->mp_fld_power_pu_nseb); /* NSEB power down */ + } + + NT_LOG(DBG, NTHW, "%s: %s: END\n", p_adapter_id_str, __func__); + + return 0; +} + +static int nthw_fpga_rst_nt200a0x_init(struct fpga_info_s *p_fpga_info, + struct nthw_fpga_rst_nt200a0x *p_rst) +{ + assert(p_fpga_info); + + const char *const p_adapter_id_str = p_fpga_info->mp_adapter_id_str; + int res = -1; + int n_si_labs_clock_synth_model = -1; + uint8_t n_si_labs_clock_synth_i2c_addr = 0; + nthw_fpga_t *p_fpga = NULL; + + p_fpga = p_fpga_info->mp_fpga; + + NT_LOG(DBG, NTHW, "%s: %s: RAB init/reset\n", p_adapter_id_str, __func__); + nthw_rac_rab_reset(p_fpga_info->mp_nthw_rac); + nthw_rac_rab_setup(p_fpga_info->mp_nthw_rac); + + res = nthw_fpga_avr_probe(p_fpga, 0); + + res = nthw_fpga_iic_scan(p_fpga, 0, 0); + res = nthw_fpga_iic_scan(p_fpga, 2, 3); + + /* + * Detect clock synth model + * check for NT200A02/NT200A01 HW-build2 - most commonly seen + */ + n_si_labs_clock_synth_i2c_addr = si5340_u23_i2c_addr_7bit; + n_si_labs_clock_synth_model = + nthw_fpga_silabs_detect(p_fpga, 0, n_si_labs_clock_synth_i2c_addr, 1); + + if (n_si_labs_clock_synth_model == -1) { + /* check for old NT200A01 HW-build1 */ + n_si_labs_clock_synth_i2c_addr = si5338_u23_i2c_addr_7bit; + n_si_labs_clock_synth_model = + nthw_fpga_silabs_detect(p_fpga, 0, n_si_labs_clock_synth_i2c_addr, 255); + + if (n_si_labs_clock_synth_model == -1) { + NT_LOG(ERR, NTHW, "%s: Failed to detect clock synth model (%d)\n", + p_adapter_id_str, n_si_labs_clock_synth_model); + return -1; + } + } + + p_rst->mn_si_labs_clock_synth_model = n_si_labs_clock_synth_model; + p_rst->mn_si_labs_clock_synth_i2c_addr = n_si_labs_clock_synth_i2c_addr; + p_rst->mn_hw_id = p_fpga_info->nthw_hw_info.hw_id; + NT_LOG(DBG, NTHW, "%s: %s: Si%04d @ 0x%02x\n", p_adapter_id_str, __func__, + p_rst->mn_si_labs_clock_synth_model, p_rst->mn_si_labs_clock_synth_i2c_addr); + + return res; +} + +static struct rst_nt200a0x_ops rst_nt200a0x_ops = { .nthw_fpga_rst_nt200a0x_init = + nthw_fpga_rst_nt200a0x_init, + .nthw_fpga_rst_nt200a0x_reset = + nthw_fpga_rst_nt200a0x_reset +}; + +static void __attribute__((constructor(65535))) rst_nt200a0x_ops_init(void) +{ + NT_LOG(INF, NTHW, "RST NT200A0X OPS INIT"); + register_rst_nt200a0x_ops(&rst_nt200a0x_ops); +} diff --git a/drivers/net/ntnic/nthw/core/nt200a0x/reset/nthw_fpga_rst_nt200a0x.h b/drivers/net/ntnic/nthw/core/nt200a0x/reset/nthw_fpga_rst_nt200a0x.h new file mode 100644 index 0000000000..af508bd2bd --- /dev/null +++ b/drivers/net/ntnic/nthw/core/nt200a0x/reset/nthw_fpga_rst_nt200a0x.h @@ -0,0 +1,9 @@ +/* + * SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef __NTHW_FPGA_RST_NT200A0X_H__ +#define __NTHW_FPGA_RST_NT200A0X_H__ + +#endif /* __NTHW_FPGA_RST_NT200A0X_H__ */ diff --git a/drivers/net/ntnic/nthw/core/nthw_fpga.c b/drivers/net/ntnic/nthw/core/nthw_fpga.c new file mode 100644 index 0000000000..bc03ff97d2 --- /dev/null +++ b/drivers/net/ntnic/nthw/core/nthw_fpga.c @@ -0,0 +1,888 @@ +/* + * SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include "ntlog.h" + +#include "nthw_drv.h" +#include "nthw_register.h" + +#include "nthw_fpga.h" + +#include "nthw_fpga_instances.h" +#include "nthw_fpga_mod_str_map.h" + +#include "nthw_spi_v3.h" + +#include + +int nthw_fpga_get_param_info(struct fpga_info_s *p_fpga_info, nthw_fpga_t *p_fpga) +{ + mcu_info_t *p_mcu_info = &p_fpga_info->mcu_info; + + const int n_nims = nthw_fpga_get_product_param(p_fpga, NT_NIMS, -1); + const int n_phy_ports = nthw_fpga_get_product_param(p_fpga, NT_PHY_PORTS, -1); + const int n_phy_quads = nthw_fpga_get_product_param(p_fpga, NT_PHY_QUADS, -1); + const int n_rx_ports = nthw_fpga_get_product_param(p_fpga, NT_RX_PORTS, -1); + const int n_tx_ports = nthw_fpga_get_product_param(p_fpga, NT_TX_PORTS, -1); + const int n_vf_offset = nthw_fpga_get_product_param(p_fpga, NT_HIF_VF_OFFSET, 4); + + p_fpga_info->n_nims = n_nims; + p_fpga_info->n_phy_ports = n_phy_ports; + p_fpga_info->n_phy_quads = n_phy_quads; + p_fpga_info->n_rx_ports = n_rx_ports; + p_fpga_info->n_tx_ports = n_tx_ports; + p_fpga_info->n_vf_offset = n_vf_offset; + p_fpga_info->profile = FPGA_INFO_PROFILE_UNKNOWN; + + /* Check for MCU */ + if (nthw_fpga_get_product_param(p_fpga, NT_MCU_PRESENT, 0) != 0) { + p_mcu_info->mb_has_mcu = true; + /* Check MCU Type */ + p_mcu_info->mn_mcu_type = nthw_fpga_get_product_param(p_fpga, NT_MCU_TYPE, -1); + /* MCU DRAM size */ + p_mcu_info->mn_mcu_dram_size = + nthw_fpga_get_product_param(p_fpga, NT_MCU_DRAM_SIZE, -1); + + } else { + p_mcu_info->mb_has_mcu = false; + p_mcu_info->mn_mcu_type = -1; + p_mcu_info->mn_mcu_dram_size = -1; + } + + /* Check for VSWITCH FPGA */ + if (nthw_fpga_get_product_param(p_fpga, NT_NFV_OVS_PRODUCT, 0) != 0) { + p_fpga_info->profile = FPGA_INFO_PROFILE_VSWITCH; + + } else if (nthw_fpga_get_product_param(p_fpga, NT_IOA_PRESENT, 0) != 0) { + /* Check for VSWITCH FPGA - legacy */ + p_fpga_info->profile = FPGA_INFO_PROFILE_VSWITCH; + + } else if (nthw_fpga_get_product_param(p_fpga, NT_QM_PRESENT, 0) != 0) { + p_fpga_info->profile = FPGA_INFO_PROFILE_CAPTURE; + + } else { + p_fpga_info->profile = FPGA_INFO_PROFILE_INLINE; + } + + return 0; +} + +int nthw_fpga_iic_scan(nthw_fpga_t *p_fpga, const int n_instance_no_begin, + const int n_instance_no_end) +{ + int i; + + assert(n_instance_no_begin <= n_instance_no_end); + + for (i = n_instance_no_begin; i <= n_instance_no_end; i++) { + nthw_iic_t *p_nthw_iic = nthw_iic_new(); + + if (p_nthw_iic) { + const int rc = nthw_iic_init(p_nthw_iic, p_fpga, i, 8); + + if (rc == 0) { + nthw_iic_set_retry_params(p_nthw_iic, -1, 100, 100, 3, 3); + nthw_iic_scan(p_nthw_iic); + } + + nthw_iic_delete(p_nthw_iic); + p_nthw_iic = NULL; + } + } + + return 0; +} + +int nthw_fpga_silabs_detect(nthw_fpga_t *p_fpga, const int n_instance_no, const int n_dev_addr, + const int n_page_reg_addr) +{ + const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str; + (void)p_adapter_id_str; + uint64_t ident = -1; + int res = -1; + + nthw_iic_t *p_nthw_iic = nthw_iic_new(); + + if (p_nthw_iic) { + uint8_t data; + uint8_t a_silabs_ident[8]; + nthw_iic_init(p_nthw_iic, p_fpga, n_instance_no, 8); + + data = 0; + /* switch to page 0 */ + nthw_iic_write_data(p_nthw_iic, (uint8_t)n_dev_addr, (uint8_t)n_page_reg_addr, 1, + &data); + res = nthw_iic_read_data(p_nthw_iic, (uint8_t)n_dev_addr, 0x00, + sizeof(a_silabs_ident), a_silabs_ident); + + if (res == 0) { + int i; + + for (i = 0; i < (int)sizeof(a_silabs_ident); i++) { + ident <<= 8; + ident |= a_silabs_ident[i]; + } + } + + nthw_iic_delete(p_nthw_iic); + p_nthw_iic = NULL; + + /* Conclude SiLabs part */ + if (res == 0) { + if (a_silabs_ident[3] == 0x53) { + if (a_silabs_ident[2] == 0x40) + res = 5340; + + else if (a_silabs_ident[2] == 0x41) + res = 5341; + + } else if (a_silabs_ident[2] == 38) { + res = 5338; + + } else { + res = -1; + } + } + } + + NT_LOG(DBG, NTHW, "%s: %016" PRIX64 ": %d\n", p_adapter_id_str, ident, res); + return res; +} + +/* + * Calculate CRC-16-CCITT of passed data + * CRC-16-CCITT ^16 + ^12 + ^5 + 1 (0x1021) (X.25, HDLC, XMODEM, Bluetooth, + * SD, many others; known as CRC-CCITT) + */ +static uint16_t _crc16(uint8_t *buffer, size_t length) +{ + uint16_t seed = 0; + + while (length--) { + seed = (uint16_t)(seed >> 8 | seed << 8); + seed = (uint16_t)(seed ^ *buffer++); + seed = (uint16_t)(seed ^ (seed & 0xff) >> 4); + seed = (uint16_t)(seed ^ seed << 8 << 4); + seed = (uint16_t)(seed ^ (seed & 0xff) << 4 << 1); + } + + return seed; +} + +int nthw_fpga_avr_probe(nthw_fpga_t *p_fpga, const int n_instance_no) +{ + struct fpga_info_s *p_fpga_info = p_fpga->p_fpga_info; + const char *const p_adapter_id_str = p_fpga_info->mp_adapter_id_str; + nthw_spi_v3_t *p_avr_spi; + int res = -1; + + p_avr_spi = nthw_spi_v3_new(); + + if (p_avr_spi) { + struct avr_vpd_info_s { + /* avr info */ + uint32_t n_avr_spi_version; + uint8_t n_avr_fw_ver_major; + uint8_t n_avr_fw_ver_minor; + uint8_t n_avr_fw_ver_micro; + uint8_t a_avr_fw_ver_str[50]; + uint8_t a_avr_fw_plat_id_str[20]; + + /* vpd_eeprom_t */ + uint8_t psu_hw_version; + uint8_t vpd_pn[GEN2_PN_SIZE]; + uint8_t vpd_pba[GEN2_PBA_SIZE]; + uint8_t vpd_sn[GEN2_SN_SIZE]; + uint8_t vpd_board_name[GEN2_BNAME_SIZE]; + uint8_t vpd_platform_section[GEN2_PLATFORM_SIZE]; + + /* board_info_t aka vpd_platform_section: */ + uint32_t product_family;/* uint8_t 1: capture, 2: Inline, 3: analysis */ + uint32_t feature_mask; /* Bit 0: OC192 capable */ + uint32_t invfeature_mask; + uint8_t no_of_macs; + uint8_t mac_address[6]; + uint16_t custom_id; + uint8_t user_id[8]; + /* + * Reserved NT operations to monitor the reprogram count of user_id with + * vpduser + */ + uint16_t user_id_erase_write_count; + + /* + * AVR_OP_SYSINFO: struct version_sysinfo_request_container + * Which version of the sysinfo container to retrieve. Set to zero to fetch + * latest. Offset zero of latest always contain an uint8_t version info + */ + uint8_t sysinfo_container_version; + + /* AVR_OP_SYSINFO: struct AvrLibcVersion */ + /* The constant __AVR_LIBC_VERSION__ */ + uint32_t sysinfo_avr_libc_version; + + /* AVR_OP_SYSINFO: struct AvrLibcSignature */ + uint8_t sysinfo_signature_0; /* The constant SIGNATURE_0 */ + uint8_t sysinfo_signature_1; /* The constant SIGNATURE_1 */ + uint8_t sysinfo_signature_2; /* The constant SIGNATURE_2 */ + + /* AVR_OP_SYSINFO: struct AvrOs */ + uint8_t sysinfo_spi_version; /* SPI command layer version */ + /* + * Hardware revision. Locked to eeprom address zero. Is also available via + * VPD read opcode (prior to v1.4b, this is required) + */ + uint8_t sysinfo_hw_revision; + /* + * Number of ticks/second (Note: Be aware this may become zero if timer + * module is rewritten to a tickles system!) + */ + uint8_t sysinfo_ticks_per_second; + uint32_t sysinfo_uptime;/* Uptime in seconds since last AVR reset */ + uint8_t sysinfo_osccal; /* OSCCAL value */ + + /* + * Meta data concluded/calculated from req/reply + */ + bool b_feature_mask_valid; + bool b_crc16_valid; + uint16_t n_crc16_stored; + uint16_t n_crc16_calced; + uint64_t n_mac_val; + }; + + struct avr_vpd_info_s avr_vpd_info; + struct tx_rx_buf tx_buf; + struct tx_rx_buf rx_buf; + char rx_data[MAX_AVR_CONTAINER_SIZE]; + uint32_t u32; + + memset(&avr_vpd_info, 0, sizeof(avr_vpd_info)); + + nthw_spi_v3_init(p_avr_spi, p_fpga, n_instance_no); + + /* AVR_OP_SPI_VERSION */ + tx_buf.size = 0; + tx_buf.p_buf = NULL; + rx_buf.size = sizeof(u32); + rx_buf.p_buf = &u32; + u32 = 0; + res = nthw_spi_v3_transfer(p_avr_spi, AVR_OP_SPI_VERSION, &tx_buf, &rx_buf); + avr_vpd_info.n_avr_spi_version = u32; + NT_LOG(DBG, NTHW, "%s: AVR%d: SPI_VER: %d\n", p_adapter_id_str, n_instance_no, + avr_vpd_info.n_avr_spi_version); + + /* AVR_OP_VERSION */ + tx_buf.size = 0; + tx_buf.p_buf = NULL; + rx_buf.size = sizeof(rx_data); + rx_buf.p_buf = &rx_data; + res = nthw_spi_v3_transfer(p_avr_spi, AVR_OP_VERSION, &tx_buf, &rx_buf); + + avr_vpd_info.n_avr_fw_ver_major = rx_data[0]; + avr_vpd_info.n_avr_fw_ver_minor = rx_data[1]; + avr_vpd_info.n_avr_fw_ver_micro = rx_data[2]; + NT_LOG(DBG, NTHW, "%s: AVR%d: FW_VER: %c.%c.%c\n", p_adapter_id_str, n_instance_no, + avr_vpd_info.n_avr_fw_ver_major, avr_vpd_info.n_avr_fw_ver_minor, + avr_vpd_info.n_avr_fw_ver_micro); + + memcpy(avr_vpd_info.a_avr_fw_ver_str, &rx_data[0 + 3], + sizeof(avr_vpd_info.a_avr_fw_ver_str)); + NT_LOG(DBG, NTHW, "%s: AVR%d: FW_VER_STR: '%.*s'\n", p_adapter_id_str, + n_instance_no, (int)sizeof(avr_vpd_info.a_avr_fw_ver_str), + avr_vpd_info.a_avr_fw_ver_str); + + memcpy(avr_vpd_info.a_avr_fw_plat_id_str, &rx_data[0 + 3 + 50], + sizeof(avr_vpd_info.a_avr_fw_plat_id_str)); + NT_LOG(DBG, NTHW, "%s: AVR%d: FW_HW_ID_STR: '%.*s'\n", p_adapter_id_str, + n_instance_no, (int)sizeof(avr_vpd_info.a_avr_fw_plat_id_str), + avr_vpd_info.a_avr_fw_plat_id_str); + + snprintf(p_fpga_info->nthw_hw_info.hw_plat_id_str, + sizeof(p_fpga_info->nthw_hw_info.hw_plat_id_str), "%s", + (char *)avr_vpd_info.a_avr_fw_plat_id_str); + p_fpga_info->nthw_hw_info + .hw_plat_id_str[sizeof(p_fpga_info->nthw_hw_info.hw_plat_id_str) - 1] = 0; + + /* AVR_OP_SYSINFO_2 */ + tx_buf.size = 0; + tx_buf.p_buf = NULL; + rx_buf.size = sizeof(rx_data); + rx_buf.p_buf = &rx_data; + res = nthw_spi_v3_transfer(p_avr_spi, AVR_OP_SYSINFO_2, &tx_buf, &rx_buf); + + if (res == 0 && avr_vpd_info.n_avr_spi_version >= 3 && rx_buf.size >= 16) { + if (rx_buf.size != 16) { + NT_LOG(WRN, NTHW, + "%s: AVR%d: SYSINFO2: reply is larger than expected: %04X %04X\n", + p_adapter_id_str, n_instance_no, rx_buf.size, 16); + + } else { + NT_LOG(DBG, NTHW, "%s: AVR%d: SYSINFO2: OK: res=%d sz=%d\n", + p_adapter_id_str, n_instance_no, res, rx_buf.size); + } + + avr_vpd_info.sysinfo_container_version = rx_data[0]; + NT_LOG(DBG, NTHW, "%s: AVR%d: SYSINFO_REQ_VER: %d\n", p_adapter_id_str, + n_instance_no, avr_vpd_info.sysinfo_container_version); + + memcpy(&avr_vpd_info.sysinfo_avr_libc_version, &rx_data[0 + 1], + sizeof(avr_vpd_info.sysinfo_avr_libc_version)); + NT_LOG(DBG, NTHW, "%s: AVR%d: LIBC_VER: %d\n", p_adapter_id_str, + n_instance_no, avr_vpd_info.sysinfo_avr_libc_version); + + avr_vpd_info.sysinfo_signature_0 = rx_data[5]; + avr_vpd_info.sysinfo_signature_1 = rx_data[6]; + avr_vpd_info.sysinfo_signature_2 = rx_data[7]; + NT_LOG(DBG, NTHW, "%s: AVR%d: SIGNATURE: %02x%02x%02x\n", p_adapter_id_str, + n_instance_no, avr_vpd_info.sysinfo_signature_0, + avr_vpd_info.sysinfo_signature_1, avr_vpd_info.sysinfo_signature_2); + + avr_vpd_info.sysinfo_spi_version = rx_data[8]; + NT_LOG(DBG, NTHW, "%s: AVR%d: SPI_VER: %d\n", p_adapter_id_str, + n_instance_no, avr_vpd_info.sysinfo_spi_version); + + avr_vpd_info.sysinfo_hw_revision = rx_data[9]; + NT_LOG(DBG, NTHW, "%s: AVR%d: HW_REV: %d\n", p_adapter_id_str, + n_instance_no, avr_vpd_info.sysinfo_hw_revision); + + avr_vpd_info.sysinfo_ticks_per_second = rx_data[10]; + NT_LOG(DBG, NTHW, "%s: AVR%d: TICKS_PER_SEC: %d\n", p_adapter_id_str, + n_instance_no, avr_vpd_info.sysinfo_ticks_per_second); + + memcpy(&avr_vpd_info.sysinfo_uptime, &rx_data[11], + sizeof(avr_vpd_info.sysinfo_uptime)); + NT_LOG(DBG, NTHW, "%s: AVR%d: UPTIME: %d\n", p_adapter_id_str, + n_instance_no, avr_vpd_info.sysinfo_uptime); + + avr_vpd_info.sysinfo_osccal = rx_data[15]; + NT_LOG(DBG, NTHW, "%s: AVR%d: OSCCAL: %d\n", p_adapter_id_str, + n_instance_no, avr_vpd_info.sysinfo_osccal); + + { + bool b_spi_ver_match = (avr_vpd_info.n_avr_spi_version == + avr_vpd_info.sysinfo_spi_version); + (void)b_spi_ver_match; + NT_LOG(DBG, NTHW, "%s: AVR%d: SPI_VER_TST: %s (%d %d)\n", + p_adapter_id_str, n_instance_no, + (b_spi_ver_match ? "OK" : "MISMATCH"), + avr_vpd_info.n_avr_spi_version, + avr_vpd_info.sysinfo_spi_version); + } + /* SYSINFO2: if response: only populate hw_id not hw_id_emulated */ + p_fpga_info->nthw_hw_info.hw_id = avr_vpd_info.sysinfo_hw_revision; + + } else { + /* AVR_OP_SYSINFO */ + tx_buf.size = 0; + tx_buf.p_buf = NULL; + rx_buf.size = sizeof(rx_data); + rx_buf.p_buf = &rx_data; + res = nthw_spi_v3_transfer(p_avr_spi, AVR_OP_SYSINFO, &tx_buf, &rx_buf); + + if (res == 0 && avr_vpd_info.n_avr_spi_version >= 3 && rx_buf.size >= 16) { + if (rx_buf.size != 16) { + NT_LOG(WRN, NTHW, + "%s: AVR%d: SYSINFO: reply is larger than expected: %04X %04X\n", + p_adapter_id_str, n_instance_no, rx_buf.size, 16); + + } else { + NT_LOG(DBG, NTHW, "%s: AVR%d: SYSINFO: OK: res=%d sz=%d\n", + p_adapter_id_str, n_instance_no, res, rx_buf.size); + } + + avr_vpd_info.sysinfo_container_version = rx_data[0]; + NT_LOG(DBG, NTHW, "%s: AVR%d: SYSINFO_REQ_VER: %d\n", + p_adapter_id_str, n_instance_no, + avr_vpd_info.sysinfo_container_version); + + memcpy(&avr_vpd_info.sysinfo_avr_libc_version, &rx_data[0 + 1], + sizeof(avr_vpd_info.sysinfo_avr_libc_version)); + NT_LOG(DBG, NTHW, "%s: AVR%d: LIBC_VER: %d\n", p_adapter_id_str, + n_instance_no, avr_vpd_info.sysinfo_avr_libc_version); + + avr_vpd_info.sysinfo_signature_0 = rx_data[5]; + avr_vpd_info.sysinfo_signature_1 = rx_data[6]; + avr_vpd_info.sysinfo_signature_2 = rx_data[7]; + NT_LOG(DBG, NTHW, "%s: AVR%d: SIGNATURE: %02x%02x%02x\n", + p_adapter_id_str, n_instance_no, + avr_vpd_info.sysinfo_signature_0, + avr_vpd_info.sysinfo_signature_1, + avr_vpd_info.sysinfo_signature_2); + + avr_vpd_info.sysinfo_spi_version = rx_data[8]; + NT_LOG(DBG, NTHW, "%s: AVR%d: SPI_VER: %d\n", p_adapter_id_str, + n_instance_no, avr_vpd_info.sysinfo_spi_version); + + avr_vpd_info.sysinfo_hw_revision = rx_data[9]; + NT_LOG(DBG, NTHW, "%s: AVR%d: HW_REV: %d\n", p_adapter_id_str, + n_instance_no, avr_vpd_info.sysinfo_hw_revision); + NT_LOG(INF, NTHW, "%s: AVR%d: HW_REV: %d\n", p_adapter_id_str, + n_instance_no, avr_vpd_info.sysinfo_hw_revision); + + avr_vpd_info.sysinfo_ticks_per_second = rx_data[10]; + NT_LOG(DBG, NTHW, "%s: AVR%d: TICKS_PER_SEC: %d\n", + p_adapter_id_str, n_instance_no, + avr_vpd_info.sysinfo_ticks_per_second); + + memcpy(&avr_vpd_info.sysinfo_uptime, &rx_data[11], + sizeof(avr_vpd_info.sysinfo_uptime)); + NT_LOG(DBG, NTHW, "%s: AVR%d: UPTIME: %d\n", p_adapter_id_str, + n_instance_no, avr_vpd_info.sysinfo_uptime); + + avr_vpd_info.sysinfo_osccal = rx_data[15]; + NT_LOG(DBG, NTHW, "%s: AVR%d: OSCCAL: %d\n", p_adapter_id_str, + n_instance_no, avr_vpd_info.sysinfo_osccal); + + { + bool b_spi_ver_match = (avr_vpd_info.n_avr_spi_version == + avr_vpd_info.sysinfo_spi_version); + (void)b_spi_ver_match; + NT_LOG(DBG, NTHW, "%s: AVR%d: SPI_VER_TST: %s (%d %d)\n", + p_adapter_id_str, n_instance_no, + (b_spi_ver_match ? "OK" : "MISMATCH"), + avr_vpd_info.n_avr_spi_version, + avr_vpd_info.sysinfo_spi_version); + } + + p_fpga_info->nthw_hw_info.hw_id = avr_vpd_info.sysinfo_hw_revision; + p_fpga_info->nthw_hw_info.hw_id_emulated = + avr_vpd_info.sysinfo_hw_revision; + + } else { + NT_LOG(ERR, NTHW, "%s: AVR%d: SYSINFO: NA: res=%d sz=%d\n", + p_adapter_id_str, n_instance_no, res, rx_buf.size); + } + } + + /* AVR_OP_VPD_READ */ + tx_buf.size = 0; + tx_buf.p_buf = NULL; + rx_buf.size = sizeof(rx_data); + rx_buf.p_buf = &rx_data; + res = nthw_spi_v3_transfer(p_avr_spi, AVR_OP_VPD_READ, &tx_buf, &rx_buf); + + if (res == 0 && avr_vpd_info.n_avr_spi_version >= 3 && + rx_buf.size >= GEN2_VPD_SIZE_TOTAL) { + avr_vpd_info.n_crc16_calced = _crc16(rx_buf.p_buf, rx_buf.size - 2); + memcpy(&avr_vpd_info.n_crc16_stored, &rx_data[rx_buf.size - 2], + sizeof(avr_vpd_info.n_crc16_stored)); + NT_LOG(DBG, NTHW, "%s: AVR%d: VPD_CRC: %04X %04X\n", p_adapter_id_str, + n_instance_no, avr_vpd_info.n_crc16_stored, + avr_vpd_info.n_crc16_calced); + + avr_vpd_info.b_crc16_valid = + (avr_vpd_info.n_crc16_stored == avr_vpd_info.n_crc16_calced); + NT_LOG(DBG, NTHW, "%s: AVR%d: CRC_TST: %s\n", p_adapter_id_str, + n_instance_no, (avr_vpd_info.b_crc16_valid ? "OK" : "ERROR")); + + if (avr_vpd_info.b_crc16_valid) { + memcpy(&avr_vpd_info.psu_hw_version, &rx_data[0], + sizeof(avr_vpd_info.psu_hw_version)); + NT_LOG(DBG, NTHW, "%s: AVR%d: PSU_HW_VER: %d\n", p_adapter_id_str, + n_instance_no, avr_vpd_info.psu_hw_version); + + memcpy(&avr_vpd_info.vpd_pn, &rx_data[0 + 1], + sizeof(avr_vpd_info.vpd_pn)); + NT_LOG(DBG, NTHW, "%s: AVR%d: PN: '%.*s'\n", p_adapter_id_str, + n_instance_no, GEN2_PN_SIZE, avr_vpd_info.vpd_pn); + + memcpy(&avr_vpd_info.vpd_pba, &rx_data[0 + 1 + GEN2_PN_SIZE], + sizeof(avr_vpd_info.vpd_pba)); + NT_LOG(DBG, NTHW, "%s: AVR%d: PBA: '%.*s'\n", p_adapter_id_str, + n_instance_no, GEN2_PBA_SIZE, avr_vpd_info.vpd_pba); + + memcpy(&avr_vpd_info.vpd_sn, + &rx_data[0 + 1 + GEN2_PN_SIZE + GEN2_PBA_SIZE], + sizeof(avr_vpd_info.vpd_sn)); + NT_LOG(DBG, NTHW, "%s: AVR%d: SN: '%.*s'\n", p_adapter_id_str, + n_instance_no, GEN2_SN_SIZE, avr_vpd_info.vpd_sn); + + memcpy(&avr_vpd_info.vpd_board_name, + &rx_data[0 + 1 + GEN2_PN_SIZE + GEN2_PBA_SIZE + + GEN2_SN_SIZE], + sizeof(avr_vpd_info.vpd_board_name)); + NT_LOG(DBG, NTHW, "%s: AVR%d: BN: '%.*s'\n", p_adapter_id_str, + n_instance_no, GEN2_BNAME_SIZE, + avr_vpd_info.vpd_board_name); + + union mac_u { + uint8_t a_u8[8]; + uint16_t a_u16[4]; + uint32_t a_u32[2]; + uint64_t a_u64[1]; + } mac; + + /* vpd_platform_section */ + uint8_t *p_vpd_board_info = + (uint8_t *)(&rx_data[1 + GEN2_PN_SIZE + GEN2_PBA_SIZE + + GEN2_SN_SIZE + GEN2_BNAME_SIZE]); + memcpy(&avr_vpd_info.product_family, &p_vpd_board_info[0], + sizeof(avr_vpd_info.product_family)); + NT_LOG(DBG, NTHW, "%s: AVR%d: PROD_FAM: %d\n", p_adapter_id_str, + n_instance_no, avr_vpd_info.product_family); + + memcpy(&avr_vpd_info.feature_mask, &p_vpd_board_info[0 + 4], + sizeof(avr_vpd_info.feature_mask)); + NT_LOG(DBG, NTHW, "%s: AVR%d: FMSK_VAL: 0x%08X\n", + p_adapter_id_str, n_instance_no, avr_vpd_info.feature_mask); + + memcpy(&avr_vpd_info.invfeature_mask, &p_vpd_board_info[0 + 4 + 4], + sizeof(avr_vpd_info.invfeature_mask)); + NT_LOG(DBG, NTHW, "%s: AVR%d: FMSK_INV: 0x%08X\n", + p_adapter_id_str, n_instance_no, + avr_vpd_info.invfeature_mask); + + avr_vpd_info.b_feature_mask_valid = + (avr_vpd_info.feature_mask == + ~avr_vpd_info.invfeature_mask); + NT_LOG(DBG, NTHW, "%s: AVR%d: FMSK_TST: %s\n", p_adapter_id_str, + n_instance_no, + (avr_vpd_info.b_feature_mask_valid ? "OK" : "ERROR")); + + memcpy(&avr_vpd_info.no_of_macs, &p_vpd_board_info[0 + 4 + 4 + 4], + sizeof(avr_vpd_info.no_of_macs)); + NT_LOG(DBG, NTHW, "%s: AVR%d: NUM_MACS: %d\n", p_adapter_id_str, + n_instance_no, avr_vpd_info.no_of_macs); + + memcpy(&avr_vpd_info.mac_address, + &p_vpd_board_info[0 + 4 + 4 + 4 + 1], + sizeof(avr_vpd_info.mac_address)); + NT_LOG(DBG, NTHW, + "%s: AVR%d: MAC_ADDR: %02x:%02x:%02x:%02x:%02x:%02x\n", + p_adapter_id_str, n_instance_no, + avr_vpd_info.mac_address[0], avr_vpd_info.mac_address[1], + avr_vpd_info.mac_address[2], avr_vpd_info.mac_address[3], + avr_vpd_info.mac_address[4], avr_vpd_info.mac_address[5]); + + mac.a_u64[0] = 0; + memcpy(&mac.a_u8[2], &avr_vpd_info.mac_address, + sizeof(avr_vpd_info.mac_address)); + { + const uint32_t u1 = ntohl(mac.a_u32[0]); + + if (u1 != mac.a_u32[0]) { + const uint32_t u0 = ntohl(mac.a_u32[1]); + mac.a_u32[0] = u0; + mac.a_u32[1] = u1; + } + } + avr_vpd_info.n_mac_val = mac.a_u64[0]; + NT_LOG(DBG, NTHW, "%s: AVR%d: MAC_U64: %012" PRIX64 "\n", + p_adapter_id_str, n_instance_no, avr_vpd_info.n_mac_val); + } + + p_fpga_info->nthw_hw_info.vpd_info.mn_mac_addr_count = + avr_vpd_info.no_of_macs; + p_fpga_info->nthw_hw_info.vpd_info.mn_mac_addr_value = + avr_vpd_info.n_mac_val; + memcpy(p_fpga_info->nthw_hw_info.vpd_info.ma_mac_addr_octets, + avr_vpd_info.mac_address, + ARRAY_SIZE(p_fpga_info->nthw_hw_info.vpd_info.ma_mac_addr_octets)); + + } else { + NT_LOG(ERR, NTHW, "%s:%u: res=%d\n", __func__, __LINE__, res); + NT_LOG(ERR, NTHW, "%s: AVR%d: SYSINFO2: NA: res=%d sz=%d\n", + p_adapter_id_str, n_instance_no, res, rx_buf.size); + } + } + + return res; +} + +/* + * NT50B01, NT200A02, NT200A01-HWbuild2 + */ +int nthw_fpga_si5340_clock_synth_init_fmt2(nthw_fpga_t *p_fpga, const uint8_t n_iic_addr, + const clk_profile_data_fmt2_t *p_clk_profile, + const int n_clk_profile_rec_cnt) +{ + int res; + nthw_iic_t *p_nthw_iic = nthw_iic_new(); + nthw_si5340_t *p_nthw_si5340 = nthw_si5340_new(); + + assert(p_nthw_iic); + assert(p_nthw_si5340); + nthw_iic_init(p_nthw_iic, p_fpga, 0, 8);/* I2C cycle time 125Mhz ~ 8ns */ + + nthw_si5340_init(p_nthw_si5340, p_nthw_iic, n_iic_addr);/* si5340_u23_i2c_addr_7bit */ + res = nthw_si5340_config_fmt2(p_nthw_si5340, p_clk_profile, n_clk_profile_rec_cnt); + nthw_si5340_delete(p_nthw_si5340); + p_nthw_si5340 = NULL; + + return res; +} + +int nthw_fpga_init(struct fpga_info_s *p_fpga_info) +{ + const char *const p_adapter_id_str = p_fpga_info->mp_adapter_id_str; + + nthw_hif_t *p_nthw_hif = NULL; + nthw_pcie3_t *p_nthw_pcie3 = NULL; + nthw_rac_t *p_nthw_rac = NULL; + nthw_tsm_t *p_nthw_tsm = NULL; + + mcu_info_t *p_mcu_info = &p_fpga_info->mcu_info; + (void)p_mcu_info; + uint64_t n_fpga_ident = 0; + nthw_fpga_mgr_t *p_fpga_mgr = NULL; + nthw_fpga_t *p_fpga = NULL; + + char s_fpga_prod_ver_rev_str[32] = { 0 }; + + int res = 0; + + assert(p_fpga_info); + + { + const uint64_t n_fpga_ident = nthw_fpga_read_ident(p_fpga_info); + const uint32_t n_fpga_build_time = nthw_fpga_read_buildtime(p_fpga_info); + const int n_fpga_type_id = nthw_fpga_extract_type_id(n_fpga_ident); + const int n_fpga_prod_id = nthw_fpga_extract_prod_id(n_fpga_ident); + const int n_fpga_ver_id = nthw_fpga_extract_ver_id(n_fpga_ident); + const int n_fpga_rev_id = nthw_fpga_extract_rev_id(n_fpga_ident); + + p_fpga_info->n_fpga_ident = n_fpga_ident; + p_fpga_info->n_fpga_type_id = n_fpga_type_id; + p_fpga_info->n_fpga_prod_id = n_fpga_prod_id; + p_fpga_info->n_fpga_ver_id = n_fpga_ver_id; + p_fpga_info->n_fpga_rev_id = n_fpga_rev_id; + p_fpga_info->n_fpga_build_time = n_fpga_build_time; + + snprintf(s_fpga_prod_ver_rev_str, sizeof(s_fpga_prod_ver_rev_str), + "%04d-%04d-%02d-%02d", n_fpga_type_id, n_fpga_prod_id, n_fpga_ver_id, + n_fpga_rev_id); + + NT_LOG(INF, NTHW, "%s: FPGA %s (%" PRIX64 ") [%08X]\n", p_adapter_id_str, + s_fpga_prod_ver_rev_str, n_fpga_ident, n_fpga_build_time); + } + + n_fpga_ident = p_fpga_info->n_fpga_ident; + + p_fpga_mgr = nthw_fpga_mgr_new(); + nthw_fpga_mgr_init(p_fpga_mgr, nthw_fpga_instances, + (const void *)sa_nthw_fpga_mod_str_map); + nthw_fpga_mgr_log_dump(p_fpga_mgr); + p_fpga = nthw_fpga_mgr_query_fpga(p_fpga_mgr, n_fpga_ident, p_fpga_info); + p_fpga_info->mp_fpga = p_fpga; + + if (p_fpga == NULL) { + NT_LOG(ERR, NTHW, "%s: Unsupported FPGA: %s (%08X)\n", p_adapter_id_str, + s_fpga_prod_ver_rev_str, p_fpga_info->n_fpga_build_time); + return -1; + } + + if (p_fpga_mgr) { + nthw_fpga_mgr_delete(p_fpga_mgr); + p_fpga_mgr = NULL; + } + + /* Read Fpga param info */ + nthw_fpga_get_param_info(p_fpga_info, p_fpga); + + /* debug: report params */ + NT_LOG(DBG, NTHW, "%s: NT_NIMS=%d\n", p_adapter_id_str, p_fpga_info->n_nims); + NT_LOG(DBG, NTHW, "%s: NT_PHY_PORTS=%d\n", p_adapter_id_str, p_fpga_info->n_phy_ports); + NT_LOG(DBG, NTHW, "%s: NT_PHY_QUADS=%d\n", p_adapter_id_str, p_fpga_info->n_phy_quads); + NT_LOG(DBG, NTHW, "%s: NT_RX_PORTS=%d\n", p_adapter_id_str, p_fpga_info->n_rx_ports); + NT_LOG(DBG, NTHW, "%s: NT_TX_PORTS=%d\n", p_adapter_id_str, p_fpga_info->n_tx_ports); + NT_LOG(DBG, NTHW, "%s: nProfile=%d\n", p_adapter_id_str, (int)p_fpga_info->profile); + NT_LOG(DBG, NTHW, "%s: bHasMcu=%d\n", p_adapter_id_str, p_mcu_info->mb_has_mcu); + NT_LOG(DBG, NTHW, "%s: McuType=%d\n", p_adapter_id_str, p_mcu_info->mn_mcu_type); + NT_LOG(DBG, NTHW, "%s: McuDramSize=%d\n", p_adapter_id_str, p_mcu_info->mn_mcu_dram_size); + + p_nthw_rac = nthw_rac_new(); + + if (p_nthw_rac == NULL) { + NT_LOG(ERR, NTHW, "%s: Unsupported FPGA: RAC is not found: %s (%08X)\n", + p_adapter_id_str, s_fpga_prod_ver_rev_str, p_fpga_info->n_fpga_build_time); + return -1; + } + + nthw_rac_init(p_nthw_rac, p_fpga, p_fpga_info); + nthw_rac_rab_flush(p_nthw_rac); + p_fpga_info->mp_nthw_rac = p_nthw_rac; + + /* special case: values below 0x100 will disable debug on RAC communication */ + { + const int n_fpga_initial_debug_mode = p_fpga_info->n_fpga_debug_mode; + nthw_fpga_set_debug_mode(p_fpga, n_fpga_initial_debug_mode); + } + bool included = true; + struct nt200a0x_ops *nt200a0x_ops = get_nt200a0x_ops(); + struct nt50b0x_ops *nt50b0x_ops = get_nt50b0x_ops(); + struct nt400dxx_ops *nt400dxx_ops = get_nt400dxx_ops(); + + switch (p_fpga_info->n_nthw_adapter_id) { + case NT_HW_ADAPTER_ID_NT200A01: /* fallthrough */ + case NT_HW_ADAPTER_ID_NT200A02: + if (nt200a0x_ops != NULL) + res = nt200a0x_ops->nthw_fpga_nt200a0x_init(p_fpga_info); + + else + included = false; + + break; + + case NT_HW_ADAPTER_ID_NT50B01: + if (nt50b0x_ops) + res = nt50b0x_ops->nthw_fpga_nt50b0x_init(p_fpga_info); + + else + included = false; + + break; + + case NT_HW_ADAPTER_ID_NT400D11: + if (nt400dxx_ops != NULL) + res = nt400dxx_ops->nthw_fpga_nt400dxx_init(p_fpga_info); + + else + included = false; + + break; + + default: + NT_LOG(ERR, NTHW, "%s: Unsupported HW product id: %d\n", p_adapter_id_str, + p_fpga_info->n_nthw_adapter_id); + res = -1; + break; + } + + if (!included) { + NT_LOG(ERR, NTHW, "%s: NOT INCLUDED HW product: %d\n", p_adapter_id_str, + p_fpga_info->n_nthw_adapter_id); + res = -1; + } + + if (res) { + NT_LOG(ERR, NTHW, "%s: status: 0x%08X\n", p_adapter_id_str, res); + return res; + } + + res = nthw_pcie3_init(NULL, p_fpga, 0); /* Probe for module */ + + if (res == 0) { + p_nthw_pcie3 = nthw_pcie3_new(); + + if (p_nthw_pcie3) { + res = nthw_pcie3_init(p_nthw_pcie3, p_fpga, 0); + + if (res == 0) { + NT_LOG(DBG, NTHW, "%s: Pcie3 module found\n", p_adapter_id_str); + nthw_pcie3_trigger_sample_time(p_nthw_pcie3); + + } else { + nthw_pcie3_delete(p_nthw_pcie3); + p_nthw_pcie3 = NULL; + } + } + + p_fpga_info->mp_nthw_pcie3 = p_nthw_pcie3; + } + + if (p_nthw_pcie3 == NULL) { + p_nthw_hif = nthw_hif_new(); + + if (p_nthw_hif) { + res = nthw_hif_init(p_nthw_hif, p_fpga, 0); + + if (res == 0) { + NT_LOG(DBG, NTHW, "%s: Hif module found\n", p_adapter_id_str); + nthw_hif_trigger_sample_time(p_nthw_hif); + + } else { + nthw_hif_delete(p_nthw_hif); + p_nthw_hif = NULL; + } + } + } + + p_fpga_info->mp_nthw_hif = p_nthw_hif; + + p_nthw_tsm = nthw_tsm_new(); + + if (p_nthw_tsm) { + nthw_tsm_init(p_nthw_tsm, p_fpga, 0); + + nthw_tsm_set_config_ts_format(p_nthw_tsm, 1); /* 1 = TSM: TS format native */ + + /* Timer T0 - stat toggle timer */ + nthw_tsm_set_timer_t0_enable(p_nthw_tsm, false); + nthw_tsm_set_timer_t0_max_count(p_nthw_tsm, 50 * 1000 * 1000); /* ns */ + nthw_tsm_set_timer_t0_enable(p_nthw_tsm, true); + + /* Timer T1 - keep alive timer */ + nthw_tsm_set_timer_t1_enable(p_nthw_tsm, false); + nthw_tsm_set_timer_t1_max_count(p_nthw_tsm, 100 * 1000 * 1000); /* ns */ + nthw_tsm_set_timer_t1_enable(p_nthw_tsm, true); + } + + p_fpga_info->mp_nthw_tsm = p_nthw_tsm; + + /* TSM sample triggering: test validation... */ +#if defined(DEBUG) && (1) + { + uint64_t n_time, n_ts; + int i; + + for (i = 0; i < 4; i++) { + if (p_nthw_hif) + nthw_hif_trigger_sample_time(p_nthw_hif); + + else if (p_nthw_pcie3) + nthw_pcie3_trigger_sample_time(p_nthw_pcie3); + + nthw_tsm_get_time(p_nthw_tsm, &n_time); + nthw_tsm_get_ts(p_nthw_tsm, &n_ts); + + NT_LOG(DBG, NTHW, "%s: TSM time: %016" PRIX64 " %016" PRIX64 "\n", + p_adapter_id_str, n_time, n_ts); + + nt_os_wait_usec(1000); + } + } +#endif + + return res; +} + +int nthw_fpga_shutdown(struct fpga_info_s *p_fpga_info) +{ + int res = -1; + + if (p_fpga_info) { + if (p_fpga_info && p_fpga_info->mp_nthw_rac) + res = nthw_rac_rab_reset(p_fpga_info->mp_nthw_rac); + } + + return res; +} + +static struct nt200a0x_ops *nt200a0x_ops; + +void register_nt200a0x_ops(struct nt200a0x_ops *ops) +{ + nt200a0x_ops = ops; +} + +struct nt200a0x_ops *get_nt200a0x_ops(void) +{ + return nt200a0x_ops; +} + +static struct nt50b0x_ops *nt50b0x_ops; + +struct nt50b0x_ops *get_nt50b0x_ops(void) +{ + return nt50b0x_ops; +} + +static struct nt400dxx_ops *nt400dxx_ops; + +struct nt400dxx_ops *get_nt400dxx_ops(void) +{ + return nt400dxx_ops; +} diff --git a/drivers/net/ntnic/nthw/core/nthw_fpga_rst.c b/drivers/net/ntnic/nthw/core/nthw_fpga_rst.c new file mode 100644 index 0000000000..e0fb0ec3d8 --- /dev/null +++ b/drivers/net/ntnic/nthw/core/nthw_fpga_rst.c @@ -0,0 +1,10 @@ +/* + * SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include "ntlog.h" + +#include "nthw_fpga.h" + +#include "nthw_fpga_rst.h" diff --git a/drivers/net/ntnic/nthw/core/nthw_hif.c b/drivers/net/ntnic/nthw/core/nthw_hif.c new file mode 100644 index 0000000000..b35b456528 --- /dev/null +++ b/drivers/net/ntnic/nthw/core/nthw_hif.c @@ -0,0 +1,312 @@ +/* + * SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include "nt_util.h" +#include "ntlog.h" + +#include "nthw_drv.h" +#include "nthw_register.h" + +#include "nthw_hif.h" + +nthw_hif_t *nthw_hif_new(void) +{ + nthw_hif_t *p = malloc(sizeof(nthw_hif_t)); + + if (p) + memset(p, 0, sizeof(nthw_hif_t)); + + return p; +} + +void nthw_hif_delete(nthw_hif_t *p) +{ + if (p) { + memset(p, 0, sizeof(nthw_hif_t)); + free(p); + } +} + +int nthw_hif_init(nthw_hif_t *p, nthw_fpga_t *p_fpga, int n_instance) +{ + const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str; + (void)p_adapter_id_str; + nthw_module_t *mod = nthw_fpga_query_module(p_fpga, MOD_HIF, n_instance); + + if (p == NULL) + return mod == NULL ? -1 : 0; + + if (mod == NULL) { + NT_LOG(ERR, NTHW, "%s: HIF %d: no such instance\n", + p_fpga->p_fpga_info->mp_adapter_id_str, n_instance); + return -1; + } + + p->mp_fpga = p_fpga; + p->mn_instance = n_instance; + p->mp_mod_hif = mod; + + /* default for (Xilinx-based) products until august 2022: (1e6/4000 = 250 MHz) */ + p->mn_fpga_param_hif_per_ps = nthw_fpga_get_product_param(p->mp_fpga, NT_HIF_PER_PS, 4000); + p->mn_fpga_hif_ref_clk_freq = + (uint32_t)(1000000000000ULL / (unsigned int)p->mn_fpga_param_hif_per_ps); + + p->mp_reg_prod_id_lsb = nthw_module_get_register(p->mp_mod_hif, HIF_PROD_ID_LSB); + p->mp_fld_prod_id_lsb_rev_id = + nthw_register_get_field(p->mp_reg_prod_id_lsb, HIF_PROD_ID_LSB_REV_ID); + p->mp_fld_prod_id_lsb_ver_id = + nthw_register_get_field(p->mp_reg_prod_id_lsb, HIF_PROD_ID_LSB_VER_ID); + p->mp_fld_prod_id_lsb_group_id = + nthw_register_get_field(p->mp_reg_prod_id_lsb, HIF_PROD_ID_LSB_GROUP_ID); + + p->mp_reg_prod_id_msb = nthw_module_get_register(p->mp_mod_hif, HIF_PROD_ID_MSB); + p->mp_fld_prod_id_msb_type_id = + nthw_register_get_field(p->mp_reg_prod_id_msb, HIF_PROD_ID_MSB_TYPE_ID); + p->mp_fld_prod_id_msb_build_no = + nthw_register_get_field(p->mp_reg_prod_id_msb, HIF_PROD_ID_MSB_BUILD_NO); + + p->mp_reg_build_time = nthw_module_get_register(p->mp_mod_hif, HIF_BUILD_TIME); + p->mp_fld_build_time = nthw_register_get_field(p->mp_reg_build_time, HIF_BUILD_TIME_TIME); + + p->mn_fpga_id_prod = nthw_field_get_updated(p->mp_fld_prod_id_lsb_group_id); + p->mn_fpga_id_ver = nthw_field_get_updated(p->mp_fld_prod_id_lsb_ver_id); + p->mn_fpga_id_rev = nthw_field_get_updated(p->mp_fld_prod_id_lsb_rev_id); + p->mn_fpga_id_build_no = nthw_field_get_updated(p->mp_fld_prod_id_msb_build_no); + p->mn_fpga_id_item = nthw_field_get_updated(p->mp_fld_prod_id_msb_type_id); + + NT_LOG(DBG, NTHW, "%s: HIF %d: %s: %d-%d-%d-%d-%d\n", p_adapter_id_str, p->mn_instance, + __func__, p->mn_fpga_id_item, p->mn_fpga_id_prod, p->mn_fpga_id_ver, + p->mn_fpga_id_rev, p->mn_fpga_id_build_no); + NT_LOG(DBG, NTHW, "%s: HIF %d: %s: HIF ref clock: %d Hz (%d ticks/ps)\n", p_adapter_id_str, + p->mn_instance, __func__, p->mn_fpga_hif_ref_clk_freq, p->mn_fpga_param_hif_per_ps); + + p->mp_reg_build_seed = NULL; /* Reg/Fld not present on HIF */ + + if (p->mp_reg_build_seed) + p->mp_fld_build_seed = NULL; /* Reg/Fld not present on HIF */ + else + p->mp_fld_build_seed = NULL; + + p->mp_reg_core_speed = NULL; /* Reg/Fld not present on HIF */ + + if (p->mp_reg_core_speed) { + p->mp_fld_core_speed = NULL; /* Reg/Fld not present on HIF */ + p->mp_fld_ddr3_speed = NULL; /* Reg/Fld not present on HIF */ + + } else { + p->mp_reg_core_speed = NULL; + p->mp_fld_core_speed = NULL; + p->mp_fld_ddr3_speed = NULL; + } + + /* Optional registers since: 2018-04-25 */ + p->mp_reg_int_mask = NULL; /* Reg/Fld not present on HIF */ + p->mp_reg_int_clr = NULL; /* Reg/Fld not present on HIF */ + p->mp_reg_int_force = NULL; /* Reg/Fld not present on HIF */ + + p->mp_fld_int_mask_timer = NULL; + p->mp_fld_int_clr_timer = NULL; + p->mp_fld_int_force_timer = NULL; + + p->mp_fld_int_mask_port = NULL; + p->mp_fld_int_clr_port = NULL; + p->mp_fld_int_force_port = NULL; + + p->mp_fld_int_mask_pps = NULL; + p->mp_fld_int_clr_pps = NULL; + p->mp_fld_int_force_pps = NULL; + + p->mp_reg_ctrl = nthw_module_get_register(p->mp_mod_hif, HIF_CONTROL); + p->mp_fld_ctrl_fsr = nthw_register_query_field(p->mp_reg_ctrl, HIF_CONTROL_FSR); + + p->mp_reg_stat_ctrl = nthw_module_get_register(p->mp_mod_hif, HIF_STAT_CTRL); + p->mp_fld_stat_ctrl_ena = + nthw_register_get_field(p->mp_reg_stat_ctrl, HIF_STAT_CTRL_STAT_ENA); + p->mp_fld_stat_ctrl_req = + nthw_register_get_field(p->mp_reg_stat_ctrl, HIF_STAT_CTRL_STAT_REQ); + + p->mp_reg_stat_rx = nthw_module_get_register(p->mp_mod_hif, HIF_STAT_RX); + p->mp_fld_stat_rx_counter = + nthw_register_get_field(p->mp_reg_stat_rx, HIF_STAT_RX_COUNTER); + + p->mp_reg_stat_tx = nthw_module_get_register(p->mp_mod_hif, HIF_STAT_TX); + p->mp_fld_stat_tx_counter = + nthw_register_get_field(p->mp_reg_stat_tx, HIF_STAT_TX_COUNTER); + + p->mp_reg_stat_ref_clk = nthw_module_get_register(p->mp_mod_hif, HIF_STAT_REFCLK); + p->mp_fld_stat_ref_clk_ref_clk = + nthw_register_get_field(p->mp_reg_stat_ref_clk, HIF_STAT_REFCLK_REFCLK250); + + p->mp_reg_status = nthw_module_query_register(p->mp_mod_hif, HIF_STATUS); + + if (p->mp_reg_status) { + p->mp_fld_status_tags_in_use = + nthw_register_query_field(p->mp_reg_status, HIF_STATUS_TAGS_IN_USE); + p->mp_fld_status_wr_err = + nthw_register_query_field(p->mp_reg_status, HIF_STATUS_WR_ERR); + p->mp_fld_status_rd_err = + nthw_register_query_field(p->mp_reg_status, HIF_STATUS_RD_ERR); + + } else { + p->mp_reg_status = nthw_module_query_register(p->mp_mod_hif, HIF_STATUS); + p->mp_fld_status_tags_in_use = + nthw_register_query_field(p->mp_reg_status, HIF_STATUS_TAGS_IN_USE); + p->mp_fld_status_wr_err = NULL; + p->mp_fld_status_rd_err = NULL; + } + + p->mp_reg_pci_test0 = nthw_module_get_register(p->mp_mod_hif, HIF_TEST0); + p->mp_fld_pci_test0 = nthw_register_get_field(p->mp_reg_pci_test0, HIF_TEST0_DATA); + + p->mp_reg_pci_test1 = nthw_module_get_register(p->mp_mod_hif, HIF_TEST1); + p->mp_fld_pci_test1 = nthw_register_get_field(p->mp_reg_pci_test1, HIF_TEST1_DATA); + + /* Module::Version({2, 0})+ */ + p->mp_reg_pci_test2 = nthw_module_query_register(p->mp_mod_hif, HIF_TEST2); + + if (p->mp_reg_pci_test2) + p->mp_fld_pci_test2 = nthw_register_get_field(p->mp_reg_pci_test2, HIF_TEST2_DATA); + + else + p->mp_fld_pci_test2 = NULL; + + /* Module::Version({1, 2})+ */ + p->mp_reg_pci_test3 = nthw_module_query_register(p->mp_mod_hif, HIF_TEST3); + + if (p->mp_reg_pci_test3) + p->mp_fld_pci_test3 = nthw_register_get_field(p->mp_reg_pci_test3, HIF_TEST3_DATA); + + else + p->mp_fld_pci_test3 = NULL; + + /* Required to run TSM */ + p->mp_reg_sample_time = nthw_module_get_register(p->mp_mod_hif, HIF_SAMPLE_TIME); + + if (p->mp_reg_sample_time) { + p->mp_fld_sample_time = nthw_register_get_field(p->mp_reg_sample_time, + HIF_SAMPLE_TIME_SAMPLE_TIME); + + } else { + p->mp_fld_sample_time = NULL; + } + + /* We need to optimize PCIe3 TLP-size read-request and extended tag usage */ + { + p->mp_reg_config = nthw_module_query_register(p->mp_mod_hif, HIF_CONFIG); + + if (p->mp_reg_config) { + p->mp_fld_max_tlp = + nthw_register_get_field(p->mp_reg_config, HIF_CONFIG_MAX_TLP); + p->mp_fld_max_read = + nthw_register_get_field(p->mp_reg_config, HIF_CONFIG_MAX_READ); + p->mp_fld_ext_tag = + nthw_register_get_field(p->mp_reg_config, HIF_CONFIG_EXT_TAG); + + } else { + p->mp_fld_max_tlp = NULL; + p->mp_fld_max_read = NULL; + p->mp_fld_ext_tag = NULL; + } + } + + return 0; +} + +int nthw_hif_trigger_sample_time(nthw_hif_t *p) +{ + nthw_field_set_val_flush32(p->mp_fld_sample_time, 0xfee1dead); + + return 0; +} + +int nthw_hif_get_stat(nthw_hif_t *p, uint32_t *p_rx_cnt, uint32_t *p_tx_cnt, + uint32_t *p_ref_clk_cnt, uint32_t *p_tg_unit_size, uint32_t *p_tg_ref_freq, + uint64_t *p_tags_in_use, uint64_t *p_rd_err, uint64_t *p_wr_err) +{ + *p_rx_cnt = nthw_field_get_updated(p->mp_fld_stat_rx_counter); + *p_tx_cnt = nthw_field_get_updated(p->mp_fld_stat_tx_counter); + + *p_ref_clk_cnt = nthw_field_get_updated(p->mp_fld_stat_ref_clk_ref_clk); + + *p_tg_unit_size = NTHW_TG_CNT_SIZE; + *p_tg_ref_freq = p->mn_fpga_hif_ref_clk_freq; + + *p_tags_in_use = (p->mp_fld_status_tags_in_use + ? nthw_field_get_updated(p->mp_fld_status_tags_in_use) + : 0); + + *p_rd_err = + (p->mp_fld_status_rd_err ? nthw_field_get_updated(p->mp_fld_status_rd_err) : 0); + *p_wr_err = + (p->mp_fld_status_wr_err ? nthw_field_get_updated(p->mp_fld_status_wr_err) : 0); + + return 0; +} + +int nthw_hif_get_stat_rate(nthw_hif_t *p, uint64_t *p_pci_rx_rate, uint64_t *p_pci_tx_rate, + uint64_t *p_ref_clk_cnt, uint64_t *p_tags_in_use, + uint64_t *p_rd_err_cnt, uint64_t *p_wr_err_cnt) +{ + uint32_t rx_cnt, tx_cnt, ref_clk_cnt, tg_unit_size, tg_ref_freq; + uint64_t n_tags_in_use, n_rd_err, n_wr_err; + + nthw_hif_get_stat(p, &rx_cnt, &tx_cnt, &ref_clk_cnt, &tg_unit_size, &tg_ref_freq, + &n_tags_in_use, &n_rd_err, &n_wr_err); + + *p_tags_in_use = n_tags_in_use; + + if (n_rd_err) + (*p_rd_err_cnt)++; + + if (n_wr_err) + (*p_wr_err_cnt)++; + + if (ref_clk_cnt) { + uint64_t rx_rate; + uint64_t tx_rate; + + *p_ref_clk_cnt = ref_clk_cnt; + + rx_rate = ((uint64_t)rx_cnt * tg_unit_size * tg_ref_freq) / (uint64_t)ref_clk_cnt; + *p_pci_rx_rate = rx_rate; + + tx_rate = ((uint64_t)tx_cnt * tg_unit_size * tg_ref_freq) / (uint64_t)ref_clk_cnt; + *p_pci_tx_rate = tx_rate; + + } else { + *p_pci_rx_rate = 0; + *p_pci_tx_rate = 0; + *p_ref_clk_cnt = 0; + } + + return 0; +} + +int nthw_hif_stat_req_enable(nthw_hif_t *p) +{ + nthw_field_set_all(p->mp_fld_stat_ctrl_ena); + nthw_field_set_all(p->mp_fld_stat_ctrl_req); + nthw_field_flush_register(p->mp_fld_stat_ctrl_req); + return 0; +} + +int nthw_hif_stat_req_disable(nthw_hif_t *p) +{ + nthw_field_clr_all(p->mp_fld_stat_ctrl_ena); + nthw_field_set_all(p->mp_fld_stat_ctrl_req); + nthw_field_flush_register(p->mp_fld_stat_ctrl_req); + return 0; +} + +int nthw_hif_end_point_counters_sample(nthw_hif_t *p, struct nthw_hif_end_point_counters *epc) +{ + assert(epc); + + /* Get stat rate and maintain rx/tx min/max */ + nthw_hif_get_stat_rate(p, &epc->cur_tx, &epc->cur_rx, &epc->n_ref_clk_cnt, + &epc->n_tags_in_use, &epc->n_rd_err, &epc->n_wr_err); + + return 0; +} diff --git a/drivers/net/ntnic/nthw/core/nthw_iic.c b/drivers/net/ntnic/nthw/core/nthw_iic.c new file mode 100644 index 0000000000..cdaee20e8a --- /dev/null +++ b/drivers/net/ntnic/nthw/core/nthw_iic.c @@ -0,0 +1,529 @@ +/* + * SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include "nt_util.h" +#include "ntlog.h" + +#include "nthw_drv.h" +#include "nthw_register.h" + +#include "nthw_iic.h" + +#define I2C_TRANSMIT_WR (0x00) +#define I2C_TRANSMIT_RD (0x01) + +#define I2C_WAIT_US(x) nt_os_wait_usec(x) + +/* + * Minimum timing values for I2C for a Marvel 88E11111 Phy. + * This Phy is used in many Trispeed NIMs. + * In order to access this Phy, the I2C clock speed is needed to be set to 100KHz. + */ +static const uint32_t SUSTA = 4700; /* ns */ +static const uint32_t SUSTO = 4000; /* ns */ +static const uint32_t HDSTA = 4000; /* ns */ +static const uint32_t SUDAT = 250; /* ns */ +static const uint32_t BUF = 4700; /* ns */ +static const uint32_t HIGH = 4000; /* ns */ +static const uint32_t LOW = 4700; /* ns */ +static const uint32_t HDDAT = 300; /* ns */ + +static int nthw_iic_reg_control_txfifo_reset(nthw_iic_t *p) +{ + nthw_field_update_register(p->mp_fld_cr_txfifo_reset); + + nthw_field_set_all(p->mp_fld_cr_txfifo_reset); + nthw_field_flush_register(p->mp_fld_cr_txfifo_reset); + + nthw_field_clr_all(p->mp_fld_cr_txfifo_reset); + nthw_field_flush_register(p->mp_fld_cr_txfifo_reset); + + return 0; +} + +static int nthw_iic_reg_tx_fifo_write(nthw_iic_t *p, uint32_t data, bool start, bool stop) +{ + if (start) + nthw_field_set_all(p->mp_fld_tx_fifo_start); + + else + nthw_field_clr_all(p->mp_fld_tx_fifo_start); + + if (stop) + nthw_field_set_all(p->mp_fld_tx_fifo_stop); + + else + nthw_field_clr_all(p->mp_fld_tx_fifo_stop); + + nthw_field_set_val32(p->mp_fld_tx_fifo_txdata, data); + + nthw_register_flush(p->mp_reg_tx_fifo, 1); + + return 0; +} + +static int nthw_iic_reg_read_i2c_rx_fifo(nthw_iic_t *p, uint8_t *p_data) +{ + assert(p_data); + + *p_data = (uint8_t)nthw_field_get_updated(p->mp_fld_rx_fifo_rxdata); + + return 0; +} + +static int nthw_iic_reg_softr(nthw_iic_t *p) +{ + nthw_field_update_register(p->mp_fld_cr_en); + nthw_field_set_val_flush32(p->mp_fld_softr_rkey, 0x0A); + + return 0; +} + +static int nthw_iic_reg_enable(nthw_iic_t *p) +{ + nthw_field_update_register(p->mp_fld_cr_en); + nthw_field_set_flush(p->mp_fld_cr_en); + + return 0; +} + +static int nthw_iic_reg_busbusy(nthw_iic_t *p, bool *pb_flag) +{ + assert(pb_flag); + + *pb_flag = nthw_field_get_updated(p->mp_fld_sr_bb) ? true : false; + + return 0; +} + +static int nthw_iic_reg_rxfifo_empty(nthw_iic_t *p, bool *pb_flag) +{ + assert(pb_flag); + + *pb_flag = nthw_field_get_updated(p->mp_fld_sr_rxfifo_empty) ? true : false; + + return 0; +} + +/* + * n_iic_cycle_time is the I2C clock cycle time in ns ie 125MHz = 8ns + */ +static int nthw_iic_reg_set_timing(nthw_iic_t *p, uint32_t n_iic_cycle_time) +{ + uint32_t val; + + val = SUSTA / n_iic_cycle_time; + nthw_field_set_val_flush(p->mp_fld_tsusta, &val, 1); + + val = SUSTO / n_iic_cycle_time; + nthw_field_set_val_flush(p->mp_fld_tsusto, &val, 1); + + val = HDSTA / n_iic_cycle_time; + nthw_field_set_val_flush(p->mp_fld_thdsta, &val, 1); + + val = SUDAT / n_iic_cycle_time; + nthw_field_set_val_flush(p->mp_fld_tsudat, &val, 1); + + val = BUF / n_iic_cycle_time; + nthw_field_set_val_flush(p->mp_fld_tbuf, &val, 1); + + val = HIGH / n_iic_cycle_time; + nthw_field_set_val_flush(p->mp_fld_thigh, &val, 1); + + val = LOW / n_iic_cycle_time; + nthw_field_set_val_flush(p->mp_fld_tlow, &val, 1); + + val = HDDAT / n_iic_cycle_time; + nthw_field_set_val_flush(p->mp_fld_thddat, &val, 1); + + return 0; +} + +nthw_iic_t *nthw_iic_new(void) +{ + nthw_iic_t *p = malloc(sizeof(nthw_iic_t)); + + if (p) + memset(p, 0, sizeof(nthw_iic_t)); + + return p; +} + +int nthw_iic_init(nthw_iic_t *p, nthw_fpga_t *p_fpga, int n_iic_instance, + uint32_t n_iic_cycle_time) +{ + const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str; + nthw_module_t *mod = nthw_fpga_query_module(p_fpga, MOD_IIC, n_iic_instance); + + if (p == NULL) + return mod == NULL ? -1 : 0; + + if (mod == NULL) { + NT_LOG(ERR, NTHW, "%s: I2C %d: no such instance\n", p_adapter_id_str, + n_iic_instance); + return -1; + } + + p->mp_fpga = p_fpga; + p->mn_iic_instance = n_iic_instance; + + p->mn_iic_cycle_time = n_iic_cycle_time; + + nthw_iic_set_retry_params(p, -1, -1, -1, -1, -1); + + p->mp_mod_iic = mod; + + /* I2C is a primary communication channel - turn off debug by default */ + nthw_module_set_debug_mode(p->mp_mod_iic, 0x00); + + p->mp_reg_tsusta = nthw_module_get_register(p->mp_mod_iic, IIC_TSUSTA); + p->mp_fld_tsusta = nthw_register_get_field(p->mp_reg_tsusta, IIC_TSUSTA_TSUSTA_VAL); + + p->mp_reg_tsusto = nthw_module_get_register(p->mp_mod_iic, IIC_TSUSTO); + p->mp_fld_tsusto = nthw_register_get_field(p->mp_reg_tsusto, IIC_TSUSTO_TSUSTO_VAL); + + p->mp_reg_thdsta = nthw_module_get_register(p->mp_mod_iic, IIC_THDSTA); + p->mp_fld_thdsta = nthw_register_get_field(p->mp_reg_thdsta, IIC_THDSTA_THDSTA_VAL); + + p->mp_reg_tsudat = nthw_module_get_register(p->mp_mod_iic, IIC_TSUDAT); + p->mp_fld_tsudat = nthw_register_get_field(p->mp_reg_tsudat, IIC_TSUDAT_TSUDAT_VAL); + + p->mp_reg_tbuf = nthw_module_get_register(p->mp_mod_iic, IIC_TBUF); + p->mp_fld_tbuf = nthw_register_get_field(p->mp_reg_tbuf, IIC_TBUF_TBUF_VAL); + + p->mp_reg_thigh = nthw_module_get_register(p->mp_mod_iic, IIC_THIGH); + p->mp_fld_thigh = nthw_register_get_field(p->mp_reg_thigh, IIC_THIGH_THIGH_VAL); + + p->mp_reg_tlow = nthw_module_get_register(p->mp_mod_iic, IIC_TLOW); + p->mp_fld_tlow = nthw_register_get_field(p->mp_reg_tlow, IIC_TLOW_TLOW_VAL); + + p->mp_reg_thddat = nthw_module_get_register(p->mp_mod_iic, IIC_THDDAT); + p->mp_fld_thddat = nthw_register_get_field(p->mp_reg_thddat, IIC_THDDAT_THDDAT_VAL); + + p->mp_reg_cr = nthw_module_get_register(p->mp_mod_iic, IIC_CR); + p->mp_fld_cr_en = nthw_register_get_field(p->mp_reg_cr, IIC_CR_EN); + p->mp_fld_cr_msms = nthw_register_get_field(p->mp_reg_cr, IIC_CR_MSMS); + p->mp_fld_cr_txfifo_reset = nthw_register_get_field(p->mp_reg_cr, IIC_CR_TXFIFO_RESET); + p->mp_fld_cr_txak = nthw_register_get_field(p->mp_reg_cr, IIC_CR_TXAK); + + p->mp_reg_sr = nthw_module_get_register(p->mp_mod_iic, IIC_SR); + p->mp_fld_sr_bb = nthw_register_get_field(p->mp_reg_sr, IIC_SR_BB); + p->mp_fld_sr_rxfifo_full = nthw_register_get_field(p->mp_reg_sr, IIC_SR_RXFIFO_FULL); + p->mp_fld_sr_rxfifo_empty = nthw_register_get_field(p->mp_reg_sr, IIC_SR_RXFIFO_EMPTY); + p->mp_fld_sr_txfifo_full = nthw_register_get_field(p->mp_reg_sr, IIC_SR_TXFIFO_FULL); + p->mp_fld_sr_txfifo_empty = nthw_register_get_field(p->mp_reg_sr, IIC_SR_TXFIFO_EMPTY); + + p->mp_reg_tx_fifo = nthw_module_get_register(p->mp_mod_iic, IIC_TX_FIFO); + p->mp_fld_tx_fifo_txdata = nthw_register_get_field(p->mp_reg_tx_fifo, IIC_TX_FIFO_TXDATA); + p->mp_fld_tx_fifo_start = nthw_register_get_field(p->mp_reg_tx_fifo, IIC_TX_FIFO_START); + p->mp_fld_tx_fifo_stop = nthw_register_get_field(p->mp_reg_tx_fifo, IIC_TX_FIFO_STOP); + + p->mp_reg_rx_fifo_pirq = nthw_module_get_register(p->mp_mod_iic, IIC_RX_FIFO_PIRQ); + p->mp_fld_rx_fifo_pirq_cmp_val = + nthw_register_get_field(p->mp_reg_rx_fifo_pirq, IIC_RX_FIFO_PIRQ_CMP_VAL); + + p->mp_reg_rx_fifo = nthw_module_get_register(p->mp_mod_iic, IIC_RX_FIFO); + p->mp_fld_rx_fifo_rxdata = nthw_register_get_field(p->mp_reg_rx_fifo, IIC_RX_FIFO_RXDATA); + + p->mp_reg_softr = nthw_module_get_register(p->mp_mod_iic, IIC_SOFTR); + p->mp_fld_softr_rkey = nthw_register_get_field(p->mp_reg_softr, IIC_SOFTR_RKEY); + + /* + * Initialize I2C controller by applying soft reset and enable the controller + */ + nthw_iic_reg_softr(p); + /* Enable the controller */ + nthw_iic_reg_enable(p); + + /* Setup controller timing */ + if (p->mn_iic_cycle_time) { + NT_LOG(DBG, NTHW, "%s: I2C%d: cycletime=%d\n", p_adapter_id_str, + p->mn_iic_instance, p->mn_iic_cycle_time); + nthw_iic_reg_set_timing(p, p->mn_iic_cycle_time); + } + + /* Reset TX fifo - must be after enable */ + nthw_iic_reg_control_txfifo_reset(p); + nthw_iic_reg_tx_fifo_write(p, 0, 0, 0); + + return 0; +} + +void nthw_iic_delete(nthw_iic_t *p) +{ + if (p) { + memset(p, 0, sizeof(nthw_iic_t)); + free(p); + } +} + +int nthw_iic_set_retry_params(nthw_iic_t *p, const int n_poll_delay, const int n_bus_ready_retry, + const int n_data_ready_retry, const int n_read_data_retry, + const int n_write_data_retry) +{ + p->mn_poll_delay = n_poll_delay >= 0 ? n_poll_delay : 10; + + p->mn_bus_ready_retry = n_bus_ready_retry >= 0 ? n_bus_ready_retry : 1000; + p->mn_data_ready_retry = n_data_ready_retry >= 0 ? n_data_ready_retry : 1000; + + p->mn_read_data_retry = n_read_data_retry >= 0 ? n_read_data_retry : 10; + p->mn_write_data_retry = n_write_data_retry >= 0 ? n_write_data_retry : 10; + + return 0; +} + +int nthw_iic_read_data(nthw_iic_t *p, uint8_t dev_addr, uint8_t a_reg_addr, uint8_t data_len, + void *p_void) +{ + const char *const p_adapter_id_str = p->mp_fpga->p_fpga_info->mp_adapter_id_str; + const int n_debug_mode = nthw_module_get_debug_mode(p->mp_mod_iic); + + uint8_t *pb = (uint8_t *)p_void; + int retry = (p->mn_read_data_retry >= 0 ? p->mn_read_data_retry : 10); + + if (n_debug_mode == 0xff) { + NT_LOG(DBG, NTHW, "%s: adr=0x%2.2x, reg=%d, len=%d\n", p_adapter_id_str, dev_addr, + a_reg_addr, data_len); + } + + while (nthw_iic_readbyte(p, dev_addr, a_reg_addr, data_len, pb) != 0) { + retry--; + + if (retry <= 0) { + NT_LOG(ERR, NTHW, + "%s: I2C%d: Read retry exhausted (dev_addr=%d a_reg_addr=%d)\n", + p_adapter_id_str, p->mn_iic_instance, dev_addr, a_reg_addr); + return -1; + + } else { + NT_LOG(DBG, NTHW, "%s: I2C%d: Read retry=%d (dev_addr=%d a_reg_addr=%d)\n", + p_adapter_id_str, p->mn_iic_instance, retry, dev_addr, a_reg_addr); + } + } + + if (n_debug_mode == 0xff) { + NT_LOG(DBG, NTHW, "%s: adr=0x%2.2x, reg=%d, len=%d, retries remaining: %d\n", + p_adapter_id_str, dev_addr, a_reg_addr, data_len, retry); + } + + return 0; +} + +int nthw_iic_readbyte(nthw_iic_t *p, uint8_t dev_addr, uint8_t a_reg_addr, uint8_t data_len, + uint8_t *p_byte) +{ + const char *const p_adapter_id_str = p->mp_fpga->p_fpga_info->mp_adapter_id_str; + + uint32_t value; + uint32_t i; + + if (nthw_iic_bus_ready(p)) { + /* Reset TX fifo */ + nthw_iic_reg_control_txfifo_reset(p); + + /* Write device address to TX_FIFO and set start bit!! */ + value = (dev_addr << 1) | I2C_TRANSMIT_WR; + nthw_iic_reg_tx_fifo_write(p, value, 1, 0); + + /* Write a_reg_addr to TX FIFO */ + nthw_iic_reg_tx_fifo_write(p, a_reg_addr, 0, 1); + + if (!nthw_iic_bus_ready(p)) { + NT_LOG(ERR, NTHW, "%s: error: (%s:%u)\n", p_adapter_id_str, __func__, + __LINE__); + return -1; + } + + /* Write device address + RD bit to TX_FIFO and set start bit!! */ + value = (dev_addr << 1) | I2C_TRANSMIT_RD; + nthw_iic_reg_tx_fifo_write(p, value, 1, 0); + + /* Write data_len to TX_FIFO and set stop bit!! */ + nthw_iic_reg_tx_fifo_write(p, data_len, 0, 1); + + for (i = 0; i < data_len; i++) { + /* Wait for RX FIFO not empty */ + if (!nthw_iic_data_ready(p)) + return -1; + + /* Read data_len bytes from RX_FIFO */ + nthw_iic_reg_read_i2c_rx_fifo(p, p_byte); + p_byte++; + } + + return 0; + + } else { + NT_LOG(ERR, NTHW, "%s: error: (%s:%u)\n", p_adapter_id_str, __func__, __LINE__); + return -1; + } + + return 0; +} + +int nthw_iic_write_data(nthw_iic_t *p, uint8_t dev_addr, uint8_t a_reg_addr, uint8_t data_len, + void *p_void) +{ + const char *const p_adapter_id_str = p->mp_fpga->p_fpga_info->mp_adapter_id_str; + int retry = (p->mn_write_data_retry >= 0 ? p->mn_write_data_retry : 10); + uint8_t *pb = (uint8_t *)p_void; + + while (nthw_iic_writebyte(p, dev_addr, a_reg_addr, data_len, pb) != 0) { + retry--; + + if (retry <= 0) { + NT_LOG(ERR, NTHW, + "%s: I2C%d: Write retry exhausted (dev_addr=%d a_reg_addr=%d)\n", + p_adapter_id_str, p->mn_iic_instance, dev_addr, a_reg_addr); + return -1; + + } else { + NT_LOG(DBG, NTHW, + "%s: I2C%d: Write retry=%d (dev_addr=%d a_reg_addr=%d)\n", + p_adapter_id_str, p->mn_iic_instance, retry, dev_addr, a_reg_addr); + } + } + + return 0; +} + +int nthw_iic_writebyte(nthw_iic_t *p, uint8_t dev_addr, uint8_t a_reg_addr, uint8_t data_len, + uint8_t *p_byte) +{ + const char *const p_adapter_id_str = p->mp_fpga->p_fpga_info->mp_adapter_id_str; + uint32_t value; + int count; + int i; + + if (data_len == 0) + return -1; + + count = data_len - 1; + + if (nthw_iic_bus_ready(p)) { + /* Reset TX fifo */ + nthw_iic_reg_control_txfifo_reset(p); + + /* Write device address to TX_FIFO and set start bit!! */ + value = (dev_addr << 1) | I2C_TRANSMIT_WR; + nthw_iic_reg_tx_fifo_write(p, value, 1, 0); + + /* Write a_reg_addr to TX FIFO */ + nthw_iic_reg_tx_fifo_write(p, a_reg_addr, 0, 0); + + for (i = 0; i < count; i++) { + /* Write data byte to TX fifo and set stop bit */ + nthw_iic_reg_tx_fifo_write(p, *p_byte, 0, 0); + p_byte++; + } + + /* Write data byte to TX fifo and set stop bit */ + nthw_iic_reg_tx_fifo_write(p, *p_byte, 0, 1); + + if (!nthw_iic_bus_ready(p)) { + NT_LOG(WRN, NTHW, "%s: warn: !busReady (%s:%u)\n", p_adapter_id_str, + __func__, __LINE__); + + while (true) + if (nthw_iic_bus_ready(p)) { + NT_LOG(DBG, NTHW, "%s: info: busReady (%s:%u)\n", + p_adapter_id_str, __func__, __LINE__); + break; + } + } + + return 0; + + } else { + NT_LOG(WRN, NTHW, "%s: (%s:%u)\n", p_adapter_id_str, __func__, __LINE__); + return -1; + } +} + +/* + * Support function for read/write functions below. Waits for bus ready. + */ +bool nthw_iic_bus_ready(nthw_iic_t *p) +{ + int count = (p->mn_bus_ready_retry >= 0 ? p->mn_bus_ready_retry : 1000); + bool b_bus_busy = true; + + while (true) { + nthw_iic_reg_busbusy(p, &b_bus_busy); + + if (!b_bus_busy) + break; + + count--; + + if (count <= 0) /* Test for timeout */ + break; + + if (p->mn_poll_delay != 0) + I2C_WAIT_US(p->mn_poll_delay); + } + + if (count == 0) + return false; + + return true; +} + +/* + * Support function for read function. Waits for data ready. + */ +bool nthw_iic_data_ready(nthw_iic_t *p) +{ + int count = (p->mn_data_ready_retry >= 0 ? p->mn_data_ready_retry : 1000); + bool b_rx_fifo_empty = true; + + while (true) { + nthw_iic_reg_rxfifo_empty(p, &b_rx_fifo_empty); + + if (!b_rx_fifo_empty) + break; + + count--; + + if (count <= 0) /* Test for timeout */ + break; + + if (p->mn_poll_delay != 0) + I2C_WAIT_US(p->mn_poll_delay); + } + + if (count == 0) + return false; + + return true; +} + +int nthw_iic_scan_dev_addr(nthw_iic_t *p, int n_dev_addr, int n_reg_addr) +{ + const char *const p_adapter_id_str = p->mp_fpga->p_fpga_info->mp_adapter_id_str; + (void)p_adapter_id_str; + int res; + uint8_t data_val = -1; + res = nthw_iic_readbyte(p, (uint8_t)n_dev_addr, (uint8_t)n_reg_addr, 1, &data_val); + + if (res == 0) { + NT_LOG(DBG, NTHW, + "%s: I2C%d: devaddr=0x%02X (%03d) regaddr=%02X val=%02X (%03d) res=%d\n", + p_adapter_id_str, p->mn_iic_instance, n_dev_addr, n_dev_addr, n_reg_addr, + data_val, data_val, res); + } + + return res; +} + +int nthw_iic_scan(nthw_iic_t *p) +{ + int i; + + for (i = 0; i < 128; i++) + (void)nthw_iic_scan_dev_addr(p, i, 0x00); + + return 0; +} diff --git a/drivers/net/ntnic/nthw/core/nthw_mac_pcs_xxv.c b/drivers/net/ntnic/nthw/core/nthw_mac_pcs_xxv.c new file mode 100644 index 0000000000..abffd34fc3 --- /dev/null +++ b/drivers/net/ntnic/nthw/core/nthw_mac_pcs_xxv.c @@ -0,0 +1,1169 @@ +/* + * SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include "ntlog.h" + +#include "nthw_drv.h" +#include "nthw_register.h" + +#include "nthw_mac_pcs_xxv.h" + +static void nthw_mac_pcs_xxv_field_set_or_clr_flush(const nthw_field_t *f, bool set) +{ + if (f) { + nthw_field_get_updated(f); + + if (set) + nthw_field_set_flush(f); + + else + nthw_field_clr_flush(f); + } +} + +nthw_mac_pcs_xxv_t *nthw_mac_pcs_xxv_new(void) +{ + nthw_mac_pcs_xxv_t *p = malloc(sizeof(nthw_mac_pcs_xxv_t)); + + if (p) + memset(p, 0, sizeof(nthw_mac_pcs_xxv_t)); + + return p; +} + +void nthw_mac_pcs_xxv_delete(nthw_mac_pcs_xxv_t *p) +{ + if (p) { + memset(p, 0, sizeof(nthw_mac_pcs_xxv_t)); + free(p); + } +} + +void nthw_mac_pcs_xxv_get_link_summary(nthw_mac_pcs_xxv_t *p, + uint32_t *p_abs, + uint32_t *p_nt_phy_link_state, + uint32_t *p_lh_abs, + uint32_t *p_ll_nt_phy_link_state, + uint32_t *p_link_down_cnt, + uint32_t *p_nim_interr, + uint32_t *p_lh_local_fault, + uint32_t *p_lh_remote_fault, + uint32_t *p_lh_internal_local_fault, + uint32_t *p_lh_received_local_fault, + uint8_t index) +{ + struct nthw_mac_pcs_xxv_registers_fields *r = &p->regs[index]; /* register and fields */ + + assert(p); + + nthw_register_update(r->mp_reg_link_summary); + + if (p_abs) + *p_abs = nthw_field_get_val32(r->mp_fld_link_summary_abs); + + if (p_nt_phy_link_state) { + *p_nt_phy_link_state = + nthw_field_get_val32(r->mp_fld_link_summary_nt_phy_link_state); + } + + if (p_lh_abs) + *p_lh_abs = nthw_field_get_val32(r->mp_fld_link_summary_lh_abs); + + if (p_ll_nt_phy_link_state) { + *p_ll_nt_phy_link_state = + nthw_field_get_val32(r->mp_fld_link_summary_ll_nt_phy_link_state); + } + + if (p_link_down_cnt) + *p_link_down_cnt = nthw_field_get_val32(r->mp_fld_link_summary_link_down_cnt); + + if (p_nim_interr) + *p_nim_interr = nthw_field_get_val32(r->mp_fld_link_summary_nim_interr); + + if (p_lh_local_fault) + *p_lh_local_fault = nthw_field_get_val32(r->mp_fld_link_summary_lh_local_fault); + + if (p_lh_remote_fault) + *p_lh_remote_fault = nthw_field_get_val32(r->mp_fld_link_summary_lh_remote_fault); + + if (p_lh_internal_local_fault) { + *p_lh_internal_local_fault = + nthw_field_get_val32(r->mp_fld_link_summary_lh_internal_local_fault); + } + + if (p_lh_received_local_fault) { + *p_lh_received_local_fault = + nthw_field_get_val32(r->mp_fld_link_summary_lh_received_local_fault); + } +} + +void nthw_mac_pcs_xxv_reset_rx_gt_data(nthw_mac_pcs_xxv_t *p, bool enable, uint8_t index) +{ + const nthw_field_t *const f = p->regs[index].mp_fld_sub_rst_rx_gt_data; + + nthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable); +} + +/* + * QPLL lock signal. + * For cores capable of 10G only, there are only 1 QPLL. For cores capable of + * 10G/25G, there are 2 QPLLs. + */ +void nthw_mac_pcs_xxv_set_rx_mac_pcs_rst(nthw_mac_pcs_xxv_t *p, bool enable, uint8_t index) +{ + const nthw_field_t *const f = p->regs[index].mp_fld_sub_rst_rx_mac_pcs; + + nthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable); +} + +int nthw_mac_pcs_xxv_init(nthw_mac_pcs_xxv_t *p, nthw_fpga_t *p_fpga, int n_instance, + int n_channels, bool mac_8x10G) +{ + nthw_module_t *p_mod = nthw_fpga_query_module(p_fpga, MOD_MAC_PCS_XXV, n_instance); + const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str; + nthw_module_t *module = p_mod; + uint64_t n_module_version_packed64 = -1; + nthw_register_t *r; + nthw_register_t *(*get_register)(nthw_module_t *, nthw_id_t) = nthw_module_get_register; + nthw_field_t *(*get_field)(const nthw_register_t *, nthw_id_t) = nthw_register_get_field; + nthw_field_t *(*query_field)(const nthw_register_t *, nthw_id_t) = + nthw_register_query_field; + struct nthw_mac_pcs_xxv_registers_fields *rf; + + if (p == NULL) + return p_mod == NULL ? -1 : 0; + + if (p_mod == NULL) { + NT_LOG(ERR, NTHW, "%s: MAC_PCS_XXV instance=%d: no such instance\n", + p_adapter_id_str, n_instance); + return -1; + } + + p->mp_fpga = p_fpga; + p->mn_instance = n_instance; + p->mp_mod_mac_pcs_xxv = p_mod; + p->m_mac_8x10G = mac_8x10G; + + memset(p->regs, 0, sizeof(p->regs)); + + n_module_version_packed64 = nthw_module_get_version_packed64(p->mp_mod_mac_pcs_xxv); + + switch (n_module_version_packed64) { + case (0UL << 32) | 0UL: /* 0.0 */ + case (0UL << 32) | 1UL: /* 0.1 */ + case (0UL << 32) | 2UL: /* 0.2 */ + case (0UL << 32) | 3UL: /* 0.3 */ + NT_LOG(DBG, NTHW, "%s: MAC_PCS_XXV instance=%d: version=0x%08lX\n", + p_adapter_id_str, p->mn_instance, n_module_version_packed64); + break; + + default: + NT_LOG(ERR, NTHW, + "%s: MAC_PCS_XXV instance=%d: version=0x%08lX: unsupported module version\n", + p_adapter_id_str, p->mn_instance, n_module_version_packed64); + return -1; + } + + assert(n_channels == 1 || n_channels == 2 || n_channels == 4); + + /* Register MAC_PCS_XXV_CORE_CONF_0 -- MAC_PCS_XXV_CORE_CONF_3 */ + if (n_channels <= 4) { + /* Initialize regs/fields for sub-module/channel 0 */ + rf = &p->regs[0]; + r = get_register(module, MAC_PCS_XXV_CORE_CONF_0); + + rf->mp_reg_core_conf = r; + rf->mp_fld_core_conf_rx_enable = get_field(r, MAC_PCS_XXV_CORE_CONF_0_RX_ENABLE); + rf->mp_fld_core_conf_rx_force_resync = + get_field(r, MAC_PCS_XXV_CORE_CONF_0_RX_FORCE_RESYNC); + rf->mp_fld_core_conf_tx_enable = get_field(r, MAC_PCS_XXV_CORE_CONF_0_TX_ENABLE); + rf->mp_fld_core_conf_tx_ins_fcs = get_field(r, MAC_PCS_XXV_CORE_CONF_0_TX_INS_FCS); + rf->mp_fld_core_conf_tx_ign_fcs = get_field(r, MAC_PCS_XXV_CORE_CONF_0_TX_IGN_FCS); + rf->mp_fld_core_conf_tx_send_lfi = + get_field(r, MAC_PCS_XXV_CORE_CONF_0_TX_SEND_LFI); + rf->mp_fld_core_conf_tx_send_rfi = + get_field(r, MAC_PCS_XXV_CORE_CONF_0_TX_SEND_RFI); + rf->mp_fld_core_conf_tx_send_idle = + get_field(r, MAC_PCS_XXV_CORE_CONF_0_TX_SEND_IDLE); + rf->mp_fld_core_conf_inline_mode = + get_field(r, MAC_PCS_XXV_CORE_CONF_0_INLINE_MODE); + rf->mp_fld_core_conf_line_loopback = + get_field(r, MAC_PCS_XXV_CORE_CONF_0_LINE_LOOPBACK); + rf->mp_fld_core_conf_ts_at_eop = get_field(r, MAC_PCS_XXV_CORE_CONF_0_TS_AT_EOP); + } + + if (n_channels >= 2) { + /* Initialize regs/fields for sub-module/channel 1 */ + rf = &p->regs[1]; + r = get_register(module, MAC_PCS_XXV_CORE_CONF_1); + + rf->mp_reg_core_conf = r; + rf->mp_fld_core_conf_rx_enable = get_field(r, MAC_PCS_XXV_CORE_CONF_1_RX_ENABLE); + rf->mp_fld_core_conf_rx_force_resync = + get_field(r, MAC_PCS_XXV_CORE_CONF_1_RX_FORCE_RESYNC); + rf->mp_fld_core_conf_tx_enable = get_field(r, MAC_PCS_XXV_CORE_CONF_1_TX_ENABLE); + rf->mp_fld_core_conf_tx_ins_fcs = get_field(r, MAC_PCS_XXV_CORE_CONF_1_TX_INS_FCS); + rf->mp_fld_core_conf_tx_ign_fcs = get_field(r, MAC_PCS_XXV_CORE_CONF_1_TX_IGN_FCS); + rf->mp_fld_core_conf_tx_send_lfi = + get_field(r, MAC_PCS_XXV_CORE_CONF_1_TX_SEND_LFI); + rf->mp_fld_core_conf_tx_send_rfi = + get_field(r, MAC_PCS_XXV_CORE_CONF_1_TX_SEND_RFI); + rf->mp_fld_core_conf_tx_send_idle = + get_field(r, MAC_PCS_XXV_CORE_CONF_1_TX_SEND_IDLE); + rf->mp_fld_core_conf_inline_mode = + get_field(r, MAC_PCS_XXV_CORE_CONF_1_INLINE_MODE); + rf->mp_fld_core_conf_line_loopback = + get_field(r, MAC_PCS_XXV_CORE_CONF_1_LINE_LOOPBACK); + rf->mp_fld_core_conf_ts_at_eop = get_field(r, MAC_PCS_XXV_CORE_CONF_1_TS_AT_EOP); + } + + if (n_channels == 4) { + /* Initialize regs/fields for sub-module/channel 2 */ + rf = &p->regs[2]; + r = get_register(module, MAC_PCS_XXV_CORE_CONF_2); + + rf->mp_reg_core_conf = r; + rf->mp_fld_core_conf_rx_enable = get_field(r, MAC_PCS_XXV_CORE_CONF_2_RX_ENABLE); + rf->mp_fld_core_conf_rx_force_resync = + get_field(r, MAC_PCS_XXV_CORE_CONF_2_RX_FORCE_RESYNC); + rf->mp_fld_core_conf_tx_enable = get_field(r, MAC_PCS_XXV_CORE_CONF_2_TX_ENABLE); + rf->mp_fld_core_conf_tx_ins_fcs = get_field(r, MAC_PCS_XXV_CORE_CONF_2_TX_INS_FCS); + rf->mp_fld_core_conf_tx_ign_fcs = get_field(r, MAC_PCS_XXV_CORE_CONF_2_TX_IGN_FCS); + rf->mp_fld_core_conf_tx_send_lfi = + get_field(r, MAC_PCS_XXV_CORE_CONF_2_TX_SEND_LFI); + rf->mp_fld_core_conf_tx_send_rfi = + get_field(r, MAC_PCS_XXV_CORE_CONF_2_TX_SEND_RFI); + rf->mp_fld_core_conf_tx_send_idle = + get_field(r, MAC_PCS_XXV_CORE_CONF_2_TX_SEND_IDLE); + rf->mp_fld_core_conf_inline_mode = + get_field(r, MAC_PCS_XXV_CORE_CONF_2_INLINE_MODE); + rf->mp_fld_core_conf_line_loopback = + get_field(r, MAC_PCS_XXV_CORE_CONF_2_LINE_LOOPBACK); + rf->mp_fld_core_conf_ts_at_eop = get_field(r, MAC_PCS_XXV_CORE_CONF_2_TS_AT_EOP); + + /* Initialize regs/fields for sub-module/channel 3 */ + rf = &p->regs[3]; + r = get_register(module, MAC_PCS_XXV_CORE_CONF_3); + + rf->mp_reg_core_conf = r; + rf->mp_fld_core_conf_rx_enable = get_field(r, MAC_PCS_XXV_CORE_CONF_3_RX_ENABLE); + rf->mp_fld_core_conf_rx_force_resync = + get_field(r, MAC_PCS_XXV_CORE_CONF_3_RX_FORCE_RESYNC); + rf->mp_fld_core_conf_tx_enable = get_field(r, MAC_PCS_XXV_CORE_CONF_3_TX_ENABLE); + rf->mp_fld_core_conf_tx_ins_fcs = get_field(r, MAC_PCS_XXV_CORE_CONF_3_TX_INS_FCS); + rf->mp_fld_core_conf_tx_ign_fcs = get_field(r, MAC_PCS_XXV_CORE_CONF_3_TX_IGN_FCS); + rf->mp_fld_core_conf_tx_send_lfi = + get_field(r, MAC_PCS_XXV_CORE_CONF_3_TX_SEND_LFI); + rf->mp_fld_core_conf_tx_send_rfi = + get_field(r, MAC_PCS_XXV_CORE_CONF_3_TX_SEND_RFI); + rf->mp_fld_core_conf_tx_send_idle = + get_field(r, MAC_PCS_XXV_CORE_CONF_3_TX_SEND_IDLE); + rf->mp_fld_core_conf_inline_mode = + get_field(r, MAC_PCS_XXV_CORE_CONF_3_INLINE_MODE); + rf->mp_fld_core_conf_line_loopback = + get_field(r, MAC_PCS_XXV_CORE_CONF_3_LINE_LOOPBACK); + rf->mp_fld_core_conf_ts_at_eop = get_field(r, MAC_PCS_XXV_CORE_CONF_3_TS_AT_EOP); + } + + /* + * Registers MAC_PCS_XXV_ANEG_CONFIG_0 -- MAC_PCS_XXV_ANEG_CONFIG_3 + * and MAC_PCS_XXV_ANEG_ABILITY_0 -- MAC_PCS_XXV_ANEG_ABILITY_3 + * and MAC_PCS_XXV_LT_CONF_0 -- MAC_PCS_XXV_LT_CONF_3 + */ + if (!mac_8x10G && n_channels <= 4) { + /* + * 2 x 10 25 G + * ANEG_CONFIG + */ + rf = &p->regs[0]; + + r = get_register(module, MAC_PCS_XXV_ANEG_CONFIG_0); + rf->mp_reg_aneg_config = r; + rf->mp_fld_aneg_config_enable = get_field(r, MAC_PCS_XXV_ANEG_CONFIG_0_ENABLE); + rf->mp_fld_aneg_config_bypass = get_field(r, MAC_PCS_XXV_ANEG_CONFIG_0_BYPASS); + rf->mp_fld_aneg_config_restart = get_field(r, MAC_PCS_XXV_ANEG_CONFIG_0_RESTART); + rf->mp_fld_aneg_config_pseudo = get_field(r, MAC_PCS_XXV_ANEG_CONFIG_0_PSEUDO); + rf->mp_fld_aneg_config_nonce_seed = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_0_NONCE_SEED); + rf->mp_fld_aneg_config_remote_fault = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_0_REMOTE_FAULT); + rf->mp_fld_aneg_config_pause = get_field(r, MAC_PCS_XXV_ANEG_CONFIG_0_PAUSE); + rf->mp_fld_aneg_config_asmdir = get_field(r, MAC_PCS_XXV_ANEG_CONFIG_0_ASMDIR); + rf->mp_fld_aneg_config_fec74_request10g = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_0_FEC74_REQUEST_10G); + rf->mp_fld_aneg_config_hide_fec74 = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_0_HIDE_FEC74); + rf->mp_fld_aneg_config_fec74_request = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_0_FEC74_REQUEST); + rf->mp_fld_aneg_config_fec91_request = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_0_FEC91_REQUEST); + rf->mp_fld_aneg_config_fec91_ability = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_0_FEC91_ABILITY); + rf->mp_fld_aneg_config_rs_fec_request = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_0_RS_FEC_REQUEST); + rf->mp_fld_aneg_config_sw_fec_overwrite = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_0_SW_FEC_OVERWRITE); + rf->mp_fld_aneg_config_sw_speed_overwrite = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_0_SW_SPEED_OVERWRITE); + + /* ANEG_ABILITY */ + r = get_register(module, MAC_PCS_XXV_ANEG_ABILITY_0); + rf->mp_reg_aneg_ability = r; + + rf->mp_fld_aneg_ability_25g_base_cr = + query_field(r, MAC_PCS_XXV_ANEG_ABILITY_0_BASE25G_CR); + + if (!rf->mp_fld_aneg_ability_25g_base_cr) { + rf->mp_fld_aneg_ability_25g_base_cr = + query_field(r, MAC_PCS_XXV_ANEG_ABILITY_0_25GBASE_CR); + } + + rf->mp_fld_aneg_ability_25g_base_crs = + query_field(r, MAC_PCS_XXV_ANEG_ABILITY_0_BASE25G_CR_S); + + if (!rf->mp_fld_aneg_ability_25g_base_crs) { + rf->mp_fld_aneg_ability_25g_base_crs = + query_field(r, MAC_PCS_XXV_ANEG_ABILITY_0_25GBASE_CR_S); + } + + rf->mp_fld_aneg_ability_25g_base_cr1 = + query_field(r, MAC_PCS_XXV_ANEG_ABILITY_0_BASE25G_CR1); + + if (!rf->mp_fld_aneg_ability_25g_base_cr1) { + rf->mp_fld_aneg_ability_25g_base_cr1 = + query_field(r, MAC_PCS_XXV_ANEG_ABILITY_0_25GBASE_CR1); + } + + /* LT_CONF */ + r = get_register(module, MAC_PCS_XXV_LT_CONF_0); + rf->mp_reg_lt_conf = r; + rf->mp_fld_lt_conf_enable = get_field(r, MAC_PCS_XXV_LT_CONF_0_ENABLE); + rf->mp_fld_lt_conf_restart = get_field(r, MAC_PCS_XXV_LT_CONF_0_RESTART); + rf->mp_fld_lt_conf_seed = get_field(r, MAC_PCS_XXV_LT_CONF_0_SEED); + } + + if (!mac_8x10G && n_channels >= 2) { + /* + * 2 x 10 25 G + * ANEG_CONFIG + */ + + /* Initialize regs/fields for sub-module/channel 1 */ + rf = &p->regs[1]; + + r = get_register(module, MAC_PCS_XXV_ANEG_CONFIG_1); + rf->mp_reg_aneg_config = r; + rf->mp_fld_aneg_config_enable = get_field(r, MAC_PCS_XXV_ANEG_CONFIG_1_ENABLE); + rf->mp_fld_aneg_config_bypass = get_field(r, MAC_PCS_XXV_ANEG_CONFIG_1_BYPASS); + rf->mp_fld_aneg_config_restart = get_field(r, MAC_PCS_XXV_ANEG_CONFIG_1_RESTART); + rf->mp_fld_aneg_config_pseudo = get_field(r, MAC_PCS_XXV_ANEG_CONFIG_1_PSEUDO); + rf->mp_fld_aneg_config_nonce_seed = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_1_NONCE_SEED); + rf->mp_fld_aneg_config_remote_fault = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_1_REMOTE_FAULT); + rf->mp_fld_aneg_config_pause = get_field(r, MAC_PCS_XXV_ANEG_CONFIG_1_PAUSE); + rf->mp_fld_aneg_config_asmdir = get_field(r, MAC_PCS_XXV_ANEG_CONFIG_1_ASMDIR); + rf->mp_fld_aneg_config_fec74_request10g = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_1_FEC74_REQUEST_10G); + rf->mp_fld_aneg_config_hide_fec74 = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_1_HIDE_FEC74); + rf->mp_fld_aneg_config_fec74_request = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_1_FEC74_REQUEST); + rf->mp_fld_aneg_config_fec91_request = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_1_FEC91_REQUEST); + rf->mp_fld_aneg_config_fec91_ability = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_1_FEC91_ABILITY); + rf->mp_fld_aneg_config_rs_fec_request = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_1_RS_FEC_REQUEST); + rf->mp_fld_aneg_config_sw_fec_overwrite = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_1_SW_FEC_OVERWRITE); + rf->mp_fld_aneg_config_sw_speed_overwrite = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_1_SW_SPEED_OVERWRITE); + + /* ANEG_ABILITY */ + r = get_register(module, MAC_PCS_XXV_ANEG_ABILITY_1); + rf->mp_reg_aneg_ability = r; + + rf->mp_fld_aneg_ability_25g_base_cr = + query_field(r, MAC_PCS_XXV_ANEG_ABILITY_1_BASE25G_CR); + + if (!rf->mp_fld_aneg_ability_25g_base_cr) { + rf->mp_fld_aneg_ability_25g_base_cr = + get_field(r, MAC_PCS_XXV_ANEG_ABILITY_1_25GBASE_CR); + } + + rf->mp_fld_aneg_ability_25g_base_crs = + query_field(r, MAC_PCS_XXV_ANEG_ABILITY_1_BASE25G_CR_S); + + if (!rf->mp_fld_aneg_ability_25g_base_crs) { + rf->mp_fld_aneg_ability_25g_base_crs = + get_field(r, MAC_PCS_XXV_ANEG_ABILITY_1_25GBASE_CR_S); + } + + rf->mp_fld_aneg_ability_25g_base_cr1 = + query_field(r, MAC_PCS_XXV_ANEG_ABILITY_1_BASE25G_CR1); + + if (!rf->mp_fld_aneg_ability_25g_base_cr1) { + rf->mp_fld_aneg_ability_25g_base_cr1 = + get_field(r, MAC_PCS_XXV_ANEG_ABILITY_1_25GBASE_CR1); + } + + /* LT_CONF */ + r = get_register(module, MAC_PCS_XXV_LT_CONF_1); + rf->mp_reg_lt_conf = r; + rf->mp_fld_lt_conf_enable = get_field(r, MAC_PCS_XXV_LT_CONF_1_ENABLE); + rf->mp_fld_lt_conf_restart = get_field(r, MAC_PCS_XXV_LT_CONF_1_RESTART); + rf->mp_fld_lt_conf_seed = get_field(r, MAC_PCS_XXV_LT_CONF_1_SEED); + } + + if (!mac_8x10G && n_channels == 4) { + /* Initialize regs/fields for sub-module/channel 2 */ + rf = &p->regs[2]; + + r = get_register(module, MAC_PCS_XXV_ANEG_CONFIG_2); + rf->mp_reg_aneg_config = r; + rf->mp_fld_aneg_config_enable = get_field(r, MAC_PCS_XXV_ANEG_CONFIG_2_ENABLE); + rf->mp_fld_aneg_config_bypass = get_field(r, MAC_PCS_XXV_ANEG_CONFIG_2_BYPASS); + rf->mp_fld_aneg_config_restart = get_field(r, MAC_PCS_XXV_ANEG_CONFIG_2_RESTART); + rf->mp_fld_aneg_config_pseudo = get_field(r, MAC_PCS_XXV_ANEG_CONFIG_2_PSEUDO); + rf->mp_fld_aneg_config_nonce_seed = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_2_NONCE_SEED); + rf->mp_fld_aneg_config_remote_fault = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_2_REMOTE_FAULT); + rf->mp_fld_aneg_config_pause = get_field(r, MAC_PCS_XXV_ANEG_CONFIG_2_PAUSE); + rf->mp_fld_aneg_config_asmdir = get_field(r, MAC_PCS_XXV_ANEG_CONFIG_2_ASMDIR); + rf->mp_fld_aneg_config_fec74_request10g = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_2_FEC74_REQUEST_10G); + rf->mp_fld_aneg_config_hide_fec74 = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_2_HIDE_FEC74); + rf->mp_fld_aneg_config_fec74_request = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_2_FEC74_REQUEST); + rf->mp_fld_aneg_config_fec91_request = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_2_FEC91_REQUEST); + rf->mp_fld_aneg_config_fec91_ability = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_2_FEC91_ABILITY); + rf->mp_fld_aneg_config_rs_fec_request = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_2_RS_FEC_REQUEST); + rf->mp_fld_aneg_config_sw_fec_overwrite = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_2_SW_FEC_OVERWRITE); + rf->mp_fld_aneg_config_sw_speed_overwrite = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_2_SW_SPEED_OVERWRITE); + + /* ANEG_ABILITY */ + r = get_register(module, MAC_PCS_XXV_ANEG_ABILITY_2); + rf->mp_reg_aneg_ability = r; + rf->mp_fld_aneg_ability_25g_base_cr = + get_field(r, MAC_PCS_XXV_ANEG_ABILITY_2_25GBASE_CR); + rf->mp_fld_aneg_ability_25g_base_crs = + get_field(r, MAC_PCS_XXV_ANEG_ABILITY_2_25GBASE_CR_S); + rf->mp_fld_aneg_ability_25g_base_cr1 = + get_field(r, MAC_PCS_XXV_ANEG_ABILITY_2_25GBASE_CR1); + + /* LT_CONF */ + r = get_register(module, MAC_PCS_XXV_LT_CONF_2); + rf->mp_reg_lt_conf = r; + rf->mp_fld_lt_conf_enable = get_field(r, MAC_PCS_XXV_LT_CONF_2_ENABLE); + rf->mp_fld_lt_conf_restart = get_field(r, MAC_PCS_XXV_LT_CONF_2_RESTART); + rf->mp_fld_lt_conf_seed = get_field(r, MAC_PCS_XXV_LT_CONF_2_SEED); + + /* Initialize regs/fields for sub-module/channel 3 */ + rf = &p->regs[3]; + + r = get_register(module, MAC_PCS_XXV_ANEG_CONFIG_3); + rf->mp_reg_aneg_config = r; + rf->mp_fld_aneg_config_enable = get_field(r, MAC_PCS_XXV_ANEG_CONFIG_3_ENABLE); + rf->mp_fld_aneg_config_bypass = get_field(r, MAC_PCS_XXV_ANEG_CONFIG_3_BYPASS); + rf->mp_fld_aneg_config_restart = get_field(r, MAC_PCS_XXV_ANEG_CONFIG_3_RESTART); + rf->mp_fld_aneg_config_pseudo = get_field(r, MAC_PCS_XXV_ANEG_CONFIG_3_PSEUDO); + rf->mp_fld_aneg_config_nonce_seed = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_3_NONCE_SEED); + rf->mp_fld_aneg_config_remote_fault = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_3_REMOTE_FAULT); + rf->mp_fld_aneg_config_pause = get_field(r, MAC_PCS_XXV_ANEG_CONFIG_3_PAUSE); + rf->mp_fld_aneg_config_asmdir = get_field(r, MAC_PCS_XXV_ANEG_CONFIG_3_ASMDIR); + rf->mp_fld_aneg_config_fec74_request10g = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_3_FEC74_REQUEST_10G); + rf->mp_fld_aneg_config_hide_fec74 = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_3_HIDE_FEC74); + rf->mp_fld_aneg_config_fec74_request = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_3_FEC74_REQUEST); + rf->mp_fld_aneg_config_fec91_request = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_3_FEC91_REQUEST); + rf->mp_fld_aneg_config_fec91_ability = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_3_FEC91_ABILITY); + rf->mp_fld_aneg_config_rs_fec_request = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_3_RS_FEC_REQUEST); + rf->mp_fld_aneg_config_sw_fec_overwrite = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_3_SW_FEC_OVERWRITE); + rf->mp_fld_aneg_config_sw_speed_overwrite = + get_field(r, MAC_PCS_XXV_ANEG_CONFIG_3_SW_SPEED_OVERWRITE); + + /* ANEG_ABILITY */ + r = get_register(module, MAC_PCS_XXV_ANEG_ABILITY_3); + rf->mp_reg_aneg_ability = r; + rf->mp_fld_aneg_ability_25g_base_cr = + get_field(r, MAC_PCS_XXV_ANEG_ABILITY_3_25GBASE_CR); + rf->mp_fld_aneg_ability_25g_base_crs = + get_field(r, MAC_PCS_XXV_ANEG_ABILITY_3_25GBASE_CR_S); + rf->mp_fld_aneg_ability_25g_base_cr1 = + get_field(r, MAC_PCS_XXV_ANEG_ABILITY_3_25GBASE_CR1); + + /* LT_CONF */ + r = get_register(module, MAC_PCS_XXV_LT_CONF_3); + rf->mp_reg_lt_conf = r; + rf->mp_fld_lt_conf_enable = get_field(r, MAC_PCS_XXV_LT_CONF_3_ENABLE); + rf->mp_fld_lt_conf_restart = get_field(r, MAC_PCS_XXV_LT_CONF_3_RESTART); + rf->mp_fld_lt_conf_seed = get_field(r, MAC_PCS_XXV_LT_CONF_3_SEED); + } + + /* + * Registers MAC_PCS_XXV_SUB_RST_0 -- MAC_PCS_XXV_SUB_RST_3 + * and MAC_PCS_XXV_SUB_RST_STATUS_0 -- MAC_PCS_XXV_SUB_RST_STATUS_3 + */ + if (n_channels <= 4) { + /* Initialize regs/fields for sub-module/channel 0 */ + rf = &p->regs[0]; + r = get_register(module, MAC_PCS_XXV_SUB_RST_0); + + rf->mp_reg_sub_rst = r; + rf->mp_fld_sub_rst_rx_mac_pcs = get_field(r, MAC_PCS_XXV_SUB_RST_0_RX_MAC_PCS); + rf->mp_fld_sub_rst_tx_mac_pcs = get_field(r, MAC_PCS_XXV_SUB_RST_0_TX_MAC_PCS); + rf->mp_fld_sub_rst_rx_gt_data = get_field(r, MAC_PCS_XXV_SUB_RST_0_RX_GT_DATA); + rf->mp_fld_sub_rst_tx_gt_data = get_field(r, MAC_PCS_XXV_SUB_RST_0_TX_GT_DATA); + rf->mp_fld_sub_rst_rx_buf = get_field(r, MAC_PCS_XXV_SUB_RST_0_RX_BUF); + rf->mp_fld_sub_rst_rx_pma = get_field(r, MAC_PCS_XXV_SUB_RST_0_RX_PMA); + rf->mp_fld_sub_rst_tx_pma = get_field(r, MAC_PCS_XXV_SUB_RST_0_TX_PMA); + rf->mp_fld_sub_rst_rx_pcs = get_field(r, MAC_PCS_XXV_SUB_RST_0_RX_PCS); + rf->mp_fld_sub_rst_tx_pcs = get_field(r, MAC_PCS_XXV_SUB_RST_0_TX_PCS); + rf->mp_fld_sub_rst_an_lt = get_field(r, MAC_PCS_XXV_SUB_RST_0_AN_LT); + rf->mp_fld_sub_rst_speed_ctrl = query_field(r, MAC_PCS_XXV_SUB_RST_0_SPEED_CTRL); + + r = get_register(module, MAC_PCS_XXV_SUB_RST_STATUS_0); + rf->mp_reg_sub_rst_status = r; + rf->mp_fld_sub_rst_status_user_rx_rst = + get_field(r, MAC_PCS_XXV_SUB_RST_STATUS_0_USER_RX_RST); + rf->mp_fld_sub_rst_status_user_tx_rst = + get_field(r, MAC_PCS_XXV_SUB_RST_STATUS_0_USER_TX_RST); + rf->mp_fld_sub_rst_status_qpll_lock = + get_field(r, MAC_PCS_XXV_SUB_RST_STATUS_0_QPLL_LOCK); + } + + if (n_channels >= 2) { + /* Initialize regs/fields for sub-module/channel 1 */ + rf = &p->regs[1]; + r = get_register(module, MAC_PCS_XXV_SUB_RST_1); + + rf->mp_reg_sub_rst = r; + rf->mp_fld_sub_rst_rx_mac_pcs = get_field(r, MAC_PCS_XXV_SUB_RST_1_RX_MAC_PCS); + rf->mp_fld_sub_rst_tx_mac_pcs = get_field(r, MAC_PCS_XXV_SUB_RST_1_TX_MAC_PCS); + rf->mp_fld_sub_rst_rx_gt_data = get_field(r, MAC_PCS_XXV_SUB_RST_1_RX_GT_DATA); + rf->mp_fld_sub_rst_tx_gt_data = get_field(r, MAC_PCS_XXV_SUB_RST_1_TX_GT_DATA); + rf->mp_fld_sub_rst_rx_buf = get_field(r, MAC_PCS_XXV_SUB_RST_1_RX_BUF); + rf->mp_fld_sub_rst_rx_pma = get_field(r, MAC_PCS_XXV_SUB_RST_1_RX_PMA); + rf->mp_fld_sub_rst_tx_pma = get_field(r, MAC_PCS_XXV_SUB_RST_1_TX_PMA); + rf->mp_fld_sub_rst_rx_pcs = get_field(r, MAC_PCS_XXV_SUB_RST_1_RX_PCS); + rf->mp_fld_sub_rst_tx_pcs = get_field(r, MAC_PCS_XXV_SUB_RST_1_TX_PCS); + rf->mp_fld_sub_rst_an_lt = get_field(r, MAC_PCS_XXV_SUB_RST_1_AN_LT); + rf->mp_fld_sub_rst_speed_ctrl = query_field(r, MAC_PCS_XXV_SUB_RST_1_SPEED_CTRL); + + r = get_register(module, MAC_PCS_XXV_SUB_RST_STATUS_1); + rf->mp_reg_sub_rst_status = r; + rf->mp_fld_sub_rst_status_user_rx_rst = + get_field(r, MAC_PCS_XXV_SUB_RST_STATUS_1_USER_RX_RST); + rf->mp_fld_sub_rst_status_user_tx_rst = + get_field(r, MAC_PCS_XXV_SUB_RST_STATUS_1_USER_TX_RST); + rf->mp_fld_sub_rst_status_qpll_lock = + get_field(r, MAC_PCS_XXV_SUB_RST_STATUS_1_QPLL_LOCK); + } + + if (n_channels == 4) { + /* Initialize regs/fields for sub-module/channel 2 */ + rf = &p->regs[2]; + r = get_register(module, MAC_PCS_XXV_SUB_RST_2); + + rf->mp_reg_sub_rst = r; + rf->mp_fld_sub_rst_rx_mac_pcs = get_field(r, MAC_PCS_XXV_SUB_RST_2_RX_MAC_PCS); + rf->mp_fld_sub_rst_tx_mac_pcs = get_field(r, MAC_PCS_XXV_SUB_RST_2_TX_MAC_PCS); + rf->mp_fld_sub_rst_rx_gt_data = get_field(r, MAC_PCS_XXV_SUB_RST_2_RX_GT_DATA); + rf->mp_fld_sub_rst_tx_gt_data = get_field(r, MAC_PCS_XXV_SUB_RST_2_TX_GT_DATA); + rf->mp_fld_sub_rst_rx_buf = get_field(r, MAC_PCS_XXV_SUB_RST_2_RX_BUF); + rf->mp_fld_sub_rst_rx_pma = get_field(r, MAC_PCS_XXV_SUB_RST_2_RX_PMA); + rf->mp_fld_sub_rst_tx_pma = get_field(r, MAC_PCS_XXV_SUB_RST_2_TX_PMA); + rf->mp_fld_sub_rst_rx_pcs = get_field(r, MAC_PCS_XXV_SUB_RST_2_RX_PCS); + rf->mp_fld_sub_rst_tx_pcs = get_field(r, MAC_PCS_XXV_SUB_RST_2_TX_PCS); + rf->mp_fld_sub_rst_an_lt = get_field(r, MAC_PCS_XXV_SUB_RST_2_AN_LT); + rf->mp_fld_sub_rst_speed_ctrl = query_field(r, MAC_PCS_XXV_SUB_RST_2_SPEED_CTRL); + + r = get_register(module, MAC_PCS_XXV_SUB_RST_STATUS_2); + rf->mp_reg_sub_rst_status = r; + rf->mp_fld_sub_rst_status_user_rx_rst = + get_field(r, MAC_PCS_XXV_SUB_RST_STATUS_2_USER_RX_RST); + rf->mp_fld_sub_rst_status_user_tx_rst = + get_field(r, MAC_PCS_XXV_SUB_RST_STATUS_2_USER_TX_RST); + rf->mp_fld_sub_rst_status_qpll_lock = + get_field(r, MAC_PCS_XXV_SUB_RST_STATUS_2_QPLL_LOCK); + + /* Initialize regs/fields for sub-module/channel 3 */ + rf = &p->regs[3]; + r = get_register(module, MAC_PCS_XXV_SUB_RST_3); + + rf->mp_reg_sub_rst = r; + rf->mp_fld_sub_rst_rx_mac_pcs = get_field(r, MAC_PCS_XXV_SUB_RST_3_RX_MAC_PCS); + rf->mp_fld_sub_rst_tx_mac_pcs = get_field(r, MAC_PCS_XXV_SUB_RST_3_TX_MAC_PCS); + rf->mp_fld_sub_rst_rx_gt_data = get_field(r, MAC_PCS_XXV_SUB_RST_3_RX_GT_DATA); + rf->mp_fld_sub_rst_tx_gt_data = get_field(r, MAC_PCS_XXV_SUB_RST_3_TX_GT_DATA); + rf->mp_fld_sub_rst_rx_buf = get_field(r, MAC_PCS_XXV_SUB_RST_3_RX_BUF); + rf->mp_fld_sub_rst_rx_pma = get_field(r, MAC_PCS_XXV_SUB_RST_3_RX_PMA); + rf->mp_fld_sub_rst_tx_pma = get_field(r, MAC_PCS_XXV_SUB_RST_3_TX_PMA); + rf->mp_fld_sub_rst_rx_pcs = get_field(r, MAC_PCS_XXV_SUB_RST_3_RX_PCS); + rf->mp_fld_sub_rst_tx_pcs = get_field(r, MAC_PCS_XXV_SUB_RST_3_TX_PCS); + rf->mp_fld_sub_rst_an_lt = get_field(r, MAC_PCS_XXV_SUB_RST_3_AN_LT); + rf->mp_fld_sub_rst_speed_ctrl = query_field(r, MAC_PCS_XXV_SUB_RST_3_SPEED_CTRL); + + r = get_register(module, MAC_PCS_XXV_SUB_RST_STATUS_3); + rf->mp_reg_sub_rst_status = r; + rf->mp_fld_sub_rst_status_user_rx_rst = + get_field(r, MAC_PCS_XXV_SUB_RST_STATUS_3_USER_RX_RST); + rf->mp_fld_sub_rst_status_user_tx_rst = + get_field(r, MAC_PCS_XXV_SUB_RST_STATUS_3_USER_TX_RST); + rf->mp_fld_sub_rst_status_qpll_lock = + get_field(r, MAC_PCS_XXV_SUB_RST_STATUS_3_QPLL_LOCK); + } + + /* Registers MAC_PCS_XXV_LINK_SUMMARY_0 -- MAC_PCS_XXV_LINK_SUMMARY_3 */ + if (n_channels <= 4) { + /* Initialize regs/fields for sub-module/channel 0 */ + rf = &p->regs[0]; + r = get_register(module, MAC_PCS_XXV_LINK_SUMMARY_0); + + rf->mp_reg_link_summary = r; + rf->mp_fld_link_summary_nt_phy_link_state = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_0_NT_PHY_LINK_STATE); + rf->mp_fld_link_summary_ll_nt_phy_link_state = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_0_LL_PHY_LINK_STATE); + rf->mp_fld_link_summary_abs = get_field(r, MAC_PCS_XXV_LINK_SUMMARY_0_ABS); + rf->mp_fld_link_summary_lh_abs = get_field(r, MAC_PCS_XXV_LINK_SUMMARY_0_LH_ABS); + rf->mp_fld_link_summary_link_down_cnt = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_0_LINK_DOWN_CNT); + + if (!mac_8x10G) { + rf->mp_fld_link_summary_ll_rx_fec74_lock = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_0_LL_RX_FEC74_LOCK); + rf->mp_fld_link_summary_lh_rx_rsfec_hi_ser = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_0_LH_RX_RSFEC_HI_SER); + rf->mp_fld_link_summary_ll_rx_rsfec_lane_alignment = + get_field(r, + MAC_PCS_XXV_LINK_SUMMARY_0_LL_RX_RSFEC_LANE_ALIGNMENT); + rf->mp_fld_link_summary_ll_tx_rsfec_lane_alignment = + get_field(r, + MAC_PCS_XXV_LINK_SUMMARY_0_LL_TX_RSFEC_LANE_ALIGNMENT); + rf->mp_fld_link_summary_lh_rx_pcs_valid_ctrl_code = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_0_LH_RX_PCS_VALID_CTRL_CODE); + } + + rf->mp_fld_link_summary_ll_rx_block_lock = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_0_LL_RX_BLOCK_LOCK); + rf->mp_fld_link_summary_lh_rx_high_bit_error_rate = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_0_LH_RX_HIGH_BIT_ERROR_RATE); + rf->mp_fld_link_summary_lh_internal_local_fault = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_0_LH_INTERNAL_LOCAL_FAULT); + rf->mp_fld_link_summary_lh_received_local_fault = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_0_LH_RECEIVED_LOCAL_FAULT); + rf->mp_fld_link_summary_lh_local_fault = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_0_LH_LOCAL_FAULT); + rf->mp_fld_link_summary_lh_remote_fault = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_0_LH_REMOTE_FAULT); + rf->mp_fld_link_summary_nim_interr = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_0_NIM_INTERR); + } + + if (n_channels >= 2) { + /* Initialize regs/fields for sub-module/channel 1 */ + rf = &p->regs[1]; + r = get_register(module, MAC_PCS_XXV_LINK_SUMMARY_1); + + rf->mp_reg_link_summary = r; + rf->mp_fld_link_summary_nt_phy_link_state = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_1_NT_PHY_LINK_STATE); + rf->mp_fld_link_summary_ll_nt_phy_link_state = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_1_LL_PHY_LINK_STATE); + rf->mp_fld_link_summary_abs = get_field(r, MAC_PCS_XXV_LINK_SUMMARY_1_ABS); + rf->mp_fld_link_summary_lh_abs = get_field(r, MAC_PCS_XXV_LINK_SUMMARY_1_LH_ABS); + rf->mp_fld_link_summary_link_down_cnt = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_1_LINK_DOWN_CNT); + + if (!mac_8x10G) { + rf->mp_fld_link_summary_ll_rx_fec74_lock = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_1_LL_RX_FEC74_LOCK); + rf->mp_fld_link_summary_lh_rx_rsfec_hi_ser = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_1_LH_RX_RSFEC_HI_SER); + rf->mp_fld_link_summary_ll_rx_rsfec_lane_alignment = + get_field(r, + MAC_PCS_XXV_LINK_SUMMARY_1_LL_RX_RSFEC_LANE_ALIGNMENT); + rf->mp_fld_link_summary_ll_tx_rsfec_lane_alignment = + get_field(r, + MAC_PCS_XXV_LINK_SUMMARY_1_LL_TX_RSFEC_LANE_ALIGNMENT); + rf->mp_fld_link_summary_lh_rx_pcs_valid_ctrl_code = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_1_LH_RX_PCS_VALID_CTRL_CODE); + } + + rf->mp_fld_link_summary_ll_rx_block_lock = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_1_LL_RX_BLOCK_LOCK); + rf->mp_fld_link_summary_lh_rx_high_bit_error_rate = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_1_LH_RX_HIGH_BIT_ERROR_RATE); + rf->mp_fld_link_summary_lh_internal_local_fault = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_1_LH_INTERNAL_LOCAL_FAULT); + rf->mp_fld_link_summary_lh_received_local_fault = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_1_LH_RECEIVED_LOCAL_FAULT); + rf->mp_fld_link_summary_lh_local_fault = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_1_LH_LOCAL_FAULT); + rf->mp_fld_link_summary_lh_remote_fault = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_1_LH_REMOTE_FAULT); + rf->mp_fld_link_summary_nim_interr = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_1_NIM_INTERR); + } + + if (n_channels == 4) { + /* Initialize regs/fields for sub-module/channel 2 */ + rf = &p->regs[2]; + r = get_register(module, MAC_PCS_XXV_LINK_SUMMARY_2); + + rf->mp_reg_link_summary = r; + rf->mp_fld_link_summary_nt_phy_link_state = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_2_NT_PHY_LINK_STATE); + rf->mp_fld_link_summary_ll_nt_phy_link_state = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_2_LL_PHY_LINK_STATE); + rf->mp_fld_link_summary_abs = get_field(r, MAC_PCS_XXV_LINK_SUMMARY_2_ABS); + rf->mp_fld_link_summary_lh_abs = get_field(r, MAC_PCS_XXV_LINK_SUMMARY_2_LH_ABS); + rf->mp_fld_link_summary_link_down_cnt = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_2_LINK_DOWN_CNT); + + if (!mac_8x10G) { + rf->mp_fld_link_summary_ll_rx_fec74_lock = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_2_LL_RX_FEC74_LOCK); + rf->mp_fld_link_summary_lh_rx_rsfec_hi_ser = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_2_LH_RX_RSFEC_HI_SER); + rf->mp_fld_link_summary_ll_rx_rsfec_lane_alignment = + get_field(r, + MAC_PCS_XXV_LINK_SUMMARY_2_LL_RX_RSFEC_LANE_ALIGNMENT); + rf->mp_fld_link_summary_ll_tx_rsfec_lane_alignment = + get_field(r, + MAC_PCS_XXV_LINK_SUMMARY_2_LL_TX_RSFEC_LANE_ALIGNMENT); + rf->mp_fld_link_summary_lh_rx_pcs_valid_ctrl_code = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_2_LH_RX_PCS_VALID_CTRL_CODE); + } + + rf->mp_fld_link_summary_ll_rx_block_lock = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_2_LL_RX_BLOCK_LOCK); + rf->mp_fld_link_summary_lh_rx_high_bit_error_rate = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_2_LH_RX_HIGH_BIT_ERROR_RATE); + rf->mp_fld_link_summary_lh_internal_local_fault = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_2_LH_INTERNAL_LOCAL_FAULT); + rf->mp_fld_link_summary_lh_received_local_fault = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_2_LH_RECEIVED_LOCAL_FAULT); + rf->mp_fld_link_summary_lh_local_fault = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_2_LH_LOCAL_FAULT); + rf->mp_fld_link_summary_lh_remote_fault = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_2_LH_REMOTE_FAULT); + rf->mp_fld_link_summary_nim_interr = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_2_NIM_INTERR); + + /* Initialize regs/fields for sub-module/channel 3 */ + rf = &p->regs[3]; + r = get_register(module, MAC_PCS_XXV_LINK_SUMMARY_3); + + rf->mp_reg_link_summary = r; + rf->mp_fld_link_summary_nt_phy_link_state = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_3_NT_PHY_LINK_STATE); + rf->mp_fld_link_summary_ll_nt_phy_link_state = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_3_LL_PHY_LINK_STATE); + rf->mp_fld_link_summary_abs = get_field(r, MAC_PCS_XXV_LINK_SUMMARY_3_ABS); + rf->mp_fld_link_summary_lh_abs = get_field(r, MAC_PCS_XXV_LINK_SUMMARY_3_LH_ABS); + rf->mp_fld_link_summary_link_down_cnt = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_3_LINK_DOWN_CNT); + + if (!mac_8x10G) { + rf->mp_fld_link_summary_ll_rx_fec74_lock = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_3_LL_RX_FEC74_LOCK); + rf->mp_fld_link_summary_lh_rx_rsfec_hi_ser = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_3_LH_RX_RSFEC_HI_SER); + rf->mp_fld_link_summary_ll_rx_rsfec_lane_alignment = + get_field(r, + MAC_PCS_XXV_LINK_SUMMARY_3_LL_RX_RSFEC_LANE_ALIGNMENT); + rf->mp_fld_link_summary_ll_tx_rsfec_lane_alignment = + get_field(r, + MAC_PCS_XXV_LINK_SUMMARY_3_LL_TX_RSFEC_LANE_ALIGNMENT); + rf->mp_fld_link_summary_lh_rx_pcs_valid_ctrl_code = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_3_LH_RX_PCS_VALID_CTRL_CODE); + } + + rf->mp_fld_link_summary_ll_rx_block_lock = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_3_LL_RX_BLOCK_LOCK); + rf->mp_fld_link_summary_lh_rx_high_bit_error_rate = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_3_LH_RX_HIGH_BIT_ERROR_RATE); + rf->mp_fld_link_summary_lh_internal_local_fault = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_3_LH_INTERNAL_LOCAL_FAULT); + rf->mp_fld_link_summary_lh_received_local_fault = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_3_LH_RECEIVED_LOCAL_FAULT); + rf->mp_fld_link_summary_lh_local_fault = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_3_LH_LOCAL_FAULT); + rf->mp_fld_link_summary_lh_remote_fault = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_3_LH_REMOTE_FAULT); + rf->mp_fld_link_summary_nim_interr = + get_field(r, MAC_PCS_XXV_LINK_SUMMARY_3_NIM_INTERR); + } + + /* + * Registers MAC_PCS_XXV_GTY_LOOP_0 -- MAC_PCS_XXV_GTY_LOOP_3 + * and MAC_PCS_XXV_GTY_CTL_RX_0 -- MAC_PCS_XXV_GTY_CTL_RX_3 + * and MAC_PCS_XXV_GTY_CTL_TX_0 -- MAC_PCS_XXV_GTY_CTL_TX_3 + * and MAC_PCS_XXV_LINK_SPEED_0 -- MAC_PCS_XXV_LINK_SPEED_3 + * and MAC_PCS_XXV_RS_FEC_CONF_0 -- MAC_PCS_XXV_RS_FEC_CONF_0 + */ + if (n_channels <= 4) { + /* Initialize regs/fields for sub-module/channel 0 */ + rf = &p->regs[0]; + + r = get_register(module, MAC_PCS_XXV_GTY_LOOP_0); + rf->mp_reg_gty_loop = r; + rf->mp_fld_gty_loop_gt_loop = get_field(r, MAC_PCS_XXV_GTY_LOOP_0_GT_LOOP); + + r = get_register(module, MAC_PCS_XXV_GTY_CTL_RX_0); + rf->mp_reg_gty_ctl_rx = r; + rf->mp_fld_gty_ctl_rx_polarity = get_field(r, MAC_PCS_XXV_GTY_CTL_RX_0_POLARITY); + rf->mp_fld_gty_ctl_rx_lpm_en = get_field(r, MAC_PCS_XXV_GTY_CTL_RX_0_LPM_EN); + rf->mp_fld_gty_ctl_rx_equa_rst = get_field(r, MAC_PCS_XXV_GTY_CTL_RX_0_EQUA_RST); + + r = get_register(module, MAC_PCS_XXV_GTY_CTL_TX_0); + rf->mp_fld_gty_ctl_tx_polarity = get_field(r, MAC_PCS_XXV_GTY_CTL_TX_0_POLARITY); + rf->mp_fld_gty_ctl_tx_inhibit = get_field(r, MAC_PCS_XXV_GTY_CTL_TX_0_INHIBIT); + + if (!mac_8x10G) { + r = get_register(module, MAC_PCS_XXV_LINK_SPEED_0); + rf->mp_reg_link_speed = get_register(module, MAC_PCS_XXV_LINK_SPEED_0); + + rf->mp_fld_link_speed_10g = query_field(r, MAC_PCS_XXV_LINK_SPEED_0_SPEED); + + if (!rf->mp_fld_link_speed_10g) { + rf->mp_fld_link_speed_10g = + get_field(r, MAC_PCS_XXV_LINK_SPEED_0_10G); + } + + rf->mp_fld_link_speed_toggle = + get_field(r, MAC_PCS_XXV_LINK_SPEED_0_TOGGLE); + + r = get_register(module, MAC_PCS_XXV_RS_FEC_CONF_0); + rf->mp_reg_rs_fec_conf = r; + rf->mp_fld_rs_fec_conf_rs_fec_enable = + get_field(r, MAC_PCS_XXV_RS_FEC_CONF_0_RS_FEC_ENABLE); + + r = get_register(module, MAC_PCS_XXV_RS_FEC_CCW_CNT_0); + rf->mp_reg_rs_fec_ccw = r; + rf->mp_field_reg_rs_fec_ccw_reg_rs_fec_ccw_cnt = + get_field(r, MAC_PCS_XXV_RS_FEC_CCW_CNT_0_RS_FEC_CCW_CNT); + + r = get_register(module, MAC_PCS_XXV_RS_FEC_UCW_CNT_0); + rf->mp_reg_rs_fec_ucw = r; + rf->mp_field_reg_rs_fec_ucw_reg_rs_fec_ucw_cnt = + get_field(r, MAC_PCS_XXV_RS_FEC_UCW_CNT_0_RS_FEC_UCW_CNT); + } + } + + if (n_channels >= 2) { + /* Initialize regs/fields for sub-module/channel 1 */ + rf = &p->regs[1]; + + r = get_register(module, MAC_PCS_XXV_GTY_LOOP_1); + rf->mp_reg_gty_loop = r; + rf->mp_fld_gty_loop_gt_loop = get_field(r, MAC_PCS_XXV_GTY_LOOP_1_GT_LOOP); + + r = get_register(module, MAC_PCS_XXV_GTY_CTL_RX_1); + rf->mp_reg_gty_ctl_rx = r; + rf->mp_fld_gty_ctl_rx_polarity = get_field(r, MAC_PCS_XXV_GTY_CTL_RX_1_POLARITY); + rf->mp_fld_gty_ctl_rx_lpm_en = get_field(r, MAC_PCS_XXV_GTY_CTL_RX_1_LPM_EN); + rf->mp_fld_gty_ctl_rx_equa_rst = get_field(r, MAC_PCS_XXV_GTY_CTL_RX_1_EQUA_RST); + + r = get_register(module, MAC_PCS_XXV_GTY_CTL_TX_1); + rf->mp_fld_gty_ctl_tx_polarity = get_field(r, MAC_PCS_XXV_GTY_CTL_TX_1_POLARITY); + rf->mp_fld_gty_ctl_tx_inhibit = get_field(r, MAC_PCS_XXV_GTY_CTL_TX_1_INHIBIT); + + if (!mac_8x10G) { + r = get_register(module, MAC_PCS_XXV_LINK_SPEED_1); + rf->mp_reg_link_speed = get_register(module, MAC_PCS_XXV_LINK_SPEED_1); + + rf->mp_fld_link_speed_10g = get_field(r, MAC_PCS_XXV_LINK_SPEED_1_SPEED); + + if (!rf->mp_fld_link_speed_10g) { + rf->mp_fld_link_speed_10g = + get_field(r, MAC_PCS_XXV_LINK_SPEED_1_10G); + } + + rf->mp_fld_link_speed_toggle = + get_field(r, MAC_PCS_XXV_LINK_SPEED_1_TOGGLE); + + r = get_register(module, MAC_PCS_XXV_RS_FEC_CONF_1); + rf->mp_reg_rs_fec_conf = r; + rf->mp_fld_rs_fec_conf_rs_fec_enable = + get_field(r, MAC_PCS_XXV_RS_FEC_CONF_1_RS_FEC_ENABLE); + + r = get_register(module, MAC_PCS_XXV_RS_FEC_CCW_CNT_1); + rf->mp_reg_rs_fec_ccw = r; + rf->mp_field_reg_rs_fec_ccw_reg_rs_fec_ccw_cnt = + get_field(r, MAC_PCS_XXV_RS_FEC_CCW_CNT_1_RS_FEC_CCW_CNT); + + r = get_register(module, MAC_PCS_XXV_RS_FEC_UCW_CNT_1); + rf->mp_reg_rs_fec_ucw = r; + rf->mp_field_reg_rs_fec_ucw_reg_rs_fec_ucw_cnt = + get_field(r, MAC_PCS_XXV_RS_FEC_UCW_CNT_1_RS_FEC_UCW_CNT); + } + } + + if (n_channels == 4) { + /* Initialize regs/fields for sub-module/channel 2 */ + rf = &p->regs[2]; + + r = get_register(module, MAC_PCS_XXV_GTY_LOOP_2); + rf->mp_reg_gty_loop = r; + rf->mp_fld_gty_loop_gt_loop = get_field(r, MAC_PCS_XXV_GTY_LOOP_2_GT_LOOP); + + r = get_register(module, MAC_PCS_XXV_GTY_CTL_RX_2); + rf->mp_reg_gty_ctl_rx = r; + rf->mp_fld_gty_ctl_rx_polarity = get_field(r, MAC_PCS_XXV_GTY_CTL_RX_2_POLARITY); + rf->mp_fld_gty_ctl_rx_lpm_en = get_field(r, MAC_PCS_XXV_GTY_CTL_RX_2_LPM_EN); + rf->mp_fld_gty_ctl_rx_equa_rst = get_field(r, MAC_PCS_XXV_GTY_CTL_RX_2_EQUA_RST); + + r = get_register(module, MAC_PCS_XXV_GTY_CTL_TX_2); + rf->mp_fld_gty_ctl_tx_polarity = get_field(r, MAC_PCS_XXV_GTY_CTL_TX_2_POLARITY); + rf->mp_fld_gty_ctl_tx_inhibit = get_field(r, MAC_PCS_XXV_GTY_CTL_TX_2_INHIBIT); + + if (!mac_8x10G) { + r = get_register(module, MAC_PCS_XXV_LINK_SPEED_2); + rf->mp_reg_link_speed = get_register(module, MAC_PCS_XXV_LINK_SPEED_2); + + rf->mp_fld_link_speed_10g = get_field(r, MAC_PCS_XXV_LINK_SPEED_2_SPEED); + + if (!rf->mp_fld_link_speed_10g) { + rf->mp_fld_link_speed_10g = + get_field(r, MAC_PCS_XXV_LINK_SPEED_2_10G); + } + + rf->mp_fld_link_speed_toggle = + get_field(r, MAC_PCS_XXV_LINK_SPEED_2_TOGGLE); + + r = get_register(module, MAC_PCS_XXV_RS_FEC_CONF_2); + rf->mp_reg_rs_fec_conf = r; + rf->mp_fld_rs_fec_conf_rs_fec_enable = + get_field(r, MAC_PCS_XXV_RS_FEC_CONF_2_RS_FEC_ENABLE); + + r = get_register(module, MAC_PCS_XXV_RS_FEC_CCW_CNT_2); + rf->mp_reg_rs_fec_ccw = r; + rf->mp_field_reg_rs_fec_ccw_reg_rs_fec_ccw_cnt = + get_field(r, MAC_PCS_XXV_RS_FEC_CCW_CNT_2_RS_FEC_CCW_CNT); + + r = get_register(module, MAC_PCS_XXV_RS_FEC_UCW_CNT_2); + rf->mp_reg_rs_fec_ucw = r; + rf->mp_field_reg_rs_fec_ucw_reg_rs_fec_ucw_cnt = + get_field(r, MAC_PCS_XXV_RS_FEC_UCW_CNT_2_RS_FEC_UCW_CNT); + } + + /* Initialize regs/fields for sub-module/channel 3 */ + rf = &p->regs[3]; + + r = get_register(module, MAC_PCS_XXV_GTY_LOOP_3); + rf->mp_reg_gty_loop = r; + rf->mp_fld_gty_loop_gt_loop = get_field(r, MAC_PCS_XXV_GTY_LOOP_3_GT_LOOP); + + r = get_register(module, MAC_PCS_XXV_GTY_CTL_RX_3); + rf->mp_reg_gty_ctl_rx = r; + rf->mp_fld_gty_ctl_rx_polarity = get_field(r, MAC_PCS_XXV_GTY_CTL_RX_3_POLARITY); + rf->mp_fld_gty_ctl_rx_lpm_en = get_field(r, MAC_PCS_XXV_GTY_CTL_RX_3_LPM_EN); + rf->mp_fld_gty_ctl_rx_equa_rst = get_field(r, MAC_PCS_XXV_GTY_CTL_RX_3_EQUA_RST); + + r = get_register(module, MAC_PCS_XXV_GTY_CTL_TX_3); + rf->mp_fld_gty_ctl_tx_polarity = get_field(r, MAC_PCS_XXV_GTY_CTL_TX_3_POLARITY); + rf->mp_fld_gty_ctl_tx_inhibit = get_field(r, MAC_PCS_XXV_GTY_CTL_TX_3_INHIBIT); + + if (!mac_8x10G) { + r = get_register(module, MAC_PCS_XXV_LINK_SPEED_3); + rf->mp_reg_link_speed = get_register(module, MAC_PCS_XXV_LINK_SPEED_3); + + rf->mp_fld_link_speed_10g = get_field(r, MAC_PCS_XXV_LINK_SPEED_3_SPEED); + + if (!rf->mp_fld_link_speed_10g) { + rf->mp_fld_link_speed_10g = + get_field(r, MAC_PCS_XXV_LINK_SPEED_3_10G); + } + + rf->mp_fld_link_speed_toggle = + get_field(r, MAC_PCS_XXV_LINK_SPEED_3_TOGGLE); + + r = get_register(module, MAC_PCS_XXV_RS_FEC_CONF_3); + rf->mp_reg_rs_fec_conf = r; + rf->mp_fld_rs_fec_conf_rs_fec_enable = + get_field(r, MAC_PCS_XXV_RS_FEC_CONF_3_RS_FEC_ENABLE); + + r = get_register(module, MAC_PCS_XXV_RS_FEC_CCW_CNT_3); + rf->mp_reg_rs_fec_ccw = r; + rf->mp_field_reg_rs_fec_ccw_reg_rs_fec_ccw_cnt = + get_field(r, MAC_PCS_XXV_RS_FEC_CCW_CNT_3_RS_FEC_CCW_CNT); + + r = get_register(module, MAC_PCS_XXV_RS_FEC_UCW_CNT_3); + rf->mp_reg_rs_fec_ucw = r; + rf->mp_field_reg_rs_fec_ucw_reg_rs_fec_ucw_cnt = + get_field(r, MAC_PCS_XXV_RS_FEC_UCW_CNT_3_RS_FEC_UCW_CNT); + } + } + + /* + * Registers MAC_PCS_XXV_DEBOUNCE_CTRL_0 -- MAC_PCS_XXV_DEBOUNCE_CTRL_3 + * and MAC_PCS_XXV_TIMESTAMP_COMP_0 -- MAC_PCS_XXV_TIMESTAMP_COMP_3 + * and MAC_PCS_XXV_GTY_PRE_CURSOR_0 -- MAC_PCS_XXV_GTY_PRE_CURSOR_3 + * and MAC_PCS_XXV_GTY_DIFF_CTL_0 -- MAC_PCS_XXV_GTY_DIFF_CTL_0 + * and MAC_PCS_XXV_GTY_POST_CURSOR_0 -- MAC_PCS_XXV_GTY_POST_CURSOR_3 + */ + if (n_channels <= 4) { + /* Initialize regs/fields for sub-module/channel 0 */ + rf = &p->regs[0]; + + r = get_register(module, MAC_PCS_XXV_DEBOUNCE_CTRL_0); + + rf->mp_reg_debounce_ctrl = r; + rf->mp_field_debounce_ctrl_nt_port_ctrl = + get_field(r, MAC_PCS_XXV_DEBOUNCE_CTRL_0_NT_PORT_CTRL); + + r = get_register(module, MAC_PCS_XXV_TIMESTAMP_COMP_0); + rf->mp_reg_timestamp_comp = r; + rf->mp_field_timestamp_comp_rx_dly = + get_field(r, MAC_PCS_XXV_TIMESTAMP_COMP_0_RX_DLY); + rf->mp_field_timestamp_comp_tx_dly = + get_field(r, MAC_PCS_XXV_TIMESTAMP_COMP_0_TX_DLY); + + /* GTY_PRE_CURSOR */ + r = get_register(p->mp_mod_mac_pcs_xxv, MAC_PCS_XXV_GTY_PRE_CURSOR_0); + rf->mp_reg_gty_pre_cursor = r; + rf->mp_field_gty_pre_cursor_tx_pre_csr = + get_field(r, MAC_PCS_XXV_GTY_PRE_CURSOR_0_TX_PRE_CSR); + + /* GTY_DIFF_CTL */ + r = get_register(module, MAC_PCS_XXV_GTY_DIFF_CTL_0); + rf->mp_reg_gty_diff_ctl = r; + rf->mp_field_gty_gty_diff_ctl_tx_diff_ctl = + get_field(r, MAC_PCS_XXV_GTY_DIFF_CTL_0_TX_DIFF_CTL); + + /* GTY_POST_CURSOR */ + r = get_register(module, MAC_PCS_XXV_GTY_POST_CURSOR_0); + rf->mp_reg_gty_post_cursor = r; + rf->mp_field_gty_post_cursor_tx_post_csr = + get_field(r, MAC_PCS_XXV_GTY_POST_CURSOR_0_TX_POST_CSR); + } + + if (n_channels >= 2) { + /* Initialize regs/fields for sub-module/channel 1 */ + rf = &p->regs[1]; + + r = get_register(module, MAC_PCS_XXV_DEBOUNCE_CTRL_1); + + rf->mp_reg_debounce_ctrl = r; + rf->mp_field_debounce_ctrl_nt_port_ctrl = + get_field(r, MAC_PCS_XXV_DEBOUNCE_CTRL_1_NT_PORT_CTRL); + + r = get_register(module, MAC_PCS_XXV_TIMESTAMP_COMP_1); + rf->mp_reg_timestamp_comp = r; + rf->mp_field_timestamp_comp_rx_dly = + get_field(r, MAC_PCS_XXV_TIMESTAMP_COMP_1_RX_DLY); + rf->mp_field_timestamp_comp_tx_dly = + get_field(r, MAC_PCS_XXV_TIMESTAMP_COMP_1_TX_DLY); + + /* GTY_PRE_CURSOR */ + r = get_register(p->mp_mod_mac_pcs_xxv, MAC_PCS_XXV_GTY_PRE_CURSOR_1); + rf->mp_reg_gty_pre_cursor = r; + rf->mp_field_gty_pre_cursor_tx_pre_csr = + get_field(r, MAC_PCS_XXV_GTY_PRE_CURSOR_1_TX_PRE_CSR); + + /* GTY_DIFF_CTL */ + r = get_register(module, MAC_PCS_XXV_GTY_DIFF_CTL_1); + rf->mp_reg_gty_diff_ctl = r; + rf->mp_field_gty_gty_diff_ctl_tx_diff_ctl = + get_field(r, MAC_PCS_XXV_GTY_DIFF_CTL_1_TX_DIFF_CTL); + + /* GTY_POST_CURSOR */ + r = get_register(module, MAC_PCS_XXV_GTY_POST_CURSOR_1); + rf->mp_reg_gty_post_cursor = r; + rf->mp_field_gty_post_cursor_tx_post_csr = + get_field(r, MAC_PCS_XXV_GTY_POST_CURSOR_1_TX_POST_CSR); + } + + if (n_channels == 4) { + /* Initialize regs/fields for sub-module/channel 2 */ + rf = &p->regs[2]; + + r = get_register(module, MAC_PCS_XXV_DEBOUNCE_CTRL_2); + + rf->mp_reg_debounce_ctrl = r; + rf->mp_field_debounce_ctrl_nt_port_ctrl = + get_field(r, MAC_PCS_XXV_DEBOUNCE_CTRL_2_NT_PORT_CTRL); + + r = get_register(module, MAC_PCS_XXV_TIMESTAMP_COMP_2); + rf->mp_reg_timestamp_comp = r; + rf->mp_field_timestamp_comp_rx_dly = + get_field(r, MAC_PCS_XXV_TIMESTAMP_COMP_2_RX_DLY); + rf->mp_field_timestamp_comp_tx_dly = + get_field(r, MAC_PCS_XXV_TIMESTAMP_COMP_2_TX_DLY); + + /* GTY_PRE_CURSOR */ + r = get_register(p->mp_mod_mac_pcs_xxv, MAC_PCS_XXV_GTY_PRE_CURSOR_2); + rf->mp_reg_gty_pre_cursor = r; + rf->mp_field_gty_pre_cursor_tx_pre_csr = + get_field(r, MAC_PCS_XXV_GTY_PRE_CURSOR_2_TX_PRE_CSR); + + /* GTY_DIFF_CTL */ + r = get_register(module, MAC_PCS_XXV_GTY_DIFF_CTL_2); + rf->mp_reg_gty_diff_ctl = r; + rf->mp_field_gty_gty_diff_ctl_tx_diff_ctl = + get_field(r, MAC_PCS_XXV_GTY_DIFF_CTL_2_TX_DIFF_CTL); + + /* GTY_POST_CURSOR */ + r = get_register(module, MAC_PCS_XXV_GTY_POST_CURSOR_2); + rf->mp_reg_gty_post_cursor = r; + rf->mp_field_gty_post_cursor_tx_post_csr = + get_field(r, MAC_PCS_XXV_GTY_POST_CURSOR_2_TX_POST_CSR); + + /* Initialize regs/fields for sub-module/channel 3 */ + rf = &p->regs[3]; + + r = get_register(module, MAC_PCS_XXV_DEBOUNCE_CTRL_3); + + rf->mp_reg_debounce_ctrl = r; + rf->mp_field_debounce_ctrl_nt_port_ctrl = + get_field(r, MAC_PCS_XXV_DEBOUNCE_CTRL_3_NT_PORT_CTRL); + + r = get_register(module, MAC_PCS_XXV_TIMESTAMP_COMP_3); + rf->mp_reg_timestamp_comp = r; + rf->mp_field_timestamp_comp_rx_dly = + get_field(r, MAC_PCS_XXV_TIMESTAMP_COMP_3_RX_DLY); + rf->mp_field_timestamp_comp_tx_dly = + get_field(r, MAC_PCS_XXV_TIMESTAMP_COMP_3_TX_DLY); + + /* GTY_PRE_CURSOR */ + r = get_register(p->mp_mod_mac_pcs_xxv, MAC_PCS_XXV_GTY_PRE_CURSOR_3); + rf->mp_reg_gty_pre_cursor = r; + rf->mp_field_gty_pre_cursor_tx_pre_csr = + get_field(r, MAC_PCS_XXV_GTY_PRE_CURSOR_3_TX_PRE_CSR); + + /* GTY_DIFF_CTL */ + r = get_register(module, MAC_PCS_XXV_GTY_DIFF_CTL_3); + rf->mp_reg_gty_diff_ctl = r; + rf->mp_field_gty_gty_diff_ctl_tx_diff_ctl = + get_field(r, MAC_PCS_XXV_GTY_DIFF_CTL_3_TX_DIFF_CTL); + + /* GTY_POST_CURSOR */ + r = get_register(module, MAC_PCS_XXV_GTY_POST_CURSOR_3); + rf->mp_reg_gty_post_cursor = r; + rf->mp_field_gty_post_cursor_tx_post_csr = + get_field(r, MAC_PCS_XXV_GTY_POST_CURSOR_3_TX_POST_CSR); + } + + return 0; +} diff --git a/drivers/net/ntnic/nthw/core/nthw_pcie3.c b/drivers/net/ntnic/nthw/core/nthw_pcie3.c new file mode 100644 index 0000000000..533d3046de --- /dev/null +++ b/drivers/net/ntnic/nthw/core/nthw_pcie3.c @@ -0,0 +1,270 @@ +/* + * SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include "ntlog.h" + +#include "nthw_drv.h" +#include "nthw_register.h" + +#include "nthw_pcie3.h" + +#define NTHW_TG_REF_FREQ (250000000ULL) + +nthw_pcie3_t *nthw_pcie3_new(void) +{ + nthw_pcie3_t *p = malloc(sizeof(nthw_pcie3_t)); + + if (p) + memset(p, 0, sizeof(nthw_pcie3_t)); + + return p; +} + +void nthw_pcie3_delete(nthw_pcie3_t *p) +{ + if (p) { + memset(p, 0, sizeof(nthw_pcie3_t)); + free(p); + } +} + +int nthw_pcie3_init(nthw_pcie3_t *p, nthw_fpga_t *p_fpga, int n_instance) +{ + nthw_module_t *mod = nthw_fpga_query_module(p_fpga, MOD_PCIE3, n_instance); + + if (p == NULL) + return mod == NULL ? -1 : 0; + + if (mod == NULL) { + NT_LOG(ERR, NTHW, "%s: PCIE3 %d: no such instance\n", + p_fpga->p_fpga_info->mp_adapter_id_str, n_instance); + return -1; + } + + p->mp_fpga = p_fpga; + p->mn_instance = n_instance; + p->mp_mod_pcie3 = mod; + + /* PCIe3 */ + p->mp_reg_stat_ctrl = nthw_module_get_register(p->mp_mod_pcie3, PCIE3_STAT_CTRL); + p->mp_fld_stat_ctrl_ena = + nthw_register_get_field(p->mp_reg_stat_ctrl, PCIE3_STAT_CTRL_STAT_ENA); + p->mp_fld_stat_ctrl_req = + nthw_register_get_field(p->mp_reg_stat_ctrl, PCIE3_STAT_CTRL_STAT_REQ); + + p->mp_reg_stat_rx = nthw_module_get_register(p->mp_mod_pcie3, PCIE3_STAT_RX); + p->mp_fld_stat_rx_counter = + nthw_register_get_field(p->mp_reg_stat_rx, PCIE3_STAT_RX_COUNTER); + + p->mp_reg_stat_tx = nthw_module_get_register(p->mp_mod_pcie3, PCIE3_STAT_TX); + p->mp_fld_stat_tx_counter = + nthw_register_get_field(p->mp_reg_stat_tx, PCIE3_STAT_TX_COUNTER); + + p->mp_reg_stat_ref_clk = nthw_module_get_register(p->mp_mod_pcie3, PCIE3_STAT_REFCLK); + p->mp_fld_stat_ref_clk_ref_clk = + nthw_register_get_field(p->mp_reg_stat_ref_clk, PCIE3_STAT_REFCLK_REFCLK250); + + p->mp_reg_stat_rq_rdy = nthw_module_get_register(p->mp_mod_pcie3, PCIE3_STAT_RQ_RDY); + p->mp_fld_stat_rq_rdy_counter = + nthw_register_get_field(p->mp_reg_stat_rq_rdy, PCIE3_STAT_RQ_RDY_COUNTER); + + p->mp_reg_stat_rq_vld = nthw_module_get_register(p->mp_mod_pcie3, PCIE3_STAT_RQ_VLD); + p->mp_fld_stat_rq_vld_counter = + nthw_register_get_field(p->mp_reg_stat_rq_vld, PCIE3_STAT_RQ_VLD_COUNTER); + + p->mp_reg_status0 = nthw_module_get_register(p->mp_mod_pcie3, PCIE3_STATUS0); + p->mp_fld_status0_tags_in_use = + nthw_register_get_field(p->mp_reg_status0, PCIE3_STATUS0_TAGS_IN_USE); + + p->mp_reg_rp_to_ep_err = nthw_module_get_register(p->mp_mod_pcie3, PCIE3_RP_TO_EP_ERR); + p->mp_fld_rp_to_ep_err_cor = + nthw_register_get_field(p->mp_reg_rp_to_ep_err, PCIE3_RP_TO_EP_ERR_ERR_COR); + p->mp_fld_rp_to_ep_err_non_fatal = + nthw_register_get_field(p->mp_reg_rp_to_ep_err, PCIE3_RP_TO_EP_ERR_ERR_NONFATAL); + p->mp_fld_rp_to_ep_err_fatal = + nthw_register_get_field(p->mp_reg_rp_to_ep_err, PCIE3_RP_TO_EP_ERR_ERR_FATAL); + + p->mp_reg_ep_to_rp_err = nthw_module_get_register(p->mp_mod_pcie3, PCIE3_EP_TO_RP_ERR); + p->mp_fld_ep_to_rp_err_cor = + nthw_register_get_field(p->mp_reg_ep_to_rp_err, PCIE3_EP_TO_RP_ERR_ERR_COR); + p->mp_fld_ep_to_rp_err_non_fatal = + nthw_register_get_field(p->mp_reg_ep_to_rp_err, PCIE3_EP_TO_RP_ERR_ERR_NONFATAL); + p->mp_fld_ep_to_rp_err_fatal = + nthw_register_get_field(p->mp_reg_ep_to_rp_err, PCIE3_EP_TO_RP_ERR_ERR_FATAL); + + p->mp_reg_sample_time = nthw_module_get_register(p->mp_mod_pcie3, PCIE3_SAMPLE_TIME); + p->mp_fld_sample_time = + nthw_register_get_field(p->mp_reg_sample_time, PCIE3_SAMPLE_TIME_SAMPLE_TIME); + + p->mp_reg_pci_end_point = nthw_module_get_register(p->mp_mod_pcie3, PCIE3_PCI_ENDPOINT); + p->mp_fld_pci_end_point_if_id = + nthw_register_get_field(p->mp_reg_pci_end_point, PCIE3_PCI_ENDPOINT_IF_ID); + p->mp_fld_pci_end_point_send_msg = + nthw_register_get_field(p->mp_reg_pci_end_point, PCIE3_PCI_ENDPOINT_SEND_MSG); + p->mp_fld_pci_end_point_get_msg = + nthw_register_get_field(p->mp_reg_pci_end_point, PCIE3_PCI_ENDPOINT_GET_MSG); + p->mp_fld_pci_end_point_dmaep0_allow_mask = + nthw_register_get_field(p->mp_reg_pci_end_point, + PCIE3_PCI_ENDPOINT_DMA_EP0_ALLOW_MASK); + p->mp_fld_pci_end_point_dmaep1_allow_mask = + nthw_register_get_field(p->mp_reg_pci_end_point, + PCIE3_PCI_ENDPOINT_DMA_EP1_ALLOW_MASK); + + if (p->mp_reg_pci_end_point) + nthw_register_update(p->mp_reg_pci_end_point); + + p->mp_reg_pci_test0 = nthw_module_get_register(p->mp_mod_pcie3, PCIE3_PCI_TEST0); + p->mp_fld_pci_test0 = nthw_register_get_field(p->mp_reg_pci_test0, PCIE3_PCI_TEST0_DATA); + + if (p->mp_reg_pci_test0) + nthw_register_update(p->mp_reg_pci_test0); + + p->mp_reg_pci_test1 = nthw_module_get_register(p->mp_mod_pcie3, PCIE3_PCI_TEST1); + p->mp_fld_pci_test1 = nthw_register_get_field(p->mp_reg_pci_test1, PCIE3_PCI_TEST1_DATA); + + if (p->mp_reg_pci_test1) + nthw_register_update(p->mp_reg_pci_test1); + + p->mp_reg_pci_e3_mark_adr_lsb = + nthw_module_get_register(p->mp_mod_pcie3, PCIE3_MARKADR_LSB); + p->mp_fld_pci_e3_mark_adr_lsb_adr = + nthw_register_get_field(p->mp_reg_pci_e3_mark_adr_lsb, PCIE3_MARKADR_LSB_ADR); + + if (p->mp_reg_pci_e3_mark_adr_lsb) + nthw_register_update(p->mp_reg_pci_e3_mark_adr_lsb); + + p->mp_reg_pci_e3_mark_adr_msb = + nthw_module_get_register(p->mp_mod_pcie3, PCIE3_MARKADR_MSB); + p->mp_fld_pci_e3_mark_adr_msb_adr = + nthw_register_get_field(p->mp_reg_pci_e3_mark_adr_msb, PCIE3_MARKADR_MSB_ADR); + + if (p->mp_reg_pci_e3_mark_adr_msb) + nthw_register_update(p->mp_reg_pci_e3_mark_adr_msb); + + /* Initial setup - disable markerscheme and bifurcation */ + if (p->mp_fld_pci_end_point_dmaep0_allow_mask) + nthw_field_clr_flush(p->mp_fld_pci_end_point_dmaep0_allow_mask); + + if (p->mp_fld_pci_end_point_dmaep1_allow_mask) + nthw_field_clr_flush(p->mp_fld_pci_end_point_dmaep1_allow_mask); + + if (p->mp_fld_pci_e3_mark_adr_lsb_adr) + nthw_field_set_val_flush32(p->mp_fld_pci_e3_mark_adr_lsb_adr, 0UL); + + if (p->mp_fld_pci_e3_mark_adr_msb_adr) + nthw_field_set_val_flush32(p->mp_fld_pci_e3_mark_adr_msb_adr, 0UL); + + if (p->mp_fld_pci_end_point_dmaep0_allow_mask) + nthw_field_set_flush(p->mp_fld_pci_end_point_dmaep0_allow_mask); + + if (p->mp_fld_pci_end_point_dmaep1_allow_mask) + nthw_field_clr_flush(p->mp_fld_pci_end_point_dmaep1_allow_mask); + + return 0; +}; + +int nthw_pcie3_trigger_sample_time(nthw_pcie3_t *p) +{ + nthw_field_set_val_flush32(p->mp_fld_sample_time, 0xfee1dead); + + return 0; +} + +int nthw_pcie3_stat_req_enable(nthw_pcie3_t *p) +{ + nthw_field_set_all(p->mp_fld_stat_ctrl_ena); + nthw_field_set_all(p->mp_fld_stat_ctrl_req); + nthw_field_flush_register(p->mp_fld_stat_ctrl_req); + return 0; +} + +int nthw_pcie3_stat_req_disable(nthw_pcie3_t *p) +{ + nthw_field_clr_all(p->mp_fld_stat_ctrl_ena); + nthw_field_set_all(p->mp_fld_stat_ctrl_req); + nthw_field_flush_register(p->mp_fld_stat_ctrl_req); + return 0; +} + +int nthw_pcie3_get_stat(nthw_pcie3_t *p, uint32_t *p_rx_cnt, uint32_t *p_tx_cnt, + uint32_t *p_ref_clk_cnt, uint32_t *p_tg_unit_size, uint32_t *p_tg_ref_freq, + uint32_t *p_tag_use_cnt, uint32_t *p_rq_rdy_cnt, uint32_t *p_rq_vld_cnt) +{ + *p_rx_cnt = nthw_field_get_updated(p->mp_fld_stat_rx_counter); + *p_tx_cnt = nthw_field_get_updated(p->mp_fld_stat_tx_counter); + + *p_ref_clk_cnt = nthw_field_get_updated(p->mp_fld_stat_ref_clk_ref_clk); + + *p_tg_unit_size = NTHW_TG_CNT_SIZE; + *p_tg_ref_freq = NTHW_TG_REF_FREQ; + + *p_tag_use_cnt = nthw_field_get_updated(p->mp_fld_status0_tags_in_use); + + *p_rq_rdy_cnt = nthw_field_get_updated(p->mp_fld_stat_rq_rdy_counter); + *p_rq_vld_cnt = nthw_field_get_updated(p->mp_fld_stat_rq_vld_counter); + + return 0; +} + +int nthw_pcie3_get_stat_rate(nthw_pcie3_t *p, uint64_t *p_pci_rx_rate, uint64_t *p_pci_tx_rate, + uint64_t *p_ref_clk_cnt, uint64_t *p_tag_use_cnt, + uint64_t *p_pci_nt_bus_util, uint64_t *p_pci_xil_bus_util) +{ + uint32_t rx_cnt, tx_cnt, ref_clk_cnt; + uint32_t tg_unit_size, tg_ref_freq; + uint32_t tag_use_cnt, rq_rdy_cnt, rq_vld_cnt; + + nthw_pcie3_get_stat(p, &rx_cnt, &tx_cnt, &ref_clk_cnt, &tg_unit_size, &tg_ref_freq, + &tag_use_cnt, &rq_rdy_cnt, &rq_vld_cnt); + + if (ref_clk_cnt) { + uint64_t nt_bus_util, xil_bus_util; + uint64_t rx_rate, tx_rate; + + rx_rate = ((uint64_t)rx_cnt * tg_unit_size * tg_ref_freq) / (uint64_t)ref_clk_cnt; + *p_pci_rx_rate = rx_rate; + + tx_rate = ((uint64_t)tx_cnt * tg_unit_size * tg_ref_freq) / (uint64_t)ref_clk_cnt; + *p_pci_tx_rate = tx_rate; + + *p_ref_clk_cnt = ref_clk_cnt; + + *p_tag_use_cnt = tag_use_cnt; + + nt_bus_util = ((uint64_t)rq_vld_cnt * 1000000ULL) / (uint64_t)ref_clk_cnt; + *p_pci_nt_bus_util = nt_bus_util; + xil_bus_util = ((uint64_t)rq_rdy_cnt * 1000000ULL) / (uint64_t)ref_clk_cnt; + *p_pci_xil_bus_util = xil_bus_util; + + } else { + *p_ref_clk_cnt = 0; + *p_pci_nt_bus_util = 0; + *p_pci_xil_bus_util = 0; + } + + return 0; +} + +int nthw_pcie3_end_point_counters_sample_pre(nthw_pcie3_t *p, + struct nthw_hif_end_point_counters *epc) +{ + NT_LOG(DBG, NTHW, "%s:%u: empty function\n", __func__, __LINE__); + + (void)p; + (void)epc; + + return 0; +} + +int nthw_pcie3_end_point_counters_sample_post(nthw_pcie3_t *p, + struct nthw_hif_end_point_counters *epc) +{ + NT_LOG(DBG, NTHW, "%s:%u:\n", __func__, __LINE__); + assert(epc); + nthw_pcie3_get_stat_rate(p, &epc->cur_tx, &epc->cur_rx, &epc->n_ref_clk_cnt, + &epc->n_tags_in_use, &epc->cur_pci_nt_util, + &epc->cur_pci_xil_util); + return 0; +} diff --git a/drivers/net/ntnic/nthw/core/nthw_sdc.c b/drivers/net/ntnic/nthw/core/nthw_sdc.c new file mode 100644 index 0000000000..7666af7e5a --- /dev/null +++ b/drivers/net/ntnic/nthw/core/nthw_sdc.c @@ -0,0 +1,176 @@ +/* + * SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include "ntlog.h" + +#include "nthw_drv.h" +#include "nthw_register.h" + +#include "nthw_sdc.h" + +nthw_sdc_t *nthw_sdc_new(void) +{ + nthw_sdc_t *p = malloc(sizeof(nthw_sdc_t)); + + if (p) + memset(p, 0, sizeof(nthw_sdc_t)); + + return p; +} + +void nthw_sdc_delete(nthw_sdc_t *p) +{ + if (p) { + memset(p, 0, sizeof(nthw_sdc_t)); + free(p); + } +} + +int nthw_sdc_init(nthw_sdc_t *p, nthw_fpga_t *p_fpga, int n_instance) +{ + const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str; + nthw_module_t *mod = nthw_fpga_query_module(p_fpga, MOD_SDC, n_instance); + + if (p == NULL) + return mod == NULL ? -1 : 0; + + if (mod == NULL) { + NT_LOG(ERR, NTHW, "%s: SDC %d: no such instance\n", p_adapter_id_str, n_instance); + return -1; + } + + p->mp_fpga = p_fpga; + p->mn_instance = n_instance; + p->mp_mod_sdc = mod; + + { + nthw_register_t *p_reg; + + p_reg = nthw_module_get_register(p->mp_mod_sdc, SDC_CTRL); + p->mp_fld_ctrl_init = nthw_register_get_field(p_reg, SDC_CTRL_INIT); + p->mp_fld_ctrl_run_test = nthw_register_get_field(p_reg, SDC_CTRL_RUN_TEST); + p->mp_fld_ctrl_stop_client = nthw_register_get_field(p_reg, SDC_CTRL_STOP_CLIENT); + p->mp_fld_ctrl_test_enable = nthw_register_get_field(p_reg, SDC_CTRL_TEST_EN); + + p_reg = nthw_module_get_register(p->mp_mod_sdc, SDC_STAT); + p->mp_fld_stat_calib = nthw_register_get_field(p_reg, SDC_STAT_CALIB); + p->mp_fld_stat_cell_cnt_stopped = + nthw_register_get_field(p_reg, SDC_STAT_CELL_CNT_STOPPED); + p->mp_fld_stat_err_found = nthw_register_get_field(p_reg, SDC_STAT_ERR_FOUND); + p->mp_fld_stat_init_done = nthw_register_get_field(p_reg, SDC_STAT_INIT_DONE); + p->mp_fld_stat_mmcm_lock = nthw_register_get_field(p_reg, SDC_STAT_MMCM_LOCK); + p->mp_fld_stat_pll_lock = nthw_register_get_field(p_reg, SDC_STAT_PLL_LOCK); + p->mp_fld_stat_resetting = nthw_register_get_field(p_reg, SDC_STAT_RESETTING); + + p_reg = nthw_module_get_register(p->mp_mod_sdc, SDC_CELL_CNT); + p->mp_fld_cell_cnt = nthw_register_get_field(p_reg, SDC_CELL_CNT_CELL_CNT); + + p_reg = nthw_module_get_register(p->mp_mod_sdc, SDC_CELL_CNT_PERIOD); + p->mp_fld_cell_cnt_period = + nthw_register_get_field(p_reg, SDC_CELL_CNT_PERIOD_CELL_CNT_PERIOD); + + p_reg = nthw_module_get_register(p->mp_mod_sdc, SDC_FILL_LVL); + p->mp_fld_fill_level = nthw_register_get_field(p_reg, SDC_FILL_LVL_FILL_LVL); + + p_reg = nthw_module_get_register(p->mp_mod_sdc, SDC_MAX_FILL_LVL); + p->mp_fld_max_fill_level = + nthw_register_get_field(p_reg, SDC_MAX_FILL_LVL_MAX_FILL_LVL); + } + return 0; +} + +int nthw_sdc_get_states(nthw_sdc_t *p, uint64_t *pn_result_mask) +{ + int n_err_cnt = 0; + uint64_t n_mask = 0; + uint32_t val; + uint32_t val_mask; + int n_val_width; + + if (!p || !pn_result_mask) + return -1; + + val = nthw_field_get_updated(p->mp_fld_stat_calib); + n_val_width = nthw_field_get_bit_width(p->mp_fld_stat_calib); + val_mask = ((1 << n_val_width) - 1); + n_mask = (n_mask << n_val_width) | (val & val_mask); + + if (val != val_mask) + n_err_cnt++; + + val = nthw_field_get_updated(p->mp_fld_stat_init_done); + n_val_width = nthw_field_get_bit_width(p->mp_fld_stat_init_done); + val_mask = ((1 << n_val_width) - 1); + n_mask = (n_mask << n_val_width) | (val & val_mask); + + if (val != val_mask) + n_err_cnt++; + + val = nthw_field_get_updated(p->mp_fld_stat_mmcm_lock); + n_val_width = nthw_field_get_bit_width(p->mp_fld_stat_mmcm_lock); + val_mask = ((1 << n_val_width) - 1); + n_mask = (n_mask << n_val_width) | (val & val_mask); + + if (val != val_mask) + n_err_cnt++; + + val = nthw_field_get_updated(p->mp_fld_stat_pll_lock); + n_val_width = nthw_field_get_bit_width(p->mp_fld_stat_pll_lock); + val_mask = ((1 << n_val_width) - 1); + n_mask = (n_mask << n_val_width) | (val & val_mask); + + if (val != val_mask) + n_err_cnt++; + + val = nthw_field_get_updated(p->mp_fld_stat_resetting); + n_val_width = nthw_field_get_bit_width(p->mp_fld_stat_resetting); + val_mask = ((1 << n_val_width) - 1); + n_mask = (n_mask << n_val_width) | (val & val_mask); + + if (val != 0) + n_err_cnt++; + + if (pn_result_mask) + *pn_result_mask = n_mask; + + return n_err_cnt; /* 0 = all ok */ +} + +int nthw_sdc_wait_states(nthw_sdc_t *p, const int n_poll_iterations, const int n_poll_interval) +{ + int res; + int n_err_cnt = 0; + + res = nthw_field_wait_set_all32(p->mp_fld_stat_calib, n_poll_iterations, n_poll_interval); + + if (res) + n_err_cnt++; + + res = nthw_field_wait_set_all32(p->mp_fld_stat_init_done, n_poll_iterations, + n_poll_interval); + + if (res) + n_err_cnt++; + + res = nthw_field_wait_set_all32(p->mp_fld_stat_mmcm_lock, n_poll_iterations, + n_poll_interval); + + if (res) + n_err_cnt++; + + res = nthw_field_wait_set_all32(p->mp_fld_stat_pll_lock, n_poll_iterations, + n_poll_interval); + + if (res) + n_err_cnt++; + + res = nthw_field_wait_clr_all32(p->mp_fld_stat_resetting, n_poll_iterations, + n_poll_interval); + + if (res) + n_err_cnt++; + + return n_err_cnt; /* 0 = all ok */ +} diff --git a/drivers/net/ntnic/nthw/core/nthw_si5340.c b/drivers/net/ntnic/nthw/core/nthw_si5340.c new file mode 100644 index 0000000000..9f5a801ddf --- /dev/null +++ b/drivers/net/ntnic/nthw/core/nthw_si5340.c @@ -0,0 +1,205 @@ +/* + * SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + * + * This file implements Si5340 clock synthesizer support. + * The implementation is generic and must be tailored to a specific use by the + * correct initialization data. + */ + +#include "nt_util.h" +#include "ntlog.h" + +#include "nthw_drv.h" +#include "nthw_register.h" + +#include "nthw_si5340.h" + +#define SI5340_WAIT_US(x) nt_os_wait_usec(x) + +#define SI5340_LOG_DEBUG(...) NT_LOG(DBG, NTHW, __VA_ARGS__) +#define SI5340_LOG_INFO(...) NT_LOG(INF, NTHW, __VA_ARGS__) +#define SI5340_LOG_WARN(...) NT_LOG(WRN, NTHW, __VA_ARGS__) +#define SI5340_LOG_ERROR(...) NT_LOG(ERR, NTHW, __VA_ARGS__) + +#define SI5340_PAGE_REG_ADDR (0x01) + +nthw_si5340_t *nthw_si5340_new(void) +{ + nthw_si5340_t *p = malloc(sizeof(nthw_si5340_t)); + + if (p) + memset(p, 0, sizeof(nthw_si5340_t)); + + return p; +} + +int nthw_si5340_init(nthw_si5340_t *p, nthw_iic_t *p_nthw_iic, uint8_t n_iic_addr) +{ + uint8_t data; + + p->mp_nthw_iic = p_nthw_iic; + p->mn_iic_addr = n_iic_addr; + p->mn_clk_cfg = -1; + + p->m_si5340_page = 0; + data = p->m_si5340_page; + nthw_iic_write_data(p->mp_nthw_iic, p->mn_iic_addr, SI5340_PAGE_REG_ADDR, 1, &data); + + return 0; +} + +void nthw_si5340_delete(nthw_si5340_t *p) +{ + if (p) { + memset(p, 0, sizeof(nthw_si5340_t)); + free(p); + } +} + +/* + * Read access (via I2C) to the clock synthesizer IC. The IC is located at I2C + * 7bit address 0x74 + */ +static uint8_t nthw_si5340_read(nthw_si5340_t *p, uint16_t reg_addr) +{ + const uint8_t offset_adr = (uint8_t)(reg_addr & 0xff); + uint8_t page = (uint8_t)((reg_addr >> 8) & 0xff); + uint8_t data; + + /* check if we are on the right page */ + if (page != p->m_si5340_page) { + nthw_iic_write_data(p->mp_nthw_iic, p->mn_iic_addr, SI5340_PAGE_REG_ADDR, 1, + &page); + p->m_si5340_page = page; + } + + nthw_iic_read_data(p->mp_nthw_iic, p->mn_iic_addr, offset_adr, 1, &data); + return data; +} + +/* + * Write access (via I2C) to the clock synthesizer IC. The IC is located at I2C + * 7 bit address 0x74 + */ +static int nthw_si5340_write(nthw_si5340_t *p, uint16_t reg_addr, uint8_t data) +{ + const uint8_t offset_adr = (uint8_t)(reg_addr & 0xff); + uint8_t page = (uint8_t)((reg_addr >> 8) & 0xff); + + /* check if we are on the right page */ + if (page != p->m_si5340_page) { + nthw_iic_write_data(p->mp_nthw_iic, p->mn_iic_addr, SI5340_PAGE_REG_ADDR, 1, + &page); + p->m_si5340_page = page; + } + + nthw_iic_write_data(p->mp_nthw_iic, p->mn_iic_addr, offset_adr, 1, &data); + + return 0; +} + +static int nthw_si5340_cfg(nthw_si5340_t *p, const void *p_data, int data_cnt, + clk_profile_data_fmt_t data_format) +{ + const char *const p_adapter_id_str = + p->mp_nthw_iic->mp_fpga->p_fpga_info->mp_adapter_id_str; + int i; + uint16_t addr; + uint8_t value; + uint8_t ctrl_value; + + NT_LOG(DBG, NTHW, "%s: %s: data_cnt = %d, data_format = %d\n", p_adapter_id_str, __func__, + data_cnt, data_format); + + for (i = 0; i < data_cnt; i++) { + if (data_format == clk_profile_data_fmt_1) { + addr = ((const clk_profile_data_fmt1_t *)p_data)->reg_addr; + value = ((const clk_profile_data_fmt1_t *)p_data)->reg_val; + p_data = ((const clk_profile_data_fmt1_t *)p_data) + 1; + + } else if (data_format == clk_profile_data_fmt_2) { + addr = (uint16_t)(((const clk_profile_data_fmt2_t *)p_data)->reg_addr); + value = ((const clk_profile_data_fmt2_t *)p_data)->reg_val; + p_data = ((const clk_profile_data_fmt2_t *)p_data) + 1; + + } else { + NT_LOG(ERR, NTHW, "%s: Unhandled Si5340 data format (%d)\n", + p_adapter_id_str, data_format); + return -1; + } + + if (addr == 0x0006) { + /* Wait 300ms before continuing. See NT200E3-2-PTP_U23_Si5340_adr0_v2.h */ + nt_os_wait_usec(300000); + } + + nthw_si5340_write(p, addr, value); + + if (addr == 0x001C) { + /* skip readback for "soft reset" register */ + continue; + } + + ctrl_value = nthw_si5340_read(p, addr); + + if (ctrl_value != value) { + NT_LOG(ERR, NTHW, + "%s: Si5340 configuration readback check failed. (Addr = 0x%04X, Write = 0x%02X, Read = 0x%02X)\n", + p_adapter_id_str, addr, value, ctrl_value); + return -1; + } + } + + return 0; +} + +int nthw_si5340_config(nthw_si5340_t *p, const void *p_data, int data_cnt, + clk_profile_data_fmt_t data_format) +{ + const char *const p_adapter_id_str = + p->mp_nthw_iic->mp_fpga->p_fpga_info->mp_adapter_id_str; + int i; + bool success = false; + uint8_t status, sticky; + uint8_t design_id[9]; + + (void)nthw_si5340_cfg(p, p_data, data_cnt, data_format); + + /* Check if DPLL is locked and SYS is calibrated */ + for (i = 0; i < 5; i++) { + status = nthw_si5340_read(p, 0x0c); + sticky = nthw_si5340_read(p, 0x11); + nthw_si5340_write(p, 0x11, 0x00); + + if (((status & 0x09) == 0x00) && ((sticky & 0x09) == 0x00)) { + success = true; + break; + } + + nt_os_wait_usec(1000000); /* 1 sec */ + } + + if (!success) { + NT_LOG(ERR, NTHW, + "%s: Si5340 configuration failed. (Status = 0x%02X, Sticky = 0x%02X)\n", + p_adapter_id_str, status, sticky); + return -1; + } + + for (i = 0; i < (int)sizeof(design_id) - 1; i++) + design_id[i] = nthw_si5340_read(p, (uint16_t)(0x26B + i)); + + design_id[sizeof(design_id) - 1] = 0; + + (void)design_id;/* Only used in debug mode */ + NT_LOG(DBG, NTHW, "%s: Si5340.Design_id = %s\n", p_adapter_id_str, design_id); + + return 0; +} + +int nthw_si5340_config_fmt2(nthw_si5340_t *p, const clk_profile_data_fmt2_t *p_data, + const int data_cnt) +{ + return nthw_si5340_config(p, p_data, data_cnt, clk_profile_data_fmt_2); +} diff --git a/drivers/net/ntnic/nthw/core/nthw_spi_v3.c b/drivers/net/ntnic/nthw/core/nthw_spi_v3.c new file mode 100644 index 0000000000..1d49eea36b --- /dev/null +++ b/drivers/net/ntnic/nthw/core/nthw_spi_v3.c @@ -0,0 +1,356 @@ +/* + * SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include "ntlog.h" + +#include "nthw_drv.h" +#include "nthw_fpga.h" + +#include "nthw_spi_v3.h" + +#include + +#undef SPI_V3_DEBUG_PRINT + +nthw_spi_v3_t *nthw_spi_v3_new(void) +{ + nthw_spi_v3_t *p = malloc(sizeof(nthw_spi_v3_t)); + + if (p) + memset(p, 0, sizeof(nthw_spi_v3_t)); + + return p; +} + +int nthw_spi_v3_set_timeout(nthw_spi_v3_t *p, int time_out) +{ + p->m_time_out = time_out; + return 0; +} + +/* + * Wait until Tx data have been sent after they have been placed in the Tx FIFO. + */ +static int wait_for_tx_data_sent(nthw_spim_t *p_spim_mod, uint64_t time_out) +{ + int result; + bool empty; + uint64_t start_time; + uint64_t cur_time; + start_time = nt_os_get_time_monotonic_counter(); + + while (true) { + nt_os_wait_usec(1000); /* Every 1ms */ + + result = nthw_spim_get_tx_fifo_empty(p_spim_mod, &empty); + + if (result != 0) { + NT_LOG(WRN, NTHW, "nthw_spim_get_tx_fifo_empty failed\n"); + return result; + } + + if (empty) + break; + + cur_time = nt_os_get_time_monotonic_counter(); + + if ((cur_time - start_time) > time_out) { + NT_LOG(WRN, NTHW, "%s: Timed out\n", __func__); + return -1; + } + } + + return 0; +} + +/* + * Wait until Rx data have been received. + */ +static int wait_for_rx_data_ready(nthw_spis_t *p_spis_mod, uint64_t time_out) +{ + int result; + bool empty; + uint64_t start_time; + uint64_t cur_time; + start_time = nt_os_get_time_monotonic_counter(); + + /* Wait for data to become ready in the Rx FIFO */ + while (true) { + nt_os_wait_usec(10000); /* Every 10ms */ + + result = nthw_spis_get_rx_fifo_empty(p_spis_mod, &empty); + + if (result != 0) { + NT_LOG(WRN, NTHW, "nthw_spis_get_rx_empty failed\n"); + return result; + } + + if (!empty) + break; + + cur_time = nt_os_get_time_monotonic_counter(); + + if ((cur_time - start_time) > time_out) { + NT_LOG(WRN, NTHW, "%s: Timed out\n", __func__); + return -1; + } + } + + return 0; +} + +#ifdef SPI_V3_DEBUG_PRINT +static void dump_hex(uint8_t *p_data, uint16_t count) +{ + int i; + int j = 0; + char tmp_str[128]; + + for (i = 0; i < count; i++) { + sprintf(&tmp_str[j * 3], "%02X ", *(p_data++)); + j++; + + if (j == 16 || i == count - 1) { + tmp_str[j * 3 - 1] = '\0'; + NT_LOG(DBG, NTHW, " %s\n", tmp_str); + j = 0; + } + } +} +#endif + +int nthw_spi_v3_init(nthw_spi_v3_t *p, nthw_fpga_t *p_fpga, int n_instance_no) +{ + const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str; + uint32_t result; + + p->mn_instance_no = n_instance_no; + + nthw_spi_v3_set_timeout(p, 1); + + /* Initialize SPIM module */ + p->mp_spim_mod = nthw_spim_new(); + + result = nthw_spim_init(p->mp_spim_mod, p_fpga, n_instance_no); + + if (result != 0) + NT_LOG(ERR, NTHW, "%s: nthw_spis_init failed: %d\n", p_adapter_id_str, result); + + /* Initialize SPIS module */ + p->mp_spis_mod = nthw_spis_new(); + + result = nthw_spis_init(p->mp_spis_mod, p_fpga, n_instance_no); + + if (result != 0) + NT_LOG(ERR, NTHW, "%s: nthw_spim_init failed: %d\n", p_adapter_id_str, result); + + /* Reset SPIM and SPIS modules */ + result = nthw_spim_reset(p->mp_spim_mod); + + if (result != 0) + NT_LOG(ERR, NTHW, "%s: nthw_spim_reset failed: %d\n", p_adapter_id_str, result); + + result = nthw_spis_reset(p->mp_spis_mod); + + if (result != 0) + NT_LOG(ERR, NTHW, "%s: nthw_spis_reset failed: %d\n", p_adapter_id_str, result); + + return result; +} + +/* + * Send Tx data using the SPIM module and receive any data using the SPIS module. + * The data are sent and received being wrapped into a SPI v3 container. + */ +int nthw_spi_v3_transfer(nthw_spi_v3_t *p, uint16_t opcode, struct tx_rx_buf *tx_buf, + struct tx_rx_buf *rx_buf) +{ + const uint16_t max_payload_rx_size = rx_buf->size; + int result = 0; + +#pragma pack(push, 1) + union { + uint32_t raw; + + struct { + uint16_t opcode; + uint16_t size; + }; + } spi_tx_hdr; + + union { + uint32_t raw; + + struct { + uint16_t error_code; + uint16_t size; + }; + } spi_rx_hdr; +#pragma pack(pop) + +#ifdef SPI_V3_DEBUG_PRINT + NT_LOG(DBG, NTHW, "%s: Started\n", __func__); +#endif + + /* Disable transmission from Tx FIFO */ + result = nthw_spim_enable(p->mp_spim_mod, false); + + if (result != 0) { + NT_LOG(WRN, NTHW, "nthw_spim_enable failed\n"); + return result; + } + + /* Enable SPIS module */ + result = nthw_spis_enable(p->mp_spis_mod, true); + + if (result != 0) { + NT_LOG(WRN, NTHW, "nthw_spis_enable failed\n"); + return result; + } + + /* Put data into Tx FIFO */ + spi_tx_hdr.opcode = opcode; + spi_tx_hdr.size = tx_buf->size; + +#ifdef SPI_V3_DEBUG_PRINT + NT_LOG(DBG, NTHW, "Opcode=0x%04X tx_bufSize=0x%04X rx_bufSize=0x%04X\n", opcode, + tx_buf->size, rx_buf->size); + +#endif /* SPI_V3_DEBUG_PRINT */ + + result = nthw_spim_write_tx_fifo(p->mp_spim_mod, htonl(spi_tx_hdr.raw)); + + if (result != 0) { + NT_LOG(WRN, NTHW, "nthw_spim_write_tx_fifo failed\n"); + return result; + } + + { + uint8_t *tx_data = (uint8_t *)tx_buf->p_buf; + uint16_t tx_size = tx_buf->size; + uint16_t count; + uint32_t value; + + while (tx_size > 0) { + if (tx_size > 4) { + count = 4; + + } else { + count = tx_size; + value = 0; + } + + memcpy(&value, tx_data, count); + + result = nthw_spim_write_tx_fifo(p->mp_spim_mod, htonl(value)); + + if (result != 0) { + NT_LOG(WRN, NTHW, "nthw_spim_write_tx_fifo failed\n"); + return result; + } + + tx_size = (uint16_t)(tx_size - count); + tx_data += count; + } + } + + /* Enable Tx FIFO */ + result = nthw_spim_enable(p->mp_spim_mod, true); + + if (result != 0) { + NT_LOG(WRN, NTHW, "nthw_spim_enable failed\n"); + return result; + } + + result = wait_for_tx_data_sent(p->mp_spim_mod, p->m_time_out); + + if (result != 0) + return result; + +#ifdef SPI_V3_DEBUG_PRINT + NT_LOG(DBG, NTHW, "%s: SPI header and payload data have been sent\n", __func__); +#endif + + { + /* Start receiving data */ + uint16_t rx_size = + sizeof(spi_rx_hdr.raw); /* The first data to read is the header */ + uint8_t *rx_data = (uint8_t *)rx_buf->p_buf; + bool rx_hdr_read = false; + + rx_buf->size = 0; + + while (true) { + uint16_t count; + uint32_t value; + + if (!rx_hdr_read) { /* Read the header */ + result = wait_for_rx_data_ready(p->mp_spis_mod, p->m_time_out); + + if (result != 0) + return result; + + result = nthw_spis_read_rx_fifo(p->mp_spis_mod, &spi_rx_hdr.raw); + + if (result != 0) { + NT_LOG(WRN, NTHW, "nthw_spis_read_rx_fifo failed\n"); + return result; + } + + spi_rx_hdr.raw = ntohl(spi_rx_hdr.raw); + rx_size = spi_rx_hdr.size; + rx_hdr_read = true; /* Next time read payload */ + +#ifdef SPI_V3_DEBUG_PRINT + NT_LOG(DBG, NTHW, + " spi_rx_hdr.error_code = 0x%04X, spi_rx_hdr.size = 0x%04X\n", + spi_rx_hdr.error_code, spi_rx_hdr.size); +#endif + + if (spi_rx_hdr.error_code != 0) { + result = -1; /* NT_ERROR_AVR_OPCODE_RETURNED_ERROR; */ + break; + } + + if (rx_size > max_payload_rx_size) { + result = 1; /* NT_ERROR_AVR_RX_BUFFER_TOO_SMALL; */ + break; + } + + } else {/* Read the payload */ + count = (uint16_t)(rx_size < 4U ? rx_size : 4U); + + if (count == 0) + break; + + result = wait_for_rx_data_ready(p->mp_spis_mod, p->m_time_out); + + if (result != 0) + return result; + + result = nthw_spis_read_rx_fifo(p->mp_spis_mod, &value); + + if (result != 0) { + NT_LOG(WRN, NTHW, "nthw_spis_read_rx_fifo failed\n"); + return result; + } + + value = ntohl(value); /* Convert to host endian */ + memcpy(rx_data, &value, count); + rx_buf->size = (uint16_t)(rx_buf->size + count); + rx_size = (uint16_t)(rx_size - count); + rx_data += count; + } + } + } + +#ifdef SPI_V3_DEBUG_PRINT + NT_LOG(DBG, NTHW, " RxData: %d\n", rx_buf->size); + dump_hex(rx_buf->p_buf, rx_buf->size); + NT_LOG(DBG, NTHW, "%s: Ended: %d\n", __func__, result); +#endif + + return result; +} diff --git a/drivers/net/ntnic/nthw/core/nthw_spim.c b/drivers/net/ntnic/nthw/core/nthw_spim.c new file mode 100644 index 0000000000..ffe4330472 --- /dev/null +++ b/drivers/net/ntnic/nthw/core/nthw_spim.c @@ -0,0 +1,121 @@ +/* + * SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include "ntlog.h" + +#include "nthw_drv.h" +#include "nthw_register.h" + +#include "nthw_spim.h" + +nthw_spim_t *nthw_spim_new(void) +{ + nthw_spim_t *p = malloc(sizeof(nthw_spim_t)); + + if (p) + memset(p, 0, sizeof(nthw_spim_t)); + + return p; +} + +int nthw_spim_init(nthw_spim_t *p, nthw_fpga_t *p_fpga, int n_instance) +{ + const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str; + nthw_module_t *mod = nthw_fpga_query_module(p_fpga, MOD_SPIM, n_instance); + + if (p == NULL) + return mod == NULL ? -1 : 0; + + if (mod == NULL) { + NT_LOG(ERR, NTHW, "%s: SPIM %d: no such instance\n", p_adapter_id_str, n_instance); + return -1; + } + + p->mp_fpga = p_fpga; + p->mn_instance = n_instance; + p->mp_mod_spim = mod; + + /* SPIM is a primary communication channel - turn off debug by default */ + nthw_module_set_debug_mode(p->mp_mod_spim, 0x00); + + p->mp_reg_srr = nthw_module_get_register(p->mp_mod_spim, SPIM_SRR); + p->mp_fld_srr_rst = nthw_register_get_field(p->mp_reg_srr, SPIM_SRR_RST); + + p->mp_reg_cr = nthw_module_get_register(p->mp_mod_spim, SPIM_CR); + p->mp_fld_cr_loop = nthw_register_get_field(p->mp_reg_cr, SPIM_CR_LOOP); + p->mp_fld_cr_en = nthw_register_get_field(p->mp_reg_cr, SPIM_CR_EN); + p->mp_fld_cr_txrst = nthw_register_get_field(p->mp_reg_cr, SPIM_CR_TXRST); + p->mp_fld_cr_rxrst = nthw_register_get_field(p->mp_reg_cr, SPIM_CR_RXRST); + + p->mp_reg_sr = nthw_module_get_register(p->mp_mod_spim, SPIM_SR); + p->mp_fld_sr_done = nthw_register_get_field(p->mp_reg_sr, SPIM_SR_DONE); + p->mp_fld_sr_txempty = nthw_register_get_field(p->mp_reg_sr, SPIM_SR_TXEMPTY); + p->mp_fld_sr_rxempty = nthw_register_get_field(p->mp_reg_sr, SPIM_SR_RXEMPTY); + p->mp_fld_sr_txfull = nthw_register_get_field(p->mp_reg_sr, SPIM_SR_TXFULL); + p->mp_fld_sr_rxfull = nthw_register_get_field(p->mp_reg_sr, SPIM_SR_RXFULL); + p->mp_fld_sr_txlvl = nthw_register_get_field(p->mp_reg_sr, SPIM_SR_TXLVL); + p->mp_fld_sr_rxlvl = nthw_register_get_field(p->mp_reg_sr, SPIM_SR_RXLVL); + + p->mp_reg_dtr = nthw_module_get_register(p->mp_mod_spim, SPIM_DTR); + p->mp_fld_dtr_dtr = nthw_register_get_field(p->mp_reg_dtr, SPIM_DTR_DTR); + + p->mp_reg_drr = nthw_module_get_register(p->mp_mod_spim, SPIM_DRR); + p->mp_fld_drr_drr = nthw_register_get_field(p->mp_reg_drr, SPIM_DRR_DRR); + + p->mp_reg_cfg = nthw_module_get_register(p->mp_mod_spim, SPIM_CFG); + p->mp_fld_cfg_pre = nthw_register_get_field(p->mp_reg_cfg, SPIM_CFG_PRE); + + p->mp_reg_cfg_clk = nthw_module_query_register(p->mp_mod_spim, SPIM_CFG_CLK); + p->mp_fld_cfg_clk_mode = nthw_register_query_field(p->mp_reg_cfg, SPIM_CFG_CLK_MODE); + + return 0; +} + +void nthw_spim_delete(nthw_spim_t *p) +{ + if (p) { + memset(p, 0, sizeof(nthw_spim_t)); + free(p); + } +} + +uint32_t nthw_spim_reset(nthw_spim_t *p) +{ + nthw_register_update(p->mp_reg_srr); + nthw_field_set_val32(p->mp_fld_srr_rst, 0x0A); /* 0x0A hardcoded value - see doc */ + nthw_register_flush(p->mp_reg_srr, 1); + + return 0; +} + +uint32_t nthw_spim_enable(nthw_spim_t *p, bool b_enable) +{ + nthw_field_update_register(p->mp_fld_cr_en); + + if (b_enable) + nthw_field_set_all(p->mp_fld_cr_en); + + else + nthw_field_clr_all(p->mp_fld_cr_en); + + nthw_field_flush_register(p->mp_fld_cr_en); + + return 0; +} + +uint32_t nthw_spim_write_tx_fifo(nthw_spim_t *p, uint32_t n_data) +{ + nthw_field_set_val_flush32(p->mp_fld_dtr_dtr, n_data); + return 0; +} + +uint32_t nthw_spim_get_tx_fifo_empty(nthw_spim_t *p, bool *pb_empty) +{ + assert(pb_empty); + + *pb_empty = nthw_field_get_updated(p->mp_fld_sr_txempty) ? true : false; + + return 0; +} diff --git a/drivers/net/ntnic/nthw/core/nthw_spis.c b/drivers/net/ntnic/nthw/core/nthw_spis.c new file mode 100644 index 0000000000..2915d71bf9 --- /dev/null +++ b/drivers/net/ntnic/nthw/core/nthw_spis.c @@ -0,0 +1,129 @@ +/* + * SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include "ntlog.h" + +#include "nthw_drv.h" +#include "nthw_register.h" + +#include "nthw_spis.h" + +nthw_spis_t *nthw_spis_new(void) +{ + nthw_spis_t *p = malloc(sizeof(nthw_spis_t)); + + if (p) + memset(p, 0, sizeof(nthw_spis_t)); + + return p; +} + +int nthw_spis_init(nthw_spis_t *p, nthw_fpga_t *p_fpga, int n_instance) +{ + const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str; + nthw_module_t *mod = nthw_fpga_query_module(p_fpga, MOD_SPIS, n_instance); + + if (p == NULL) + return mod == NULL ? -1 : 0; + + if (mod == NULL) { + NT_LOG(ERR, NTHW, "%s: SPIS %d: no such instance\n", p_adapter_id_str, n_instance); + return -1; + } + + p->mp_fpga = p_fpga; + p->mn_instance = n_instance; + p->mp_mod_spis = mod; + + /* SPIS is a primary communication channel - turn off debug by default */ + nthw_module_set_debug_mode(p->mp_mod_spis, 0x00); + + p->mp_reg_srr = nthw_module_get_register(p->mp_mod_spis, SPIS_SRR); + p->mp_fld_srr_rst = nthw_register_get_field(p->mp_reg_srr, SPIS_SRR_RST); + + p->mp_reg_cr = nthw_module_get_register(p->mp_mod_spis, SPIS_CR); + p->mp_fld_cr_loop = nthw_register_get_field(p->mp_reg_cr, SPIS_CR_LOOP); + p->mp_fld_cr_en = nthw_register_get_field(p->mp_reg_cr, SPIS_CR_EN); + p->mp_fld_cr_txrst = nthw_register_get_field(p->mp_reg_cr, SPIS_CR_TXRST); + p->mp_fld_cr_rxrst = nthw_register_get_field(p->mp_reg_cr, SPIS_CR_RXRST); + p->mp_fld_cr_debug = nthw_register_get_field(p->mp_reg_cr, SPIS_CR_DEBUG); + + p->mp_reg_sr = nthw_module_get_register(p->mp_mod_spis, SPIS_SR); + p->mp_fld_sr_done = nthw_register_get_field(p->mp_reg_sr, SPIS_SR_DONE); + p->mp_fld_sr_txempty = nthw_register_get_field(p->mp_reg_sr, SPIS_SR_TXEMPTY); + p->mp_fld_sr_rxempty = nthw_register_get_field(p->mp_reg_sr, SPIS_SR_RXEMPTY); + p->mp_fld_sr_txfull = nthw_register_get_field(p->mp_reg_sr, SPIS_SR_TXFULL); + p->mp_fld_sr_rxfull = nthw_register_get_field(p->mp_reg_sr, SPIS_SR_RXFULL); + p->mp_fld_sr_txlvl = nthw_register_get_field(p->mp_reg_sr, SPIS_SR_TXLVL); + p->mp_fld_sr_rxlvl = nthw_register_get_field(p->mp_reg_sr, SPIS_SR_RXLVL); + p->mp_fld_sr_frame_err = nthw_register_get_field(p->mp_reg_sr, SPIS_SR_FRAME_ERR); + p->mp_fld_sr_read_err = nthw_register_get_field(p->mp_reg_sr, SPIS_SR_READ_ERR); + p->mp_fld_sr_write_err = nthw_register_get_field(p->mp_reg_sr, SPIS_SR_WRITE_ERR); + + p->mp_reg_dtr = nthw_module_get_register(p->mp_mod_spis, SPIS_DTR); + p->mp_fld_dtr_dtr = nthw_register_get_field(p->mp_reg_dtr, SPIS_DTR_DTR); + + p->mp_reg_drr = nthw_module_get_register(p->mp_mod_spis, SPIS_DRR); + p->mp_fld_drr_drr = nthw_register_get_field(p->mp_reg_drr, SPIS_DRR_DRR); + + p->mp_reg_ram_ctrl = nthw_module_get_register(p->mp_mod_spis, SPIS_RAM_CTRL); + p->mp_fld_ram_ctrl_adr = nthw_register_get_field(p->mp_reg_ram_ctrl, SPIS_RAM_CTRL_ADR); + p->mp_fld_ram_ctrl_cnt = nthw_register_get_field(p->mp_reg_ram_ctrl, SPIS_RAM_CTRL_CNT); + + p->mp_reg_ram_data = nthw_module_get_register(p->mp_mod_spis, SPIS_RAM_DATA); + p->mp_fld_ram_data_data = nthw_register_get_field(p->mp_reg_ram_data, SPIS_RAM_DATA_DATA); + + return 0; +} + +void nthw_spis_delete(nthw_spis_t *p) +{ + if (p) { + memset(p, 0, sizeof(nthw_spis_t)); + free(p); + } +} + +uint32_t nthw_spis_reset(nthw_spis_t *p) +{ + nthw_register_update(p->mp_reg_srr); + nthw_field_set_val32(p->mp_fld_srr_rst, 0x0A); /* 0x0A hardcoded value - see doc */ + nthw_register_flush(p->mp_reg_srr, 1); + + return 0; +} + +uint32_t nthw_spis_enable(nthw_spis_t *p, bool b_enable) +{ + nthw_field_update_register(p->mp_fld_cr_en); + + if (b_enable) + nthw_field_set_all(p->mp_fld_cr_en); + + else + nthw_field_clr_all(p->mp_fld_cr_en); + + nthw_field_flush_register(p->mp_fld_cr_en); + + return 0; +} + +uint32_t nthw_spis_get_rx_fifo_empty(nthw_spis_t *p, bool *pb_empty) +{ + assert(pb_empty); + + *pb_empty = nthw_field_get_updated(p->mp_fld_sr_rxempty) ? true : false; + + return 0; +} + +uint32_t nthw_spis_read_rx_fifo(nthw_spis_t *p, uint32_t *p_data) +{ + assert(p_data); + + *p_data = nthw_field_get_updated(p->mp_fld_drr_drr); + + return 0; +} diff --git a/drivers/net/ntnic/nthw/core/nthw_tsm.c b/drivers/net/ntnic/nthw/core/nthw_tsm.c new file mode 100644 index 0000000000..e0bf61652d --- /dev/null +++ b/drivers/net/ntnic/nthw/core/nthw_tsm.c @@ -0,0 +1,167 @@ +/* + * SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include "ntlog.h" + +#include "nthw_drv.h" +#include "nthw_register.h" + +#include "nthw_tsm.h" + +nthw_tsm_t *nthw_tsm_new(void) +{ + nthw_tsm_t *p = malloc(sizeof(nthw_tsm_t)); + + if (p) + memset(p, 0, sizeof(nthw_tsm_t)); + + return p; +} + +int nthw_tsm_init(nthw_tsm_t *p, nthw_fpga_t *p_fpga, int n_instance) +{ + const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str; + nthw_module_t *mod = nthw_fpga_query_module(p_fpga, MOD_TSM, n_instance); + + if (p == NULL) + return mod == NULL ? -1 : 0; + + if (mod == NULL) { + NT_LOG(ERR, NTHW, "%s: TSM %d: no such instance\n", p_adapter_id_str, n_instance); + return -1; + } + + p->mp_fpga = p_fpga; + p->mn_instance = n_instance; + p->mp_mod_tsm = mod; + + { + nthw_register_t *p_reg; + + p_reg = nthw_module_get_register(p->mp_mod_tsm, TSM_CONFIG); + p->mp_fld_config_ts_format = nthw_register_get_field(p_reg, TSM_CONFIG_TS_FORMAT); + + p_reg = nthw_module_get_register(p->mp_mod_tsm, TSM_TIMER_CTRL); + p->mp_fld_timer_ctrl_timer_en_t0 = + nthw_register_get_field(p_reg, TSM_TIMER_CTRL_TIMER_EN_T0); + p->mp_fld_timer_ctrl_timer_en_t1 = + nthw_register_get_field(p_reg, TSM_TIMER_CTRL_TIMER_EN_T1); + + p_reg = nthw_module_get_register(p->mp_mod_tsm, TSM_TIMER_T0); + p->mp_fld_timer_timer_t0_max_count = + nthw_register_get_field(p_reg, TSM_TIMER_T0_MAX_COUNT); + + p_reg = nthw_module_get_register(p->mp_mod_tsm, TSM_TIMER_T1); + p->mp_fld_timer_timer_t1_max_count = + nthw_register_get_field(p_reg, TSM_TIMER_T1_MAX_COUNT); + + p->mp_reg_time_lo = nthw_module_get_register(p->mp_mod_tsm, TSM_TIME_LO); + p_reg = p->mp_reg_time_lo; + p->mp_fld_time_lo = nthw_register_get_field(p_reg, TSM_TIME_LO_NS); + + p->mp_reg_time_hi = nthw_module_get_register(p->mp_mod_tsm, TSM_TIME_HI); + p_reg = p->mp_reg_time_hi; + p->mp_fld_time_hi = nthw_register_get_field(p_reg, TSM_TIME_HI_SEC); + + p->mp_reg_ts_lo = nthw_module_get_register(p->mp_mod_tsm, TSM_TS_LO); + p_reg = p->mp_reg_ts_lo; + p->mp_fld_ts_lo = nthw_register_get_field(p_reg, TSM_TS_LO_TIME); + + p->mp_reg_ts_hi = nthw_module_get_register(p->mp_mod_tsm, TSM_TS_HI); + p_reg = p->mp_reg_ts_hi; + p->mp_fld_ts_hi = nthw_register_get_field(p_reg, TSM_TS_HI_TIME); + } + return 0; +} + +int nthw_tsm_get_ts(nthw_tsm_t *p, uint64_t *p_ts) +{ + uint32_t n_ts_lo, n_ts_hi; + uint64_t val; + + if (!p_ts) + return -1; + + n_ts_lo = nthw_field_get_updated(p->mp_fld_ts_lo); + n_ts_hi = nthw_field_get_updated(p->mp_fld_ts_hi); + + val = ((((uint64_t)n_ts_hi) << 32UL) | n_ts_lo); + + if (p_ts) + *p_ts = val; + + return 0; +} + +int nthw_tsm_get_time(nthw_tsm_t *p, uint64_t *p_time) +{ + uint32_t n_time_lo, n_time_hi; + uint64_t val; + + if (!p_time) + return -1; + + n_time_lo = nthw_field_get_updated(p->mp_fld_time_lo); + n_time_hi = nthw_field_get_updated(p->mp_fld_time_hi); + + val = ((((uint64_t)n_time_hi) << 32UL) | n_time_lo); + + if (p_time) + *p_time = val; + + return 0; +} + +int nthw_tsm_set_timer_t0_enable(nthw_tsm_t *p, bool b_enable) +{ + nthw_field_update_register(p->mp_fld_timer_ctrl_timer_en_t0); + + if (b_enable) + nthw_field_set_flush(p->mp_fld_timer_ctrl_timer_en_t0); + + else + nthw_field_clr_flush(p->mp_fld_timer_ctrl_timer_en_t0); + + return 0; +} + +int nthw_tsm_set_timer_t0_max_count(nthw_tsm_t *p, uint32_t n_timer_val) +{ + /* Timer T0 - stat toggle timer */ + nthw_field_update_register(p->mp_fld_timer_timer_t0_max_count); + nthw_field_set_val_flush32(p->mp_fld_timer_timer_t0_max_count, + n_timer_val); /* ns (50*1000*1000) */ + return 0; +} + +int nthw_tsm_set_timer_t1_enable(nthw_tsm_t *p, bool b_enable) +{ + nthw_field_update_register(p->mp_fld_timer_ctrl_timer_en_t1); + + if (b_enable) + nthw_field_set_flush(p->mp_fld_timer_ctrl_timer_en_t1); + + else + nthw_field_clr_flush(p->mp_fld_timer_ctrl_timer_en_t1); + + return 0; +} + +int nthw_tsm_set_timer_t1_max_count(nthw_tsm_t *p, uint32_t n_timer_val) +{ + /* Timer T1 - keep alive timer */ + nthw_field_update_register(p->mp_fld_timer_timer_t1_max_count); + nthw_field_set_val_flush32(p->mp_fld_timer_timer_t1_max_count, + n_timer_val); /* ns (100*1000*1000) */ + return 0; +} + +int nthw_tsm_set_config_ts_format(nthw_tsm_t *p, uint32_t n_val) +{ + nthw_field_update_register(p->mp_fld_config_ts_format); + /* 0x1: Native - 10ns units, start date: 1970-01-01. */ + nthw_field_set_val_flush32(p->mp_fld_config_ts_format, n_val); + return 0; +} -- 2.44.0