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 8D74F45501; Wed, 26 Jun 2024 21:58:44 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 828BF40DD2; Wed, 26 Jun 2024 21:56:37 +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 8924B40E35 for ; Wed, 26 Jun 2024 21:56:34 +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:32 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=faNuVeWTd/7m9HpRSSOK0qtOabtQhz0bJ3sVRDsSJZafKIf2de2kSJugY4VTAnctlu278BLoFh5Mg6Krf32wkj2ltVwAZZEl0apy9KUx6bbd5T318725nKeA1rA4pwuc0cuk4Sjs5xHd1ESq7cRz6ydQjay1WvGfaTBIYH5x/9uDQX2XjjEM5xF0AjBmIiwnASVYon2fmSCLD4EZAGzfyGi1zPEJGoSl6sYWFFD3m5ZooI5PjrDWXZ/QGotBiJHkQVVXDV2XtVM1MmIk+8063/d/fTLquYnc2h9KSHhvWKHdq7W2bSZWBW52XJb2TunMOeOP6sqZ3qPEfLY6m6AtAQ== 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=CczwOubocpzwlyxhozdpUMeLccFA66H1QAyOKwAjdO0=; b=adr1WmnV/8nU33pLQI6tm7PlKmWh6+dAKy1y0zWdBXE4Bw7tc6tuScTqJVKvoGJxZtPeq5i//flVfeV5b+/7E9NKjyGfS6MsIp4f8bqGQX17Mir+gL/Fw7SXjh1yP5wXWZAxh2Z06Uunjf2g5wkArkH+jQOA6lxwkEKbaq6NC6Z2Xtt66PBpdiceFe2PPZJ3ghfSjYstp4gt053P2+aAobLDZbKqTcDXhyny9w9ltdzUcEmZwd8qfu0FjHPOjKpbJsSsBDhRj+t7q0GWgOEb7lQOpSGxVsFdO3gtpI6d4XtA9+XoCe2R6NARcRSRgIjrs86TZp3H0Bw5NvYW1nBclQ== 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=CczwOubocpzwlyxhozdpUMeLccFA66H1QAyOKwAjdO0=; b=EcgusuJPpppIUkV66y1XKbq9wynrpDxJmYXE0EJlcteG147teClhK/eg6zZD0lRua1SRwTdrjbH3S3FCgJrIbeDmnoFr8fITfScUE1oimHsOkBwx3tHiixm7QcWiwLCiCWKxJBNpqRMFfKIK03mDSkJNhc1e3cfFBErIEw0JWEU= Received: from AS4P250CA0023.EURP250.PROD.OUTLOOK.COM (2603:10a6:20b:5e3::11) 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:13 +0000 Received: from AMS0EPF000001AC.eurprd05.prod.outlook.com (2603:10a6:20b:5e3:cafe::dc) by AS4P250CA0023.outlook.office365.com (2603:10a6:20b:5e3::11) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7719.25 via Frontend Transport; Wed, 26 Jun 2024 19:56:11 +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:11 +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 18/23] net/ntnic: add NIM module Date: Wed, 26 Jun 2024 21:55:28 +0200 Message-ID: <20240626195545.1793419-18-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: 21ab98e7-9e2f-4399-ce68-08dc961a0768 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?EM2c18SD90/UWnBPD+dzsa68IOcbL1lHPGcy67g0A0UnwmiWUTOVrAAWlkTy?= =?us-ascii?Q?c6RTdlKNkvN6PVlbfun0wrzSiK0legkHJcLRlJ1jrq+zRnvkvsPcA1xVRvVK?= =?us-ascii?Q?q3btGtrz/VgTFKpHYtIYyGV3C18///hr7LKcCkvmo5kLslt3jwsTS23ZgLq0?= =?us-ascii?Q?7Gd1qYIJ3BNZ272ofUMEdOmXY3XWFEyhcM+rDLxOn1P4tZLWiWGfiXVEZCkE?= =?us-ascii?Q?ddYgUJOsVxt7qj5lTYJOG6ypYRaNDcBrRmQW0DtTKPwVGvnF0jtWNzN4cfF4?= =?us-ascii?Q?dnvn0rdy/rYaBWKBpcRv0fmjMAM6K0+AVVJgh0gW50l4qJEK+Rjbeyo0owpC?= =?us-ascii?Q?oamSGfFbZs4mCSTliHUBq1a7N0UPJo9cNvKTLU1WCLp0d+pYmFBMWGy36vO0?= =?us-ascii?Q?qEhcpHYdRvx1XE5fe5p2QCMhhnWISwTAXuVUoRKWUwQcolur9JDKBnwzOh26?= =?us-ascii?Q?NB8eP+29bCsPQ69EgfbXbu2UZ6gfhpDmHhkxIU7no6a7k1CrJWdO/43OPgah?= =?us-ascii?Q?EgECusomZ2oKXknPypupymN0YyBMX/E5h5/6MRk3Z5ZjKKtiGDnpofwjX/qJ?= =?us-ascii?Q?/pVkGjAr6aUmpFA5Y9WUQGR4CAXqgE8Gg/+j6lKYDNfpHUdPyx7sYFXk3gmG?= =?us-ascii?Q?YhKGR69oaGZ3f4fTXEbOdaW9ZjckTkBI7eux3okrH7CAUAOKOVz1WwYmCP5q?= =?us-ascii?Q?NEPHzPH3q/lbd1LnWNVIywa3hKnNHPASjI2xYWtgpPVieC8aRyP/UWI86ChB?= =?us-ascii?Q?7lypaPWw0X5dV4unBM0SgqpIiMqcy18B9osTMW0JFUlDgMpOXUzJPl9N6zkD?= =?us-ascii?Q?sX0WnUtYvH5nwHJaF5lgKMwyAaqANQeyCKVLv6YvxkHq8+Feh07yZ45mvC6/?= =?us-ascii?Q?76zr1cI1ZJja2hmnW+r/NrHoCoAAK03lL9wR+pq+fAhZqfZm2gqK4QC8gmbE?= =?us-ascii?Q?mzel+gX4jz4MDOKHmSucnBUsqc/DUxOYQNNSbiC7xXmiG2IZB3/Pgq0+2Kpr?= =?us-ascii?Q?lg6d6cCRwa7KdSQCUzFJlZc+Ve83EaWqub8VXrQqjREIhKONNAgDGY4Aryil?= =?us-ascii?Q?11bNDOqmGztSu5Xu4qFcKJg70drVqg0CHTwx/RmMKLJMonESFaarndtLuovF?= =?us-ascii?Q?fPP0T2lo6oEPwOrG4H5mB8tAMTnRvIFuJfN2ZEB/Z0+cKr2vY4YjFecxd6Yc?= =?us-ascii?Q?IeAOcAODyMyH5FEFQ+tzXbkBy223hZcm/3bhqSz6NKYUjk8e3Xfs83FuZsX5?= =?us-ascii?Q?jHBzfN/KD+xR9YObUn5yx3n5StaA7rm6FweSk0LPtwt7t9jdYn2UHtVD4dOk?= =?us-ascii?Q?uOfxN8HSKF1q/HgAdbDfluuX4fcN/eRMnEOEhvnsEYRuaIw76pm3ZxwU6wxw?= =?us-ascii?Q?ceyldRONr9LnFDHd0pzG6Wa2ByW4icSYtTUnCJL53GvwIOJcaSDq8CeQ++ib?= =?us-ascii?Q?iXtLZRR0Y0nayNN7de0x7IPiQs0BlQPo?= 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: jsKo6bk1tFNHPDi2CF4DWBAbkvWWZhQs1F9IrLHMJf51td52J/cxQsgUWt9kJrUmTpeeNKwiJ8LAlXWWK80bZHZj3G7tYLfVUrG6scK2FQJkgZz5+UB+9C0H/HrTPqWSo+xf3wxqXbOjaGGw3qJwtp1LW2sRDsRoxylcORud2rl3mYc7GlVdCk2tvN67JdUWUQG9A8//1AL7+w2OmT64H1V89CcBDrf4P0ozerHQDjOUryh7fGLIOb/QDTCTRc+eWExBtQgf12yw2QIjLR0ZZYKUiNzdodDLv818GJwKUUqUqsXlcK943U2HWMgZRvxQJTV944Z9140cjQzIkxlEy9uv+fYB4fCa6MNPBpD6yW71+vWSlKodUF1VSt1RTkp3f57KhsQwdPW7TRVrl3FkWEo5cGLscsmnVHhtL48BZnVPUQvNMkdi4Gs8lyoqd+WV+oU9IkZ5MMUVEnkkF+9htC6dXBCViBzlZdGb8ddw/iCbmGR+7Q/Zf1ToShZ99W2rjjpS31EjPtG3AchUNk61sBXeQ1U+1rH06JLd08Wsk4cmbYp4VNFRu+IiP/9NHgisKE767QR3xilz8onNtQfFE04PVOS7RJ5O8J8XILPJx4DOFfzbBFMCAstkzqFAwvc6iOIKDqg0o0UqmZH7F6gpbQ== X-OriginatorOrg: napatech.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 26 Jun 2024 19:56:11.5830 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 21ab98e7-9e2f-4399-ce68-08dc961a0768 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-3 X-BESS-VER: 2019.1_20240620.2317 X-BESS-Apparent-Source-IP: 104.47.17.104 X-BESS-Parts: H4sIAAAAAAACA4uuVkqtKFGyUioBkjpK+cVKVsYm5uYWQGYGUNTI2MDQwsTIyM IgycI82cwi1dLcIinJ0hDINUtONTdRqo0FAGJ4615CAAAA X-BESS-Outbound-Spam-Score: 0.50 X-BESS-Outbound-Spam-Report: Code version 3.2, rules version 3.2.2.257218 [from cloudscan11-42.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 X-BESS-Outbound-Spam-Status: SCORE=0.50 using account:ESS113687 scores of KILL_LEVEL=7.0 tests=BSF_RULE7568M, 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 control NIM Signed-off-by: Serhii Iliushyk --- drivers/net/ntnic/adapter/nt4ga_adapter.c | 34 +++ drivers/net/ntnic/include/nt4ga_adapter.h | 3 + drivers/net/ntnic/include/nt4ga_link.h | 13 + drivers/net/ntnic/include/ntnic_nim.h | 61 +++++ .../link_mgmt/link_100g/nt4ga_link_100g.c | 214 ++++++++++++++++- drivers/net/ntnic/link_mgmt/nt4ga_link.c | 13 + drivers/net/ntnic/meson.build | 3 + drivers/net/ntnic/nim/i2c_nim.c | 224 ++++++++++++++++++ drivers/net/ntnic/nim/i2c_nim.h | 24 ++ drivers/net/ntnic/nim/nim_defines.h | 29 +++ .../net/ntnic/nthw/core/include/nthw_core.h | 1 + .../net/ntnic/nthw/core/include/nthw_i2cm.h | 50 ++++ drivers/net/ntnic/nthw/core/nthw_fpga.c | 3 + drivers/net/ntnic/nthw/core/nthw_i2cm.c | 192 +++++++++++++++ drivers/net/ntnic/nthw/nthw_drv.h | 1 + drivers/net/ntnic/ntnic_mod_reg.h | 7 + 16 files changed, 871 insertions(+), 1 deletion(-) create mode 100644 drivers/net/ntnic/include/ntnic_nim.h create mode 100644 drivers/net/ntnic/nim/i2c_nim.c create mode 100644 drivers/net/ntnic/nim/i2c_nim.h create mode 100644 drivers/net/ntnic/nim/nim_defines.h create mode 100644 drivers/net/ntnic/nthw/core/include/nthw_i2cm.h create mode 100644 drivers/net/ntnic/nthw/core/nthw_i2cm.c diff --git a/drivers/net/ntnic/adapter/nt4ga_adapter.c b/drivers/net/ntnic/adapter/nt4ga_adapter.c index 807c1dcde3..b22ffd6cef 100644 --- a/drivers/net/ntnic/adapter/nt4ga_adapter.c +++ b/drivers/net/ntnic/adapter/nt4ga_adapter.c @@ -9,6 +9,32 @@ #include "nthw_fpga.h" #include "ntnic_mod_reg.h" +/* + * Global variables shared by NT adapter types + */ +rte_thread_t monitor_tasks[NUM_ADAPTER_MAX]; +volatile int monitor_task_is_running[NUM_ADAPTER_MAX]; + +/* + * Signal-handler to stop all monitor threads + */ +static void stop_monitor_tasks(int signum) +{ + const size_t N = ARRAY_SIZE(monitor_task_is_running); + size_t i; + + /* Stop all monitor tasks */ + for (i = 0; i < N; i++) { + const int is_running = monitor_task_is_running[i]; + monitor_task_is_running[i] = 0; + + if (signum == -1 && is_running != 0) { + rte_thread_join(monitor_tasks[i], NULL); + memset(&monitor_tasks[i], 0, sizeof(monitor_tasks[0])); + } + } +} + static int nt4ga_adapter_show_info(struct adapter_info_s *p_adapter_info, FILE *pfh) { const char *const p_dev_name = p_adapter_info->p_dev_name; @@ -35,6 +61,9 @@ static int nt4ga_adapter_show_info(struct adapter_info_s *p_adapter_info, FILE * p_fpga_info->n_fpga_ver_id, p_fpga_info->n_fpga_rev_id, p_fpga_info->n_fpga_ident, p_fpga_info->n_fpga_build_time); fprintf(pfh, "%s: FpgaDebugMode=0x%x\n", p_adapter_id_str, p_fpga_info->n_fpga_debug_mode); + fprintf(pfh, "%s: Nims=%d PhyPorts=%d PhyQuads=%d RxPorts=%d TxPorts=%d\n", + p_adapter_id_str, p_fpga_info->n_nims, p_fpga_info->n_phy_ports, + p_fpga_info->n_phy_quads, p_fpga_info->n_rx_ports, p_fpga_info->n_tx_ports); fprintf(pfh, "%s: Hw=0x%02X_rev%d: %s\n", p_adapter_id_str, p_hw_info->hw_platform_id, p_fpga_info->nthw_hw_info.hw_id, p_fpga_info->nthw_hw_info.hw_plat_id_str); fprintf(pfh, "%s: MCU Details:\n", p_adapter_id_str); @@ -56,6 +85,7 @@ static int nt4ga_adapter_init(struct adapter_info_s *p_adapter_info) * (nthw_fpga_init()) */ int n_phy_ports = -1; + int n_nim_ports = -1; int res = -1; nthw_fpga_t *p_fpga = NULL; @@ -124,6 +154,8 @@ static int nt4ga_adapter_init(struct adapter_info_s *p_adapter_info) assert(p_fpga); n_phy_ports = fpga_info->n_phy_ports; assert(n_phy_ports >= 1); + n_nim_ports = fpga_info->n_nims; + assert(n_nim_ports >= 1); { int i; @@ -173,6 +205,8 @@ static int nt4ga_adapter_deinit(struct adapter_info_s *p_adapter_info) int i; int res; + stop_monitor_tasks(-1); + nthw_fpga_shutdown(&p_adapter_info->fpga_info); /* Rac rab reset flip flop */ diff --git a/drivers/net/ntnic/include/nt4ga_adapter.h b/drivers/net/ntnic/include/nt4ga_adapter.h index ed14936b38..4b204742a2 100644 --- a/drivers/net/ntnic/include/nt4ga_adapter.h +++ b/drivers/net/ntnic/include/nt4ga_adapter.h @@ -39,5 +39,8 @@ typedef struct adapter_info_s { int n_tx_host_buffers; } adapter_info_t; +extern rte_thread_t monitor_tasks[NUM_ADAPTER_MAX]; +extern volatile int monitor_task_is_running[NUM_ADAPTER_MAX]; + #endif /* _NT4GA_ADAPTER_H_ */ diff --git a/drivers/net/ntnic/include/nt4ga_link.h b/drivers/net/ntnic/include/nt4ga_link.h index 849261ce3a..0851057f81 100644 --- a/drivers/net/ntnic/include/nt4ga_link.h +++ b/drivers/net/ntnic/include/nt4ga_link.h @@ -7,6 +7,7 @@ #define NT4GA_LINK_H_ #include "ntos_drv.h" +#include "ntnic_nim.h" enum nt_link_state_e { NT_LINK_STATE_UNKNOWN = 0, /* The link state has not been read yet */ @@ -41,6 +42,8 @@ enum nt_link_auto_neg_e { typedef struct link_state_s { bool link_disabled; + bool nim_present; + bool lh_nim_absent; bool link_up; enum nt_link_state_e link_state; enum nt_link_state_e link_state_latched; @@ -73,12 +76,22 @@ typedef struct port_action_s { uint32_t port_lpbk_mode; } port_action_t; +typedef struct adapter_100g_s { + nim_i2c_ctx_t nim_ctx[NUM_ADAPTER_PORTS_MAX]; /* Should be the first field */ +} adapter_100g_t; + +typedef union adapter_var_s { + nim_i2c_ctx_t nim_ctx[NUM_ADAPTER_PORTS_MAX]; /* First field in all the adapters type */ + adapter_100g_t var100g; +} adapter_var_u; + typedef struct nt4ga_link_s { link_state_t link_state[NUM_ADAPTER_PORTS_MAX]; link_info_t link_info[NUM_ADAPTER_PORTS_MAX]; port_action_t port_action[NUM_ADAPTER_PORTS_MAX]; uint32_t speed_capa; bool variables_initialized; + adapter_var_u u; } nt4ga_link_t; #endif /* NT4GA_LINK_H_ */ diff --git a/drivers/net/ntnic/include/ntnic_nim.h b/drivers/net/ntnic/include/ntnic_nim.h new file mode 100644 index 0000000000..263875a857 --- /dev/null +++ b/drivers/net/ntnic/include/ntnic_nim.h @@ -0,0 +1,61 @@ +/* + * SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2024 Napatech A/S + */ + +#ifndef _NTNIC_NIM_H_ +#define _NTNIC_NIM_H_ + +#include + +typedef enum i2c_type { + I2C_HWIIC, +} i2c_type_e; + +enum nt_port_type_e { + NT_PORT_TYPE_NOT_AVAILABLE = 0, /* The NIM/port type is not available (unknown) */ + NT_PORT_TYPE_NOT_RECOGNISED, /* The NIM/port type not recognized */ +}; + +typedef enum nt_port_type_e nt_port_type_t, *nt_port_type_p; + +typedef struct nim_i2c_ctx { + union { + nthw_iic_t hwiic; /* depends on *Fpga_t, instance number, and cycle time */ + struct { + nthw_i2cm_t *p_nt_i2cm; + int mux_channel; + } hwagx; + }; + i2c_type_e type;/* 0 = hwiic (xilinx) - 1 = hwagx (agilex) */ + uint8_t instance; + uint8_t devaddr; + uint8_t regaddr; + uint8_t nim_id; + nt_port_type_t port_type; + + char vendor_name[17]; + char prod_no[17]; + char serial_no[17]; + char date[9]; + char rev[5]; + bool avg_pwr; + bool content_valid; + uint8_t pwr_level_req; + uint8_t pwr_level_cur; + uint16_t len_info[5]; + uint32_t speed_mask; /* Speeds supported by the NIM */ + int8_t lane_idx; + uint8_t lane_count; + uint32_t options; + bool tx_disable; + bool dmi_supp; + +} nim_i2c_ctx_t, *nim_i2c_ctx_p; + +struct nim_sensor_group { + struct nim_i2c_ctx *ctx; + struct nim_sensor_group *next; +}; + +#endif /* _NTNIC_NIM_H_ */ 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 36c4bf031f..4c159431e1 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 @@ -7,16 +7,202 @@ #include "nt_util.h" #include "ntlog.h" +#include "i2c_nim.h" #include "ntnic_mod_reg.h" +/* + * Initialize NIM, Code based on nt200e3_2_ptp.cpp: MyPort::createNim() + */ +static int _create_nim(adapter_info_t *drv, int port) +{ + int res = 0; + const uint8_t valid_nim_id = 17U; + nim_i2c_ctx_t *nim_ctx; + nt4ga_link_t *link_info = &drv->nt4ga_link; + + assert(port >= 0 && port < NUM_ADAPTER_PORTS_MAX); + assert(link_info->variables_initialized); + + nim_ctx = &link_info->u.var100g.nim_ctx[port]; + + /* + * Wait a little after a module has been inserted before trying to access I2C + * data, otherwise the module will not respond correctly. + */ + nt_os_wait_usec(1000000); /* pause 1.0s */ + + res = construct_and_preinit_nim(nim_ctx); + + if (res) + return res; + + /* + * Does the driver support the NIM module type? + */ + if (nim_ctx->nim_id != valid_nim_id) { + NT_LOG(ERR, NTHW, "%s: The driver does not support the NIM module type %s\n", + drv->mp_port_id_str[port], nim_id_to_text(nim_ctx->nim_id)); + NT_LOG(DBG, NTHW, "%s: The driver supports the NIM module type %s\n", + drv->mp_port_id_str[port], nim_id_to_text(valid_nim_id)); + return -1; + } + + return res; +} + +/* + * Initialize one 100 Gbps port. + * 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) +{ + int res; + nt4ga_link_t *link_info = &drv->nt4ga_link; + + assert(port >= 0 && port < NUM_ADAPTER_PORTS_MAX); + assert(link_info->variables_initialized); + + /* + * Phase 1. Pre-state machine (`port init` functions) + * 1.1) nt4ga_adapter::port_init() + */ + + /* No adapter set-up here, only state variables */ + + /* 1.2) MyPort::init() */ + link_info->link_info[port].link_speed = NT_LINK_SPEED_100G; + 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; + + /* Phase 3. Link state machine steps */ + + /* 3.1) Create NIM, ::createNim() */ + res = _create_nim(drv, port); + + if (res) { + NT_LOG(WRN, NTNIC, "%s: NIM initialization failed\n", drv->mp_port_id_str[port]); + return res; + } + + NT_LOG(DBG, NTNIC, "%s: NIM initialized\n", drv->mp_port_id_str[port]); + + return res; +} + +/* + * State machine shared between kernel and userland + */ +static int _common_ptp_nim_state_machine(void *data) +{ + adapter_info_t *drv = (adapter_info_t *)data; + fpga_info_t *fpga_info = &drv->fpga_info; + nt4ga_link_t *link_info = &drv->nt4ga_link; + nthw_fpga_t *fpga = fpga_info->mp_fpga; + const int adapter_no = drv->adapter_no; + const int nb_ports = fpga_info->n_phy_ports; + uint32_t last_lpbk_mode[NUM_ADAPTER_PORTS_MAX]; + + link_state_t *link_state; + + if (!fpga) { + NT_LOG(ERR, NTNIC, "%s: fpga is NULL\n", drv->mp_adapter_id_str); + goto NT4GA_LINK_100G_MON_EXIT; + } + + assert(adapter_no >= 0 && adapter_no < NUM_ADAPTER_MAX); + link_state = link_info->link_state; + + monitor_task_is_running[adapter_no] = 1; + memset(last_lpbk_mode, 0, sizeof(last_lpbk_mode)); + + if (monitor_task_is_running[adapter_no]) + NT_LOG(DBG, NTNIC, "%s: link state machine running...\n", drv->mp_adapter_id_str); + + while (monitor_task_is_running[adapter_no]) { + int i; + + for (i = 0; i < nb_ports; i++) { + 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; + const bool enable_port = !is_port_disabled && was_port_disabled; + + if (!monitor_task_is_running[adapter_no]) /* stop quickly */ + break; + + /* Has the administrative port state changed? */ + assert(!(disable_port && enable_port)); + + if (disable_port) { + 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; + /* Turn off laser and LED, etc. */ + (void)_create_nim(drv, i); + NT_LOG(DBG, NTNIC, "%s: Port %i is disabled\n", + drv->mp_port_id_str[i], i); + continue; + } + + if (enable_port) { + link_state[i].link_disabled = false; + NT_LOG(DBG, NTNIC, "%s: Port %i is enabled\n", + drv->mp_port_id_str[i], i); + } + + if (is_port_disabled) + continue; + + if (link_info->port_action[i].port_lpbk_mode != last_lpbk_mode[i]) { + /* Loopback mode has changed. Do something */ + _port_init(drv, 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); + + if (link_info->port_action[i].port_lpbk_mode == 1) + link_state[i].link_up = true; + + last_lpbk_mode[i] = link_info->port_action[i].port_lpbk_mode; + continue; + } + + } /* end-for */ + + if (monitor_task_is_running[adapter_no]) + nt_os_wait_usec(5 * 100000U); /* 5 x 0.1s = 0.5s */ + } + +NT4GA_LINK_100G_MON_EXIT: + + NT_LOG(DBG, NTNIC, "%s: Stopped NT4GA 100 Gbps link monitoring thread.\n", + drv->mp_adapter_id_str); + + return 0; +} + +/* + * Userland NIM state machine + */ +static uint32_t nt4ga_link_100g_mon(void *data) +{ + (void)_common_ptp_nim_state_machine(data); + + return 0; +} + /* * Initialize all ports * The driver calls this function during initialization (of the driver). */ static int nt4ga_link_100g_ports_init(struct adapter_info_s *p_adapter_info, nthw_fpga_t *fpga) { - (void)fpga; + fpga_info_t *fpga_info = &p_adapter_info->fpga_info; const int adapter_no = p_adapter_info->adapter_no; + const int nb_ports = fpga_info->n_phy_ports; int res = 0; NT_LOG(DBG, NTNIC, "%s: Initializing ports\n", p_adapter_info->mp_adapter_id_str); @@ -27,12 +213,38 @@ 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) { + nim_i2c_ctx_t *nim_ctx = p_adapter_info->nt4ga_link.u.var100g.nim_ctx; + int i; + + for (i = 0; i < nb_ports; i++) { + /* 2 + adapter port number */ + const uint8_t instance = (uint8_t)(2U + i); + + res = nthw_iic_init(&nim_ctx[i].hwiic, fpga, instance, 8 /* timing */); + + if (res != 0) + break; + + nim_ctx[i].instance = instance; + nim_ctx[i].devaddr = 0x50; /* 0xA0 / 2 */ + nim_ctx[i].regaddr = 0U; + nim_ctx[i].type = I2C_HWIIC; + } + if (res == 0) { p_adapter_info->nt4ga_link.speed_capa = NT_LINK_SPEED_100G; p_adapter_info->nt4ga_link.variables_initialized = true; } } + /* Create state-machine thread */ + if (res == 0) { + if (!monitor_task_is_running[adapter_no]) { + res = rte_thread_create(&monitor_tasks[adapter_no], NULL, + nt4ga_link_100g_mon, p_adapter_info); + } + } + return res; } diff --git a/drivers/net/ntnic/link_mgmt/nt4ga_link.c b/drivers/net/ntnic/link_mgmt/nt4ga_link.c index b1e1184fdf..44805bc704 100644 --- a/drivers/net/ntnic/link_mgmt/nt4ga_link.c +++ b/drivers/net/ntnic/link_mgmt/nt4ga_link.c @@ -12,6 +12,7 @@ #include "ntnic_mod_reg.h" #include "nt4ga_link.h" +#include "i2c_nim.h" /* * port: speed capabilites @@ -26,6 +27,16 @@ static uint32_t nt4ga_port_get_link_speed_capabilities(struct adapter_info_s *p, return nt_link_speed_capa; } +/* + * port: nim present + */ +static bool nt4ga_port_get_nim_present(struct adapter_info_s *p, int port) +{ + nt4ga_link_t *const p_link = &p->nt4ga_link; + const bool nim_present = p_link->link_state[port].nim_present; + return nim_present; +} + /* * port: link mode */ @@ -131,6 +142,8 @@ static uint32_t nt4ga_port_get_loopback_mode(struct adapter_info_s *p, int port) static const struct port_ops ops = { + .get_nim_present = nt4ga_port_get_nim_present, + /* * port:s link mode */ diff --git a/drivers/net/ntnic/meson.build b/drivers/net/ntnic/meson.build index ace080c0b8..d6346a5986 100644 --- a/drivers/net/ntnic/meson.build +++ b/drivers/net/ntnic/meson.build @@ -22,6 +22,7 @@ includes = [ include_directories('nthw'), include_directories('nthw/supported'), include_directories('nthw/model'), + include_directories('nim/'), ] # all sources @@ -29,6 +30,7 @@ sources = files( 'adapter/nt4ga_adapter.c', 'link_mgmt/link_100g/nt4ga_link_100g.c', 'link_mgmt/nt4ga_link.c', + 'nim/i2c_nim.c', 'nthw/supported/nthw_fpga_9563_055_039_0000.c', 'nthw/supported/nthw_fpga_instances.c', 'nthw/supported/nthw_fpga_mod_str_map.c', @@ -38,6 +40,7 @@ sources = files( 'nthw/core/nt200a0x/reset/nthw_fpga_rst_nt200a0x.c', 'nthw/core/nthw_fpga.c', 'nthw/core/nthw_hif.c', + 'nthw/core/nthw_i2cm.c', 'nthw/core/nthw_iic.c', 'nthw/core/nthw_pcie3.c', 'nthw/core/nthw_sdc.c', diff --git a/drivers/net/ntnic/nim/i2c_nim.c b/drivers/net/ntnic/nim/i2c_nim.c new file mode 100644 index 0000000000..2918eda072 --- /dev/null +++ b/drivers/net/ntnic/nim/i2c_nim.c @@ -0,0 +1,224 @@ +/* + * SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#include /* memset */ + +#include "nthw_drv.h" +#include "i2c_nim.h" +#include "ntlog.h" +#include "nt_util.h" +#include "ntnic_mod_reg.h" +#include "nim_defines.h" + +#define NIM_READ false +#define NIM_WRITE true +#define NIM_PAGE_SEL_REGISTER 127 +#define NIM_I2C_0XA0 0xA0 /* Basic I2C address */ + +static int nim_read_write_i2c_data(nim_i2c_ctx_p ctx, bool do_write, uint16_t lin_addr, + uint8_t i2c_addr, uint8_t a_reg_addr, uint8_t seq_cnt, + uint8_t *p_data) +{ + /* Divide i2c_addr by 2 because nthw_iic_read/writeData multiplies by 2 */ + const uint8_t i2c_devaddr = i2c_addr / 2U; + (void)lin_addr; /* Unused */ + + if (do_write) { + if (ctx->type == I2C_HWIIC) { + return nthw_iic_write_data(&ctx->hwiic, i2c_devaddr, a_reg_addr, seq_cnt, + p_data); + + } else { + return 0; + } + + } else if (ctx->type == I2C_HWIIC) { + return nthw_iic_read_data(&ctx->hwiic, i2c_devaddr, a_reg_addr, seq_cnt, p_data); + + } else { + return 0; + } +} + +/* + * ------------------------------------------------------------------------------ + * Selects a new page for page addressing. This is only relevant if the NIM + * supports this. Since page switching can take substantial time the current page + * select is read and subsequently only changed if necessary. + * Important: + * XFP Standard 8077, Ver 4.5, Page 61 states that: + * If the host attempts to write a table select value which is not supported in + * a particular module, the table select byte will revert to 01h. + * This can lead to some surprising result that some pages seems to be duplicated. + * ------------------------------------------------------------------------------ + */ + +static int nim_setup_page(nim_i2c_ctx_p ctx, uint8_t page_sel) +{ + uint8_t curr_page_sel; + + /* Read the current page select value */ + if (nim_read_write_i2c_data(ctx, NIM_READ, NIM_PAGE_SEL_REGISTER, NIM_I2C_0XA0, + NIM_PAGE_SEL_REGISTER, sizeof(curr_page_sel), + &curr_page_sel) != 0) { + return -1; + } + + /* Only write new page select value if necessary */ + if (page_sel != curr_page_sel) { + if (nim_read_write_i2c_data(ctx, NIM_WRITE, NIM_PAGE_SEL_REGISTER, NIM_I2C_0XA0, + NIM_PAGE_SEL_REGISTER, sizeof(page_sel), + &page_sel) != 0) { + return -1; + } + } + + return 0; +} + +static int nim_read_write_data_lin(nim_i2c_ctx_p ctx, bool m_page_addressing, uint16_t lin_addr, + uint16_t length, uint8_t *p_data, bool do_write) +{ + uint16_t i; + uint8_t a_reg_addr; /* The actual register address in I2C device */ + uint8_t i2c_addr; + int block_size = 128; /* Equal to size of MSA pages */ + int seq_cnt; + int max_seq_cnt = 1; + int multi_byte = 1; /* One byte per I2C register is default */ + + for (i = 0; i < length;) { + bool use_page_select = false; + + /* + * Find out how much can be read from the current block in case of + * single byte access + */ + if (multi_byte == 1) + max_seq_cnt = block_size - (lin_addr % block_size); + + if (m_page_addressing) { + if (lin_addr >= 128) { /* Only page setup above this address */ + use_page_select = true; + + /* Map to [128..255] of 0xA0 device */ + a_reg_addr = (uint8_t)(block_size + (lin_addr % block_size)); + + } else { + a_reg_addr = (uint8_t)lin_addr; + } + + i2c_addr = NIM_I2C_0XA0;/* Base I2C address */ + + } else if (lin_addr >= 256) { + /* Map to address [0..255] of 0xA2 device */ + a_reg_addr = (uint8_t)(lin_addr - 256); + i2c_addr = NIM_I2C_0XA2; + + } else { + a_reg_addr = (uint8_t)lin_addr; + i2c_addr = NIM_I2C_0XA0;/* Base I2C address */ + } + + /* Now actually do the reading/writing */ + seq_cnt = length - i; /* Number of remaining bytes */ + + if (seq_cnt > max_seq_cnt) + seq_cnt = max_seq_cnt; + + /* + * Read a number of bytes without explicitly specifying a new address. + * This can speed up I2C access since automatic incrementation of the + * I2C device internal address counter can be used. It also allows + * a HW implementation, that can deal with block access. + * Furthermore it also allows for access to data that must be accessed + * as 16bit words reading two bytes at each address eg PHYs. + */ + if (use_page_select) { + if (nim_setup_page(ctx, (uint8_t)((lin_addr / 128) - 1)) != 0) { + NT_LOG(ERR, NTNIC, + "Cannot set up page for linear address %u\n", lin_addr); + return -1; + } + } + + if (nim_read_write_i2c_data(ctx, do_write, lin_addr, i2c_addr, a_reg_addr, + (uint8_t)seq_cnt, p_data) != 0) { + NT_LOG(ERR, NTNIC, " Call to nim_read_write_i2c_data failed\n"); + return -1; + } + + p_data += seq_cnt; + i = (uint16_t)(i + seq_cnt); + lin_addr = (uint16_t)(lin_addr + (seq_cnt / multi_byte)); + } + + return 0; +} + +static int nim_read_id(nim_i2c_ctx_t *ctx) +{ + /* We are only reading the first byte so we don't care about pages here. */ + const bool USE_PAGE_ADDRESSING = false; + + if (nim_read_write_data_lin(ctx, USE_PAGE_ADDRESSING, NIM_IDENTIFIER_ADDR, + sizeof(ctx->nim_id), &ctx->nim_id, NIM_READ) != 0) { + return -1; + } + + return 0; +} + +static int i2c_nim_common_construct(nim_i2c_ctx_p ctx) +{ + ctx->nim_id = 0; + int res; + + if (ctx->type == I2C_HWIIC) + res = nim_read_id(ctx); + + else + res = -1; + + if (res) { + NT_LOG(ERR, PMD, "Can't read NIM id."); + return res; + } + + memset(ctx->vendor_name, 0, sizeof(ctx->vendor_name)); + memset(ctx->prod_no, 0, sizeof(ctx->prod_no)); + memset(ctx->serial_no, 0, sizeof(ctx->serial_no)); + memset(ctx->date, 0, sizeof(ctx->date)); + memset(ctx->rev, 0, sizeof(ctx->rev)); + + ctx->content_valid = false; + memset(ctx->len_info, 0, sizeof(ctx->len_info)); + ctx->pwr_level_req = 0; + ctx->pwr_level_cur = 0; + ctx->avg_pwr = false; + ctx->tx_disable = false; + ctx->lane_idx = -1; + ctx->lane_count = 1; + ctx->options = 0; + return 0; +} + +const char *nim_id_to_text(uint8_t nim_id) +{ + switch (nim_id) { + case 0x0: + return "UNKNOWN"; + + default: + return "ILLEGAL!"; + } +} + +int construct_and_preinit_nim(nim_i2c_ctx_p ctx) +{ + int res = i2c_nim_common_construct(ctx); + + return res; +} diff --git a/drivers/net/ntnic/nim/i2c_nim.h b/drivers/net/ntnic/nim/i2c_nim.h new file mode 100644 index 0000000000..e89ae47835 --- /dev/null +++ b/drivers/net/ntnic/nim/i2c_nim.h @@ -0,0 +1,24 @@ +/* + * SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef I2C_NIM_H_ +#define I2C_NIM_H_ + +#include "ntnic_nim.h" + +/* + * Returns a type name such as "SFP/SFP+" for a given NIM type identifier, + * or the string "ILLEGAL!". + */ +const char *nim_id_to_text(uint8_t nim_id); + +/* + * This function tries to classify NIM based on it's ID and some register reads + * and collects information into ctx structure. The @extra parameter could contain + * the initialization argument for specific type of NIMS. + */ +int construct_and_preinit_nim(nim_i2c_ctx_p ctx); + +#endif /* I2C_NIM_H_ */ diff --git a/drivers/net/ntnic/nim/nim_defines.h b/drivers/net/ntnic/nim/nim_defines.h new file mode 100644 index 0000000000..9ba861bb4f --- /dev/null +++ b/drivers/net/ntnic/nim/nim_defines.h @@ -0,0 +1,29 @@ +/* + * SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef NIM_DEFINES_H_ +#define NIM_DEFINES_H_ + +#define NIM_IDENTIFIER_ADDR 0 /* 1 byte */ + +/* I2C addresses */ +#define NIM_I2C_0XA0 0xA0 /* Basic I2C address */ +#define NIM_I2C_0XA2 0xA2 /* Diagnostic monitoring */ + +typedef enum { + NIM_OPTION_TX_DISABLE, + /* Indicates that the module should be checked for the two next FEC types */ + NIM_OPTION_FEC, + NIM_OPTION_MEDIA_SIDE_FEC, + NIM_OPTION_HOST_SIDE_FEC, + NIM_OPTION_RX_ONLY +} nim_option_t; + +enum nt_nim_identifier_e { + NT_NIM_UNKNOWN = 0x00, /* Nim type is unknown */ +}; +typedef enum nt_nim_identifier_e nt_nim_identifier_t; + +#endif /* NIM_DEFINES_H_ */ diff --git a/drivers/net/ntnic/nthw/core/include/nthw_core.h b/drivers/net/ntnic/nthw/core/include/nthw_core.h index 5648bd8983..8d9d78b86d 100644 --- a/drivers/net/ntnic/nthw/core/include/nthw_core.h +++ b/drivers/net/ntnic/nthw/core/include/nthw_core.h @@ -15,6 +15,7 @@ #include "nthw_hif.h" #include "nthw_pcie3.h" #include "nthw_iic.h" +#include "nthw_i2cm.h" #include "nthw_sdc.h" diff --git a/drivers/net/ntnic/nthw/core/include/nthw_i2cm.h b/drivers/net/ntnic/nthw/core/include/nthw_i2cm.h new file mode 100644 index 0000000000..6e0ec4cf5e --- /dev/null +++ b/drivers/net/ntnic/nthw/core/include/nthw_i2cm.h @@ -0,0 +1,50 @@ +/* + * SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Napatech A/S + */ + +#ifndef __NTHW_II2CM_H__ +#define __NTHW_II2CM_H__ + +#include "nthw_fpga_model.h" +#include "pthread.h" + +struct nt_i2cm { + nthw_fpga_t *mp_fpga; + + nthw_module_t *m_mod_i2cm; + + int mn_i2c_instance; + + nthw_register_t *mp_reg_prer_low; + nthw_field_t *mp_fld_prer_low_prer_low; + + nthw_register_t *mp_reg_prer_high; + nthw_field_t *mp_fld_prer_high_prer_high; + + nthw_register_t *mp_reg_ctrl; + nthw_field_t *mp_fld_ctrl_ien; + nthw_field_t *mp_fld_ctrl_en; + + nthw_register_t *mp_reg_data; + nthw_field_t *mp_fld_data_data; + + nthw_register_t *mp_reg_cmd_status; + nthw_field_t *mp_fld_cmd_status_cmd_status; + + nthw_register_t *mp_reg_select; + nthw_field_t *mp_fld_select_select; + + nthw_register_t *mp_reg_io_exp; + nthw_field_t *mp_fld_io_exp_rst; + nthw_field_t *mp_fld_io_exp_int_b; + + pthread_mutex_t i2cmmutex; +}; + +typedef struct nt_i2cm nthw_i2cm_t; + +int nthw_i2cm_read(nthw_i2cm_t *p, uint8_t dev_addr, uint8_t reg_addr, uint8_t *value); +int nthw_i2cm_write(nthw_i2cm_t *p, uint8_t dev_addr, uint8_t reg_addr, uint8_t value); + +#endif /* __NTHW_II2CM_H__ */ diff --git a/drivers/net/ntnic/nthw/core/nthw_fpga.c b/drivers/net/ntnic/nthw/core/nthw_fpga.c index 38169176a5..d70205e5e3 100644 --- a/drivers/net/ntnic/nthw/core/nthw_fpga.c +++ b/drivers/net/ntnic/nthw/core/nthw_fpga.c @@ -19,12 +19,14 @@ int nthw_fpga_get_param_info(struct fpga_info_s *p_fpga_info, nthw_fpga_t *p_fpg { 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; @@ -236,6 +238,7 @@ int nthw_fpga_init(struct fpga_info_s *p_fpga_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); diff --git a/drivers/net/ntnic/nthw/core/nthw_i2cm.c b/drivers/net/ntnic/nthw/core/nthw_i2cm.c new file mode 100644 index 0000000000..b5f8e299ff --- /dev/null +++ b/drivers/net/ntnic/nthw/core/nthw_i2cm.c @@ -0,0 +1,192 @@ +/* + * 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_i2cm.h" + +#define NT_I2C_CMD_START 0x80 +#define NT_I2C_CMD_STOP 0x40 +#define NT_I2C_CMD_RD 0x20 +#define NT_I2C_CMD_WR 0x10 +#define NT_I2C_CMD_NACK 0x08 +#define NT_I2C_CMD_IRQ_ACK 0x01 + +#define NT_I2C_STATUS_NACK 0x80 +#define NT_I2C_STATUS_TIP 0x02 + +#define NT_I2C_TRANSMIT_WR 0x00 +#define NT_I2C_TRANSMIT_RD 0x01 + +#define NUM_RETRIES 50U +#define SLEEP_USECS 100U/* 0.1 ms */ + + +static bool nthw_i2cm_ready(nthw_i2cm_t *p, bool wait_for_ack) +{ + uint32_t flags = NT_I2C_STATUS_TIP | (wait_for_ack ? NT_I2C_STATUS_NACK : 0U); + + for (uint32_t i = 0U; i < NUM_RETRIES; i++) { + uint32_t status = nthw_field_get_updated(p->mp_fld_cmd_status_cmd_status); + uint32_t ready = (status & flags) == 0U; + /* MUST have a short break to avoid time-outs, even if ready == true */ + nt_os_wait_usec(SLEEP_USECS); + + if (ready) + return true; + } + + return false; +} + +static int nthw_i2cm_write_internal(nthw_i2cm_t *p, uint8_t value) +{ + /* Write data to data register */ + nthw_field_set_val_flush32(p->mp_fld_data_data, value); + nthw_field_set_val_flush32(p->mp_fld_cmd_status_cmd_status, + NT_I2C_CMD_WR | NT_I2C_CMD_IRQ_ACK); + + if (!nthw_i2cm_ready(p, true)) { + nthw_field_set_val_flush32(p->mp_fld_cmd_status_cmd_status, + NT_I2C_CMD_STOP | NT_I2C_CMD_IRQ_ACK); + NT_LOG(ERR, NTHW, "%s: Time-out writing data %u", __PRETTY_FUNCTION__, value); + return 1; + } + + /* Generate stop condition and clear interrupt */ + nthw_field_set_val_flush32(p->mp_fld_cmd_status_cmd_status, + NT_I2C_CMD_STOP | NT_I2C_CMD_IRQ_ACK); + + if (!nthw_i2cm_ready(p, true)) { + nthw_field_set_val_flush32(p->mp_fld_cmd_status_cmd_status, + NT_I2C_CMD_STOP | NT_I2C_CMD_IRQ_ACK); + NT_LOG(ERR, NTHW, "%s: Time-out sending stop condition", __PRETTY_FUNCTION__); + return 1; + } + + return 0; +} + +static int nthw_i2cm_write_reg_addr_internal(nthw_i2cm_t *p, uint8_t dev_addr, uint8_t reg_addr, + bool send_stop) +{ + /* Write device address to data register */ + nthw_field_set_val_flush32(p->mp_fld_data_data, + (uint8_t)(dev_addr << 1 | NT_I2C_TRANSMIT_WR)); + + /* #Set start condition along with secondary I2C dev_addr */ + nthw_field_set_val_flush32(p->mp_fld_cmd_status_cmd_status, + NT_I2C_CMD_START | NT_I2C_CMD_WR | NT_I2C_CMD_IRQ_ACK); + + if (!nthw_i2cm_ready(p, true)) { + nthw_field_set_val_flush32(p->mp_fld_cmd_status_cmd_status, + NT_I2C_CMD_STOP | NT_I2C_CMD_IRQ_ACK); + NT_LOG(ERR, NTHW, "%s: Time-out writing device address %u, reg_addr=%u", + __PRETTY_FUNCTION__, dev_addr, reg_addr); + return 1; + } + + /* Writing I2C register address */ + nthw_field_set_val_flush32(p->mp_fld_data_data, reg_addr); + + if (send_stop) { + nthw_field_set_val_flush32(p->mp_fld_cmd_status_cmd_status, + NT_I2C_CMD_WR | NT_I2C_CMD_IRQ_ACK | NT_I2C_CMD_STOP); + + } else { + nthw_field_set_val_flush32(p->mp_fld_cmd_status_cmd_status, + NT_I2C_CMD_WR | NT_I2C_CMD_IRQ_ACK); + } + + if (!nthw_i2cm_ready(p, true)) { + nthw_field_set_val_flush32(p->mp_fld_cmd_status_cmd_status, + NT_I2C_CMD_STOP | NT_I2C_CMD_IRQ_ACK); + NT_LOG(ERR, NTHW, "%s: Time-out writing register address %u", __PRETTY_FUNCTION__, + reg_addr); + return 1; + } + + return 0; +} + +static int nthw_i2cm_read_internal(nthw_i2cm_t *p, uint8_t dev_addr, uint8_t *value) +{ + /* Write I2C device address - with LSBit set to READ */ + + nthw_field_set_val_flush32(p->mp_fld_data_data, + (uint8_t)(dev_addr << 1 | NT_I2C_TRANSMIT_RD)); + /* #Send START condition along with secondary I2C dev_addr */ + nthw_field_set_val_flush32(p->mp_fld_cmd_status_cmd_status, + NT_I2C_CMD_START | NT_I2C_CMD_WR | NT_I2C_CMD_IRQ_ACK); + + if (!nthw_i2cm_ready(p, true)) { + nthw_field_set_val_flush32(p->mp_fld_cmd_status_cmd_status, + NT_I2C_CMD_STOP | NT_I2C_CMD_IRQ_ACK); + NT_LOG(ERR, NTHW, "%s: Time-out rewriting device address %u", __PRETTY_FUNCTION__, + dev_addr); + return 1; + } + + nthw_field_set_val_flush32(p->mp_fld_cmd_status_cmd_status, + NT_I2C_CMD_RD | NT_I2C_CMD_NACK | NT_I2C_CMD_IRQ_ACK); + + if (!nthw_i2cm_ready(p, false)) { + nthw_field_set_val_flush32(p->mp_fld_cmd_status_cmd_status, + NT_I2C_CMD_STOP | NT_I2C_CMD_IRQ_ACK); + NT_LOG(ERR, NTHW, "%s: Time-out during read operation", __PRETTY_FUNCTION__); + return 1; + } + + *value = (uint8_t)nthw_field_get_updated(p->mp_fld_data_data); + + /* Generate stop condition and clear interrupt */ + nthw_field_set_val_flush32(p->mp_fld_cmd_status_cmd_status, + NT_I2C_CMD_STOP | NT_I2C_CMD_IRQ_ACK); + + if (!nthw_i2cm_ready(p, false)) { + nthw_field_set_val_flush32(p->mp_fld_cmd_status_cmd_status, + NT_I2C_CMD_STOP | NT_I2C_CMD_IRQ_ACK); + NT_LOG(ERR, NTHW, "%s: Time-out sending stop condition", __PRETTY_FUNCTION__); + return 1; + } + + return 0; +} + +int nthw_i2cm_read(nthw_i2cm_t *p, uint8_t dev_addr, uint8_t reg_addr, uint8_t *value) +{ + int status; + status = nthw_i2cm_write_reg_addr_internal(p, dev_addr, reg_addr, false); + + if (status != 0) + return status; + + status = nthw_i2cm_read_internal(p, dev_addr, value); + + if (status != 0) + return status; + + return 0; +} + +int nthw_i2cm_write(nthw_i2cm_t *p, uint8_t dev_addr, uint8_t reg_addr, uint8_t value) +{ + int status; + status = nthw_i2cm_write_reg_addr_internal(p, dev_addr, reg_addr, false); + + if (status != 0) + return status; + + status = nthw_i2cm_write_internal(p, value); + + if (status != 0) + return status; + + return 0; +} diff --git a/drivers/net/ntnic/nthw/nthw_drv.h b/drivers/net/ntnic/nthw/nthw_drv.h index 071618eb6e..de60ae171e 100644 --- a/drivers/net/ntnic/nthw/nthw_drv.h +++ b/drivers/net/ntnic/nthw/nthw_drv.h @@ -52,6 +52,7 @@ typedef struct fpga_info_s { int n_fpga_debug_mode; + int n_nims; int n_phy_ports; int n_phy_quads; int n_rx_ports; diff --git a/drivers/net/ntnic/ntnic_mod_reg.h b/drivers/net/ntnic/ntnic_mod_reg.h index 68629412b7..3189b04f33 100644 --- a/drivers/net/ntnic/ntnic_mod_reg.h +++ b/drivers/net/ntnic/ntnic_mod_reg.h @@ -22,6 +22,8 @@ const struct link_ops_s *get_100g_link_ops(void); void link_100g_init(void); struct port_ops { + bool (*get_nim_present)(struct adapter_info_s *p, int port); + /* * port:s link mode */ @@ -60,6 +62,11 @@ struct port_ops { uint32_t (*get_link_speed_capabilities)(struct adapter_info_s *p, int port); + /* + * port: nim capabilities + */ + nim_i2c_ctx_t (*get_nim_capabilities)(struct adapter_info_s *p, int port); + /* * port: tx power */ -- 2.45.0