Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/2197263/?format=api
{ "id": 2197263, "url": "http://patchwork.ozlabs.org/api/patches/2197263/?format=api", "web_url": "http://patchwork.ozlabs.org/project/intel-wired-lan/patch/20260217155808.1209194-1-arkadiusz.kubalewski@intel.com/", "project": { "id": 46, "url": "http://patchwork.ozlabs.org/api/projects/46/?format=api", "name": "Intel Wired Ethernet development", "link_name": "intel-wired-lan", "list_id": "intel-wired-lan.osuosl.org", "list_email": "intel-wired-lan@osuosl.org", "web_url": "", "scm_url": "", "webscm_url": "", "list_archive_url": "", "list_archive_url_format": "", "commit_url_format": "" }, "msgid": "<20260217155808.1209194-1-arkadiusz.kubalewski@intel.com>", "list_archive_url": null, "date": "2026-02-17T15:58:08", "name": "[iwl-next,v11] ice: add support for unmanaged DPLL on E830 NIC", "commit_ref": null, "pull_url": null, "state": "under-review", "archived": false, "hash": "295b2981a17f7aaaff3993344873fd22a643f539", "submitter": { "id": 78857, "url": "http://patchwork.ozlabs.org/api/people/78857/?format=api", "name": "Kubalewski, Arkadiusz", "email": "arkadiusz.kubalewski@intel.com" }, "delegate": { "id": 109701, "url": "http://patchwork.ozlabs.org/api/users/109701/?format=api", "username": "anguy11", "first_name": "Anthony", "last_name": "Nguyen", "email": "anthony.l.nguyen@intel.com" }, "mbox": "http://patchwork.ozlabs.org/project/intel-wired-lan/patch/20260217155808.1209194-1-arkadiusz.kubalewski@intel.com/mbox/", "series": [ { "id": 492446, "url": "http://patchwork.ozlabs.org/api/series/492446/?format=api", "web_url": "http://patchwork.ozlabs.org/project/intel-wired-lan/list/?series=492446", "date": "2026-02-17T15:58:08", "name": "[iwl-next,v11] ice: add support for unmanaged DPLL on E830 NIC", "version": 11, "mbox": "http://patchwork.ozlabs.org/series/492446/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/2197263/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/2197263/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "<intel-wired-lan-bounces@osuosl.org>", "X-Original-To": [ "incoming@patchwork.ozlabs.org", "intel-wired-lan@lists.osuosl.org" ], "Delivered-To": [ "patchwork-incoming@legolas.ozlabs.org", "intel-wired-lan@lists.osuosl.org" ], "Authentication-Results": [ "legolas.ozlabs.org;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=osuosl.org header.i=@osuosl.org header.a=rsa-sha256\n header.s=default header.b=8DgoZvp/;\n\tdkim-atps=neutral", "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=osuosl.org\n (client-ip=2605:bc80:3010::138; helo=smtp1.osuosl.org;\n envelope-from=intel-wired-lan-bounces@osuosl.org;\n receiver=patchwork.ozlabs.org)" ], "Received": [ "from smtp1.osuosl.org (smtp1.osuosl.org [IPv6:2605:bc80:3010::138])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4fFkxN6Qchz1xpY\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 18 Feb 2026 03:04:56 +1100 (AEDT)", "from localhost (localhost [127.0.0.1])\n\tby smtp1.osuosl.org (Postfix) with ESMTP id 3BF6081239;\n\tTue, 17 Feb 2026 16:04:55 +0000 (UTC)", "from smtp1.osuosl.org ([127.0.0.1])\n by localhost (smtp1.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP\n id 4osG0ST0MzTg; Tue, 17 Feb 2026 16:04:53 +0000 (UTC)", "from lists1.osuosl.org (lists1.osuosl.org [140.211.166.142])\n\tby smtp1.osuosl.org (Postfix) with ESMTP id 7C16281274;\n\tTue, 17 Feb 2026 16:04:53 +0000 (UTC)", "from smtp1.osuosl.org (smtp1.osuosl.org [IPv6:2605:bc80:3010::138])\n by lists1.osuosl.org (Postfix) with ESMTP id 2AB491EB\n for <intel-wired-lan@lists.osuosl.org>; Tue, 17 Feb 2026 16:04:52 +0000 (UTC)", "from localhost (localhost [127.0.0.1])\n by smtp1.osuosl.org (Postfix) with ESMTP id 0BB0F80CD3\n for <intel-wired-lan@lists.osuosl.org>; Tue, 17 Feb 2026 16:04:52 +0000 (UTC)", "from smtp1.osuosl.org ([127.0.0.1])\n by localhost (smtp1.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP\n id Oi0GF8HZhvwd for <intel-wired-lan@lists.osuosl.org>;\n Tue, 17 Feb 2026 16:04:50 +0000 (UTC)", "from mgamail.intel.com (mgamail.intel.com [192.198.163.17])\n by smtp1.osuosl.org (Postfix) with ESMTPS id 0145280C80\n for <intel-wired-lan@lists.osuosl.org>; Tue, 17 Feb 2026 16:04:49 +0000 (UTC)", "from fmviesa003.fm.intel.com ([10.60.135.143])\n by fmvoesa111.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384;\n 17 Feb 2026 08:04:49 -0800", "from amlin-018-114.igk.intel.com ([10.102.18.114])\n by fmviesa003.fm.intel.com with ESMTP; 17 Feb 2026 08:04:45 -0800" ], "X-Virus-Scanned": [ "amavis at osuosl.org", "amavis at osuosl.org" ], "X-Comment": "SPF check N/A for local connections - client-ip=140.211.166.142;\n helo=lists1.osuosl.org; envelope-from=intel-wired-lan-bounces@osuosl.org;\n receiver=<UNKNOWN> ", "DKIM-Filter": [ "OpenDKIM Filter v2.11.0 smtp1.osuosl.org 7C16281274", "OpenDKIM Filter v2.11.0 smtp1.osuosl.org 0145280C80" ], "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=osuosl.org;\n\ts=default; t=1771344293;\n\tbh=2XM4GT+Y3gxQgUMKp6UAMRGoFf6xv4rx6zDiQDG8ezI=;\n\th=From:To:Date:Subject:List-Id:List-Unsubscribe:List-Archive:\n\t List-Post:List-Help:List-Subscribe:Cc:From;\n\tb=8DgoZvp/oItfUW0jUw+BZYZkOrIAo0IprJUk2vC6rzxhhD5O4V6Qxfz+4efLRcaXf\n\t IpGFNHOSYi6Mv0D8MkH/9qewAHmRhpKYCNZyiCeUXMndL29Y9iBYkXtSimIlLzYH9o\n\t 3KUVK85X7yXyyxHA/ArLgzqZq+6cTruLOiNM0sjGy6P83jA6waM5CP+01CSIWRg0xG\n\t 8+VS1qUDnckHy5z05LkxnI6pL8v2MpnK5SAEjZCVeqwpbuLlxuFjAWPOpLwp9brJFP\n\t 3aKR3VazTs/EoEPIxnM9+BX1L87ZJwvHTFrekBMdA6zhTgrtV18xblvXiblEzlzFtM\n\t tevzZAAioXqyg==", "Received-SPF": "Pass (mailfrom) identity=mailfrom; client-ip=192.198.163.17;\n helo=mgamail.intel.com; envelope-from=arkadiusz.kubalewski@intel.com;\n receiver=<UNKNOWN>", "DMARC-Filter": "OpenDMARC Filter v1.4.2 smtp1.osuosl.org 0145280C80", "X-CSE-ConnectionGUID": [ "QbWcxRqjTkCTvxJ3G5dfbQ==", "+6COPBY4TS2a/cQDp1UzUg==" ], "X-CSE-MsgGUID": [ "ezXfxl9lSY2Q/HFaazlIXg==", "HFoSUF9TSXuLX416zUmp7w==" ], "X-IronPort-AV": [ "E=McAfee;i=\"6800,10657,11704\"; a=\"72323992\"", "E=Sophos;i=\"6.21,296,1763452800\"; d=\"scan'208\";a=\"72323992\"" ], "X-ExtLoop1": "1", "From": "Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>", "To": "intel-wired-lan@lists.osuosl.org", "Date": "Tue, 17 Feb 2026 16:58:08 +0100", "Message-Id": "<20260217155808.1209194-1-arkadiusz.kubalewski@intel.com>", "X-Mailer": "git-send-email 2.38.1", "MIME-Version": "1.0", "Content-Type": "text/plain; charset=UTF-8", "Content-Transfer-Encoding": "8bit", "X-Mailman-Original-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/simple;\n d=intel.com; i=@intel.com; q=dns/txt; s=Intel;\n t=1771344290; x=1802880290;\n h=from:to:cc:subject:date:message-id:mime-version:\n content-transfer-encoding;\n bh=fnoXtS+TmdsJPGOuUtNc+m4hkZ4Sq6MnLYSvTXs1edo=;\n b=VsH70nRcXqgkSOBaZ/3H0joAScERkaZJidFO0sXNkXjUdJ8DCEBNwSB9\n /ipAnUp900L5iJ4QplYvR4vLFwsALmpyQM3C/2BKXcFpDQCJj+A6zgVNj\n 8FrZIcVHNf3smdieEI7U9LuBqEaW/ZHufVpjmdPRNk3KlYGCw3X3Y6ctQ\n U8fj9VjUAVeBVorMK6l3ItOXS3FDFG5fEldmWPN72LVMI1+51ZE35Li7K\n i6s54SBtxrhXeqskGwVZGDEMMW1kcrw8NoTgRQt+0y6t2bNSso2FcQ09N\n qt+P/F/Uh+iB3nfllahaNu91VpybTR2YppzWlb1vodqITStAnfIbFxpWU\n w==;", "X-Mailman-Original-Authentication-Results": [ "smtp1.osuosl.org;\n dmarc=pass (p=none dis=none)\n header.from=intel.com", "smtp1.osuosl.org;\n dkim=pass (2048-bit key,\n unprotected) header.d=intel.com header.i=@intel.com header.a=rsa-sha256\n header.s=Intel header.b=VsH70nRc" ], "Subject": "[Intel-wired-lan] [PATCH iwl-next v11] ice: add support for\n unmanaged DPLL on E830 NIC", "X-BeenThere": "intel-wired-lan@osuosl.org", "X-Mailman-Version": "2.1.30", "Precedence": "list", "List-Id": "Intel Wired Ethernet Linux Kernel Driver Development\n <intel-wired-lan.osuosl.org>", "List-Unsubscribe": "<https://lists.osuosl.org/mailman/options/intel-wired-lan>,\n <mailto:intel-wired-lan-request@osuosl.org?subject=unsubscribe>", "List-Archive": "<http://lists.osuosl.org/pipermail/intel-wired-lan/>", "List-Post": "<mailto:intel-wired-lan@osuosl.org>", "List-Help": "<mailto:intel-wired-lan-request@osuosl.org?subject=help>", "List-Subscribe": "<https://lists.osuosl.org/mailman/listinfo/intel-wired-lan>,\n <mailto:intel-wired-lan-request@osuosl.org?subject=subscribe>", "Cc": "pmenzel@molgen.mpg.de, linux-doc@vger.kernel.org, netdev@vger.kernel.org,\n linux-kernel@vger.kernel.org,\n Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>,\n aleksandr.loktionov@intel.com, anthony.l.nguyen@intel.com,\n zoltan.fodor@intel.com, horms@kernel.org, przemyslaw.kitszel@intel.com,\n vgrinber@redhat.com", "Errors-To": "intel-wired-lan-bounces@osuosl.org", "Sender": "\"Intel-wired-lan\" <intel-wired-lan-bounces@osuosl.org>" }, "content": "Hardware variants of E830 may support an unmanaged DPLL where the\nconfiguration is hardcoded within the hardware and firmware, meaning\nusers cannot modify settings. However, users are able to check the DPLL\nlock status and obtain configuration information through the Linux DPLL\nand devlink health subsystem.\n\nAvailability of 'loss of lock' health status code determines if such\nsupport is available, if true, register single DPLL device with 1 input\nand 1 output and provide hardcoded/read only properties of a pin and\nDPLL device. User is only allowed to check DPLL device status and receive\nnotifications on DPLL lock status change.\n\nWhen present, the DPLL device locks to an external signal provided\nthrough the PCIe/OCP pin. The expected input signal is 1PPS\n(1 Pulse Per Second) embedded on a 10MHz reference clock.\nThe DPLL produces output:\n- for MAC (Media Access Control) & PHY (Physical Layer) clocks,\n- 1PPS for synchronization of onboard PHC (Precision Hardware Clock) timer.\n\nReviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>\nReviewed-by: Paul Menzel <pmenzel@molgen.mpg.de>\nSigned-off-by: Grzegorz Nitka <grzegorz.nitka@intel.com>\nSigned-off-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>\n---\nv11:\n- rebase and fix conflicts\nv10:\n- move mutex so is always initialized when used\n- check and use return value of ice_dpll_lock_state_init_unmanaged()\nv9:\n- reorder the flow of ice_dpll_init_direct_pins, drop if no cgu and make less\n indentation\n- remove floating code block\nv8:\n- fix uninitalized bool *supported\n- fix properly set esync->range_num\nv7:\n- validate 'first' is present on error path\nv6:\n- change dpll type EEC -> PPS, this dpll serves both functionalisites but PPS\n is superset of EEC type\n- use DPLL_MODE_MANUAL instead of AUTOMATIC, which is correct for the input\n pins that doesn't have capability to set the priority\nv5:\n- rebased (baseline does not include dependent e825C patches now)\n- added health status notification (thru devlink and DPLL subsystem)\nv4:\n- add correct strcuture for reading supported health status codes and\n use it to parse the outcome of 0xFF21 AQ command.\n---\n .../device_drivers/ethernet/intel/ice.rst | 83 +++++\n .../net/ethernet/intel/ice/devlink/health.c | 4 +\n .../net/ethernet/intel/ice/ice_adminq_cmd.h | 12 +\n drivers/net/ethernet/intel/ice/ice_common.c | 136 ++++++++\n drivers/net/ethernet/intel/ice/ice_common.h | 8 +\n drivers/net/ethernet/intel/ice/ice_dpll.c | 301 ++++++++++++++++--\n drivers/net/ethernet/intel/ice/ice_dpll.h | 10 +\n drivers/net/ethernet/intel/ice/ice_main.c | 11 +-\n drivers/net/ethernet/intel/ice/ice_ptp_hw.c | 46 +++\n drivers/net/ethernet/intel/ice/ice_ptp_hw.h | 1 +\n 10 files changed, 591 insertions(+), 21 deletions(-)\n\n\nbase-commit: 8137e3db7f1c02548b11fd905bdc2cfd5255f6c7", "diff": "diff --git a/Documentation/networking/device_drivers/ethernet/intel/ice.rst b/Documentation/networking/device_drivers/ethernet/intel/ice.rst\nindex 0bca293cf9cb..7c24761d1008 100644\n--- a/Documentation/networking/device_drivers/ethernet/intel/ice.rst\n+++ b/Documentation/networking/device_drivers/ethernet/intel/ice.rst\n@@ -941,6 +941,89 @@ To see input signal on those PTP pins, you need to configure DPLL properly.\n Output signal is only visible on DPLL and to send it to the board SMA/U.FL pins,\n DPLL output pins have to be manually configured.\n \n+Unmanaged DPLL Support\n+----------------------\n+Hardware variants of E830 may support an unmanaged DPLL:\n+\n+- Intel® Ethernet Network Adapter E830-XXVDA8F for OCP 3.0,\n+\n+- Intel® Ethernet Network Adapter E830-XXVDA4F.\n+\n+In the case of the unmanaged DPLL, the configuration is hardcoded within the\n+hardware and firmware, meaning users cannot modify settings. However,\n+users can check the DPLL lock status and obtain configuration information\n+through the Linux DPLL subsystem.\n+\n+When present, the DPLL device locks to an external signal provided through the\n+PCIe/OCP pin. The expected input signal is 1PPS (1 Pulse Per Second) embedded\n+on a 10MHz reference clock.\n+The DPLL produces output:\n+\n+- for MAC (Media Access Control) & PHY (Physical Layer) clocks,\n+\n+- 1PPS for synchronization of onboard PHC (Precision Hardware Clock) timer.\n+\n+Requirements: The Linux kernel must have support for both the DPLL Subsystem\n+and the Embedded Sync patch series.\n+\n+Example output of querying the Linux DPLL subsystem can be found below.\n+\n+.. code-block:: console\n+ :caption: Dumping the DPLL pins\n+\n+ $ <ynl> --spec Documentation/netlink/specs/dpll.yaml --dump pin-get\n+ [{'board-label': '1588-TIME_SYNC',\n+ 'capabilities': set(),\n+ 'clock-id': 282574471561216,\n+ 'esync-frequency': 1,\n+ 'esync-frequency-supported': [{'frequency-max': 1, 'frequency-min': 1}],\n+ 'esync-pulse': 25,\n+ 'frequency': 10000000,\n+ 'id': 13,\n+ 'module-name': 'ice',\n+ 'parent-device': [{'direction': 'input',\n+ 'parent-id': 6,\n+ 'state': 'connected'}],\n+ 'phase-adjust-max': 0,\n+ 'phase-adjust-min': 0,\n+ 'type': 'ext'},\n+ {'board-label': 'MAC-PHY-CLK',\n+ 'capabilities': set(),\n+ 'clock-id': 282574471561216,\n+ 'frequency': 156250000,\n+ 'id': 14,\n+ 'module-name': 'ice',\n+ 'parent-device': [{'direction': 'output',\n+ 'parent-id': 6,\n+ 'state': 'connected'}],\n+ 'phase-adjust-max': 0,\n+ 'phase-adjust-min': 0,\n+ 'type': 'synce-eth-port'},\n+ {'board-label': '1588-TIME_REF',\n+ 'capabilities': set(),\n+ 'clock-id': 282574471561216,\n+ 'frequency': 1,\n+ 'id': 15,\n+ 'module-name': 'ice',\n+ 'parent-device': [{'direction': 'output',\n+ 'parent-id': 6,\n+ 'state': 'connected'}],\n+ 'phase-adjust-max': 0,\n+ 'phase-adjust-min': 0,\n+ 'type': 'int-oscillator'}]\n+\n+.. code-block:: console\n+ :caption: Dumping the DPLL devices\n+\n+ $ <ynl> --spec Documentation/netlink/specs/dpll.yaml --dump device-get\n+ [{'clock-id': 282574471561216,\n+ 'id': 6,\n+ 'lock-status': 'locked',\n+ 'mode': 'manual',\n+ 'mode-supported': ['manual'],\n+ 'module-name': 'ice',\n+ 'type': 'pps'}]\n+\n GNSS module\n -----------\n Requires kernel compiled with CONFIG_GNSS=y or CONFIG_GNSS=m.\ndiff --git a/drivers/net/ethernet/intel/ice/devlink/health.c b/drivers/net/ethernet/intel/ice/devlink/health.c\nindex 8e9a8a8178d4..31e6c5107c97 100644\n--- a/drivers/net/ethernet/intel/ice/devlink/health.c\n+++ b/drivers/net/ethernet/intel/ice/devlink/health.c\n@@ -101,6 +101,8 @@ static const struct ice_health_status ice_health_status_lookup[] = {\n \t\t\"Supplied MIB file is invalid. DCB reverted to default configuration.\",\n \t\t\"Disable FW-LLDP and check DCBx system configuration.\",\n \t\t{ice_port_number_label, \"MIB ID\"}},\n+\t{ICE_AQC_HEALTH_STATUS_INFO_LOSS_OF_LOCK, \"Local DPLL lock status\",\n+\t\tNULL,},\n };\n \n static int ice_health_status_lookup_compare(const void *a, const void *b)\n@@ -242,6 +244,8 @@ void ice_process_health_status_event(struct ice_pf *pf, struct ice_rq_event_info\n \t\t\t\tpf->health_reporters.fw_status = *health_info;\n \t\t\t\tdevlink_health_report(pf->health_reporters.fw,\n \t\t\t\t\t\t \"FW syndrome reported\", NULL);\n+\t\t\t\tif (status_code == ICE_AQC_HEALTH_STATUS_INFO_LOSS_OF_LOCK)\n+\t\t\t\t\tice_dpll_lock_state_set_unmanaged(pf, health_info, true);\n \t\t\t\tbreak;\n \t\t\tcase ICE_AQC_HEALTH_STATUS_PF:\n \t\t\tcase ICE_AQC_HEALTH_STATUS_PORT:\ndiff --git a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h\nindex b2685ebd37d6..2064efcdea19 100644\n--- a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h\n+++ b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h\n@@ -1498,6 +1498,7 @@ struct ice_aqc_get_link_topo {\n #define ICE_AQC_GET_LINK_TOPO_NODE_NR_PCA9575\t\t0x21\n #define ICE_AQC_GET_LINK_TOPO_NODE_NR_ZL30632_80032\t0x24\n #define ICE_AQC_GET_LINK_TOPO_NODE_NR_SI5383_5384\t0x25\n+#define ICE_AQC_GET_LINK_TOPO_NODE_NR_ZL80640\t\t0x27\n #define ICE_AQC_GET_LINK_TOPO_NODE_NR_E822_PHY\t\t0x30\n #define ICE_AQC_GET_LINK_TOPO_NODE_NR_C827\t\t0x31\n #define ICE_AQC_GET_LINK_TOPO_NODE_NR_GEN_CLK_MUX\t0x47\n@@ -2481,11 +2482,14 @@ enum ice_aqc_health_status {\n \tICE_AQC_HEALTH_STATUS_ERR_BMC_RESET\t\t\t= 0x50B,\n \tICE_AQC_HEALTH_STATUS_ERR_LAST_MNG_FAIL\t\t\t= 0x50C,\n \tICE_AQC_HEALTH_STATUS_ERR_RESOURCE_ALLOC_FAIL\t\t= 0x50D,\n+\tICE_AQC_HEALTH_STATUS_INFO_LOSS_OF_LOCK\t\t\t= 0x601,\n \tICE_AQC_HEALTH_STATUS_ERR_FW_LOOP\t\t\t= 0x1000,\n \tICE_AQC_HEALTH_STATUS_ERR_FW_PFR_FAIL\t\t\t= 0x1001,\n \tICE_AQC_HEALTH_STATUS_ERR_LAST_FAIL_AQ\t\t\t= 0x1002,\n };\n \n+#define ICE_AQC_HEALTH_STATUS_CODE_NUM\t\t\t\t64\n+\n /* Get Health Status (indirect 0xFF22) */\n struct ice_aqc_get_health_status {\n \t__le16 health_status_count;\n@@ -2512,6 +2516,13 @@ struct ice_aqc_health_status_elem {\n \t__le32 internal_data2;\n };\n \n+/* Get Health Status response buffer entry, (0xFF21)\n+ * repeated per reported health status\n+ */\n+struct ice_aqc_health_status_supp_elem {\n+\t__le16 health_status_code;\n+};\n+\n /* Admin Queue command opcodes */\n enum ice_adminq_opc {\n \t/* AQ commands */\n@@ -2675,6 +2686,7 @@ enum ice_adminq_opc {\n \n \t/* System Diagnostic commands */\n \tice_aqc_opc_set_health_status_cfg\t\t= 0xFF20,\n+\tice_aqc_opc_get_supported_health_status_codes\t= 0xFF21,\n \tice_aqc_opc_get_health_status\t\t\t= 0xFF22,\n \n \t/* FW Logging Commands */\ndiff --git a/drivers/net/ethernet/intel/ice/ice_common.c b/drivers/net/ethernet/intel/ice/ice_common.c\nindex 8866902efb91..0fde268378f4 100644\n--- a/drivers/net/ethernet/intel/ice/ice_common.c\n+++ b/drivers/net/ethernet/intel/ice/ice_common.c\n@@ -3051,6 +3051,29 @@ bool ice_is_cgu_in_netlist(struct ice_hw *hw)\n \treturn false;\n }\n \n+/**\n+ * ice_is_unmanaged_cgu_in_netlist - check for unmanaged CGU presence\n+ * @hw: pointer to the hw struct\n+ *\n+ * Check if the unmanaged Clock Generation Unit (CGU) device is present in the netlist.\n+ * Save the CGU part number in the hw structure for later use.\n+ * Return:\n+ * * true - unmanaged cgu is present\n+ * * false - unmanaged cgu is not present\n+ */\n+bool ice_is_unmanaged_cgu_in_netlist(struct ice_hw *hw)\n+{\n+\tif (!ice_find_netlist_node(hw, ICE_AQC_LINK_TOPO_NODE_TYPE_CLK_CTRL,\n+\t\t\t\t ICE_AQC_LINK_TOPO_NODE_CTX_GLOBAL,\n+\t\t\t\t ICE_AQC_GET_LINK_TOPO_NODE_NR_ZL80640,\n+\t\t\t\t NULL)) {\n+\t\thw->cgu_part_number = ICE_AQC_GET_LINK_TOPO_NODE_NR_ZL80640;\n+\t\treturn true;\n+\t}\n+\n+\treturn false;\n+}\n+\n /**\n * ice_is_gps_in_netlist\n * @hw: pointer to the hw struct\n@@ -6313,6 +6336,119 @@ bool ice_is_fw_health_report_supported(struct ice_hw *hw)\n \t\t\t\t ICE_FW_API_HEALTH_REPORT_PATCH);\n }\n \n+/**\n+ * ice_aq_get_health_status_supported - get supported health status codes\n+ * @hw: pointer to the HW struct\n+ * @buff: pointer to buffer where health status elements will be stored\n+ * @num: number of health status elements buffer can hold\n+ *\n+ * Return:\n+ * * 0 - success,\n+ * * negative - AQ error code.\n+ */\n+static int\n+ice_aq_get_health_status_supported(struct ice_hw *hw,\n+\t\t\t\t struct ice_aqc_health_status_supp_elem *buff,\n+\t\t\t\t int num)\n+{\n+\tu16 code = ice_aqc_opc_get_supported_health_status_codes;\n+\tstruct libie_aq_desc desc;\n+\n+\tice_fill_dflt_direct_cmd_desc(&desc, code);\n+\n+\treturn ice_aq_send_cmd(hw, &desc, buff, num * sizeof(*buff), NULL);\n+}\n+\n+/**\n+ * ice_aq_get_health_status - get current health status array from the firmware\n+ * @hw: pointer to the HW struct\n+ * @buff: pointer to buffer where health status elements will be stored\n+ * @num: number of health status elements buffer can hold\n+ *\n+ * Return:\n+ * * 0 - success,\n+ * * negative - AQ error code.\n+ */\n+int ice_aq_get_health_status(struct ice_hw *hw,\n+\t\t\t struct ice_aqc_health_status_elem *buff, int num)\n+{\n+\tstruct libie_aq_desc desc;\n+\n+\tice_fill_dflt_direct_cmd_desc(&desc,\n+\t\t\t\t ice_aqc_opc_get_health_status);\n+\n+\treturn ice_aq_send_cmd(hw, &desc, buff, num * sizeof(*buff), NULL);\n+}\n+\n+/**\n+ * ice_is_health_status_code_supported - check if health status code is supported\n+ * @hw: pointer to the hardware structure\n+ * @code: health status code to check\n+ * @supported: pointer to boolean result\n+ *\n+ * Return: 0 on success, negative error code otherwise\n+ */\n+int ice_is_health_status_code_supported(struct ice_hw *hw, u16 code,\n+\t\t\t\t\tbool *supported)\n+{\n+\tconst int BUFF_SIZE = ICE_AQC_HEALTH_STATUS_CODE_NUM;\n+\tstruct ice_aqc_health_status_supp_elem *buff;\n+\tint ret;\n+\n+\t*supported = false;\n+\tbuff = kcalloc(BUFF_SIZE, sizeof(*buff), GFP_KERNEL);\n+\tif (!buff)\n+\t\treturn -ENOMEM;\n+\tret = ice_aq_get_health_status_supported(hw, buff, BUFF_SIZE);\n+\tif (ret)\n+\t\tgoto free_buff;\n+\tfor (int i = 0; i < BUFF_SIZE && buff[i].health_status_code; i++)\n+\t\tif (le16_to_cpu(buff[i].health_status_code) == code) {\n+\t\t\t*supported = true;\n+\t\t\tbreak;\n+\t\t}\n+\n+free_buff:\n+\tkfree(buff);\n+\treturn ret;\n+}\n+\n+/**\n+ * ice_get_last_health_status_code - get last health status for given code\n+ * @hw: pointer to the hardware structure\n+ * @out: pointer to the health status struct to be filled\n+ * @code: health status code to check\n+ *\n+ * Return: 0 on success, negative error code otherwise\n+ */\n+int ice_get_last_health_status_code(struct ice_hw *hw,\n+\t\t\t\t struct ice_aqc_health_status_elem *out,\n+\t\t\t\t u16 code)\n+{\n+\tconst int BUFF_SIZE = ICE_AQC_HEALTH_STATUS_CODE_NUM;\n+\tstruct ice_aqc_health_status_elem *buff;\n+\tint ret, last_status = -1;\n+\n+\tbuff = kcalloc(BUFF_SIZE, sizeof(*buff), GFP_KERNEL);\n+\tif (!buff)\n+\t\treturn -ENOMEM;\n+\tret = ice_aq_get_health_status(hw, buff, BUFF_SIZE);\n+\tif (ret)\n+\t\tgoto free_buff;\n+\tfor (int i = 0; i < BUFF_SIZE && buff[i].health_status_code; i++)\n+\t\tif (le16_to_cpu(buff[i].health_status_code) == code)\n+\t\t\tlast_status = i;\n+\n+\tif (last_status >= 0)\n+\t\tmemcpy(out, &buff[last_status], sizeof(*out));\n+\telse\n+\t\tmemset(out, 0, sizeof(*out));\n+\n+free_buff:\n+\tkfree(buff);\n+\treturn ret;\n+}\n+\n /**\n * ice_aq_set_health_status_cfg - Configure FW health events\n * @hw: pointer to the HW struct\ndiff --git a/drivers/net/ethernet/intel/ice/ice_common.h b/drivers/net/ethernet/intel/ice/ice_common.h\nindex ff6393e9be0c..ebced9edd5e3 100644\n--- a/drivers/net/ethernet/intel/ice/ice_common.h\n+++ b/drivers/net/ethernet/intel/ice/ice_common.h\n@@ -162,6 +162,7 @@ ice_aq_get_phy_caps(struct ice_port_info *pi, bool qual_mods, u8 report_mode,\n bool ice_is_phy_rclk_in_netlist(struct ice_hw *hw);\n bool ice_is_clock_mux_in_netlist(struct ice_hw *hw);\n bool ice_is_cgu_in_netlist(struct ice_hw *hw);\n+bool ice_is_unmanaged_cgu_in_netlist(struct ice_hw *hw);\n bool ice_is_gps_in_netlist(struct ice_hw *hw);\n int\n ice_aq_get_netlist_node(struct ice_hw *hw, struct ice_aqc_get_link_topo *cmd,\n@@ -188,6 +189,13 @@ ice_get_link_default_override(struct ice_link_default_override_tlv *ldo,\n \t\t\t struct ice_port_info *pi);\n bool ice_is_phy_caps_an_enabled(struct ice_aqc_get_phy_caps_data *caps);\n bool ice_is_fw_health_report_supported(struct ice_hw *hw);\n+int ice_aq_get_health_status(struct ice_hw *hw,\n+\t\t\t struct ice_aqc_health_status_elem *buff, int num);\n+int ice_is_health_status_code_supported(struct ice_hw *hw, u16 code,\n+\t\t\t\t\tbool *supported);\n+int ice_get_last_health_status_code(struct ice_hw *hw,\n+\t\t\t\t struct ice_aqc_health_status_elem *out,\n+\t\t\t\t u16 code);\n int ice_aq_set_health_status_cfg(struct ice_hw *hw, u8 event_source);\n int ice_aq_get_phy_equalization(struct ice_hw *hw, u16 data_in, u16 op_code,\n \t\t\t\tu8 serdes_num, int *output);\ndiff --git a/drivers/net/ethernet/intel/ice/ice_dpll.c b/drivers/net/ethernet/intel/ice/ice_dpll.c\nindex 73a4e28ed75f..64518202dfff 100644\n--- a/drivers/net/ethernet/intel/ice/ice_dpll.c\n+++ b/drivers/net/ethernet/intel/ice/ice_dpll.c\n@@ -18,6 +18,8 @@\n #define ICE_DPLL_SW_PIN_INPUT_BASE_SFP\t\t4\n #define ICE_DPLL_SW_PIN_INPUT_BASE_QSFP\t\t6\n #define ICE_DPLL_SW_PIN_OUTPUT_BASE\t\t0\n+#define ICE_DPLL_HEALTH_STATUS_LOCKED\t\t1\n+#define ICE_DPLL_HEALTH_STATUS_UNLOCKED\t\t0\n \n #define ICE_DPLL_PIN_SW_INPUT_ABS(in_idx) \\\n \t(ICE_DPLL_SW_PIN_INPUT_BASE_SFP + (in_idx))\n@@ -80,6 +82,10 @@ static const struct dpll_pin_frequency ice_esync_range[] = {\n \tDPLL_PIN_FREQUENCY_RANGE(0, DPLL_PIN_FREQUENCY_1_HZ),\n };\n \n+static const struct dpll_pin_frequency ice_esync_range_unmanaged[] = {\n+\tDPLL_PIN_FREQUENCY_1PPS,\n+};\n+\n /**\n * ice_dpll_is_sw_pin - check if given pin shall be controlled by SW\n * @pf: private board structure\n@@ -1089,9 +1095,11 @@ ice_dpll_pin_state_get(const struct dpll_pin *pin, void *pin_priv,\n \t\treturn -EBUSY;\n \n \tmutex_lock(&pf->dplls.lock);\n-\tret = ice_dpll_pin_state_update(pf, p, pin_type, extack);\n-\tif (ret)\n-\t\tgoto unlock;\n+\tif (!pf->dplls.unmanaged) {\n+\t\tret = ice_dpll_pin_state_update(pf, p, pin_type, extack);\n+\t\tif (ret)\n+\t\t\tgoto unlock;\n+\t}\n \tif (pin_type == ICE_DPLL_PIN_TYPE_INPUT ||\n \t pin_type == ICE_DPLL_PIN_TYPE_OUTPUT)\n \t\t*state = p->state[d->dpll_idx];\n@@ -2151,9 +2159,14 @@ ice_dpll_input_esync_get(const struct dpll_pin *pin, void *pin_priv,\n \t\tmutex_unlock(&pf->dplls.lock);\n \t\treturn -EOPNOTSUPP;\n \t}\n-\tesync->range = ice_esync_range;\n-\tesync->range_num = ARRAY_SIZE(ice_esync_range);\n-\tif (p->flags[0] & ICE_AQC_GET_CGU_IN_CFG_FLG2_ESYNC_EN) {\n+\tif (pf->dplls.unmanaged) {\n+\t\tesync->range = ice_esync_range_unmanaged;\n+\t\tesync->range_num = ARRAY_SIZE(ice_esync_range_unmanaged);\n+\t} else {\n+\t\tesync->range = ice_esync_range;\n+\t\tesync->range_num = ARRAY_SIZE(ice_esync_range);\n+\t}\n+\tif (p->flags[0] & ICE_DPLL_IN_ESYNC_ENABLED) {\n \t\tesync->freq = DPLL_PIN_FREQUENCY_1_HZ;\n \t\tesync->pulse = ICE_DPLL_PIN_ESYNC_PULSE_HIGH_PERCENT;\n \t} else {\n@@ -2588,6 +2601,21 @@ static const struct dpll_pin_ops ice_dpll_output_ops = {\n \t.esync_get = ice_dpll_output_esync_get,\n };\n \n+static const struct dpll_pin_ops ice_dpll_input_unmanaged_ops = {\n+\t.frequency_get = ice_dpll_input_frequency_get,\n+\t.direction_get = ice_dpll_input_direction,\n+\t.state_on_dpll_get = ice_dpll_input_state_get,\n+#if defined(HAVE_DPLL_ESYNC)\n+\t.esync_get = ice_dpll_input_esync_get,\n+#endif /* HAVE_DPLL_ESYNC */\n+};\n+\n+static const struct dpll_pin_ops ice_dpll_output_unmanaged_ops = {\n+\t.frequency_get = ice_dpll_output_frequency_get,\n+\t.direction_get = ice_dpll_output_direction,\n+\t.state_on_dpll_get = ice_dpll_output_state_get,\n+};\n+\n static const struct dpll_device_ops ice_dpll_ops = {\n \t.lock_status_get = ice_dpll_lock_status_get,\n \t.mode_get = ice_dpll_mode_get,\n@@ -3153,12 +3181,15 @@ ice_dpll_init_direct_pins(struct ice_pf *pf, bool cgu,\n \tint ret;\n \n \tret = ice_dpll_get_pins(pf, pins, start_idx, count, pf->dplls.clock_id);\n-\tif (ret)\n+\tif (!cgu || ret)\n \t\treturn ret;\n-\tif (cgu) {\n+\n+\tif (first) {\n \t\tret = ice_dpll_register_pins(first, pins, ops, count);\n \t\tif (ret)\n \t\t\tgoto release_pins;\n+\t}\n+\tif (second) {\n \t\tret = ice_dpll_register_pins(second, pins, ops, count);\n \t\tif (ret)\n \t\t\tgoto unregister_first;\n@@ -3167,7 +3198,8 @@ ice_dpll_init_direct_pins(struct ice_pf *pf, bool cgu,\n \treturn 0;\n \n unregister_first:\n-\tice_dpll_unregister_pins(first, pins, ops, count);\n+\tif (first)\n+\t\tice_dpll_unregister_pins(first, pins, ops, count);\n release_pins:\n \tice_dpll_release_pins(pins, count);\n \treturn ret;\n@@ -3424,6 +3456,18 @@ static void ice_dpll_deinit_pins(struct ice_pf *pf, bool cgu)\n \tstruct ice_dpll *de = &d->eec;\n \tstruct ice_dpll *dp = &d->pps;\n \n+\tif (d->unmanaged) {\n+\t\tice_dpll_unregister_pins(dp->dpll, inputs,\n+\t\t\t\t\t &ice_dpll_input_unmanaged_ops,\n+\t\t\t\t\t num_inputs);\n+\t\tice_dpll_unregister_pins(dp->dpll, outputs,\n+\t\t\t\t\t &ice_dpll_output_unmanaged_ops,\n+\t\t\t\t\t num_outputs);\n+\t\tice_dpll_release_pins(inputs, num_inputs);\n+\t\tice_dpll_release_pins(outputs, num_outputs);\n+\t\treturn;\n+\t}\n+\n \tice_dpll_deinit_rclk_pin(pf);\n \tif (pf->hw.mac_type == ICE_MAC_GENERIC_3K_E825)\n \t\tice_dpll_deinit_fwnode_pins(pf, pf->dplls.inputs, 0);\n@@ -3608,23 +3652,29 @@ static int ice_dpll_init_pins(struct ice_pf *pf, bool cgu)\n \tconst struct dpll_pin_ops *input_ops;\n \tint ret, count;\n \n-\tinput_ops = &ice_dpll_input_ops;\n-\toutput_ops = &ice_dpll_output_ops;\n+\tif (!pf->dplls.unmanaged) {\n+\t\tinput_ops = &ice_dpll_input_ops;\n+\t\toutput_ops = &ice_dpll_output_ops;\n+\t} else {\n+\t\tinput_ops = &ice_dpll_input_unmanaged_ops;\n+\t\toutput_ops = &ice_dpll_output_unmanaged_ops;\n+\t}\n \n \tret = ice_dpll_init_direct_pins(pf, cgu, pf->dplls.inputs, 0,\n \t\t\t\t\tpf->dplls.num_inputs, input_ops,\n-\t\t\t\t\tpf->dplls.eec.dpll,\n-\t\t\t\t\tpf->dplls.pps.dpll);\n+\t\t\t\t\tpf->dplls.eec.dpll, pf->dplls.pps.dpll);\n \tif (ret)\n \t\treturn ret;\n \tcount = pf->dplls.num_inputs;\n-\tif (cgu) {\n+\tif (cgu || pf->dplls.unmanaged) {\n \t\tret = ice_dpll_init_direct_pins(pf, cgu, pf->dplls.outputs,\n \t\t\t\t\t\tcount, pf->dplls.num_outputs,\n \t\t\t\t\t\toutput_ops, pf->dplls.eec.dpll,\n \t\t\t\t\t\tpf->dplls.pps.dpll);\n \t\tif (ret)\n \t\t\tgoto deinit_inputs;\n+\t\tif (pf->dplls.unmanaged)\n+\t\t\treturn 0;\n \t\tcount += pf->dplls.num_outputs;\n \t\tif (!pf->dplls.generic) {\n \t\t\tret = ice_dpll_init_direct_pins(pf, cgu, pf->dplls.sma,\n@@ -3737,7 +3787,8 @@ ice_dpll_init_dpll(struct ice_pf *pf, struct ice_dpll *d, bool cgu,\n \n \t\tif (type == DPLL_TYPE_PPS && ice_dpll_is_pps_phase_monitor(pf))\n \t\t\tops = &ice_dpll_pom_ops;\n-\t\tice_dpll_update_state(pf, d, true);\n+\t\tif (!pf->dplls.unmanaged)\n+\t\t\tice_dpll_update_state(pf, d, true);\n \t\tret = dpll_device_register(d->dpll, type, ops, d);\n \t\tif (ret) {\n \t\t\tdpll_device_put(d->dpll, &d->tracker);\n@@ -3764,6 +3815,33 @@ static void ice_dpll_deinit_worker(struct ice_pf *pf)\n \tkthread_destroy_worker(d->kworker);\n }\n \n+/**\n+ * ice_dpll_pin_freq_info - find pin frequency from supported ones\n+ * @hw: pointer to the hardware structure\n+ * @pin_idx: pin index\n+ * @input: if input pin\n+ *\n+ * This function searches through the array of supported frequencies for a\n+ * DPLL pin and returns single frequency pin is capable, if pin support only\n+ * one frequency. Shall be used only for dpll with driver hardcoded frequency.\n+ *\n+ * Return:\n+ * * 0 - failure, pin uses multiple frequencies,\n+ * * frequency - success.\n+ */\n+static u64 ice_dpll_pin_freq_info(struct ice_hw *hw, u8 pin_idx, bool input)\n+{\n+\tstruct dpll_pin_frequency *freqs;\n+\tu8 freq_num;\n+\n+\t/* Get supported frequencies for this pin */\n+\tfreqs = ice_cgu_get_pin_freq_supp(hw, pin_idx, input, &freq_num);\n+\tif (!freqs || freq_num != 1 || freqs[0].min != freqs[0].max)\n+\t\treturn 0;\n+\n+\treturn freqs[0].min;\n+}\n+\n /**\n * ice_dpll_init_worker - Initialize DPLLs periodic worker\n * @pf: board private structure\n@@ -3923,6 +4001,15 @@ ice_dpll_init_info_direct_pins(struct ice_pf *pf,\n \t\tpins[i].prop.board_label = ice_cgu_get_pin_name(hw, i, input);\n \t\tpins[i].prop.type = ice_cgu_get_pin_type(hw, i, input);\n \t\tif (input) {\n+\t\t\tif (pf->dplls.unmanaged) {\n+\t\t\t\tpins[i].freq = ice_dpll_pin_freq_info(hw, i,\n+\t\t\t\t\t\t\t\t input);\n+\t\t\t\tpins[i].state[0] = DPLL_PIN_STATE_CONNECTED;\n+\t\t\t\tpins[i].status =\n+\t\t\t\t\tICE_AQC_GET_CGU_IN_CFG_STATUS_ESYNC_CAP;\n+\t\t\t\tpins[i].flags[0] = ICE_DPLL_IN_ESYNC_ENABLED;\n+\t\t\t\tcontinue;\n+\t\t\t}\n \t\t\tret = ice_aq_get_cgu_ref_prio(hw, de->dpll_idx, i,\n \t\t\t\t\t\t &de->input_prio[i]);\n \t\t\tif (ret)\n@@ -3936,6 +4023,12 @@ ice_dpll_init_info_direct_pins(struct ice_pf *pf,\n \t\t\tif (ice_dpll_is_sw_pin(pf, i, true))\n \t\t\t\tpins[i].hidden = true;\n \t\t} else {\n+\t\t\tif (pf->dplls.unmanaged) {\n+\t\t\t\tpins[i].freq = ice_dpll_pin_freq_info(hw, i,\n+\t\t\t\t\t\t\t\t input);\n+\t\t\t\tpins[i].state[0] = DPLL_PIN_STATE_CONNECTED;\n+\t\t\t\tcontinue;\n+\t\t\t}\n \t\t\tret = ice_cgu_get_output_pin_state_caps(hw, i, &caps);\n \t\t\tif (ret)\n \t\t\t\treturn ret;\n@@ -3953,10 +4046,13 @@ ice_dpll_init_info_direct_pins(struct ice_pf *pf,\n \t\tpins[i].prop.freq_supported_num = freq_supp_num;\n \t\tpins[i].pf = pf;\n \t}\n-\tif (input)\n+\tif (input && !pf->dplls.unmanaged) {\n \t\tret = ice_dpll_init_ref_sync_inputs(pf);\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\t}\n \n-\treturn ret;\n+\treturn 0;\n }\n \n /**\n@@ -4149,7 +4245,6 @@ static int ice_dpll_init_info_e825c(struct ice_pf *pf)\n \n \td->clock_id = ice_generate_clock_id(pf);\n \td->num_inputs = ICE_SYNCE_CLK_NUM;\n-\n \td->inputs = kcalloc(d->num_inputs, sizeof(*d->inputs), GFP_KERNEL);\n \tif (!d->inputs)\n \t\treturn -ENOMEM;\n@@ -4174,6 +4269,81 @@ static int ice_dpll_init_info_e825c(struct ice_pf *pf)\n \treturn ret;\n }\n \n+/* ice_dpll_lock_state_init_unmanaged - initialize lock state for unmanaged dpll\n+ * @pf: board private structure\n+ *\n+ * Initialize the lock state for unmanaged DPLL by checking health status.\n+ * For unmanaged DPLL, we rely on hardware autonomous operation.\n+ *\n+ * Return:\n+ * * 0 - success\n+ * * negative - init failure reason\n+ */\n+static int ice_dpll_lock_state_init_unmanaged(struct ice_pf *pf)\n+{\n+\tu16 code = ICE_AQC_HEALTH_STATUS_INFO_LOSS_OF_LOCK;\n+\tstruct ice_aqc_health_status_elem buff;\n+\tint ret;\n+\n+\tret = ice_get_last_health_status_code(&pf->hw, &buff, code);\n+\tif (ret)\n+\t\treturn ret;\n+\tice_dpll_lock_state_set_unmanaged(pf, &buff, false);\n+\n+\treturn ret;\n+}\n+\n+/**\n+ * ice_dpll_init_info_unmanaged - init dpll information for unmanaged dpll\n+ * @pf: board private structure\n+ *\n+ * Acquire (from HW) and set basic dpll information (on pf->dplls struct).\n+ * For unmanaged dpll mode.\n+ *\n+ * Return:\n+ * * 0 - success\n+ * * negative - init failure reason\n+ */\n+static int ice_dpll_init_info_unmanaged(struct ice_pf *pf)\n+{\n+\tstruct ice_dplls *d = &pf->dplls;\n+\tint ret;\n+\n+\td->clock_id = ice_generate_clock_id(pf);\n+\td->num_inputs = ice_cgu_get_pin_num(&pf->hw, true);\n+\td->num_outputs = ice_cgu_get_pin_num(&pf->hw, false);\n+\tret = ice_dpll_lock_state_init_unmanaged(pf);\n+\tif (ret)\n+\t\treturn ret;\n+\td->inputs = kcalloc(d->num_inputs, sizeof(*d->inputs), GFP_KERNEL);\n+\tif (!d->inputs)\n+\t\treturn -ENOMEM;\n+\n+\tret = ice_dpll_init_pins_info(pf, ICE_DPLL_PIN_TYPE_INPUT);\n+\tif (ret)\n+\t\tgoto deinit_info;\n+\n+\td->outputs = kcalloc(d->num_outputs, sizeof(*d->outputs), GFP_KERNEL);\n+\tif (!d->outputs) {\n+\t\tret = -ENOMEM;\n+\t\tgoto deinit_info;\n+\t}\n+\n+\tret = ice_dpll_init_pins_info(pf, ICE_DPLL_PIN_TYPE_OUTPUT);\n+\tif (ret)\n+\t\tgoto deinit_info;\n+\n+\td->pps.mode = DPLL_MODE_MANUAL;\n+\tdev_dbg(ice_pf_to_dev(pf), \"%s - success, inputs:%u, outputs:%u\\n\",\n+\t\t__func__, d->num_inputs, d->num_outputs);\n+\treturn 0;\n+deinit_info:\n+\tdev_err(ice_pf_to_dev(pf), \"%s - fail: d->inputs:%p, d->outputs:%p\\n\",\n+\t\t__func__, d->inputs, d->outputs);\n+\tice_dpll_deinit_info(pf);\n+\treturn ret;\n+}\n+\n /**\n * ice_dpll_init_info - prepare pf's dpll information structure\n * @pf: board private structure\n@@ -4273,6 +4443,42 @@ static int ice_dpll_init_info(struct ice_pf *pf, bool cgu)\n \treturn ret;\n }\n \n+/**\n+ * ice_dpll_lock_state_set_unmanaged - determine lock state from health status\n+ * @pf: board private structure\n+ * @buff: health status buffer\n+ * @notify: if true, notify dpll device\n+ *\n+ * Set unmanaged dpll lock state based on health status code and internal data.\n+ * Context: Acquires and releases pf->dplls.lock (must release before notify\n+ * if called).\n+ */\n+void ice_dpll_lock_state_set_unmanaged(struct ice_pf *pf,\n+\t\t\t\t const struct ice_aqc_health_status_elem *buff,\n+\t\t\t\t bool notify)\n+{\n+\tu32 internal_data = le32_to_cpu(buff->internal_data1);\n+\tstruct ice_dpll *d = &pf->dplls.pps;\n+\n+\tif (!ice_pf_src_tmr_owned(pf))\n+\t\treturn;\n+\n+\tmutex_lock(&pf->dplls.lock);\n+\tif (buff->health_status_code == 0 ||\n+\t internal_data == ICE_DPLL_HEALTH_STATUS_LOCKED)\n+\t\td->dpll_state = DPLL_LOCK_STATUS_LOCKED;\n+\telse\n+\t\td->dpll_state = DPLL_LOCK_STATUS_UNLOCKED;\n+\n+\tif (d->prev_dpll_state == d->dpll_state)\n+\t\tnotify = false;\n+\telse\n+\t\td->prev_dpll_state = d->dpll_state;\n+\tmutex_unlock(&pf->dplls.lock);\n+\tif (notify && d->dpll)\n+\t\tdpll_device_change_ntf(d->dpll);\n+}\n+\n /**\n * ice_dpll_deinit - Disable the driver/HW support for dpll subsystem\n * the dpll device.\n@@ -4292,15 +4498,55 @@ void ice_dpll_deinit(struct ice_pf *pf)\n \tif (cgu)\n \t\tice_dpll_deinit_worker(pf);\n \n-\tice_dpll_deinit_pins(pf, cgu);\n+\tice_dpll_deinit_pins(pf, cgu || pf->dplls.unmanaged);\n \tif (!IS_ERR_OR_NULL(pf->dplls.pps.dpll))\n-\t\tice_dpll_deinit_dpll(pf, &pf->dplls.pps, cgu);\n+\t\tice_dpll_deinit_dpll(pf, &pf->dplls.pps,\n+\t\t\t\t cgu || pf->dplls.unmanaged);\n \tif (!IS_ERR_OR_NULL(pf->dplls.eec.dpll))\n \t\tice_dpll_deinit_dpll(pf, &pf->dplls.eec, cgu);\n \tice_dpll_deinit_info(pf);\n \tmutex_destroy(&pf->dplls.lock);\n }\n \n+/**\n+ * ice_dpll_init_unmanaged - initialize support for unmanaged dpll subsystem\n+ * @pf: board private structure\n+ *\n+ * Set up the device dplls for unmanaged mode, register them and pins connected\n+ * within Linux dpll subsystem. Allow userspace to obtain state of DPLL.\n+ *\n+ * Context: Initializes pf->dplls.lock mutex.\n+ */\n+static void ice_dpll_init_unmanaged(struct ice_pf *pf)\n+{\n+\tstruct ice_dplls *d = &pf->dplls;\n+\tint err;\n+\n+\tif (!ice_pf_src_tmr_owned(pf))\n+\t\treturn;\n+\tmutex_init(&d->lock);\n+\terr = ice_dpll_init_info_unmanaged(pf);\n+\tif (err)\n+\t\tgoto err_exit;\n+\terr = ice_dpll_init_dpll(pf, &pf->dplls.pps, true, DPLL_TYPE_PPS);\n+\tif (err)\n+\t\tgoto deinit_info;\n+\terr = ice_dpll_init_pins(pf, true);\n+\tif (err)\n+\t\tgoto deinit_pps;\n+\tset_bit(ICE_FLAG_DPLL, pf->flags);\n+\n+\treturn;\n+\n+deinit_pps:\n+\tice_dpll_deinit_dpll(pf, &pf->dplls.pps, true);\n+deinit_info:\n+\tice_dpll_deinit_info(pf);\n+err_exit:\n+\tmutex_destroy(&d->lock);\n+\tdev_warn(ice_pf_to_dev(pf), \"DPLLs init failure err:%d\\n\", err);\n+}\n+\n /**\n * ice_dpll_init_e825 - initialize support for dpll subsystem\n * @pf: board private structure\n@@ -4388,8 +4634,23 @@ static void ice_dpll_init_e810(struct ice_pf *pf)\n \tdev_warn(ice_pf_to_dev(pf), \"DPLLs init failure err:%d\\n\", err);\n }\n \n+/**\n+ * ice_dpll_init - initialize support for dpll subsystem\n+ * @pf: board private structure\n+ *\n+ * Set up the device dplls, register them and pins connected within Linux dpll\n+ * subsystem. Allow userspace to obtain state of DPLL and handling of DPLL\n+ * configuration requests.\n+ *\n+ * Context: Initializes pf->dplls.lock mutex.\n+ */\n void ice_dpll_init(struct ice_pf *pf)\n {\n+\tif (pf->dplls.unmanaged) {\n+\t\tice_dpll_init_unmanaged(pf);\n+\t\treturn;\n+\t}\n+\n \tswitch (pf->hw.mac_type) {\n \tcase ICE_MAC_GENERIC_3K_E825:\n \t\tice_dpll_init_e825(pf);\ndiff --git a/drivers/net/ethernet/intel/ice/ice_dpll.h b/drivers/net/ethernet/intel/ice/ice_dpll.h\nindex 8678575359b9..bb70c4333789 100644\n--- a/drivers/net/ethernet/intel/ice/ice_dpll.h\n+++ b/drivers/net/ethernet/intel/ice/ice_dpll.h\n@@ -23,6 +23,8 @@\n #define ICE_CGU_R11_SYNCE_S_BYP_CLK\tGENMASK(6, 1)\n \n #define ICE_CGU_BYPASS_MUX_OFFSET_E825C\t3\n+#define ICE_DPLL_UNMANAGED_PIN_NUM\t4\n+#define ICE_DPLL_IN_ESYNC_ENABLED\tICE_AQC_GET_CGU_IN_CFG_FLG2_ESYNC_EN\n \n /**\n * enum ice_dpll_pin_sw - enumerate ice software pin indices:\n@@ -162,14 +164,22 @@ struct ice_dplls {\n \ts32 output_phase_adj_max;\n \tu32 periodic_counter;\n \tbool generic;\n+\tbool unmanaged;\n };\n \n #if IS_ENABLED(CONFIG_PTP_1588_CLOCK)\n void ice_dpll_init(struct ice_pf *pf);\n void ice_dpll_deinit(struct ice_pf *pf);\n+void ice_dpll_lock_state_set_unmanaged(struct ice_pf *pf,\n+\t\t\t\t const struct ice_aqc_health_status_elem *buff,\n+\t\t\t\t bool notify);\n #else\n static inline void ice_dpll_init(struct ice_pf *pf) { }\n static inline void ice_dpll_deinit(struct ice_pf *pf) { }\n+static inline void\n+ice_dpll_lock_state_set_unmanaged(struct ice_pf *pf,\n+\t\t\t\t const struct ice_aqc_health_status_elem *buff,\n+\t\t\t\t bool notify) { }\n #endif\n \n #endif\ndiff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c\nindex dd3a75cc3df3..aa1a1fcbc4e0 100644\n--- a/drivers/net/ethernet/intel/ice/ice_main.c\n+++ b/drivers/net/ethernet/intel/ice/ice_main.c\n@@ -4790,7 +4790,9 @@ void ice_deinit_dev(struct ice_pf *pf)\n \n static void ice_init_features(struct ice_pf *pf)\n {\n+\tu16 code = ICE_AQC_HEALTH_STATUS_INFO_LOSS_OF_LOCK;\n \tstruct device *dev = ice_pf_to_dev(pf);\n+\tint err;\n \n \tif (ice_is_safe_mode(pf))\n \t\treturn;\n@@ -4802,8 +4804,15 @@ static void ice_init_features(struct ice_pf *pf)\n \tif (ice_is_feature_supported(pf, ICE_F_GNSS))\n \t\tice_gnss_init(pf);\n \n+\t/* Initialize unmanaged DPLL detection */\n+\terr = ice_is_health_status_code_supported(&pf->hw, code,\n+\t\t\t\t\t\t &pf->dplls.unmanaged);\n+\tif (err || !ice_is_unmanaged_cgu_in_netlist(&pf->hw))\n+\t\tpf->dplls.unmanaged = false;\n+\n \tif (ice_is_feature_supported(pf, ICE_F_CGU) ||\n-\t ice_is_feature_supported(pf, ICE_F_PHY_RCLK))\n+\t ice_is_feature_supported(pf, ICE_F_PHY_RCLK) ||\n+\t pf->dplls.unmanaged)\n \t\tice_dpll_init(pf);\n \n \t/* Note: Flow director init failure is non-fatal to load */\ndiff --git a/drivers/net/ethernet/intel/ice/ice_ptp_hw.c b/drivers/net/ethernet/intel/ice/ice_ptp_hw.c\nindex 5a5c511ccbb6..690f9d874443 100644\n--- a/drivers/net/ethernet/intel/ice/ice_ptp_hw.c\n+++ b/drivers/net/ethernet/intel/ice/ice_ptp_hw.c\n@@ -20,6 +20,10 @@ static struct dpll_pin_frequency ice_cgu_pin_freq_10_mhz[] = {\n \tDPLL_PIN_FREQUENCY_10MHZ,\n };\n \n+static struct dpll_pin_frequency ice_cgu_pin_freq_156_25mhz[] = {\n+\tDPLL_PIN_FREQUENCY_RANGE(156250000, 156250000),\n+};\n+\n static const struct ice_cgu_pin_desc ice_e810t_sfp_cgu_inputs[] = {\n \t{ \"CVL-SDP22\",\t ZL_REF0P, DPLL_PIN_TYPE_INT_OSCILLATOR,\n \t\tARRAY_SIZE(ice_cgu_pin_freq_common), ice_cgu_pin_freq_common },\n@@ -131,6 +135,18 @@ static const struct ice_cgu_pin_desc ice_e823_zl_cgu_outputs[] = {\n \t{ \"NONE\",\t ZL_OUT5, 0, 0 },\n };\n \n+static const struct ice_cgu_pin_desc ice_e830_unmanaged_inputs[] = {\n+\t{ \"1588-TIME_SYNC\", 0, DPLL_PIN_TYPE_EXT,\n+\t ARRAY_SIZE(ice_cgu_pin_freq_10_mhz), ice_cgu_pin_freq_10_mhz },\n+};\n+\n+static const struct ice_cgu_pin_desc ice_e830_unmanaged_outputs[] = {\n+\t{ \"MAC-PHY-CLK\", 0, DPLL_PIN_TYPE_SYNCE_ETH_PORT,\n+\t ARRAY_SIZE(ice_cgu_pin_freq_156_25mhz), ice_cgu_pin_freq_156_25mhz },\n+\t{ \"1588-TIME_REF\", 1, DPLL_PIN_TYPE_INT_OSCILLATOR,\n+\t ARRAY_SIZE(ice_cgu_pin_freq_1_hz), ice_cgu_pin_freq_1_hz},\n+};\n+\n /* Low level functions for interacting with and managing the device clock used\n * for the Precision Time Protocol.\n *\n@@ -5684,6 +5700,24 @@ ice_cgu_get_pin_desc(struct ice_hw *hw, bool input, int *size)\n \tcase ICE_DEV_ID_E823C_SGMII:\n \t\tt = ice_cgu_get_pin_desc_e823(hw, input, size);\n \t\tbreak;\n+\tcase ICE_DEV_ID_E830CC_BACKPLANE:\n+\tcase ICE_DEV_ID_E830CC_QSFP56:\n+\tcase ICE_DEV_ID_E830CC_SFP:\n+\tcase ICE_DEV_ID_E830CC_SFP_DD:\n+\tcase ICE_DEV_ID_E830C_BACKPLANE:\n+\tcase ICE_DEV_ID_E830C_QSFP:\n+\tcase ICE_DEV_ID_E830C_SFP:\n+\tcase ICE_DEV_ID_E830_XXV_BACKPLANE:\n+\tcase ICE_DEV_ID_E830_XXV_QSFP:\n+\tcase ICE_DEV_ID_E830_XXV_SFP:\n+\t\tif (input) {\n+\t\t\tt = ice_e830_unmanaged_inputs;\n+\t\t\t*size = ARRAY_SIZE(ice_e830_unmanaged_inputs);\n+\t\t} else {\n+\t\t\tt = ice_e830_unmanaged_outputs;\n+\t\t\t*size = ARRAY_SIZE(ice_e830_unmanaged_outputs);\n+\t\t}\n+\t\tbreak;\n \tdefault:\n \t\tbreak;\n \t}\n@@ -5710,6 +5744,18 @@ int ice_cgu_get_num_pins(struct ice_hw *hw, bool input)\n \treturn 0;\n }\n \n+/**\n+ * ice_cgu_get_pin_num - get pin description array size\n+ * @hw: pointer to the hw struct\n+ * @input: if request is done against input or output pins\n+ *\n+ * Return: size of pin description array for given hw.\n+ */\n+int ice_cgu_get_pin_num(struct ice_hw *hw, bool input)\n+{\n+\treturn ice_cgu_get_num_pins(hw, input);\n+}\n+\n /**\n * ice_cgu_get_pin_type - get pin's type\n * @hw: pointer to the hw struct\ndiff --git a/drivers/net/ethernet/intel/ice/ice_ptp_hw.h b/drivers/net/ethernet/intel/ice/ice_ptp_hw.h\nindex 9bfd3e79c580..87aa4cfc5a46 100644\n--- a/drivers/net/ethernet/intel/ice/ice_ptp_hw.h\n+++ b/drivers/net/ethernet/intel/ice/ice_ptp_hw.h\n@@ -356,6 +356,7 @@ int ice_read_sma_ctrl(struct ice_hw *hw, u8 *data);\n int ice_write_sma_ctrl(struct ice_hw *hw, u8 data);\n int ice_ptp_read_sdp_ac(struct ice_hw *hw, __le16 *entries, uint *num_entries);\n int ice_cgu_get_num_pins(struct ice_hw *hw, bool input);\n+int ice_cgu_get_pin_num(struct ice_hw *hw, bool input);\n enum dpll_pin_type ice_cgu_get_pin_type(struct ice_hw *hw, u8 pin, bool input);\n struct dpll_pin_frequency *\n ice_cgu_get_pin_freq_supp(struct ice_hw *hw, u8 pin, bool input, u8 *num);\n", "prefixes": [ "iwl-next", "v11" ] }