{"id":2219415,"url":"http://patchwork.ozlabs.org/api/1.0/patches/2219415/?format=json","project":{"id":46,"url":"http://patchwork.ozlabs.org/api/1.0/projects/46/?format=json","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":""},"msgid":"<20260402230626.3826719-6-grzegorz.nitka@intel.com>","date":"2026-04-02T23:06:23","name":"[v5,net-next,5/8] ice: introduce TXC DPLL device and TX ref clock pin framework for E825","commit_ref":null,"pull_url":null,"state":"handled-elsewhere","archived":false,"hash":"ecba5f4944b953e3b467895f03ff9e95553c5bfe","submitter":{"id":82711,"url":"http://patchwork.ozlabs.org/api/1.0/people/82711/?format=json","name":"Grzegorz Nitka","email":"grzegorz.nitka@intel.com"},"delegate":null,"mbox":"http://patchwork.ozlabs.org/project/intel-wired-lan/patch/20260402230626.3826719-6-grzegorz.nitka@intel.com/mbox/","series":[{"id":498564,"url":"http://patchwork.ozlabs.org/api/1.0/series/498564/?format=json","date":"2026-04-02T23:06:18","name":"dpll/ice: Add TXC DPLL type and full TX reference clock control for E825","version":5,"mbox":"http://patchwork.ozlabs.org/series/498564/mbox/"}],"check":"pending","checks":"http://patchwork.ozlabs.org/api/patches/2219415/checks/","tags":{},"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=xa3qf0QG;\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 4fmyJV2X0dz1yCs\n\tfor <incoming@patchwork.ozlabs.org>; Fri, 03 Apr 2026 10:10:50 +1100 (AEDT)","from localhost (localhost [127.0.0.1])\n\tby smtp1.osuosl.org (Postfix) with ESMTP id 04C3A81307;\n\tThu,  2 Apr 2026 23:10:49 +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 nYyI1qQJMy4m; Thu,  2 Apr 2026 23:10:48 +0000 (UTC)","from lists1.osuosl.org (lists1.osuosl.org [140.211.166.142])\n\tby smtp1.osuosl.org (Postfix) with ESMTP id E1B7D812D5;\n\tThu,  2 Apr 2026 23:10:47 +0000 (UTC)","from smtp4.osuosl.org (smtp4.osuosl.org [IPv6:2605:bc80:3010::137])\n by lists1.osuosl.org (Postfix) with ESMTP id 3F3412A2\n for <intel-wired-lan@lists.osuosl.org>; Thu,  2 Apr 2026 23:10:46 +0000 (UTC)","from localhost (localhost [127.0.0.1])\n by smtp4.osuosl.org (Postfix) with ESMTP id 3141F403EB\n for <intel-wired-lan@lists.osuosl.org>; Thu,  2 Apr 2026 23:10:46 +0000 (UTC)","from smtp4.osuosl.org ([127.0.0.1])\n by localhost (smtp4.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP\n id Hp5RLbEl1jbR for <intel-wired-lan@lists.osuosl.org>;\n Thu,  2 Apr 2026 23:10:45 +0000 (UTC)","from mgamail.intel.com (mgamail.intel.com [198.175.65.19])\n by smtp4.osuosl.org (Postfix) with ESMTPS id E21CE40510\n for <intel-wired-lan@lists.osuosl.org>; Thu,  2 Apr 2026 23:10:44 +0000 (UTC)","from orviesa008.jf.intel.com ([10.64.159.148])\n by orvoesa111.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384;\n 02 Apr 2026 16:10:44 -0700","from gklab-003-001.igk.intel.com ([10.91.173.48])\n by orviesa008.jf.intel.com with ESMTP; 02 Apr 2026 16:10:40 -0700"],"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 E1B7D812D5","OpenDKIM Filter v2.11.0 smtp4.osuosl.org E21CE40510"],"DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed; d=osuosl.org;\n\ts=default; t=1775171447;\n\tbh=XN5FZ6UQfPOQ3xQpZb0tkh/efMAofgYEDyhSEJWzfwg=;\n\th=From:To:Date:In-Reply-To:References:Subject:List-Id:\n\t List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe:\n\t Cc:From;\n\tb=xa3qf0QGeb1/DHB8xQsEKNFSrlIOY+UZYW810TnOV3Xws8PhHpEalowQVPNUTLsCV\n\t pc3yrJ1549hKQWER3bz3rOSIbO1VtyM9EjHvCo49kYjWkU0eaFlUQsB25X53xCeLWt\n\t h02MiKV0P3bZkBQToaEp86Ct+C5RFzRL5QA+aKCiKHM+dmINvOrEz+vEWeqjv/ZJ4Y\n\t xo/gNPyTTgNQajyTcPgpIh2gmeIQXBnusXzol3hWUUpzlauj9ne/HRU8rl8gGG39FY\n\t P31wJdbbo0XMjNujNyV9jveMA5uyXOmfTwoJ+WRKPFZnkqKBhLbd7okAp3JmtJje0t\n\t 490as7GL42xug==","Received-SPF":"Pass (mailfrom) identity=mailfrom; client-ip=198.175.65.19;\n helo=mgamail.intel.com; envelope-from=grzegorz.nitka@intel.com;\n receiver=<UNKNOWN>","DMARC-Filter":"OpenDMARC Filter v1.4.2 smtp4.osuosl.org E21CE40510","X-CSE-ConnectionGUID":["R7guR204Qy2LIxkza8WNEw==","6xLc6h6QQUeTUv4ANRvt8A=="],"X-CSE-MsgGUID":["83hQhYXdSKelfjgu5LbiJg==","9XKUPJh3Q/aaGY5RtAXCMA=="],"X-IronPort-AV":["E=McAfee;i=\"6800,10657,11747\"; a=\"76123114\"","E=Sophos;i=\"6.23,156,1770624000\"; d=\"scan'208\";a=\"76123114\"","E=Sophos;i=\"6.23,156,1770624000\"; d=\"scan'208\";a=\"227044448\""],"X-ExtLoop1":"1","From":"Grzegorz Nitka <grzegorz.nitka@intel.com>","To":"netdev@vger.kernel.org","Date":"Fri,  3 Apr 2026 01:06:23 +0200","Message-Id":"<20260402230626.3826719-6-grzegorz.nitka@intel.com>","X-Mailer":"git-send-email 2.39.3","In-Reply-To":"<20260402230626.3826719-1-grzegorz.nitka@intel.com>","References":"<20260402230626.3826719-1-grzegorz.nitka@intel.com>","MIME-Version":"1.0","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=1775171445; x=1806707445;\n h=from:to:cc:subject:date:message-id:in-reply-to:\n references:mime-version:content-transfer-encoding;\n bh=st23kF2Yc7Fmt4Y/dZXWPHXpJtnUoyHWUmvR5RF1WT4=;\n b=nVsqYyVwERxpMmAKJqVAZ/7PXGgCO9XIkyAER6VjbmNCc47b2K8Mb80y\n T+K0xQuS27bsFNyOC56/fsRJDP9q8GyS/sA5FKHtZzY74ic59y75SA7kK\n EZyDxbwKizPtZVjbw1fxS0DN7xu09hWII8JqzSy0OAdjkIl90/VjJjgIT\n KD8NucPhhTxLA/3B9T6Ec88j4I6TK7cWviBkzn/mRCtH4xqwrbScTShAK\n UFGy4+hVeaAp6j4pcqCGV8zE7Abu9/QNf17OZoyDGFiI6N4+XDvQGURgb\n ncMh5ni2CvH/0NpItVvCr3C5IWkTCgXiGGOKzR+YMlMZnZNc+qZyEXrW9\n w==;","X-Mailman-Original-Authentication-Results":["smtp4.osuosl.org;\n dmarc=pass (p=none dis=none)\n header.from=intel.com","smtp4.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=nVsqYyVw"],"Subject":"[Intel-wired-lan] [PATCH v5 net-next 5/8] ice: introduce TXC DPLL\n device and TX ref clock pin framework for E825","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":"ivecera@redhat.com, vadim.fedorenko@linux.dev, kuba@kernel.org,\n jiri@resnulli.us, edumazet@google.com, przemyslaw.kitszel@intel.com,\n richardcochran@gmail.com, donald.hunter@gmail.com,\n linux-kernel@vger.kernel.org, arkadiusz.kubalewski@intel.com,\n andrew+netdev@lunn.ch, intel-wired-lan@lists.osuosl.org, horms@kernel.org,\n Prathosh.Satish@microchip.com, anthony.l.nguyen@intel.com, pabeni@redhat.com,\n davem@davemloft.net","Errors-To":"intel-wired-lan-bounces@osuosl.org","Sender":"\"Intel-wired-lan\" <intel-wired-lan-bounces@osuosl.org>"},"content":"E825 devices provide a dedicated TX clock (TXC) domain which may be\ndriven by multiple reference clock sources, including external board\nreferences and port-derived SyncE. To support future TX clock control\nand observability through the Linux DPLL subsystem, introduce a\nseparate TXC DPLL device and a framework for representing TX reference\nclock inputs.\n\nThis change adds a new DPLL pin type (TXCLK) and registers TX reference\nclock pins for E825-based devices:\n- EXT_EREF0: a board-level external electrical reference\n- SYNCE: a port-derived SyncE reference described via firmware nodes\n\nThe TXC DPLL device is created and managed alongside the existing\nPPS and EEC DPLL instances. TXCLK pins are registered directly or\ndeferred via a notifier when backed by fwnode-described firmware pins.\nA per-pin attribute encodes the TX reference source associated with\neach TXCLK pin.\n\nAt this stage, TXCLK pin state callbacks and TXC DPLL lock status\nreporting are implemented as placeholders. Pin state getters always\nreturn DISCONNECTED, and the TXC DPLL is initialized in the UNLOCKED\nstate. No hardware configuration or TX reference switching is\nperformed yet.\n\nThis patch establishes the structural groundwork required for\nhardware-backed TX reference selection, verification, and\nsynchronization\nstatus reporting, which will be implemented in subsequent patches.\n\nReviewed-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>\nSigned-off-by: Grzegorz Nitka <grzegorz.nitka@intel.com>\n---\n drivers/net/ethernet/intel/ice/ice_dpll.c   | 296 ++++++++++++++++++--\n drivers/net/ethernet/intel/ice/ice_dpll.h   |   6 +\n drivers/net/ethernet/intel/ice/ice_ptp_hw.h |   7 +\n 3 files changed, 286 insertions(+), 23 deletions(-)","diff":"diff --git a/drivers/net/ethernet/intel/ice/ice_dpll.c b/drivers/net/ethernet/intel/ice/ice_dpll.c\nindex 62f75701d652..ab62aac77399 100644\n--- a/drivers/net/ethernet/intel/ice/ice_dpll.c\n+++ b/drivers/net/ethernet/intel/ice/ice_dpll.c\n@@ -19,6 +19,11 @@\n #define ICE_DPLL_SW_PIN_INPUT_BASE_QSFP\t\t6\n #define ICE_DPLL_SW_PIN_OUTPUT_BASE\t\t0\n \n+#define E825_EXT_EREF_PIN_IDX\t\t\t0\n+#define E825_EXT_SYNCE_PIN_IDX\t\t\t1\n+#define E825_RCLK_PARENT_0_PIN_IDX\t\t0\n+#define E825_RCLK_PARENT_1_PIN_IDX\t\t1\n+\n #define ICE_DPLL_PIN_SW_INPUT_ABS(in_idx) \\\n \t(ICE_DPLL_SW_PIN_INPUT_BASE_SFP + (in_idx))\n \n@@ -57,6 +62,7 @@\n  * @ICE_DPLL_PIN_TYPE_OUTPUT: output pin\n  * @ICE_DPLL_PIN_TYPE_RCLK_INPUT: recovery clock input pin\n  * @ICE_DPLL_PIN_TYPE_SOFTWARE: software controlled SMA/U.FL pins\n+ * @ICE_DPLL_PIN_TYPE_TXCLK: transmit clock reference input pin\n  */\n enum ice_dpll_pin_type {\n \tICE_DPLL_PIN_INVALID,\n@@ -64,6 +70,7 @@ enum ice_dpll_pin_type {\n \tICE_DPLL_PIN_TYPE_OUTPUT,\n \tICE_DPLL_PIN_TYPE_RCLK_INPUT,\n \tICE_DPLL_PIN_TYPE_SOFTWARE,\n+\tICE_DPLL_PIN_TYPE_TXCLK,\n };\n \n static const char * const pin_type_name[] = {\n@@ -71,10 +78,13 @@ static const char * const pin_type_name[] = {\n \t[ICE_DPLL_PIN_TYPE_OUTPUT] = \"output\",\n \t[ICE_DPLL_PIN_TYPE_RCLK_INPUT] = \"rclk-input\",\n \t[ICE_DPLL_PIN_TYPE_SOFTWARE] = \"software\",\n+\t[ICE_DPLL_PIN_TYPE_TXCLK] = \"txclk-input\",\n };\n \n static const char * const ice_dpll_sw_pin_sma[] = { \"SMA1\", \"SMA2\" };\n static const char * const ice_dpll_sw_pin_ufl[] = { \"U.FL1\", \"U.FL2\" };\n+static const char * const ice_dpll_ext_eref_pin = \"EXT_EREF0\";\n+static const char * const ice_dpll_fwnode_ext_synce = \"clk_ref_synce\";\n \n static const struct dpll_pin_frequency ice_esync_range[] = {\n \tDPLL_PIN_FREQUENCY_RANGE(0, DPLL_PIN_FREQUENCY_1_HZ),\n@@ -2517,12 +2527,75 @@ ice_dpll_rclk_state_on_pin_get(const struct dpll_pin *pin, void *pin_priv,\n \treturn ret;\n }\n \n+/**\n+ * ice_dpll_txclk_state_on_dpll_set - set a state on TX clk pin\n+ * @pin: pointer to a pin\n+ * @pin_priv: private data pointer passed on pin registration\n+ * @dpll: registered dpll pointer\n+ * @dpll_priv: private data pointer passed on dpll registration\n+ * @state: state to be set on pin\n+ * @extack: error reporting\n+ *\n+ * Dpll subsystem callback, set a state of a Tx reference clock pin\n+ *\n+ * Return:\n+ * * negative - failure\n+ */\n+static int\n+ice_dpll_txclk_state_on_dpll_set(const struct dpll_pin *pin, void *pin_priv,\n+\t\t\t\t const struct dpll_device *dpll,\n+\t\t\t\t void *dpll_priv, enum dpll_pin_state state,\n+\t\t\t\t struct netlink_ext_ack *extack)\n+{\n+\t/*\n+\t * TODO: set HW accordingly to selected TX reference clock.\n+\t * To be added in the follow up patches.\n+\t */\n+\treturn -EOPNOTSUPP;\n+}\n+\n+/**\n+ * ice_dpll_txclk_state_on_dpll_get - get a state of Tx clk reference pin\n+ * @pin: pointer to a pin\n+ * @pin_priv: private data pointer passed on pin registration\n+ * @dpll: registered dpll pointer\n+ * @dpll_priv: private data pointer passed on dpll registration\n+ * @state: on success holds pin state on parent pin\n+ * @extack: error reporting\n+ *\n+ * dpll subsystem callback, get a state of a TX clock reference pin.\n+ *\n+ * Return:\n+ * * 0 - success\n+ */\n+static int\n+ice_dpll_txclk_state_on_dpll_get(const struct dpll_pin *pin, void *pin_priv,\n+\t\t\t\t const struct dpll_device *dpll,\n+\t\t\t\t void *dpll_priv,\n+\t\t\t\t enum dpll_pin_state *state,\n+\t\t\t\t struct netlink_ext_ack *extack)\n+{\n+\t/*\n+\t * TODO: query HW status to determine if the TX reference is selected.\n+\t * To be added in the follow up patches.\n+\t */\n+\t*state = DPLL_PIN_STATE_DISCONNECTED;\n+\n+\treturn 0;\n+}\n+\n static const struct dpll_pin_ops ice_dpll_rclk_ops = {\n \t.state_on_pin_set = ice_dpll_rclk_state_on_pin_set,\n \t.state_on_pin_get = ice_dpll_rclk_state_on_pin_get,\n \t.direction_get = ice_dpll_input_direction,\n };\n \n+static const struct dpll_pin_ops ice_dpll_txclk_ops = {\n+\t.state_on_dpll_set = ice_dpll_txclk_state_on_dpll_set,\n+\t.state_on_dpll_get = ice_dpll_txclk_state_on_dpll_get,\n+\t.direction_get = ice_dpll_input_direction,\n+};\n+\n static const struct dpll_pin_ops ice_dpll_pin_sma_ops = {\n \t.state_on_dpll_set = ice_dpll_sma_pin_state_set,\n \t.state_on_dpll_get = ice_dpll_sw_pin_state_get,\n@@ -3023,9 +3096,13 @@ ice_dpll_unregister_pins(struct dpll_device *dpll, struct ice_dpll_pin *pins,\n {\n \tint i;\n \n-\tfor (i = 0; i < count; i++)\n-\t\tif (!pins[i].hidden)\n-\t\t\tdpll_pin_unregister(dpll, pins[i].pin, ops, &pins[i]);\n+\tfor (i = 0; i < count; i++) {\n+\t\tif (pins[i].hidden)\n+\t\t\tcontinue;\n+\t\tif (IS_ERR_OR_NULL(pins[i].pin))\n+\t\t\tcontinue;\n+\t\tdpll_pin_unregister(dpll, pins[i].pin, ops, &pins[i]);\n+\t}\n }\n \n /**\n@@ -3199,19 +3276,40 @@ static bool ice_dpll_is_fwnode_pin(struct ice_dpll_pin *pin)\n \treturn !IS_ERR_OR_NULL(pin->fwnode);\n }\n \n+static bool ice_dpll_fwnode_eq(const struct fwnode_handle *a,\n+\t\t\t       const struct fwnode_handle *b)\n+{\n+\treturn a && b && a == b;\n+}\n+\n static void ice_dpll_pin_notify_work(struct work_struct *work)\n {\n \tstruct ice_dpll_pin_work *w = container_of(work,\n \t\t\t\t\t\t   struct ice_dpll_pin_work,\n \t\t\t\t\t\t   work);\n \tstruct ice_dpll_pin *pin, *parent = w->pin;\n+\tbool is_tx_synce_parent = false;\n \tstruct ice_pf *pf = parent->pf;\n+\tbool is_rclk_parent = false;\n \tint ret;\n \n \twait_for_completion(&pf->dplls.dpll_init);\n \tif (!test_bit(ICE_FLAG_DPLL, pf->flags))\n \t\tgoto out; /* DPLL initialization failed */\n \n+\t/* Decide which parent we are handling, defensively checking FWNs */\n+\tis_rclk_parent =\n+\t\tice_dpll_fwnode_eq(parent->fwnode,\n+\t\t\t\t   pf->dplls.inputs[E825_RCLK_PARENT_0_PIN_IDX].fwnode) ||\n+\t\tice_dpll_fwnode_eq(parent->fwnode,\n+\t\t\t\t   pf->dplls.inputs[E825_RCLK_PARENT_1_PIN_IDX].fwnode);\n+\n+\tis_tx_synce_parent =\n+\t\tice_dpll_fwnode_eq(parent->fwnode,\n+\t\t\t\t   pf->dplls.txclks[E825_EXT_SYNCE_PIN_IDX].fwnode);\n+\tif (!is_rclk_parent && !is_tx_synce_parent)\n+\t\tgoto out;\n+\n \tswitch (w->action) {\n \tcase DPLL_PIN_CREATED:\n \t\tif (!IS_ERR_OR_NULL(parent->pin)) {\n@@ -3228,16 +3326,28 @@ static void ice_dpll_pin_notify_work(struct work_struct *work)\n \t\t\tgoto out;\n \t\t}\n \n-\t\t/* Register rclk pin */\n-\t\tpin = &pf->dplls.rclk;\n-\t\tret = dpll_pin_on_pin_register(parent->pin, pin->pin,\n-\t\t\t\t\t       &ice_dpll_rclk_ops, pin);\n-\t\tif (ret) {\n-\t\t\tdev_err(ice_pf_to_dev(pf),\n-\t\t\t\t\"Failed to register pin: %pe\\n\", ERR_PTR(ret));\n-\t\t\tdpll_pin_put(parent->pin, &parent->tracker);\n-\t\t\tparent->pin = NULL;\n-\t\t\tgoto out;\n+\t\tif (is_rclk_parent) {\n+\t\t\t/* Register rclk pin via on-pin relationship */\n+\t\t\tpin = &pf->dplls.rclk;\n+\t\t\tret = dpll_pin_on_pin_register(parent->pin, pin->pin,\n+\t\t\t\t\t\t       &ice_dpll_rclk_ops, pin);\n+\t\t\tif (ret) {\n+\t\t\t\tdev_err(ice_pf_to_dev(pf),\n+\t\t\t\t\t\"RCLK pin register failed: %pe\\n\",\n+\t\t\t\t\tERR_PTR(ret));\n+\t\t\t\tgoto drop_parent_ref;\n+\t\t\t}\n+\t\t} else if (is_tx_synce_parent) {\n+\t\t\t/* Register TX-CLK SYNCE pin directly to TXC DPLL */\n+\t\t\tpin = &pf->dplls.txclks[E825_EXT_SYNCE_PIN_IDX];\n+\t\t\tret = dpll_pin_register(pf->dplls.txc.dpll, pin->pin,\n+\t\t\t\t\t\t&ice_dpll_txclk_ops, pin);\n+\t\t\tif (ret) {\n+\t\t\t\tdev_err(ice_pf_to_dev(pf),\n+\t\t\t\t\t\"TX SYNCE pin register failed: %pe\\n\",\n+\t\t\t\t\tERR_PTR(ret));\n+\t\t\t\tgoto drop_parent_ref;\n+\t\t\t}\n \t\t}\n \t\tbreak;\n \tcase DPLL_PIN_DELETED:\n@@ -3246,11 +3356,18 @@ static void ice_dpll_pin_notify_work(struct work_struct *work)\n \t\t\tgoto out;\n \t\t}\n \n-\t\t/* Unregister rclk pin */\n-\t\tpin = &pf->dplls.rclk;\n-\t\tdpll_pin_on_pin_unregister(parent->pin, pin->pin,\n-\t\t\t\t\t   &ice_dpll_rclk_ops, pin);\n-\n+\t\tif (is_rclk_parent) {\n+\t\t\t/* Unregister rclk pin */\n+\t\t\tpin = &pf->dplls.rclk;\n+\t\t\tdpll_pin_on_pin_unregister(parent->pin, pin->pin,\n+\t\t\t\t\t\t   &ice_dpll_rclk_ops, pin);\n+\t\t} else if (is_tx_synce_parent) {\n+\t\t\t/* Unregister TX-CLK SYNCE pin from TXC DPLL */\n+\t\t\tpin = &pf->dplls.txclks[E825_EXT_SYNCE_PIN_IDX];\n+\t\t\tdpll_pin_unregister(pf->dplls.txc.dpll, pin->pin,\n+\t\t\t\t\t    &ice_dpll_txclk_ops, pin);\n+\t\t}\n+drop_parent_ref:\n \t\t/* Drop fwnode pin reference */\n \t\tdpll_pin_put(parent->pin, &parent->tracker);\n \t\tparent->pin = NULL;\n@@ -3276,6 +3393,12 @@ static int ice_dpll_pin_notify(struct notifier_block *nb, unsigned long action,\n \tif (pin->fwnode != info->fwnode)\n \t\treturn NOTIFY_DONE; /* Not this pin */\n \n+\t/* Ignore notification which are the outcome of internal pin\n+\t * registration/unregistration calls - synce pin case.\n+\t */\n+\tif (info->src_clock_id == pin->pf->dplls.clock_id)\n+\t\treturn NOTIFY_DONE;\n+\n \twork = kzalloc_obj(*work);\n \tif (!work)\n \t\treturn NOTIFY_DONE;\n@@ -3401,6 +3524,19 @@ ice_dpll_deinit_fwnode_pins(struct ice_pf *pf, struct ice_dpll_pin *pins,\n \tdestroy_workqueue(pf->dplls.wq);\n }\n \n+static int ice_dpll_deinit_txclk_pins(struct ice_pf *pf)\n+{\n+\tstruct ice_dpll_pin *synce_pin = &pf->dplls.txclks[E825_EXT_SYNCE_PIN_IDX];\n+\tstruct ice_dpll *dt = &pf->dplls.txc;\n+\n+\tice_dpll_unregister_pins(dt->dpll, pf->dplls.txclks,\n+\t\t\t\t &ice_dpll_txclk_ops,\n+\t\t\t\t ARRAY_SIZE(pf->dplls.txclks));\n+\tice_dpll_release_pins(&pf->dplls.txclks[E825_EXT_EREF_PIN_IDX], 1);\n+\tice_dpll_deinit_fwnode_pin(synce_pin);\n+\treturn 0;\n+}\n+\n /**\n  * ice_dpll_deinit_pins - deinitialize direct pins\n  * @pf: board private structure\n@@ -3420,8 +3556,10 @@ static void ice_dpll_deinit_pins(struct ice_pf *pf, bool cgu)\n \tstruct ice_dpll *dp = &d->pps;\n \n \tice_dpll_deinit_rclk_pin(pf);\n-\tif (pf->hw.mac_type == ICE_MAC_GENERIC_3K_E825)\n+\tif (pf->hw.mac_type == ICE_MAC_GENERIC_3K_E825) {\n+\t\tice_dpll_deinit_txclk_pins(pf);\n \t\tice_dpll_deinit_fwnode_pins(pf, pf->dplls.inputs, 0);\n+\t}\n \tif (cgu) {\n \t\tice_dpll_unregister_pins(dp->dpll, inputs, &ice_dpll_input_ops,\n \t\t\t\t\t num_inputs);\n@@ -3552,6 +3690,58 @@ ice_dpll_init_fwnode_pins(struct ice_pf *pf, struct ice_dpll_pin *pins,\n \treturn ret;\n }\n \n+static int ice_dpll_init_txclk_pins(struct ice_pf *pf, int start_idx)\n+{\n+\tstruct ice_dpll_pin *ref_pin = pf->dplls.txclks;\n+\tstruct ice_dpll *txc = &pf->dplls.txc;\n+\tint ret;\n+\n+\t/* Configure EXT_EREF0 pin */\n+\tret = ice_dpll_get_pins(pf, ref_pin, start_idx, 1, pf->dplls.clock_id);\n+\tif (ret)\n+\t\treturn ret;\n+\tret = dpll_pin_register(txc->dpll, ref_pin->pin, &ice_dpll_txclk_ops,\n+\t\t\t\tref_pin);\n+\tif (ret)\n+\t\tgoto err_release_ext_eref;\n+\n+\t/*\n+\t * Configure EXT_SYNCE pin (fwnode-backed).\n+\t * The pin may not yet be available; in that case registration\n+\t * will be deferred via the notifier path.\n+\t */\n+\tref_pin++;\n+\tret = ice_dpll_init_fwnode_pin(ref_pin, ice_dpll_fwnode_ext_synce);\n+\tif (ret)\n+\t\tgoto err_unregister_ext_eref;\n+\n+\tif (IS_ERR_OR_NULL(ref_pin->pin)) {\n+\t\tdev_dbg(ice_pf_to_dev(pf),\n+\t\t\t\"Tx-clk SYNCE pin not registered yet\\n\");\n+\t\treturn 0;\n+\t}\n+\n+\tret = dpll_pin_register(txc->dpll, ref_pin->pin, &ice_dpll_txclk_ops,\n+\t\t\t\tref_pin);\n+\tif (ret)\n+\t\tgoto err_deinit_synce;\n+\n+\treturn 0;\n+\n+err_deinit_synce:\n+\tice_dpll_deinit_fwnode_pin(ref_pin);\n+err_unregister_ext_eref:\n+\tdpll_pin_unregister(txc->dpll,\n+\t\t\t    pf->dplls.txclks[E825_EXT_EREF_PIN_IDX].pin,\n+\t\t\t    &ice_dpll_txclk_ops,\n+\t\t\t    &pf->dplls.txclks[E825_EXT_EREF_PIN_IDX]);\n+\n+err_release_ext_eref:\n+\tice_dpll_release_pins(&pf->dplls.txclks[E825_EXT_EREF_PIN_IDX], 1);\n+\n+\treturn ret;\n+}\n+\n /**\n  * ice_dpll_init_pins_e825 - init pins and register pins with a dplls\n  * @pf: board private structure\n@@ -3574,6 +3764,15 @@ static int ice_dpll_init_pins_e825(struct ice_pf *pf)\n \n \tret = ice_dpll_init_rclk_pin(pf, DPLL_PIN_IDX_UNSPEC,\n \t\t\t\t     &ice_dpll_rclk_ops);\n+\n+\tif (ret)\n+\t\tgoto unregister_pins;\n+\n+\tret = ice_dpll_init_txclk_pins(pf, 0);\n+\tif (ret)\n+\t\tice_dpll_deinit_rclk_pin(pf);\n+\n+unregister_pins:\n \tif (ret) {\n \t\t/* Inform DPLL notifier works that DPLL init was finished\n \t\t * unsuccessfully (ICE_DPLL_FLAG not set).\n@@ -3692,7 +3891,7 @@ static int ice_dpll_init_pins(struct ice_pf *pf, bool cgu)\n static void\n ice_dpll_deinit_dpll(struct ice_pf *pf, struct ice_dpll *d, bool cgu)\n {\n-\tif (cgu)\n+\tif (cgu || pf->hw.mac_type == ICE_MAC_GENERIC_3K_E825)\n \t\tdpll_device_unregister(d->dpll, d->ops, d);\n \tdpll_device_put(d->dpll, &d->tracker);\n }\n@@ -3727,12 +3926,13 @@ ice_dpll_init_dpll(struct ice_pf *pf, struct ice_dpll *d, bool cgu,\n \t\treturn ret;\n \t}\n \td->pf = pf;\n-\tif (cgu) {\n+\tif (cgu || pf->hw.mac_type == ICE_MAC_GENERIC_3K_E825) {\n \t\tconst struct dpll_device_ops *ops = &ice_dpll_ops;\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 (cgu)\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@@ -4081,6 +4281,36 @@ static int ice_dpll_init_info_sw_pins(struct ice_pf *pf)\n \treturn 0;\n }\n \n+/**\n+ * ice_dpll_init_info_txclk_pins_e825c - initializes tx-clk pins information\n+ * @pf: board private structure\n+ *\n+ * Init information for tx-clks pin, cache them in pf->dplls.txclks\n+ *\n+ * Return:\n+ * * 0 - success\n+ */\n+static int ice_dpll_init_info_txclk_pins_e825c(struct ice_pf *pf)\n+{\n+\tstruct ice_dpll_pin *tx_pin;\n+\n+\tfor (int i = 0; i < ICE_DPLL_TXCLK_NUM_MAX; i++) {\n+\t\ttx_pin = &pf->dplls.txclks[i];\n+\t\ttx_pin->prop.type = DPLL_PIN_TYPE_EXT;\n+\t\ttx_pin->prop.capabilities |=\n+\t\t\t\t DPLL_PIN_CAPABILITIES_STATE_CAN_CHANGE;\n+\t\ttx_pin->pf = pf;\n+\t\tif (i == E825_EXT_EREF_PIN_IDX) {\n+\t\t\ttx_pin->prop.board_label = ice_dpll_ext_eref_pin;\n+\t\t\ttx_pin->tx_ref_src = ICE_REF_CLK_EREF0;\n+\t\t} else if (i == E825_EXT_SYNCE_PIN_IDX) {\n+\t\t\ttx_pin->tx_ref_src = ICE_REF_CLK_SYNCE;\n+\t\t}\n+\t}\n+\n+\treturn 0;\n+}\n+\n /**\n  * ice_dpll_init_pins_info - init pins info wrapper\n  * @pf: board private structure\n@@ -4106,6 +4336,9 @@ ice_dpll_init_pins_info(struct ice_pf *pf, enum ice_dpll_pin_type pin_type)\n \t\t\treturn ice_dpll_init_info_rclk_pin(pf);\n \tcase ICE_DPLL_PIN_TYPE_SOFTWARE:\n \t\treturn ice_dpll_init_info_sw_pins(pf);\n+\n+\tcase ICE_DPLL_PIN_TYPE_TXCLK:\n+\t\treturn ice_dpll_init_info_txclk_pins_e825c(pf);\n \tdefault:\n \t\treturn -EINVAL;\n \t}\n@@ -4139,11 +4372,15 @@ static void ice_dpll_deinit_info(struct ice_pf *pf)\n static int ice_dpll_init_info_e825c(struct ice_pf *pf)\n {\n \tstruct ice_dplls *d = &pf->dplls;\n+\tstruct ice_dpll *dt = &d->txc;\n \tint ret = 0;\n \tint i;\n \n \td->clock_id = ice_generate_clock_id(pf);\n \td->num_inputs = ICE_SYNCE_CLK_NUM;\n+\tdt->dpll_state = DPLL_LOCK_STATUS_UNLOCKED;\n+\tdt->mode = DPLL_MODE_MANUAL;\n+\tdt->dpll_idx = pf->ptp.port.port_num;\n \n \td->inputs = kzalloc_objs(*d->inputs, d->num_inputs);\n \tif (!d->inputs)\n@@ -4160,6 +4397,11 @@ static int ice_dpll_init_info_e825c(struct ice_pf *pf)\n \tret = ice_dpll_init_pins_info(pf, ICE_DPLL_PIN_TYPE_RCLK_INPUT);\n \tif (ret)\n \t\tgoto deinit_info;\n+\n+\tret = ice_dpll_init_pins_info(pf, ICE_DPLL_PIN_TYPE_TXCLK);\n+\tif (ret)\n+\t\tgoto deinit_info;\n+\n \tdev_dbg(ice_pf_to_dev(pf),\n \t\t\"%s - success, inputs: %u, outputs: %u, rclk-parents: %u\\n\",\n \t\t __func__, d->num_inputs, d->num_outputs, d->rclk.num_parents);\n@@ -4292,6 +4534,9 @@ void ice_dpll_deinit(struct ice_pf *pf)\n \t\tice_dpll_deinit_dpll(pf, &pf->dplls.pps, cgu);\n \tif (!IS_ERR_OR_NULL(pf->dplls.eec.dpll))\n \t\tice_dpll_deinit_dpll(pf, &pf->dplls.eec, cgu);\n+\tif (!IS_ERR_OR_NULL(pf->dplls.txc.dpll))\n+\t\tice_dpll_deinit_dpll(pf, &pf->dplls.txc, false);\n+\n \tice_dpll_deinit_info(pf);\n \tmutex_destroy(&pf->dplls.lock);\n }\n@@ -4317,14 +4562,19 @@ static void ice_dpll_init_e825(struct ice_pf *pf)\n \terr = ice_dpll_init_info_e825c(pf);\n \tif (err)\n \t\tgoto err_exit;\n-\terr = ice_dpll_init_pins_e825(pf);\n+\terr = ice_dpll_init_dpll(pf, &pf->dplls.txc, false, DPLL_TYPE_TXC);\n \tif (err)\n \t\tgoto deinit_info;\n+\terr = ice_dpll_init_pins_e825(pf);\n+\tif (err)\n+\t\tgoto deinit_txclk;\n \tset_bit(ICE_FLAG_DPLL, pf->flags);\n \tcomplete_all(&d->dpll_init);\n \n \treturn;\n \n+deinit_txclk:\n+\tice_dpll_deinit_dpll(pf, &pf->dplls.txc, false);\n deinit_info:\n \tice_dpll_deinit_info(pf);\n err_exit:\ndiff --git a/drivers/net/ethernet/intel/ice/ice_dpll.h b/drivers/net/ethernet/intel/ice/ice_dpll.h\nindex ae42cdea0ee1..23f9d4da73c5 100644\n--- a/drivers/net/ethernet/intel/ice/ice_dpll.h\n+++ b/drivers/net/ethernet/intel/ice/ice_dpll.h\n@@ -7,6 +7,7 @@\n #include \"ice.h\"\n \n #define ICE_DPLL_RCLK_NUM_MAX\t4\n+#define ICE_DPLL_TXCLK_NUM_MAX\t2\n \n /**\n  * enum ice_dpll_pin_sw - enumerate ice software pin indices:\n@@ -63,6 +64,7 @@ struct ice_dpll_pin {\n \tu8 ref_sync;\n \tbool active;\n \tbool hidden;\n+\tenum ice_e825c_ref_clk tx_ref_src;\n };\n \n /** ice_dpll - store info required for DPLL control\n@@ -111,9 +113,11 @@ struct ice_dpll {\n  * @lock: locks access to configuration of a dpll\n  * @eec: pointer to EEC dpll dev\n  * @pps: pointer to PPS dpll dev\n+ * @txc: pointer to TXC dpll dev\n  * @inputs: input pins pointer\n  * @outputs: output pins pointer\n  * @rclk: recovered pins pointer\n+ * @txclks: TX clock reference pins pointer\n  * @num_inputs: number of input pins available on dpll\n  * @num_outputs: number of output pins available on dpll\n  * @cgu_state_acq_err_num: number of errors returned during periodic work\n@@ -131,11 +135,13 @@ struct ice_dplls {\n \tstruct completion dpll_init;\n \tstruct ice_dpll eec;\n \tstruct ice_dpll pps;\n+\tstruct ice_dpll txc;\n \tstruct ice_dpll_pin *inputs;\n \tstruct ice_dpll_pin *outputs;\n \tstruct ice_dpll_pin sma[ICE_DPLL_PIN_SW_NUM];\n \tstruct ice_dpll_pin ufl[ICE_DPLL_PIN_SW_NUM];\n \tstruct ice_dpll_pin rclk;\n+\tstruct ice_dpll_pin txclks[ICE_DPLL_TXCLK_NUM_MAX];\n \tu8 num_inputs;\n \tu8 num_outputs;\n \tu8 sma_data;\ndiff --git a/drivers/net/ethernet/intel/ice/ice_ptp_hw.h b/drivers/net/ethernet/intel/ice/ice_ptp_hw.h\nindex 9bfd3e79c580..cbc9693179a1 100644\n--- a/drivers/net/ethernet/intel/ice/ice_ptp_hw.h\n+++ b/drivers/net/ethernet/intel/ice/ice_ptp_hw.h\n@@ -265,6 +265,13 @@ struct ice_cgu_pin_desc {\n \tstruct dpll_pin_frequency *freq_supp;\n };\n \n+enum ice_e825c_ref_clk {\n+\tICE_REF_CLK_ENET,\n+\tICE_REF_CLK_SYNCE,\n+\tICE_REF_CLK_EREF0,\n+\tICE_REF_CLK_MAX,\n+};\n+\n #define E810C_QSFP_C827_0_HANDLE 2\n #define E810C_QSFP_C827_1_HANDLE 3\n \n","prefixes":["v5","net-next","5/8"]}