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 6A77945501; Wed, 26 Jun 2024 21:58:53 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 2B59840E26; Wed, 26 Jun 2024 21:56:42 +0200 (CEST) Received: from egress-ip42a.ess.de.barracuda.com (egress-ip42a.ess.de.barracuda.com [18.185.115.201]) by mails.dpdk.org (Postfix) with ESMTP id C817D40E35 for ; Wed, 26 Jun 2024 21:56:39 +0200 (CEST) Received: from EUR05-DB8-obe.outbound.protection.outlook.com (mail-db8eur05lp2104.outbound.protection.outlook.com [104.47.17.104]) by mx-outbound42-4.eu-central-1c.ess.aws.cudaops.com (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Wed, 26 Jun 2024 19:56:36 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=RGywamDemqbJP//m0lthbDTM4NvBfhjjMeU6NwiCn9oybV8Mq/nwImMZAtdeiKJ+nqM1L2bNKn5utla1+0NqoiL9DxoHl5zw2YiHqOVRbsxmcHNh8ldCZp8bL10eL6cCu4NPHM/P9iQYDJm5lG3Hn9Dea9SmKayMResjXv7jdEhyxEQV20oAyaw7MFRnQ5pz4zRMoOxiVK3JomZmNjYCZd/zrKYYqryRr2QkX13UjRbieO+lHRVvtD3Beq/V0HpOqjHWPQgu++sKng/hQWzsy5pMn6kgP9l6NrcO5uWCfNYXKQokd1uyWYokZ34+5HEJwnboaYvM6L+OOIauGC8DkQ== 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=Rqcx4i+UJATmmIcqAE1GdRK1vBJDNmVcvgeJJAceEHY=; b=fEam7MJkcF8D2LnODYyAmbcA/t3EbiEjJqunkNOsk0SV5/+t2eOtRBlPVLcvP3ONV6cxbhX5hiemSBHUPXU/Sz+HtlI/0qACgBuDBunWGgmCV917xziarGADpcmrMzHuPnaieeJuwlUCD/7haCgUGTzSVLE6ExkXfEU5qnKLMtwlxAg2UCh1wp6zfslztEter0Zpa/xbTRfjXX4pvn7h5SMxBcRKzCvYfj+1SKkfipLpR6r3FKG1qYFsjQXUk/F8vd6M+E7KgR27JudZqnf0CcvbVIubSoC4E575TZaDeeE1cgaWuqtpVGG0UbUd9junktqe3VZqWTqQcKuh7A+Hkg== 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=Rqcx4i+UJATmmIcqAE1GdRK1vBJDNmVcvgeJJAceEHY=; b=TFSNE8u3LDQsl8vtFl8p08CqgtLPNR2FnfPL3qisYACnFPa7NCMaIvMlSKaDC+1qVa5IcqtYLq8YEH0no2HYooApmjNwvP38MmE8giNEE+VXcENvZM5irKthe8X0jFy+MSiOrj2VJZqD99cXM+rfSbcbhsU5E1K9q3uiQihfyac= Received: from AS4P250CA0019.EURP250.PROD.OUTLOOK.COM (2603:10a6:20b:5e3::10) by VI0P190MB2164.EURP190.PROD.OUTLOOK.COM (2603:10a6:800:255::9) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7698.32; Wed, 26 Jun 2024 19:56:16 +0000 Received: from AMS0EPF000001AC.eurprd05.prod.outlook.com (2603:10a6:20b:5e3:cafe::66) by AS4P250CA0019.outlook.office365.com (2603:10a6:20b:5e3::10) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7719.22 via Frontend Transport; Wed, 26 Jun 2024 19:56:15 +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 AMS0EPF000001AC.mail.protection.outlook.com (10.167.16.152) with Microsoft SMTP Server id 15.20.7677.15 via Frontend Transport; Wed, 26 Jun 2024 19:56:15 +0000 From: Serhii Iliushyk To: dev@dpdk.org Cc: mko-plv@napatech.com, sil-plv@napatech.com, ckm@napatech.com, andrew.rybchenko@oktetlabs.ru, ferruh.yigit@amd.com Subject: [PATCH v4 22/23] net/ntnic: add MAC PCS register interface module Date: Wed, 26 Jun 2024 21:55:32 +0200 Message-ID: <20240626195545.1793419-22-sil-plv@napatech.com> X-Mailer: git-send-email 2.45.0 In-Reply-To: <20240626195545.1793419-1-sil-plv@napatech.com> References: <20240530144929.4127931-1-sil-plv@napatech.com> <20240626195545.1793419-1-sil-plv@napatech.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: AMS0EPF000001AC:EE_|VI0P190MB2164:EE_ Content-Type: text/plain X-MS-Office365-Filtering-Correlation-Id: 58e5ca19-0d43-4c65-056e-08dc961a0986 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; ARA:13230038|1800799022|36860700011|82310400024|376012; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?GV4UTnkQ20wT19IVvQ/fYw166Dz7YATB4eMxgqRUlYUrOHIrmeVlEpUSY7qZ?= =?us-ascii?Q?ikgDMDBCqo2nroq757TaMTDdCYYSP0RvoAXj4LYCmh4zO8xOBF/cE8fQyEta?= =?us-ascii?Q?849ayORJfSzapB5x3pqn7jQQX/M6EWvYgv3cY/2M5CIgFD7R9oMPsfSMyusU?= =?us-ascii?Q?wuFDKNjWciZcd6IsYaWpE/PCo72Lt0x8EhaBqHdIaf8MT3hDhneioJjOEjPc?= =?us-ascii?Q?Uu3mzSkx2HtUMQO/HgKepqS9rM9ew/rNYoL7d9o8ryqu+oJO03727MG2XSZS?= =?us-ascii?Q?FeRtfbptjM8VD1dc2sI+z8FM6xrGFS8s5OJ2qH4Exbw7sws03yi4r/DUGYhj?= =?us-ascii?Q?TfGve8/aJh8EPF0ANt6UjjM4mwU479hmAP5CFwERQyn9AYH5UieCJ/7FPzNs?= =?us-ascii?Q?XFDkb/bJOoKzlqyN89O4VxUI1ZF1AEnk25nKsuqxwdKFJot8r+ACbVtlKFr5?= =?us-ascii?Q?gDJtH5B6kWkX7LP/BKo3AIdkat/HZyhN0hsoxbvhRQzihqZVk8ZE16qbdMG/?= =?us-ascii?Q?O1yjmFrfilcsG7DkIWa8XdaMrhgieHPf0S/teAjfycE7fvoRrLs/5fmr1pxh?= =?us-ascii?Q?qfRGBKFQq2yhMWAkhDIog7puYZdhtdD9Ch90yVlqB0oUXIINOCsSXrS+6Imo?= =?us-ascii?Q?ulpHhjCkQ/Oi53luD873RH8Z2H/SUtlnGSs/21M/gA8xoKwl2WVg+P5rcO6F?= =?us-ascii?Q?GSa2d4sOlPjKdsMWOKUbXHbwEeTm43hiTZ5cR/6edQVdvbNe1uBU4kdWkTVD?= =?us-ascii?Q?VZ4fy3wLMiqbCk0dstI2pYGLkENsuspXWW6epJvFBsLUiQitUNKAGl06V9n5?= =?us-ascii?Q?NHTOXablm9HT+cwoWZp7mqzPPztIfE5Xjl4kOmcrvk3bhj0dDvb7lhlVLgza?= =?us-ascii?Q?mTg93N0yOHn68pU8pJ2FRHH/xgMa6aH8r35O67Tm9dnAbOgOsHlV/vgyUf4e?= =?us-ascii?Q?jWBgdcV2lN1zbYQYDawYTIwFaDp0PPeMtKDpjDwn0TwtzmKcsiIwf/pmQ0rI?= =?us-ascii?Q?4yaMQKXaTzycuHGcHgreQEbcP321Qi5T9huL8f0WHq/VM0OyZR/0+BAnfYSN?= =?us-ascii?Q?gz5hO7zJmEyJ1mOFogynnowiqpmAR7GaGtLAi1yWt0fJVaKD7yx0m9LNgGmh?= =?us-ascii?Q?pWDc/yu2QfTRodJarTGw/wY89YbBXYN7cfpiDzidKWk2JpQ2fWTSkPCeVK2U?= =?us-ascii?Q?d7Wsexurj2sBEgFyjpHjLl//NpZffl4Ev7L1h12zr6PHw9fSCC1IbjerPKSo?= =?us-ascii?Q?rnd0egZnQRyXorSL+AcA792oS9mvXtIBYC1tHppZiJNJJtB2psmgvY5iKTWQ?= =?us-ascii?Q?BJczHdjegzYyFOWjxUa6qOZ425IOaEPokzbI+y8jBXy0FFMIRg4iFsO6wyLl?= =?us-ascii?Q?ayxpWHuvz/cnh6NLzyf1SdSn1q1m?= 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:(13230038)(1800799022)(36860700011)(82310400024)(376012); DIR:OUT; SFP:1102; X-MS-Exchange-AntiSpam-ExternalHop-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-ExternalHop-MessageData-0: Q1vt6pZ0mFlzQG0EAAPkqcY9epfz70CMSETvwywldFNUyJJv9/lJT302tqFJDAKG9GvLBPmR7jguownvuH6Au2vheIoHCPtpR3rBF4a44GKjHFmNqtVOZkGFonq8AWbFHbCi5AL+ErVzQo0xmFm5t/2ZMdoVaG2sZPlfEOfmUBShuPcMW+CMQ17uhKZ+DMwFr+pvpyq6RrTUGSAeSI+Jh9Lv1WNgUSp27Wn0InXySwe5NPy73a7K8Hql60Pw9aKmTv4YvladTiEpbGWRgyEzAbc+AiUHg5tKi9XuR9P7DcDhArxBeB8CVf2DGaUbGMFBSSoaS50oqAxJ61WH6CW3OlLtlHDNECf4o/rtMg4VSljd9llEq3a4LJ6k9SKJD31ECE56BhWNp1EX0sKNY40KdZVmr4yNJHhvWnCZjzTuXP1bt5ztT9iP5h/lxe4fRKrzJq63LCgGdtpSr3DnrGlqQTUUH9zSR6WfCUxuyVW16c4Mj8HZFb50hTXenklVoGi/fG3S5d6LuQmVaEHP/daf3E88+0XNiqilp7llsGe/gshmoqq6xk6e8epA3pLPNyPa+mTYSoDSQ5nkZJXOe/l3/1Uzr5mXigu9JhdGB5FhOajyRs2PFfLrIc9KSv2szqNImiNfppwls6wel0Hi/pCynA== X-OriginatorOrg: napatech.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 26 Jun 2024 19:56:15.1455 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 58e5ca19-0d43-4c65-056e-08dc961a0986 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: AMS0EPF000001AC.eurprd05.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: VI0P190MB2164 X-BESS-ID: 1719431774-310756-12660-57160-4 X-BESS-VER: 2019.1_20240620.2317 X-BESS-Apparent-Source-IP: 104.47.17.104 X-BESS-Parts: H4sIAAAAAAACA4uuVkqtKFGyUioBkjpK+cVKVqYWZmamQGYGUDTR3CDRMiXF0t AyJS3NMtXU2MjEODXVKNUwKc3cNDExSak2FgA41e1jQgAAAA== X-BESS-Outbound-Spam-Score: 0.00 X-BESS-Outbound-Spam-Report: Code version 3.2, rules version 3.2.2.257218 [from cloudscan19-163.eu-central-1b.ess.aws.cudaops.com] Rule breakdown below pts rule name description ---- ---------------------- -------------------------------- 0.00 BSF_BESS_OUTBOUND META: BESS Outbound X-BESS-Outbound-Spam-Status: SCORE=0.00 using account:ESS113687 scores of KILL_LEVEL=7.0 tests=BSF_BESS_OUTBOUND 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 API for MAC and PCS(Physical Coding Sublayer) Signed-off-by: Serhii Iliushyk --- drivers/net/ntnic/include/nt4ga_link.h | 1 + .../link_mgmt/link_100g/nt4ga_link_100g.c | 393 +++++++- drivers/net/ntnic/meson.build | 1 + .../net/ntnic/nthw/core/include/nthw_core.h | 1 + .../ntnic/nthw/core/include/nthw_mac_pcs.h | 250 +++++ drivers/net/ntnic/nthw/core/nthw_mac_pcs.c | 894 ++++++++++++++++++ 6 files changed, 1538 insertions(+), 2 deletions(-) create mode 100644 drivers/net/ntnic/nthw/core/include/nthw_mac_pcs.h create mode 100644 drivers/net/ntnic/nthw/core/nthw_mac_pcs.c diff --git a/drivers/net/ntnic/include/nt4ga_link.h b/drivers/net/ntnic/include/nt4ga_link.h index 5a16afea2a..8366484830 100644 --- a/drivers/net/ntnic/include/nt4ga_link.h +++ b/drivers/net/ntnic/include/nt4ga_link.h @@ -78,6 +78,7 @@ typedef struct port_action_s { typedef struct adapter_100g_s { nim_i2c_ctx_t nim_ctx[NUM_ADAPTER_PORTS_MAX]; /* Should be the first field */ + nthw_mac_pcs_t mac_pcs100g[NUM_ADAPTER_PORTS_MAX]; nthw_gpio_phy_t gpio_phy[NUM_ADAPTER_PORTS_MAX]; } adapter_100g_t; diff --git a/drivers/net/ntnic/link_mgmt/link_100g/nt4ga_link_100g.c b/drivers/net/ntnic/link_mgmt/link_100g/nt4ga_link_100g.c index 499f5de8eb..9d55733ddc 100644 --- a/drivers/net/ntnic/link_mgmt/link_100g/nt4ga_link_100g.c +++ b/drivers/net/ntnic/link_mgmt/link_100g/nt4ga_link_100g.c @@ -10,6 +10,168 @@ #include "i2c_nim.h" #include "ntnic_mod_reg.h" +/* + * Swap tx/rx polarity + */ +static int _swap_tx_rx_polarity(adapter_info_t *drv, nthw_mac_pcs_t *mac_pcs, int port, bool swap) +{ + const bool tx_polarity_swap[2][4] = { { true, true, false, false }, + { false, true, false, false } + }; + const bool rx_polarity_swap[2][4] = { { false, true, true, true }, + { false, true, true, false } + }; + uint8_t lane; + + (void)drv; + + for (lane = 0U; lane < 4U; lane++) { + if (swap) { + nthw_mac_pcs_swap_gty_tx_polarity(mac_pcs, lane, + tx_polarity_swap[port][lane]); + nthw_mac_pcs_swap_gty_rx_polarity(mac_pcs, lane, + rx_polarity_swap[port][lane]); + + } else { + nthw_mac_pcs_swap_gty_tx_polarity(mac_pcs, lane, false); + nthw_mac_pcs_swap_gty_rx_polarity(mac_pcs, lane, false); + } + } + + return 0; +} + +/* + * Reset RX + */ +static int _reset_rx(adapter_info_t *drv, nthw_mac_pcs_t *mac_pcs) +{ + (void)drv; + + nthw_mac_pcs_rx_path_rst(mac_pcs, true); + nt_os_wait_usec(10000); /* 10ms */ + nthw_mac_pcs_rx_path_rst(mac_pcs, false); + nt_os_wait_usec(10000); /* 10ms */ + + return 0; +} + +static void _set_loopback(struct adapter_info_s *p_adapter_info, + nthw_mac_pcs_t *mac_pcs, + int intf_no, + uint32_t mode, + uint32_t last_mode) +{ + bool swap_polerity = true; + + switch (mode) { + case 1: + NT_LOG(INF, NTNIC, "%s: Applying host loopback\n", + p_adapter_info->mp_port_id_str[intf_no]); + nthw_mac_pcs_set_fec(mac_pcs, true); + nthw_mac_pcs_set_host_loopback(mac_pcs, true); + swap_polerity = false; + break; + + case 2: + NT_LOG(INF, NTNIC, "%s: Applying line loopback\n", + p_adapter_info->mp_port_id_str[intf_no]); + nthw_mac_pcs_set_line_loopback(mac_pcs, true); + break; + + default: + switch (last_mode) { + case 1: + NT_LOG(INF, NTNIC, "%s: Removing host loopback\n", + p_adapter_info->mp_port_id_str[intf_no]); + nthw_mac_pcs_set_host_loopback(mac_pcs, false); + break; + + case 2: + NT_LOG(INF, NTNIC, "%s: Removing line loopback\n", + p_adapter_info->mp_port_id_str[intf_no]); + nthw_mac_pcs_set_line_loopback(mac_pcs, false); + break; + + default: + /* Do nothing */ + break; + } + + break; + } + + if (p_adapter_info->fpga_info.nthw_hw_info.hw_id == 2 || + p_adapter_info->hw_info.n_nthw_adapter_id == NT_HW_ADAPTER_ID_NT200A02) { + (void)_swap_tx_rx_polarity(p_adapter_info, mac_pcs, intf_no, swap_polerity); + } + + /* After changing the loopback the system must be properly reset */ + _reset_rx(p_adapter_info, mac_pcs); + + nt_os_wait_usec(10000); /* 10ms - arbitrary choice */ + + if (!nthw_mac_pcs_is_rx_path_rst(mac_pcs)) { + nthw_mac_pcs_reset_bip_counters(mac_pcs); + + if (!nthw_mac_pcs_get_fec_bypass(mac_pcs)) + nthw_mac_pcs_reset_fec_counters(mac_pcs); + } +} + +/* + * Function to retrieve the current state of a link (for one port) + */ +static int _link_state_build(adapter_info_t *drv, nthw_mac_pcs_t *mac_pcs, + nthw_gpio_phy_t *gpio_phy, int port, link_state_t *state, + bool is_port_disabled) +{ + uint32_t abs; + uint32_t phy_link_state; + uint32_t lh_abs; + uint32_t ll_phy_link_state; + uint32_t link_down_cnt; + uint32_t nim_interr; + uint32_t lh_local_fault; + uint32_t lh_remote_fault; + uint32_t lh_internal_local_fault; + uint32_t lh_received_local_fault; + + memset(state, 0, sizeof(*state)); + state->link_disabled = is_port_disabled; + nthw_mac_pcs_get_link_summary(mac_pcs, &abs, &phy_link_state, &lh_abs, &ll_phy_link_state, + &link_down_cnt, &nim_interr, &lh_local_fault, + &lh_remote_fault, &lh_internal_local_fault, + &lh_received_local_fault); + + assert(port >= 0 && port < NUM_ADAPTER_PORTS_MAX); + state->nim_present = nthw_gpio_phy_is_module_present(gpio_phy, (uint8_t)port); + state->lh_nim_absent = !state->nim_present; + state->link_up = phy_link_state ? true : false; + + { + static char lsbuf[NUM_ADAPTER_MAX][NUM_ADAPTER_PORTS_MAX][256]; + char buf[255]; + const int adapter_no = drv->adapter_no; + snprintf(buf, sizeof(buf), + "%s: Port = %d: abs = %u, phy_link_state = %u, lh_abs = %u, " + "ll_phy_link_state = %u, " + "link_down_cnt = %u, nim_interr = %u, lh_local_fault = %u, lh_remote_fault = " + "%u, lh_internal_local_fault = %u, lh_received_local_fault = %u", + drv->mp_adapter_id_str, mac_pcs->mn_instance, abs, phy_link_state, lh_abs, + ll_phy_link_state, link_down_cnt, nim_interr, lh_local_fault, + lh_remote_fault, lh_internal_local_fault, lh_received_local_fault); + + if (strcmp(lsbuf[adapter_no][port], buf) != 0) { + snprintf(lsbuf[adapter_no][port], sizeof(lsbuf[adapter_no][port]), "%s", + buf); + lsbuf[adapter_no][port][sizeof(lsbuf[adapter_no][port]) - 1U] = '\0'; + NT_LOG(DBG, NTNIC, "%s\n", lsbuf[adapter_no][port]); + } + } + return 0; +} + /* * Check whether a NIM module is present */ @@ -20,6 +182,69 @@ static bool _nim_is_present(nthw_gpio_phy_t *gpio_phy, uint8_t if_no) return nthw_gpio_phy_is_module_present(gpio_phy, if_no); } +/* + * Enable RX + */ +static int _enable_rx(adapter_info_t *drv, nthw_mac_pcs_t *mac_pcs) +{ + (void)drv; /* unused */ + nthw_mac_pcs_set_rx_enable(mac_pcs, true); + return 0; +} + +/* + * Enable TX + */ +static int _enable_tx(adapter_info_t *drv, nthw_mac_pcs_t *mac_pcs) +{ + (void)drv; /* unused */ + nthw_mac_pcs_set_tx_enable(mac_pcs, true); + nthw_mac_pcs_set_tx_sel_host(mac_pcs, true); + return 0; +} + +/* + * Disable RX + */ +static int _disable_rx(adapter_info_t *drv, nthw_mac_pcs_t *mac_pcs) +{ + (void)drv; /* unused */ + nthw_mac_pcs_set_rx_enable(mac_pcs, false); + return 0; +} + +/* + * Disable TX + */ +static int _disable_tx(adapter_info_t *drv, nthw_mac_pcs_t *mac_pcs) +{ + (void)drv; /* unused */ + nthw_mac_pcs_set_tx_enable(mac_pcs, false); + nthw_mac_pcs_set_tx_sel_host(mac_pcs, false); + return 0; +} + +/* + * Check link once NIM is installed and link can be expected. + */ +static int check_link_state(adapter_info_t *drv, nthw_mac_pcs_t *mac_pcs) +{ + bool rst_required; + bool ber; + bool fec_all_locked; + + rst_required = nthw_mac_pcs_reset_required(mac_pcs); + + ber = nthw_mac_pcs_get_hi_ber(mac_pcs); + + fec_all_locked = nthw_mac_pcs_get_fec_stat_all_am_locked(mac_pcs); + + if (rst_required || ber || !fec_all_locked) + _reset_rx(drv, mac_pcs); + + return 0; +} + /* * Initialize NIM, Code based on nt200e3_2_ptp.cpp: MyPort::createNim() */ @@ -31,6 +256,7 @@ static int _create_nim(adapter_info_t *drv, int port, bool enable) nim_i2c_ctx_t *nim_ctx; sfp_nim_state_t nim; nt4ga_link_t *link_info = &drv->nt4ga_link; + nthw_mac_pcs_t *mac_pcs = &link_info->u.var100g.mac_pcs100g[port]; assert(port >= 0 && port < NUM_ADAPTER_PORTS_MAX); assert(link_info->variables_initialized); @@ -46,6 +272,12 @@ static int _create_nim(adapter_info_t *drv, int port, bool enable) return 0; } + if (!enable) { + _disable_rx(drv, mac_pcs); + _disable_tx(drv, mac_pcs); + _reset_rx(drv, mac_pcs); + } + /* * Perform PHY reset. */ @@ -114,14 +346,29 @@ static int _create_nim(adapter_info_t *drv, int port, bool enable) * The function shall not assume anything about the state of the adapter * and/or port. */ -static int _port_init(adapter_info_t *drv, int port) +static int _port_init(adapter_info_t *drv, nthw_fpga_t *fpga, int port) { + int adapter_id; + int hw_id; int res; nt4ga_link_t *link_info = &drv->nt4ga_link; + nthw_mac_pcs_t *mac_pcs; + assert(port >= 0 && port < NUM_ADAPTER_PORTS_MAX); assert(link_info->variables_initialized); + if (fpga && fpga->p_fpga_info) { + adapter_id = fpga->p_fpga_info->n_nthw_adapter_id; + hw_id = fpga->p_fpga_info->nthw_hw_info.hw_id; + + } else { + adapter_id = -1; + hw_id = -1; + } + + mac_pcs = &link_info->u.var100g.mac_pcs100g[port]; + /* * Phase 1. Pre-state machine (`port init` functions) * 1.1) nt4ga_adapter::port_init() @@ -134,6 +381,28 @@ static int _port_init(adapter_info_t *drv, int port) link_info->link_info[port].link_duplex = NT_LINK_DUPLEX_FULL; link_info->link_info[port].link_auto_neg = NT_LINK_AUTONEG_OFF; link_info->speed_capa |= NT_LINK_SPEED_100G; + nthw_mac_pcs_set_led_mode(mac_pcs, NTHW_MAC_PCS_LED_AUTO); + nthw_mac_pcs_set_receiver_equalization_mode(mac_pcs, nthw_mac_pcs_receiver_mode_lpm); + + /* + * NT200A01 build 2 HW and NT200A02 that require GTY polarity swap + * if (adapter is `NT200A01 build 2 HW or NT200A02`) + */ + if (adapter_id == NT_HW_ADAPTER_ID_NT200A02 || hw_id == 2) + (void)_swap_tx_rx_polarity(drv, mac_pcs, port, true); + + nthw_mac_pcs_set_ts_eop(mac_pcs, true); /* end-of-frame timestamping */ + + /* Work in ABSOLUTE timing mode, don't set IFG mode. */ + + /* Phase 2. Pre-state machine (`setup` functions) */ + + /* 2.1) nt200a0x.cpp:Myport::setup() */ + NT_LOG(DBG, NTNIC, "%s: Setting up port %d\n", drv->mp_port_id_str[port], port); + + NT_LOG(DBG, NTNIC, "%s: Port %d: PHY TX enable\n", drv->mp_port_id_str[port], port); + _enable_tx(drv, mac_pcs); + _reset_rx(drv, mac_pcs); /* Phase 3. Link state machine steps */ @@ -147,6 +416,50 @@ static int _port_init(adapter_info_t *drv, int port) NT_LOG(DBG, NTNIC, "%s: NIM initialized\n", drv->mp_port_id_str[port]); + /* 3.2) MyPort::nimReady() */ + + /* 3.3) MyPort::nimReady100Gb() */ + + /* Setting FEC resets the lane counter in one half of the GMF */ + nthw_mac_pcs_set_fec(mac_pcs, true); + NT_LOG(DBG, NTNIC, "%s: Port %d: HOST FEC enabled\n", drv->mp_port_id_str[port], port); + + if (adapter_id == NT_HW_ADAPTER_ID_NT200A02 || hw_id == 2) { + const uint8_t pre = 5; + const uint8_t diff = 25; + const uint8_t post = 12; + + uint8_t lane = 0; + + for (lane = 0; lane < 4; lane++) + nthw_mac_pcs_set_gty_tx_tuning(mac_pcs, lane, pre, diff, post); + + } else { + NT_LOG(ERR, NTNIC, "Unhandled AdapterId/HwId: %02x_hwid%d\n", adapter_id, hw_id); + assert(0); + } + + _reset_rx(drv, mac_pcs); + + /* + * 3.4) MyPort::setLinkState() + * + * Compensation = 1640 - dly + * CMAC-core dly 188 ns + * FEC no correction 87 ns + * FEC active correction 211 + */ + if (nthw_mac_pcs_get_fec_valid(mac_pcs)) + nthw_mac_pcs_set_timestamp_comp_rx(mac_pcs, (1640 - 188 - 211)); + + else + nthw_mac_pcs_set_timestamp_comp_rx(mac_pcs, (1640 - 188 - 87)); + + /* 3.5) uint32_t MyPort::macConfig(nt_link_state_t link_state) */ + _enable_rx(drv, mac_pcs); + + nthw_mac_pcs_set_host_loopback(mac_pcs, false); + return res; } @@ -163,7 +476,9 @@ static int _common_ptp_nim_state_machine(void *data) const int nb_ports = fpga_info->n_phy_ports; uint32_t last_lpbk_mode[NUM_ADAPTER_PORTS_MAX]; + nim_i2c_ctx_t *nim_ctx; link_state_t *link_state; + nthw_mac_pcs_t *mac_pcs; nthw_gpio_phy_t *gpio_phy; if (!fpga) { @@ -172,7 +487,9 @@ static int _common_ptp_nim_state_machine(void *data) } assert(adapter_no >= 0 && adapter_no < NUM_ADAPTER_MAX); + nim_ctx = link_info->u.var100g.nim_ctx; link_state = link_info->link_state; + mac_pcs = link_info->u.var100g.mac_pcs100g; gpio_phy = link_info->u.var100g.gpio_phy; monitor_task_is_running[adapter_no] = 1; @@ -183,8 +500,10 @@ static int _common_ptp_nim_state_machine(void *data) while (monitor_task_is_running[adapter_no]) { int i; + static bool reported_link[NUM_ADAPTER_PORTS_MAX] = { false }; for (i = 0; i < nb_ports; i++) { + link_state_t new_link_state; const bool is_port_disabled = link_info->port_action[i].port_disable; const bool was_port_disabled = link_state[i].link_disabled; const bool disable_port = is_port_disabled && !was_port_disabled; @@ -200,6 +519,7 @@ static int _common_ptp_nim_state_machine(void *data) memset(&link_state[i], 0, sizeof(link_state[i])); link_info->link_info[i].link_speed = NT_LINK_SPEED_UNKNOWN; link_state[i].link_disabled = true; + reported_link[i] = false; /* Turn off laser and LED, etc. */ (void)_create_nim(drv, i, false); NT_LOG(DBG, NTNIC, "%s: Port %i is disabled\n", @@ -223,12 +543,17 @@ static int _common_ptp_nim_state_machine(void *data) * If there is no Nim present, we need to initialize the * port anyway */ - _port_init(drv, i); + _port_init(drv, fpga, i); } NT_LOG(INF, NTNIC, "%s: Loopback mode changed=%u\n", drv->mp_port_id_str[i], link_info->port_action[i].port_lpbk_mode); + _set_loopback(drv, + &mac_pcs[i], + i, + link_info->port_action[i].port_lpbk_mode, + last_lpbk_mode[i]); if (link_info->port_action[i].port_lpbk_mode == 1) link_state[i].link_up = true; @@ -237,6 +562,65 @@ static int _common_ptp_nim_state_machine(void *data) continue; } + (void)_link_state_build(drv, &mac_pcs[i], &gpio_phy[i], i, &new_link_state, + is_port_disabled); + + if (!new_link_state.nim_present) { + if (link_state[i].nim_present) { + NT_LOG(INF, NTNIC, "%s: NIM module removed\n", + drv->mp_port_id_str[i]); + } + + link_state[i] = new_link_state; + continue; + } + + /* NIM module is present */ + if (new_link_state.lh_nim_absent || !link_state[i].nim_present) { + sfp_nim_state_t new_state; + + NT_LOG(DBG, NTNIC, "%s: NIM module inserted\n", + drv->mp_port_id_str[i]); + + if (_port_init(drv, fpga, i)) { + NT_LOG(ERR, NTNIC, + "%s: Failed to initialize NIM module\n", + drv->mp_port_id_str[i]); + continue; + } + + if (nim_state_build(&nim_ctx[i], &new_state)) { + NT_LOG(ERR, NTNIC, "%s: Cannot read basic NIM data\n", + drv->mp_port_id_str[i]); + continue; + } + + assert(new_state.br); /* Cannot be zero if NIM is present */ + NT_LOG(DBG, NTNIC, + "%s: NIM id = %u (%s), br = %u, vendor = '%s', pn = '%s', sn='%s'\n", + drv->mp_port_id_str[i], nim_ctx->nim_id, + nim_id_to_text(nim_ctx->nim_id), (unsigned int)new_state.br, + nim_ctx->vendor_name, nim_ctx->prod_no, nim_ctx->serial_no); + + (void)_link_state_build(drv, &mac_pcs[i], &gpio_phy[i], i, + &link_state[i], is_port_disabled); + + NT_LOG(DBG, NTNIC, "%s: NIM module initialized\n", + drv->mp_port_id_str[i]); + continue; + } + + if (reported_link[i] != new_link_state.link_up) { + NT_LOG(INF, NTNIC, "%s: link is %s\n", drv->mp_port_id_str[i], + (new_link_state.link_up ? "up" : "down")); + link_info->link_info[i].link_speed = + (new_link_state.link_up ? NT_LINK_SPEED_100G + : NT_LINK_SPEED_UNKNOWN); + link_state[i].link_up = new_link_state.link_up; + reported_link[i] = new_link_state.link_up; + } + + check_link_state(drv, &mac_pcs[i]); } /* end-for */ if (monitor_task_is_running[adapter_no]) @@ -280,6 +664,7 @@ static int nt4ga_link_100g_ports_init(struct adapter_info_s *p_adapter_info, nth assert(adapter_no >= 0 && adapter_no < NUM_ADAPTER_MAX); if (res == 0 && !p_adapter_info->nt4ga_link.variables_initialized) { + nthw_mac_pcs_t *mac_pcs = p_adapter_info->nt4ga_link.u.var100g.mac_pcs100g; nim_i2c_ctx_t *nim_ctx = p_adapter_info->nt4ga_link.u.var100g.nim_ctx; nthw_gpio_phy_t *gpio_phy = p_adapter_info->nt4ga_link.u.var100g.gpio_phy; int i; @@ -287,6 +672,10 @@ static int nt4ga_link_100g_ports_init(struct adapter_info_s *p_adapter_info, nth for (i = 0; i < nb_ports; i++) { /* 2 + adapter port number */ const uint8_t instance = (uint8_t)(2U + i); + res = nthw_mac_pcs_init(&mac_pcs[i], fpga, i /* int n_instance */); + + if (res != 0) + break; res = nthw_iic_init(&nim_ctx[i].hwiic, fpga, instance, 8 /* timing */); diff --git a/drivers/net/ntnic/meson.build b/drivers/net/ntnic/meson.build index eb0ead4835..77f87ffa8e 100644 --- a/drivers/net/ntnic/meson.build +++ b/drivers/net/ntnic/meson.build @@ -43,6 +43,7 @@ sources = files( 'nthw/core/nthw_hif.c', 'nthw/core/nthw_i2cm.c', 'nthw/core/nthw_iic.c', + 'nthw/core/nthw_mac_pcs.c', 'nthw/core/nthw_pcie3.c', 'nthw/core/nthw_sdc.c', 'nthw/core/nthw_si5340.c', diff --git a/drivers/net/ntnic/nthw/core/include/nthw_core.h b/drivers/net/ntnic/nthw/core/include/nthw_core.h index 5cce56e13f..fe32891712 100644 --- a/drivers/net/ntnic/nthw/core/include/nthw_core.h +++ b/drivers/net/ntnic/nthw/core/include/nthw_core.h @@ -18,6 +18,7 @@ #include "nthw_i2cm.h" #include "nthw_gpio_phy.h" +#include "nthw_mac_pcs.h" #include "nthw_sdc.h" #include "nthw_si5340.h" diff --git a/drivers/net/ntnic/nthw/core/include/nthw_mac_pcs.h b/drivers/net/ntnic/nthw/core/include/nthw_mac_pcs.h new file mode 100644 index 0000000000..8d0e81bd73 --- /dev/null +++ b/drivers/net/ntnic/nthw/core/include/nthw_mac_pcs.h @@ -0,0 +1,250 @@ +/* + * SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef NTHW_MAC_PCS_H_ +#define NTHW_MAC_PCS_H_ + +enum nthw_mac_pcs_led_mode_e { + NTHW_MAC_PCS_LED_AUTO = 0x00, + NTHW_MAC_PCS_LED_ON = 0x01, + NTHW_MAC_PCS_LED_OFF = 0x02, + NTHW_MAC_PCS_LED_PORTID = 0x03, +}; + +#define nthw_mac_pcs_receiver_mode_dfe (0) +#define nthw_mac_pcs_receiver_mode_lpm (1) + +struct nthw_mac_pcs { + uint8_t m_port_no; + + nthw_fpga_t *mp_fpga; + nthw_module_t *mp_mod_mac_pcs; + int mn_instance; + + /* Block lock status */ + nthw_field_t *mp_fld_block_lock_lock; + uint32_t m_fld_block_lock_lock_mask; + + /* Lane lock status */ + nthw_field_t *mp_fld_vl_demuxed_lock; + uint32_t m_fld_vl_demuxed_lock_mask; + + /* GTY_STAT */ + nthw_field_t *mp_fld_gty_stat_rx_rst_done0; + nthw_field_t *mp_fld_gty_stat_rx_rst_done1; + nthw_field_t *mp_fld_gty_stat_rx_rst_done2; + nthw_field_t *mp_fld_gty_stat_rx_rst_done3; + nthw_field_t *mp_fld_gty_stat_tx_rst_done0; + nthw_field_t *mp_fld_gty_stat_tx_rst_done1; + nthw_field_t *mp_fld_gty_stat_tx_rst_done2; + nthw_field_t *mp_fld_gty_stat_tx_rst_done3; + uint32_t m_fld_gty_stat_rx_rst_done_mask; + uint32_t m_fld_gty_stat_tx_rst_done_mask; + + /* GTY_LOOP */ + nthw_register_t *mp_reg_gty_loop; + nthw_field_t *mp_fld_gty_loop_gt_loop0; + nthw_field_t *mp_fld_gty_loop_gt_loop1; + nthw_field_t *mp_fld_gty_loop_gt_loop2; + nthw_field_t *mp_fld_gty_loop_gt_loop3; + + /* MAC_PCS_CONFIG */ + nthw_field_t *mp_fld_pcs_config_tx_path_rst; + nthw_field_t *mp_fld_pcs_config_rx_path_rst; + nthw_field_t *mp_fld_pcs_config_rx_enable; + nthw_field_t *mp_fld_pcs_config_rx_force_resync; + nthw_field_t *mp_fld_pcs_config_rx_test_pattern; + nthw_field_t *mp_fld_pcs_config_tx_enable; + nthw_field_t *mp_fld_pcs_config_tx_send_idle; + nthw_field_t *mp_fld_pcs_config_tx_send_rfi; + nthw_field_t *mp_fld_pcs_config_tx_test_pattern; + + /* STAT PCS */ + nthw_field_t *mp_fld_stat_pcs_rx_status; + nthw_field_t *mp_fld_stat_pcs_rx_aligned; + nthw_field_t *mp_fld_stat_pcs_rx_aligned_err; + nthw_field_t *mp_fld_stat_pcs_rx_misaligned; + nthw_field_t *mp_fld_stat_pcs_rx_internal_local_fault; + nthw_field_t *mp_fld_stat_pcs_rx_received_local_fault; + nthw_field_t *mp_fld_stat_pcs_rx_local_fault; + nthw_field_t *mp_fld_stat_pcs_rx_remote_fault; + nthw_field_t *mp_fld_stat_pcs_rx_hi_ber; + + /* STAT_PCS_RX_LATCH */ + nthw_field_t *mp_fld_stat_pcs_rx_latch_status; + + /* PHYMAC_MISC */ + nthw_field_t *mp_fld_phymac_misc_tx_sel_host; + nthw_field_t *mp_fld_phymac_misc_tx_sel_tfg; + nthw_field_t *mp_fld_phymac_misc_tx_sel_rx_loop; + nthw_field_t *mp_fld_phymac_misc_ts_eop; + + /* LINK_SUMMARY */ + nthw_register_t *mp_reg_link_summary; + nthw_field_t *mp_fld_link_summary_abs; + nthw_field_t *mp_fld_link_summary_nt_phy_link_state; + nthw_field_t *mp_fld_link_summary_lh_abs; + nthw_field_t *mp_fld_link_summary_ll_nt_phy_link_state; + nthw_field_t *mp_fld_link_summary_link_down_cnt; + nthw_field_t *mp_fld_link_summary_nim_interr; + nthw_field_t *mp_fld_link_summary_lh_local_fault; + nthw_field_t *mp_fld_link_summary_lh_remote_fault; + nthw_field_t *mp_fld_link_summary_local_fault; + nthw_field_t *mp_fld_link_summary_remote_fault; + + /* BIP_ERR */ + nthw_register_t *mp_reg_bip_err; + nthw_field_t *mp_fld_reg_bip_err_bip_err; + + /* FEC_CTRL */ + nthw_register_t *mp_reg_fec_ctrl; + nthw_field_t *mp_field_fec_ctrl_reg_rs_fec_ctrl_in; + + /* FEC_STAT */ + nthw_register_t *mp_reg_fec_stat; + nthw_field_t *mp_field_fec_stat_bypass; + nthw_field_t *mp_field_fec_stat_valid; + nthw_field_t *mp_field_fec_stat_am_lock0; + nthw_field_t *mp_field_fec_stat_am_lock1; + nthw_field_t *mp_field_fec_stat_am_lock2; + nthw_field_t *mp_field_fec_stat_am_lock3; + nthw_field_t *mp_field_fec_stat_fec_lane_algn; + + /* FEC Corrected code word count */ + nthw_register_t *mp_reg_fec_cw_cnt; + nthw_field_t *mp_field_fec_cw_cnt_cw_cnt; + + /* FEC Uncorrected code word count */ + nthw_register_t *mp_reg_fec_ucw_cnt; + nthw_field_t *mp_field_fec_ucw_cnt_ucw_cnt; + + /* GTY_RX_BUF_STAT */ + nthw_register_t *mp_reg_gty_rx_buf_stat; + nthw_field_t *mp_field_gty_rx_buf_stat_rx_buf_stat0; + nthw_field_t *mp_field_gty_rx_buf_stat_rx_buf_stat1; + nthw_field_t *mp_field_gty_rx_buf_stat_rx_buf_stat2; + nthw_field_t *mp_field_gty_rx_buf_stat_rx_buf_stat3; + nthw_field_t *mp_field_gty_rx_buf_stat_rx_buf_stat_changed0; + nthw_field_t *mp_field_gty_rx_buf_stat_rx_buf_stat_changed1; + nthw_field_t *mp_field_gty_rx_buf_stat_rx_buf_stat_changed2; + nthw_field_t *mp_field_gty_rx_buf_stat_rx_buf_stat_changed3; + + /* GTY_PRE_CURSOR */ + nthw_register_t *mp_reg_gty_pre_cursor; + nthw_field_t *mp_field_gty_pre_cursor_tx_pre_csr0; + nthw_field_t *mp_field_gty_pre_cursor_tx_pre_csr1; + nthw_field_t *mp_field_gty_pre_cursor_tx_pre_csr2; + nthw_field_t *mp_field_gty_pre_cursor_tx_pre_csr3; + + /* GTY_DIFF_CTL */ + nthw_register_t *mp_reg_gty_diff_ctl; + nthw_field_t *mp_field_gty_gty_diff_ctl_tx_diff_ctl0; + nthw_field_t *mp_field_gty_gty_diff_ctl_tx_diff_ctl1; + nthw_field_t *mp_field_gty_gty_diff_ctl_tx_diff_ctl2; + nthw_field_t *mp_field_gty_gty_diff_ctl_tx_diff_ctl3; + + /* GTY_POST_CURSOR */ + nthw_register_t *mp_reg_gty_post_cursor; + nthw_field_t *mp_field_gty_post_cursor_tx_post_csr0; + nthw_field_t *mp_field_gty_post_cursor_tx_post_csr1; + nthw_field_t *mp_field_gty_post_cursor_tx_post_csr2; + nthw_field_t *mp_field_gty_post_cursor_tx_post_csr3; + + /* GTY_CTL */ + nthw_register_t *mp_reg_gty_ctl; + nthw_register_t *mp_reg_gty_ctl_tx; + nthw_field_t *mp_field_gty_ctl_tx_pol0; + nthw_field_t *mp_field_gty_ctl_tx_pol1; + nthw_field_t *mp_field_gty_ctl_tx_pol2; + nthw_field_t *mp_field_gty_ctl_tx_pol3; + nthw_field_t *mp_field_gty_ctl_rx_pol0; + nthw_field_t *mp_field_gty_ctl_rx_pol1; + nthw_field_t *mp_field_gty_ctl_rx_pol2; + nthw_field_t *mp_field_gty_ctl_rx_pol3; + nthw_field_t *mp_field_gty_ctl_rx_lpm_en0; + nthw_field_t *mp_field_gty_ctl_rx_lpm_en1; + nthw_field_t *mp_field_gty_ctl_rx_lpm_en2; + nthw_field_t *mp_field_gty_ctl_rx_lpm_en3; + nthw_field_t *mp_field_gty_ctl_rx_equa_rst0; + nthw_field_t *mp_field_gty_ctl_rx_equa_rst1; + nthw_field_t *mp_field_gty_ctl_rx_equa_rst2; + nthw_field_t *mp_field_gty_ctl_rx_equa_rst3; + + /* DEBOUNCE_CTRL */ + nthw_register_t *mp_reg_debounce_ctrl; + nthw_field_t *mp_field_debounce_ctrl_nt_port_ctrl; + + /* TIMESTAMP_COMP */ + nthw_register_t *mp_reg_time_stamp_comp; + nthw_field_t *mp_field_time_stamp_comp_rx_dly; + nthw_field_t *mp_field_time_stamp_comp_tx_dly; + + /* STAT_PCS_RX */ + nthw_register_t *mp_reg_stat_pcs_rx; + + /* STAT_PCS_RX */ + nthw_register_t *mp_reg_stat_pcs_rx_latch; + + /* PHYMAC_MISC */ + nthw_register_t *mp_reg_phymac_misc; + + /* BLOCK_LOCK */ + nthw_register_t *mp_reg_block_lock; +}; + +typedef struct nthw_mac_pcs nthw_mac_pcs_t; + +int nthw_mac_pcs_init(nthw_mac_pcs_t *p, nthw_fpga_t *p_fpga, int n_instance); + +void nthw_mac_pcs_tx_path_rst(nthw_mac_pcs_t *p, bool enable); +void nthw_mac_pcs_rx_path_rst(nthw_mac_pcs_t *p, bool enable); +bool nthw_mac_pcs_is_rx_path_rst(nthw_mac_pcs_t *p); +/* wrapper - for ease of use */ +void nthw_mac_pcs_set_rx_enable(nthw_mac_pcs_t *p, bool enable); +void nthw_mac_pcs_set_tx_enable(nthw_mac_pcs_t *p, bool enable); +void nthw_mac_pcs_set_tx_sel_host(nthw_mac_pcs_t *p, bool enable); +void nthw_mac_pcs_set_tx_sel_tfg(nthw_mac_pcs_t *p, bool enable); +void nthw_mac_pcs_set_ts_eop(nthw_mac_pcs_t *p, bool enable); +void nthw_mac_pcs_set_host_loopback(nthw_mac_pcs_t *p, bool enable); +void nthw_mac_pcs_set_line_loopback(nthw_mac_pcs_t *p, bool enable); +void nthw_mac_pcs_reset_bip_counters(nthw_mac_pcs_t *p); +bool nthw_mac_pcs_get_hi_ber(nthw_mac_pcs_t *p); + +void nthw_mac_pcs_get_link_summary(nthw_mac_pcs_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_local_fault, + uint32_t *p_remote_fault); + +bool nthw_mac_pcs_reset_required(nthw_mac_pcs_t *p); +void nthw_mac_pcs_set_fec(nthw_mac_pcs_t *p, bool enable); +bool nthw_mac_pcs_get_fec_bypass(nthw_mac_pcs_t *p); +bool nthw_mac_pcs_get_fec_valid(nthw_mac_pcs_t *p); +bool nthw_mac_pcs_get_fec_stat_all_am_locked(nthw_mac_pcs_t *p); +void nthw_mac_pcs_reset_fec_counters(nthw_mac_pcs_t *p); +void nthw_mac_pcs_set_gty_tx_tuning(nthw_mac_pcs_t *p, + uint8_t lane, + uint8_t tx_pre_csr, + uint8_t tx_diff_ctl, + uint8_t tx_post_csr); +void nthw_mac_pcs_swap_gty_tx_polarity(nthw_mac_pcs_t *p, uint8_t lane, bool swap); +void nthw_mac_pcs_swap_gty_rx_polarity(nthw_mac_pcs_t *p, uint8_t lane, bool swap); +void nthw_mac_pcs_set_receiver_equalization_mode(nthw_mac_pcs_t *p, uint8_t mode); +void nthw_mac_pcs_set_led_mode(nthw_mac_pcs_t *p, uint8_t mode); +void nthw_mac_pcs_set_timestamp_comp_rx(nthw_mac_pcs_t *p, uint16_t rx_dly); +void nthw_mac_pcs_set_port_no(nthw_mac_pcs_t *p, uint8_t port_no); + +uint32_t nthw_mac_pcs_get_fld_block_lock_lock(nthw_mac_pcs_t *p); +uint32_t nthw_mac_pcs_get_fld_block_lock_lock_mask(nthw_mac_pcs_t *p); +uint32_t nthw_mac_pcs_get_fld_lane_lock_lock(nthw_mac_pcs_t *p); +uint32_t nthw_mac_pcs_get_fld_lane_lock_lock_mask(nthw_mac_pcs_t *p); + +#endif /* NTHW_MAC_PCS_H_ */ diff --git a/drivers/net/ntnic/nthw/core/nthw_mac_pcs.c b/drivers/net/ntnic/nthw/core/nthw_mac_pcs.c new file mode 100644 index 0000000000..76040ec9c0 --- /dev/null +++ b/drivers/net/ntnic/nthw/core/nthw_mac_pcs.c @@ -0,0 +1,894 @@ +/* + * 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_mac_pcs.h" + +#define NTHW_MAC_PCS_LANES (20) + +static const uint8_t c_pcs_lanes = NTHW_MAC_PCS_LANES; +static const uint8_t c_mac_pcs_receiver_mode_dfe; + +/* + * Parameters: + * p != NULL: init struct pointed to by p + * p == NULL: check fpga module(s) presence (but no struct to init) + * + * Return value: + * <0: if p == NULL then fpga module(s) is/are not present. + * if p != NULL then fpga module(s) is/are not present, struct undefined + * ==0: if p == NULL then fpga module(s) is/are present (no struct to init) + * : if p != NULL then fpga module(s) is/are present and struct initialized + */ +int nthw_mac_pcs_init(nthw_mac_pcs_t *p, nthw_fpga_t *p_fpga, int n_instance) +{ + nthw_module_t *mod = nthw_fpga_query_module(p_fpga, MOD_MAC_PCS, n_instance); + + if (p == NULL) + return mod == NULL ? -1 : 0; + + if (mod == NULL) { + NT_LOG(ERR, NTHW, "%s: MAC_PCS %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_mac_pcs = mod; + + assert(n_instance >= 0 && n_instance <= 255); + nthw_mac_pcs_set_port_no(p, (uint8_t)n_instance); + + { + nthw_register_t *p_reg_block_lock, *p_reg_stat_pcs_rx, *p_reg_stat_pcs_rx_latch; + nthw_register_t *p_reg_vl_demuxed, *p_reg_gty_stat, *p_reg_pcs_config, + *p_reg_phymac_misc; + const int product_id = nthw_fpga_get_product_id(p_fpga); + + p_reg_block_lock = nthw_module_get_register(p->mp_mod_mac_pcs, MAC_PCS_BLOCK_LOCK); + p->mp_reg_block_lock = p_reg_block_lock; + p->mp_fld_block_lock_lock = + nthw_register_get_field(p_reg_block_lock, MAC_PCS_BLOCK_LOCK_LOCK); + + p_reg_stat_pcs_rx = + nthw_module_get_register(p->mp_mod_mac_pcs, MAC_PCS_STAT_PCS_RX); + p->mp_reg_stat_pcs_rx = p_reg_stat_pcs_rx; + p->mp_fld_stat_pcs_rx_status = + nthw_register_get_field(p_reg_stat_pcs_rx, MAC_PCS_STAT_PCS_RX_STATUS); + p->mp_fld_stat_pcs_rx_aligned = + nthw_register_get_field(p_reg_stat_pcs_rx, MAC_PCS_STAT_PCS_RX_ALIGNED); + p->mp_fld_stat_pcs_rx_aligned_err = + nthw_register_get_field(p_reg_stat_pcs_rx, + MAC_PCS_STAT_PCS_RX_ALIGNED_ERR); + p->mp_fld_stat_pcs_rx_misaligned = + nthw_register_get_field(p_reg_stat_pcs_rx, MAC_PCS_STAT_PCS_RX_MISALIGNED); + p->mp_fld_stat_pcs_rx_internal_local_fault = + nthw_register_get_field(p_reg_stat_pcs_rx, + MAC_PCS_STAT_PCS_RX_INTERNAL_LOCAL_FAULT); + p->mp_fld_stat_pcs_rx_received_local_fault = + nthw_register_get_field(p_reg_stat_pcs_rx, + MAC_PCS_STAT_PCS_RX_RECEIVED_LOCAL_FAULT); + p->mp_fld_stat_pcs_rx_local_fault = + nthw_register_get_field(p_reg_stat_pcs_rx, + MAC_PCS_STAT_PCS_RX_LOCAL_FAULT); + p->mp_fld_stat_pcs_rx_remote_fault = + nthw_register_get_field(p_reg_stat_pcs_rx, + MAC_PCS_STAT_PCS_RX_REMOTE_FAULT); + p->mp_fld_stat_pcs_rx_hi_ber = + nthw_register_get_field(p_reg_stat_pcs_rx, MAC_PCS_STAT_PCS_RX_HI_BER); + + p_reg_stat_pcs_rx_latch = + nthw_module_get_register(p->mp_mod_mac_pcs, MAC_PCS_STAT_PCS_RX_LATCH); + p->mp_reg_stat_pcs_rx_latch = p_reg_stat_pcs_rx_latch; + p->mp_fld_stat_pcs_rx_latch_status = + nthw_register_get_field(p_reg_stat_pcs_rx_latch, + MAC_PCS_STAT_PCS_RX_LATCH_STATUS); + + p_reg_vl_demuxed = nthw_module_get_register(p->mp_mod_mac_pcs, MAC_PCS_VL_DEMUXED); + p->mp_fld_vl_demuxed_lock = + nthw_register_get_field(p_reg_vl_demuxed, MAC_PCS_VL_DEMUXED_LOCK); + + p_reg_gty_stat = nthw_module_get_register(p->mp_mod_mac_pcs, MAC_PCS_GTY_STAT); + p->mp_fld_gty_stat_tx_rst_done0 = + nthw_register_get_field(p_reg_gty_stat, MAC_PCS_GTY_STAT_TX_RST_DONE_0); + p->mp_fld_gty_stat_tx_rst_done1 = + nthw_register_get_field(p_reg_gty_stat, MAC_PCS_GTY_STAT_TX_RST_DONE_1); + p->mp_fld_gty_stat_tx_rst_done2 = + nthw_register_get_field(p_reg_gty_stat, MAC_PCS_GTY_STAT_TX_RST_DONE_2); + p->mp_fld_gty_stat_tx_rst_done3 = + nthw_register_get_field(p_reg_gty_stat, MAC_PCS_GTY_STAT_TX_RST_DONE_3); + p->mp_fld_gty_stat_rx_rst_done0 = + nthw_register_get_field(p_reg_gty_stat, MAC_PCS_GTY_STAT_RX_RST_DONE_0); + p->mp_fld_gty_stat_rx_rst_done1 = + nthw_register_get_field(p_reg_gty_stat, MAC_PCS_GTY_STAT_RX_RST_DONE_1); + p->mp_fld_gty_stat_rx_rst_done2 = + nthw_register_get_field(p_reg_gty_stat, MAC_PCS_GTY_STAT_RX_RST_DONE_2); + p->mp_fld_gty_stat_rx_rst_done3 = + nthw_register_get_field(p_reg_gty_stat, MAC_PCS_GTY_STAT_RX_RST_DONE_3); + + p->m_fld_block_lock_lock_mask = 0; + p->m_fld_vl_demuxed_lock_mask = 0; + p->m_fld_gty_stat_tx_rst_done_mask = 0; + p->m_fld_gty_stat_rx_rst_done_mask = 0; + + if (product_id == 9563) { + /* NT200A01_2X100 implements 20 virtual lanes */ + p->m_fld_block_lock_lock_mask = (1 << 20) - 1; + /* NT200A01_2X100 implements 20 virtual lanes */ + p->m_fld_vl_demuxed_lock_mask = (1 << 20) - 1; + p->m_fld_gty_stat_tx_rst_done_mask = + 1; /* NT200A01_2X100 implements 4 GTY */ + p->m_fld_gty_stat_rx_rst_done_mask = + 1; /* NT200A01_2X100 implements 4 GTY */ + + } else { + /* Remember to add new product_ids */ + assert(0); + } + + p_reg_pcs_config = + nthw_module_get_register(p->mp_mod_mac_pcs, MAC_PCS_MAC_PCS_CONFIG); + p->mp_fld_pcs_config_tx_path_rst = + nthw_register_get_field(p_reg_pcs_config, + MAC_PCS_MAC_PCS_CONFIG_TX_PATH_RST); + p->mp_fld_pcs_config_rx_path_rst = + nthw_register_get_field(p_reg_pcs_config, + MAC_PCS_MAC_PCS_CONFIG_RX_PATH_RST); + p->mp_fld_pcs_config_rx_enable = + nthw_register_get_field(p_reg_pcs_config, + MAC_PCS_MAC_PCS_CONFIG_RX_ENABLE); + p->mp_fld_pcs_config_rx_force_resync = + nthw_register_get_field(p_reg_pcs_config, + MAC_PCS_MAC_PCS_CONFIG_RX_FORCE_RESYNC); + p->mp_fld_pcs_config_rx_test_pattern = + nthw_register_get_field(p_reg_pcs_config, + MAC_PCS_MAC_PCS_CONFIG_RX_TEST_PATTERN); + p->mp_fld_pcs_config_tx_enable = + nthw_register_get_field(p_reg_pcs_config, + MAC_PCS_MAC_PCS_CONFIG_TX_ENABLE); + p->mp_fld_pcs_config_tx_send_idle = + nthw_register_get_field(p_reg_pcs_config, + MAC_PCS_MAC_PCS_CONFIG_TX_SEND_IDLE); + p->mp_fld_pcs_config_tx_send_rfi = + nthw_register_get_field(p_reg_pcs_config, + MAC_PCS_MAC_PCS_CONFIG_TX_SEND_RFI); + p->mp_fld_pcs_config_tx_test_pattern = + nthw_register_get_field(p_reg_pcs_config, + MAC_PCS_MAC_PCS_CONFIG_TX_TEST_PATTERN); + + p->mp_reg_gty_loop = nthw_module_get_register(p->mp_mod_mac_pcs, MAC_PCS_GTY_LOOP); + p->mp_fld_gty_loop_gt_loop0 = + nthw_register_get_field(p->mp_reg_gty_loop, MAC_PCS_GTY_LOOP_GT_LOOP_0); + p->mp_fld_gty_loop_gt_loop1 = + nthw_register_get_field(p->mp_reg_gty_loop, MAC_PCS_GTY_LOOP_GT_LOOP_1); + p->mp_fld_gty_loop_gt_loop2 = + nthw_register_get_field(p->mp_reg_gty_loop, MAC_PCS_GTY_LOOP_GT_LOOP_2); + p->mp_fld_gty_loop_gt_loop3 = + nthw_register_get_field(p->mp_reg_gty_loop, MAC_PCS_GTY_LOOP_GT_LOOP_3); + + p_reg_phymac_misc = + nthw_module_get_register(p->mp_mod_mac_pcs, MAC_PCS_PHYMAC_MISC); + p->mp_reg_phymac_misc = p_reg_phymac_misc; + p->mp_fld_phymac_misc_tx_sel_host = + nthw_register_get_field(p_reg_phymac_misc, + MAC_PCS_PHYMAC_MISC_TX_SEL_HOST); + p->mp_fld_phymac_misc_tx_sel_tfg = + nthw_register_get_field(p_reg_phymac_misc, MAC_PCS_PHYMAC_MISC_TX_SEL_TFG); + p->mp_fld_phymac_misc_tx_sel_rx_loop = + nthw_register_get_field(p_reg_phymac_misc, + MAC_PCS_PHYMAC_MISC_TX_SEL_RX_LOOP); + + /* SOP or EOP TIMESTAMP */ + p->mp_fld_phymac_misc_ts_eop = + nthw_register_query_field(p_reg_phymac_misc, MAC_PCS_PHYMAC_MISC_TS_EOP); + + p->mp_reg_link_summary = + nthw_module_get_register(p->mp_mod_mac_pcs, MAC_PCS_LINK_SUMMARY); + p->mp_fld_link_summary_abs = + nthw_register_get_field(p->mp_reg_link_summary, MAC_PCS_LINK_SUMMARY_ABS); + p->mp_fld_link_summary_nt_phy_link_state = + nthw_register_get_field(p->mp_reg_link_summary, + MAC_PCS_LINK_SUMMARY_NT_PHY_LINK_STATE); + p->mp_fld_link_summary_lh_abs = + nthw_register_get_field(p->mp_reg_link_summary, + MAC_PCS_LINK_SUMMARY_LH_ABS); + p->mp_fld_link_summary_ll_nt_phy_link_state = + nthw_register_get_field(p->mp_reg_link_summary, + MAC_PCS_LINK_SUMMARY_LL_PHY_LINK_STATE); + p->mp_fld_link_summary_link_down_cnt = + nthw_register_get_field(p->mp_reg_link_summary, + MAC_PCS_LINK_SUMMARY_LINK_DOWN_CNT); + p->mp_fld_link_summary_nim_interr = + nthw_register_get_field(p->mp_reg_link_summary, + MAC_PCS_LINK_SUMMARY_NIM_INTERR); + p->mp_fld_link_summary_lh_local_fault = + nthw_register_get_field(p->mp_reg_link_summary, + MAC_PCS_LINK_SUMMARY_LH_LOCAL_FAULT); + p->mp_fld_link_summary_lh_remote_fault = + nthw_register_get_field(p->mp_reg_link_summary, + MAC_PCS_LINK_SUMMARY_LH_REMOTE_FAULT); + p->mp_fld_link_summary_local_fault = + nthw_register_get_field(p->mp_reg_link_summary, + MAC_PCS_LINK_SUMMARY_LOCAL_FAULT); + p->mp_fld_link_summary_remote_fault = + nthw_register_get_field(p->mp_reg_link_summary, + MAC_PCS_LINK_SUMMARY_REMOTE_FAULT); + + p->mp_reg_bip_err = nthw_module_get_register(p->mp_mod_mac_pcs, MAC_PCS_BIP_ERR); + p->mp_fld_reg_bip_err_bip_err = + nthw_register_get_field(p->mp_reg_bip_err, MAC_PCS_BIP_ERR_BIP_ERR); + + p->mp_reg_fec_ctrl = nthw_module_get_register(p->mp_mod_mac_pcs, MAC_PCS_FEC_CTRL); + p->mp_field_fec_ctrl_reg_rs_fec_ctrl_in = + nthw_register_get_field(p->mp_reg_fec_ctrl, + MAC_PCS_FEC_CTRL_RS_FEC_CTRL_IN); + + p->mp_reg_fec_stat = nthw_module_get_register(p->mp_mod_mac_pcs, MAC_PCS_FEC_STAT); + p->mp_field_fec_stat_bypass = + nthw_register_get_field(p->mp_reg_fec_stat, MAC_PCS_FEC_STAT_BYPASS); + p->mp_field_fec_stat_valid = + nthw_register_get_field(p->mp_reg_fec_stat, MAC_PCS_FEC_STAT_VALID); + p->mp_field_fec_stat_am_lock0 = + nthw_register_get_field(p->mp_reg_fec_stat, MAC_PCS_FEC_STAT_AM_LOCK_0); + p->mp_field_fec_stat_am_lock1 = + nthw_register_get_field(p->mp_reg_fec_stat, MAC_PCS_FEC_STAT_AM_LOCK_1); + p->mp_field_fec_stat_am_lock2 = + nthw_register_get_field(p->mp_reg_fec_stat, MAC_PCS_FEC_STAT_AM_LOCK_2); + p->mp_field_fec_stat_am_lock3 = + nthw_register_get_field(p->mp_reg_fec_stat, MAC_PCS_FEC_STAT_AM_LOCK_3); + p->mp_field_fec_stat_fec_lane_algn = + nthw_register_get_field(p->mp_reg_fec_stat, + MAC_PCS_FEC_STAT_FEC_LANE_ALGN); + + p->mp_reg_fec_cw_cnt = + nthw_module_get_register(p->mp_mod_mac_pcs, MAC_PCS_FEC_CW_CNT); + p->mp_field_fec_cw_cnt_cw_cnt = + nthw_register_get_field(p->mp_reg_fec_cw_cnt, MAC_PCS_FEC_CW_CNT_CW_CNT); + + p->mp_reg_fec_ucw_cnt = + nthw_module_get_register(p->mp_mod_mac_pcs, MAC_PCS_FEC_UCW_CNT); + p->mp_field_fec_ucw_cnt_ucw_cnt = + nthw_register_get_field(p->mp_reg_fec_ucw_cnt, + MAC_PCS_FEC_UCW_CNT_UCW_CNT); + + /* GTY_RX_BUF_STAT */ +#ifdef RXBUFSTAT + p->mp_reg_gty_rx_buf_stat = + nthw_module_get_register(p->mp_mod_mac_pcs, MAC_PCS_GTY_RX_BUF_STAT); + p->mp_field_gty_rx_buf_stat_rx_buf_stat0 = + nthw_register_get_field(p->mp_reg_gty_rx_buf_stat, + MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_0); + p->mp_field_gty_rx_buf_stat_rx_buf_stat1 = + nthw_register_get_field(p->mp_reg_gty_rx_buf_stat, + MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_1); + p->mp_field_gty_rx_buf_stat_rx_buf_stat2 = + nthw_register_get_field(p->mp_reg_gty_rx_buf_stat, + MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_2); + p->mp_field_gty_rx_buf_stat_rx_buf_stat3 = + nthw_register_get_field(p->mp_reg_gty_rx_buf_stat, + MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_3); + p->mp_field_gty_rx_buf_stat_rx_buf_stat_changed0 = + nthw_register_get_field(p->mp_reg_gty_rx_buf_stat, + MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_CHANGED_0); + p->mp_field_gty_rx_buf_stat_rx_buf_stat_changed1 = + nthw_register_get_field(p->mp_reg_gty_rx_buf_stat, + MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_CHANGED_1); + p->mp_field_gty_rx_buf_stat_rx_buf_stat_changed2 = + nthw_register_get_field(p->mp_reg_gty_rx_buf_stat, + MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_CHANGED_2); + p->mp_field_gty_rx_buf_stat_rx_buf_stat_changed3 = + nthw_register_get_field(p->mp_reg_gty_rx_buf_stat, + MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_CHANGED_3); +#endif + + /* GTY_PRE_CURSOR */ + p->mp_reg_gty_pre_cursor = + nthw_module_get_register(p->mp_mod_mac_pcs, MAC_PCS_GTY_PRE_CURSOR); + p->mp_field_gty_pre_cursor_tx_pre_csr0 = + nthw_register_get_field(p->mp_reg_gty_pre_cursor, + MAC_PCS_GTY_PRE_CURSOR_TX_PRE_CSR_0); + p->mp_field_gty_pre_cursor_tx_pre_csr1 = + nthw_register_get_field(p->mp_reg_gty_pre_cursor, + MAC_PCS_GTY_PRE_CURSOR_TX_PRE_CSR_1); + p->mp_field_gty_pre_cursor_tx_pre_csr2 = + nthw_register_get_field(p->mp_reg_gty_pre_cursor, + MAC_PCS_GTY_PRE_CURSOR_TX_PRE_CSR_2); + p->mp_field_gty_pre_cursor_tx_pre_csr3 = + nthw_register_get_field(p->mp_reg_gty_pre_cursor, + MAC_PCS_GTY_PRE_CURSOR_TX_PRE_CSR_3); + + /* GTY_DIFF_CTL */ + p->mp_reg_gty_diff_ctl = + nthw_module_get_register(p->mp_mod_mac_pcs, MAC_PCS_GTY_DIFF_CTL); + p->mp_field_gty_gty_diff_ctl_tx_diff_ctl0 = + nthw_register_get_field(p->mp_reg_gty_diff_ctl, + MAC_PCS_GTY_DIFF_CTL_TX_DIFF_CTL_0); + p->mp_field_gty_gty_diff_ctl_tx_diff_ctl1 = + nthw_register_get_field(p->mp_reg_gty_diff_ctl, + MAC_PCS_GTY_DIFF_CTL_TX_DIFF_CTL_1); + p->mp_field_gty_gty_diff_ctl_tx_diff_ctl2 = + nthw_register_get_field(p->mp_reg_gty_diff_ctl, + MAC_PCS_GTY_DIFF_CTL_TX_DIFF_CTL_2); + p->mp_field_gty_gty_diff_ctl_tx_diff_ctl3 = + nthw_register_get_field(p->mp_reg_gty_diff_ctl, + MAC_PCS_GTY_DIFF_CTL_TX_DIFF_CTL_3); + + /* GTY_POST_CURSOR */ + p->mp_reg_gty_post_cursor = + nthw_module_get_register(p->mp_mod_mac_pcs, MAC_PCS_GTY_POST_CURSOR); + p->mp_field_gty_post_cursor_tx_post_csr0 = + nthw_register_get_field(p->mp_reg_gty_post_cursor, + MAC_PCS_GTY_POST_CURSOR_TX_POST_CSR_0); + p->mp_field_gty_post_cursor_tx_post_csr1 = + nthw_register_get_field(p->mp_reg_gty_post_cursor, + MAC_PCS_GTY_POST_CURSOR_TX_POST_CSR_1); + p->mp_field_gty_post_cursor_tx_post_csr2 = + nthw_register_get_field(p->mp_reg_gty_post_cursor, + MAC_PCS_GTY_POST_CURSOR_TX_POST_CSR_2); + p->mp_field_gty_post_cursor_tx_post_csr3 = + nthw_register_get_field(p->mp_reg_gty_post_cursor, + MAC_PCS_GTY_POST_CURSOR_TX_POST_CSR_3); + + /* GTY_CTL */ + p->mp_reg_gty_ctl = nthw_module_query_register(p->mp_mod_mac_pcs, MAC_PCS_GTY_CTL); + + if (p->mp_reg_gty_ctl) { + p->mp_field_gty_ctl_tx_pol0 = + nthw_register_get_field(p->mp_reg_gty_ctl, + MAC_PCS_GTY_CTL_TX_POLARITY_0); + p->mp_field_gty_ctl_tx_pol1 = + nthw_register_get_field(p->mp_reg_gty_ctl, + MAC_PCS_GTY_CTL_TX_POLARITY_1); + p->mp_field_gty_ctl_tx_pol2 = + nthw_register_get_field(p->mp_reg_gty_ctl, + MAC_PCS_GTY_CTL_TX_POLARITY_2); + p->mp_field_gty_ctl_tx_pol3 = + nthw_register_get_field(p->mp_reg_gty_ctl, + MAC_PCS_GTY_CTL_TX_POLARITY_3); + + } else { + p->mp_reg_gty_ctl = + nthw_module_get_register(p->mp_mod_mac_pcs, MAC_PCS_GTY_CTL_RX); + p->mp_reg_gty_ctl_tx = + nthw_module_get_register(p->mp_mod_mac_pcs, MAC_PCS_GTY_CTL_TX); + p->mp_field_gty_ctl_tx_pol0 = + nthw_register_get_field(p->mp_reg_gty_ctl_tx, + MAC_PCS_GTY_CTL_TX_POLARITY_0); + p->mp_field_gty_ctl_tx_pol1 = + nthw_register_get_field(p->mp_reg_gty_ctl_tx, + MAC_PCS_GTY_CTL_TX_POLARITY_1); + p->mp_field_gty_ctl_tx_pol2 = + nthw_register_get_field(p->mp_reg_gty_ctl_tx, + MAC_PCS_GTY_CTL_TX_POLARITY_2); + p->mp_field_gty_ctl_tx_pol3 = + nthw_register_get_field(p->mp_reg_gty_ctl_tx, + MAC_PCS_GTY_CTL_TX_POLARITY_3); + } + + p->mp_field_gty_ctl_rx_pol0 = + nthw_register_get_field(p->mp_reg_gty_ctl, MAC_PCS_GTY_CTL_RX_POLARITY_0); + p->mp_field_gty_ctl_rx_pol1 = + nthw_register_get_field(p->mp_reg_gty_ctl, MAC_PCS_GTY_CTL_RX_POLARITY_1); + p->mp_field_gty_ctl_rx_pol2 = + nthw_register_get_field(p->mp_reg_gty_ctl, MAC_PCS_GTY_CTL_RX_POLARITY_2); + p->mp_field_gty_ctl_rx_pol3 = + nthw_register_get_field(p->mp_reg_gty_ctl, MAC_PCS_GTY_CTL_RX_POLARITY_3); + p->mp_field_gty_ctl_rx_lpm_en0 = + nthw_register_get_field(p->mp_reg_gty_ctl, MAC_PCS_GTY_CTL_RX_LPM_EN_0); + p->mp_field_gty_ctl_rx_lpm_en1 = + nthw_register_get_field(p->mp_reg_gty_ctl, MAC_PCS_GTY_CTL_RX_LPM_EN_1); + p->mp_field_gty_ctl_rx_lpm_en2 = + nthw_register_get_field(p->mp_reg_gty_ctl, MAC_PCS_GTY_CTL_RX_LPM_EN_2); + p->mp_field_gty_ctl_rx_lpm_en3 = + nthw_register_get_field(p->mp_reg_gty_ctl, MAC_PCS_GTY_CTL_RX_LPM_EN_3); + p->mp_field_gty_ctl_rx_equa_rst0 = + nthw_register_get_field(p->mp_reg_gty_ctl, MAC_PCS_GTY_CTL_RX_EQUA_RST_0); + p->mp_field_gty_ctl_rx_equa_rst1 = + nthw_register_get_field(p->mp_reg_gty_ctl, MAC_PCS_GTY_CTL_RX_EQUA_RST_1); + p->mp_field_gty_ctl_rx_equa_rst2 = + nthw_register_get_field(p->mp_reg_gty_ctl, MAC_PCS_GTY_CTL_RX_EQUA_RST_2); + p->mp_field_gty_ctl_rx_equa_rst3 = + nthw_register_get_field(p->mp_reg_gty_ctl, MAC_PCS_GTY_CTL_RX_EQUA_RST_3); + + /* DEBOUNCE_CTRL */ + p->mp_reg_debounce_ctrl = + nthw_module_get_register(p->mp_mod_mac_pcs, MAC_PCS_DEBOUNCE_CTRL); + p->mp_field_debounce_ctrl_nt_port_ctrl = + nthw_register_get_field(p->mp_reg_debounce_ctrl, + MAC_PCS_DEBOUNCE_CTRL_NT_PORT_CTRL); + + p->mp_reg_time_stamp_comp = + nthw_module_query_register(p->mp_mod_mac_pcs, MAC_PCS_TIMESTAMP_COMP); + + if (p->mp_reg_time_stamp_comp) { + /* TIMESTAMP_COMP */ + p->mp_field_time_stamp_comp_rx_dly = + nthw_register_get_field(p->mp_reg_time_stamp_comp, + MAC_PCS_TIMESTAMP_COMP_RX_DLY); + p->mp_field_time_stamp_comp_tx_dly = + nthw_register_get_field(p->mp_reg_time_stamp_comp, + MAC_PCS_TIMESTAMP_COMP_TX_DLY); + } + } + return 0; +} + +void nthw_mac_pcs_set_rx_enable(nthw_mac_pcs_t *p, bool enable) +{ + nthw_field_get_updated(p->mp_fld_pcs_config_rx_enable); + + if (enable) + nthw_field_set_flush(p->mp_fld_pcs_config_rx_enable); + + else + nthw_field_clr_flush(p->mp_fld_pcs_config_rx_enable); +} + +void nthw_mac_pcs_set_tx_enable(nthw_mac_pcs_t *p, bool enable) +{ + nthw_field_get_updated(p->mp_fld_pcs_config_tx_enable); + + if (enable) + nthw_field_set_flush(p->mp_fld_pcs_config_tx_enable); + + else + nthw_field_clr_flush(p->mp_fld_pcs_config_tx_enable); +} + +void nthw_mac_pcs_set_tx_sel_host(nthw_mac_pcs_t *p, bool enable) +{ + nthw_field_get_updated(p->mp_fld_phymac_misc_tx_sel_host); + + if (enable) + nthw_field_set_flush(p->mp_fld_phymac_misc_tx_sel_host); + + else + nthw_field_clr_flush(p->mp_fld_phymac_misc_tx_sel_host); +} + +void nthw_mac_pcs_set_tx_sel_tfg(nthw_mac_pcs_t *p, bool enable) +{ + nthw_field_get_updated(p->mp_fld_phymac_misc_tx_sel_tfg); + + if (enable) + nthw_field_set_flush(p->mp_fld_phymac_misc_tx_sel_tfg); + + else + nthw_field_clr_flush(p->mp_fld_phymac_misc_tx_sel_tfg); +} + +void nthw_mac_pcs_set_ts_eop(nthw_mac_pcs_t *p, bool enable) +{ + if (p->mp_fld_phymac_misc_ts_eop) { + nthw_field_get_updated(p->mp_fld_phymac_misc_ts_eop); + + if (enable) + nthw_field_set_flush(p->mp_fld_phymac_misc_ts_eop); + + else + nthw_field_clr_flush(p->mp_fld_phymac_misc_ts_eop); + } +} + +void nthw_mac_pcs_tx_path_rst(nthw_mac_pcs_t *p, bool enable) +{ + nthw_field_get_updated(p->mp_fld_pcs_config_tx_path_rst); + + if (enable) + nthw_field_set_flush(p->mp_fld_pcs_config_tx_path_rst); + + else + nthw_field_clr_flush(p->mp_fld_pcs_config_tx_path_rst); +} + +void nthw_mac_pcs_rx_path_rst(nthw_mac_pcs_t *p, bool enable) +{ + nthw_field_get_updated(p->mp_fld_pcs_config_rx_path_rst); + + if (enable) + nthw_field_set_flush(p->mp_fld_pcs_config_rx_path_rst); + + else + nthw_field_clr_flush(p->mp_fld_pcs_config_rx_path_rst); +} + +bool nthw_mac_pcs_is_rx_path_rst(nthw_mac_pcs_t *p) +{ + return nthw_field_get_updated(p->mp_fld_pcs_config_rx_path_rst); +} + +void nthw_mac_pcs_set_host_loopback(nthw_mac_pcs_t *p, bool enable) +{ + nthw_register_update(p->mp_reg_gty_loop); + + if (enable) { + nthw_field_set_val32(p->mp_fld_gty_loop_gt_loop0, 2); + nthw_field_set_val32(p->mp_fld_gty_loop_gt_loop1, 2); + nthw_field_set_val32(p->mp_fld_gty_loop_gt_loop2, 2); + nthw_field_set_val32(p->mp_fld_gty_loop_gt_loop3, 2); + + } else { + nthw_field_set_val32(p->mp_fld_gty_loop_gt_loop0, 0); + nthw_field_set_val32(p->mp_fld_gty_loop_gt_loop1, 0); + nthw_field_set_val32(p->mp_fld_gty_loop_gt_loop2, 0); + nthw_field_set_val32(p->mp_fld_gty_loop_gt_loop3, 0); + } + + nthw_register_flush(p->mp_reg_gty_loop, 1); +} + +void nthw_mac_pcs_set_line_loopback(nthw_mac_pcs_t *p, bool enable) +{ + nthw_register_update(p->mp_reg_gty_loop); + + if (enable) { + nthw_field_set_val32(p->mp_fld_gty_loop_gt_loop0, 4); + nthw_field_set_val32(p->mp_fld_gty_loop_gt_loop1, 4); + nthw_field_set_val32(p->mp_fld_gty_loop_gt_loop2, 4); + nthw_field_set_val32(p->mp_fld_gty_loop_gt_loop3, 4); + + } else { + nthw_field_set_val32(p->mp_fld_gty_loop_gt_loop0, 0); + nthw_field_set_val32(p->mp_fld_gty_loop_gt_loop1, 0); + nthw_field_set_val32(p->mp_fld_gty_loop_gt_loop2, 0); + nthw_field_set_val32(p->mp_fld_gty_loop_gt_loop3, 0); + } + + nthw_register_flush(p->mp_reg_gty_loop, 1); +} + +void nthw_mac_pcs_reset_bip_counters(nthw_mac_pcs_t *p) +{ + uint32_t lane_bit_errors[NTHW_MAC_PCS_LANES]; + nthw_register_update(p->mp_reg_bip_err); + nthw_field_get_val(p->mp_fld_reg_bip_err_bip_err, (uint32_t *)lane_bit_errors, + ARRAY_SIZE(lane_bit_errors)); + + (void)c_pcs_lanes; /* unused - kill warning */ +} + +bool nthw_mac_pcs_get_hi_ber(nthw_mac_pcs_t *p) +{ + return nthw_field_get_updated(p->mp_fld_stat_pcs_rx_hi_ber); +} + +void nthw_mac_pcs_get_link_summary(nthw_mac_pcs_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_local_fault, + uint32_t *p_remote_fault) +{ + nthw_register_update(p->mp_reg_link_summary); + + if (p_abs) + *p_abs = nthw_field_get_val32(p->mp_fld_link_summary_abs); + + if (p_nt_phy_link_state) { + *p_nt_phy_link_state = + nthw_field_get_val32(p->mp_fld_link_summary_nt_phy_link_state); + } + + if (p_lh_abs) + *p_lh_abs = nthw_field_get_val32(p->mp_fld_link_summary_lh_abs); + + if (p_ll_nt_phy_link_state) { + *p_ll_nt_phy_link_state = + nthw_field_get_val32(p->mp_fld_link_summary_ll_nt_phy_link_state); + } + + if (p_link_down_cnt) + *p_link_down_cnt = nthw_field_get_val32(p->mp_fld_link_summary_link_down_cnt); + + if (p_nim_interr) + *p_nim_interr = nthw_field_get_val32(p->mp_fld_link_summary_nim_interr); + + if (p_lh_local_fault) + *p_lh_local_fault = nthw_field_get_val32(p->mp_fld_link_summary_lh_local_fault); + + if (p_lh_remote_fault) + *p_lh_remote_fault = nthw_field_get_val32(p->mp_fld_link_summary_lh_remote_fault); + + if (p_local_fault) + *p_local_fault = nthw_field_get_val32(p->mp_fld_link_summary_local_fault); + + if (p_remote_fault) + *p_remote_fault = nthw_field_get_val32(p->mp_fld_link_summary_remote_fault); +} + +/* + * Returns true if the lane/block lock bits indicate that a reset is required. + * This is the case if Block/Lane lock is not all zero but not all set either. + */ +bool nthw_mac_pcs_reset_required(nthw_mac_pcs_t *p) +{ + uint32_t block_lock = nthw_mac_pcs_get_fld_block_lock_lock(p); + uint32_t lane_lock = nthw_mac_pcs_get_fld_lane_lock_lock(p); + uint32_t block_lock_mask = nthw_mac_pcs_get_fld_block_lock_lock_mask(p); + uint32_t lane_lock_mask = nthw_mac_pcs_get_fld_lane_lock_lock_mask(p); + + return ((block_lock != 0) && (block_lock != block_lock_mask)) || + ((lane_lock != 0) && (lane_lock != lane_lock_mask)); +} + +void nthw_mac_pcs_set_fec(nthw_mac_pcs_t *p, bool enable) +{ + NT_LOG(DBG, NTHW, "Port %u: Set FEC: %u\n", p->m_port_no, enable); + + nthw_field_get_updated(p->mp_field_fec_ctrl_reg_rs_fec_ctrl_in); + + if (enable) + nthw_field_set_val_flush32(p->mp_field_fec_ctrl_reg_rs_fec_ctrl_in, 0); + + else + nthw_field_set_val_flush32(p->mp_field_fec_ctrl_reg_rs_fec_ctrl_in, (1 << 5) - 1); + + /* Both Rx and Tx must be reset for new FEC state to become active */ + nthw_mac_pcs_rx_path_rst(p, true); + nthw_mac_pcs_tx_path_rst(p, true); + nt_os_wait_usec(10000); /* 10ms */ + + nthw_mac_pcs_rx_path_rst(p, false); + nthw_mac_pcs_tx_path_rst(p, false); + nt_os_wait_usec(10000); /* 10ms */ +} + +bool nthw_mac_pcs_get_fec_bypass(nthw_mac_pcs_t *p) +{ + return nthw_field_get_updated(p->mp_field_fec_stat_bypass); +} + +bool nthw_mac_pcs_get_fec_valid(nthw_mac_pcs_t *p) +{ + return nthw_field_get_updated(p->mp_field_fec_stat_valid); +} + +bool nthw_mac_pcs_get_fec_stat_all_am_locked(nthw_mac_pcs_t *p) +{ + nthw_register_update(p->mp_reg_fec_stat); + + if ((nthw_field_get_val32(p->mp_field_fec_stat_am_lock0)) && + (nthw_field_get_val32(p->mp_field_fec_stat_am_lock1)) && + (nthw_field_get_val32(p->mp_field_fec_stat_am_lock2)) && + (nthw_field_get_val32(p->mp_field_fec_stat_am_lock3))) { + return true; + } + + return false; +} + +void nthw_mac_pcs_reset_fec_counters(nthw_mac_pcs_t *p) +{ + nthw_register_update(p->mp_reg_fec_cw_cnt); + nthw_register_update(p->mp_reg_fec_ucw_cnt); + + if (nthw_field_get_val32(p->mp_field_fec_cw_cnt_cw_cnt)) { + NT_LOG(DBG, NTHW, "Port %u: FEC_CW_CNT: %u\n", p->m_port_no, + nthw_field_get_val32(p->mp_field_fec_cw_cnt_cw_cnt)); + } + + if (nthw_field_get_val32(p->mp_field_fec_ucw_cnt_ucw_cnt)) { + NT_LOG(DBG, NTHW, "Port %u: FEC_UCW_CNT: %u\n", p->m_port_no, + nthw_field_get_val32(p->mp_field_fec_ucw_cnt_ucw_cnt)); + } +} + +void nthw_mac_pcs_set_gty_tx_tuning(nthw_mac_pcs_t *p, uint8_t lane, uint8_t tx_pre_csr, + uint8_t tx_diff_ctl, uint8_t tx_post_csr) +{ + /* GTY_PRE_CURSOR */ + nthw_register_update(p->mp_reg_gty_pre_cursor); + + switch (lane) { + case 0: + nthw_field_set_val_flush32(p->mp_field_gty_pre_cursor_tx_pre_csr0, + tx_pre_csr & 0x1F); + break; + + case 1: + nthw_field_set_val_flush32(p->mp_field_gty_pre_cursor_tx_pre_csr1, + tx_pre_csr & 0x1F); + break; + + case 2: + nthw_field_set_val_flush32(p->mp_field_gty_pre_cursor_tx_pre_csr2, + tx_pre_csr & 0x1F); + break; + + case 3: + nthw_field_set_val_flush32(p->mp_field_gty_pre_cursor_tx_pre_csr3, + tx_pre_csr & 0x1F); + break; + } + + /* GTY_DIFF_CTL */ + nthw_register_update(p->mp_reg_gty_diff_ctl); + + switch (lane) { + case 0: + nthw_field_set_val_flush32(p->mp_field_gty_gty_diff_ctl_tx_diff_ctl0, + tx_diff_ctl & 0x1F); + break; + + case 1: + nthw_field_set_val_flush32(p->mp_field_gty_gty_diff_ctl_tx_diff_ctl1, + tx_diff_ctl & 0x1F); + break; + + case 2: + nthw_field_set_val_flush32(p->mp_field_gty_gty_diff_ctl_tx_diff_ctl2, + tx_diff_ctl & 0x1F); + break; + + case 3: + nthw_field_set_val_flush32(p->mp_field_gty_gty_diff_ctl_tx_diff_ctl3, + tx_diff_ctl & 0x1F); + break; + } + + /* GTY_POST_CURSOR */ + nthw_register_update(p->mp_reg_gty_post_cursor); + + switch (lane) { + case 0: + nthw_field_set_val_flush32(p->mp_field_gty_post_cursor_tx_post_csr0, + tx_post_csr & 0x1F); + break; + + case 1: + nthw_field_set_val_flush32(p->mp_field_gty_post_cursor_tx_post_csr1, + tx_post_csr & 0x1F); + break; + + case 2: + nthw_field_set_val_flush32(p->mp_field_gty_post_cursor_tx_post_csr2, + tx_post_csr & 0x1F); + break; + + case 3: + nthw_field_set_val_flush32(p->mp_field_gty_post_cursor_tx_post_csr3, + tx_post_csr & 0x1F); + break; + } + + NT_LOG(DBG, NTHW, + "Port %u, lane %u: GTY tx_pre_csr: %d, tx_diff_ctl: %d, tx_post_csr: %d\n", + p->m_port_no, lane, tx_pre_csr, tx_diff_ctl, tx_post_csr); +} + +/* + * Set receiver equalization mode + * 0: enable DFE + * 1: enable LPM + * + * See UltraScale Architecture GTY Transceivers www.xilinx.com page 181, + * UG578 (v1.1) November 24, 2015 + */ +void nthw_mac_pcs_set_receiver_equalization_mode(nthw_mac_pcs_t *p, uint8_t mode) +{ + nthw_register_update(p->mp_reg_gty_ctl); + nthw_field_set_val32(p->mp_field_gty_ctl_rx_lpm_en0, mode & 0x1); + nthw_field_set_val32(p->mp_field_gty_ctl_rx_lpm_en1, mode & 0x1); + nthw_field_set_val32(p->mp_field_gty_ctl_rx_lpm_en2, mode & 0x1); + nthw_field_set_val_flush32(p->mp_field_gty_ctl_rx_lpm_en3, mode & 0x1); + + /* Toggle reset */ + nthw_field_set_val32(p->mp_field_gty_ctl_rx_equa_rst0, 1); + nthw_field_set_val32(p->mp_field_gty_ctl_rx_equa_rst1, 1); + nthw_field_set_val32(p->mp_field_gty_ctl_rx_equa_rst2, 1); + nthw_field_set_val_flush32(p->mp_field_gty_ctl_rx_equa_rst3, 1); + + nt_os_wait_usec(1000); /* 1ms */ + + nthw_field_set_val32(p->mp_field_gty_ctl_rx_equa_rst0, 0); + nthw_field_set_val32(p->mp_field_gty_ctl_rx_equa_rst1, 0); + nthw_field_set_val32(p->mp_field_gty_ctl_rx_equa_rst2, 0); + nthw_field_set_val_flush32(p->mp_field_gty_ctl_rx_equa_rst3, 0); + + NT_LOG(DBG, NTHW, "Port %u: GTY receiver mode: %s\n", p->m_port_no, + (mode == c_mac_pcs_receiver_mode_dfe ? "DFE" : "LPM")); +} + +void nthw_mac_pcs_swap_gty_tx_polarity(nthw_mac_pcs_t *p, uint8_t lane, bool swap) +{ + nthw_register_update(p->mp_reg_gty_ctl); + + switch (lane) { + case 0: + nthw_field_set_val_flush32(p->mp_field_gty_ctl_tx_pol0, swap); + break; + + case 1: + nthw_field_set_val_flush32(p->mp_field_gty_ctl_tx_pol1, swap); + break; + + case 2: + nthw_field_set_val_flush32(p->mp_field_gty_ctl_tx_pol2, swap); + break; + + case 3: + nthw_field_set_val_flush32(p->mp_field_gty_ctl_tx_pol3, swap); + break; + } + + NT_LOG(DBG, NTHW, "Port %u: set GTY Tx lane (%d) polarity: %d\n", p->m_port_no, lane, + swap); +} + +void nthw_mac_pcs_swap_gty_rx_polarity(nthw_mac_pcs_t *p, uint8_t lane, bool swap) +{ + nthw_register_update(p->mp_reg_gty_ctl); + + switch (lane) { + case 0: + nthw_field_set_val_flush32(p->mp_field_gty_ctl_rx_pol0, swap); + break; + + case 1: + nthw_field_set_val_flush32(p->mp_field_gty_ctl_rx_pol1, swap); + break; + + case 2: + nthw_field_set_val_flush32(p->mp_field_gty_ctl_rx_pol2, swap); + break; + + case 3: + nthw_field_set_val_flush32(p->mp_field_gty_ctl_rx_pol3, swap); + break; + } + + NT_LOG(DBG, NTHW, "Port %u: set GTY Rx lane (%d) polarity: %d\n", p->m_port_no, lane, + swap); +} + +void nthw_mac_pcs_set_led_mode(nthw_mac_pcs_t *p, uint8_t mode) +{ + nthw_field_get_updated(p->mp_field_debounce_ctrl_nt_port_ctrl); + nthw_field_set_val_flush32(p->mp_field_debounce_ctrl_nt_port_ctrl, mode); +} + +void nthw_mac_pcs_set_timestamp_comp_rx(nthw_mac_pcs_t *p, uint16_t rx_dly) +{ + if (p->mp_field_time_stamp_comp_rx_dly) { + nthw_field_get_updated(p->mp_field_time_stamp_comp_rx_dly); + nthw_field_set_val_flush32(p->mp_field_time_stamp_comp_rx_dly, rx_dly); + } +} + +void nthw_mac_pcs_set_port_no(nthw_mac_pcs_t *p, uint8_t port_no) +{ + p->m_port_no = port_no; +} + +uint32_t nthw_mac_pcs_get_fld_block_lock_lock(nthw_mac_pcs_t *p) +{ + return nthw_field_get_updated(p->mp_fld_block_lock_lock); +} + +uint32_t nthw_mac_pcs_get_fld_block_lock_lock_mask(nthw_mac_pcs_t *p) +{ + return p->m_fld_block_lock_lock_mask; +} + +uint32_t nthw_mac_pcs_get_fld_lane_lock_lock(nthw_mac_pcs_t *p) +{ + return nthw_field_get_updated(p->mp_fld_vl_demuxed_lock); +} + +uint32_t nthw_mac_pcs_get_fld_lane_lock_lock_mask(nthw_mac_pcs_t *p) +{ + return p->m_fld_vl_demuxed_lock_mask; +} -- 2.45.0