From nobody Sat Apr 4 01:33:45 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id ADB4C3B6362; Thu, 2 Apr 2026 23:10:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.19 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775171446; cv=none; b=mpShlS5MlYbVCqXiI3TIhzfHk2hjulHQyecDxsQBtVkGAv0MxEYcCEGB4h68QSQiJ4NMgrtXD9xxc/ufd6Ae925j3v9TZQOiizXqaZkK/Oag0l1etfplHc5zgX3I6ZFRSy53ykMoECABX8/kTMgCyjCVjilOwKlm4/szAiyINbw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775171446; c=relaxed/simple; bh=st23kF2Yc7Fmt4Y/dZXWPHXpJtnUoyHWUmvR5RF1WT4=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=ke6wGVZLNgWjfNWJLm19yGbfD/MFih3hqzEKH6r9y4QbK4C4o6det7GCP0OhQv4XQJBpzPEgnQnZ100q+WCno64gcasZjaOyl7PTI+01ft/4gQdEIyWNRHv0kzHeQ8MQgbU0mX8xK2ENJkVwqC9iVEXbNsZ/6OyUjwj1/LHoScA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=nVsqYyVw; arc=none smtp.client-ip=198.175.65.19 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="nVsqYyVw" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1775171445; x=1806707445; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=st23kF2Yc7Fmt4Y/dZXWPHXpJtnUoyHWUmvR5RF1WT4=; b=nVsqYyVwERxpMmAKJqVAZ/7PXGgCO9XIkyAER6VjbmNCc47b2K8Mb80y T+K0xQuS27bsFNyOC56/fsRJDP9q8GyS/sA5FKHtZzY74ic59y75SA7kK EZyDxbwKizPtZVjbw1fxS0DN7xu09hWII8JqzSy0OAdjkIl90/VjJjgIT KD8NucPhhTxLA/3B9T6Ec88j4I6TK7cWviBkzn/mRCtH4xqwrbScTShAK UFGy4+hVeaAp6j4pcqCGV8zE7Abu9/QNf17OZoyDGFiI6N4+XDvQGURgb ncMh5ni2CvH/0NpItVvCr3C5IWkTCgXiGGOKzR+YMlMZnZNc+qZyEXrW9 w==; X-CSE-ConnectionGUID: eB1ID32TSXGl9Y8KD41fHQ== X-CSE-MsgGUID: ZtD6sJKiTceO5DzqNC97YQ== X-IronPort-AV: E=McAfee;i="6800,10657,11747"; a="76123112" X-IronPort-AV: E=Sophos;i="6.23,156,1770624000"; d="scan'208";a="76123112" Received: from orviesa008.jf.intel.com ([10.64.159.148]) by orvoesa111.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 02 Apr 2026 16:10:44 -0700 X-CSE-ConnectionGUID: 6xLc6h6QQUeTUv4ANRvt8A== X-CSE-MsgGUID: 9XKUPJh3Q/aaGY5RtAXCMA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,156,1770624000"; d="scan'208";a="227044448" Received: from gklab-003-001.igk.intel.com ([10.91.173.48]) by orviesa008.jf.intel.com with ESMTP; 02 Apr 2026 16:10:40 -0700 From: Grzegorz Nitka To: netdev@vger.kernel.org Cc: linux-kernel@vger.kernel.org, intel-wired-lan@lists.osuosl.org, poros@redhat.com, richardcochran@gmail.com, andrew+netdev@lunn.ch, przemyslaw.kitszel@intel.com, anthony.l.nguyen@intel.com, Prathosh.Satish@microchip.com, ivecera@redhat.com, jiri@resnulli.us, arkadiusz.kubalewski@intel.com, vadim.fedorenko@linux.dev, donald.hunter@gmail.com, horms@kernel.org, pabeni@redhat.com, kuba@kernel.org, davem@davemloft.net, edumazet@google.com, Grzegorz Nitka Subject: [PATCH v5 net-next 5/8] ice: introduce TXC DPLL device and TX ref clock pin framework for E825 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> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" E825 devices provide a dedicated TX clock (TXC) domain which may be driven by multiple reference clock sources, including external board references and port-derived SyncE. To support future TX clock control and observability through the Linux DPLL subsystem, introduce a separate TXC DPLL device and a framework for representing TX reference clock inputs. This change adds a new DPLL pin type (TXCLK) and registers TX reference clock pins for E825-based devices: - EXT_EREF0: a board-level external electrical reference - SYNCE: a port-derived SyncE reference described via firmware nodes The TXC DPLL device is created and managed alongside the existing PPS and EEC DPLL instances. TXCLK pins are registered directly or deferred via a notifier when backed by fwnode-described firmware pins. A per-pin attribute encodes the TX reference source associated with each TXCLK pin. At this stage, TXCLK pin state callbacks and TXC DPLL lock status reporting are implemented as placeholders. Pin state getters always return DISCONNECTED, and the TXC DPLL is initialized in the UNLOCKED state. No hardware configuration or TX reference switching is performed yet. This patch establishes the structural groundwork required for hardware-backed TX reference selection, verification, and synchronization status reporting, which will be implemented in subsequent patches. Reviewed-by: Arkadiusz Kubalewski Signed-off-by: Grzegorz Nitka --- drivers/net/ethernet/intel/ice/ice_dpll.c | 296 ++++++++++++++++++-- drivers/net/ethernet/intel/ice/ice_dpll.h | 6 + drivers/net/ethernet/intel/ice/ice_ptp_hw.h | 7 + 3 files changed, 286 insertions(+), 23 deletions(-) diff --git a/drivers/net/ethernet/intel/ice/ice_dpll.c b/drivers/net/ethern= et/intel/ice/ice_dpll.c index 62f75701d652..ab62aac77399 100644 --- a/drivers/net/ethernet/intel/ice/ice_dpll.c +++ b/drivers/net/ethernet/intel/ice/ice_dpll.c @@ -19,6 +19,11 @@ #define ICE_DPLL_SW_PIN_INPUT_BASE_QSFP 6 #define ICE_DPLL_SW_PIN_OUTPUT_BASE 0 =20 +#define E825_EXT_EREF_PIN_IDX 0 +#define E825_EXT_SYNCE_PIN_IDX 1 +#define E825_RCLK_PARENT_0_PIN_IDX 0 +#define E825_RCLK_PARENT_1_PIN_IDX 1 + #define ICE_DPLL_PIN_SW_INPUT_ABS(in_idx) \ (ICE_DPLL_SW_PIN_INPUT_BASE_SFP + (in_idx)) =20 @@ -57,6 +62,7 @@ * @ICE_DPLL_PIN_TYPE_OUTPUT: output pin * @ICE_DPLL_PIN_TYPE_RCLK_INPUT: recovery clock input pin * @ICE_DPLL_PIN_TYPE_SOFTWARE: software controlled SMA/U.FL pins + * @ICE_DPLL_PIN_TYPE_TXCLK: transmit clock reference input pin */ enum ice_dpll_pin_type { ICE_DPLL_PIN_INVALID, @@ -64,6 +70,7 @@ enum ice_dpll_pin_type { ICE_DPLL_PIN_TYPE_OUTPUT, ICE_DPLL_PIN_TYPE_RCLK_INPUT, ICE_DPLL_PIN_TYPE_SOFTWARE, + ICE_DPLL_PIN_TYPE_TXCLK, }; =20 static const char * const pin_type_name[] =3D { @@ -71,10 +78,13 @@ static const char * const pin_type_name[] =3D { [ICE_DPLL_PIN_TYPE_OUTPUT] =3D "output", [ICE_DPLL_PIN_TYPE_RCLK_INPUT] =3D "rclk-input", [ICE_DPLL_PIN_TYPE_SOFTWARE] =3D "software", + [ICE_DPLL_PIN_TYPE_TXCLK] =3D "txclk-input", }; =20 static const char * const ice_dpll_sw_pin_sma[] =3D { "SMA1", "SMA2" }; static const char * const ice_dpll_sw_pin_ufl[] =3D { "U.FL1", "U.FL2" }; +static const char * const ice_dpll_ext_eref_pin =3D "EXT_EREF0"; +static const char * const ice_dpll_fwnode_ext_synce =3D "clk_ref_synce"; =20 static const struct dpll_pin_frequency ice_esync_range[] =3D { DPLL_PIN_FREQUENCY_RANGE(0, DPLL_PIN_FREQUENCY_1_HZ), @@ -2517,12 +2527,75 @@ ice_dpll_rclk_state_on_pin_get(const struct dpll_pi= n *pin, void *pin_priv, return ret; } =20 +/** + * ice_dpll_txclk_state_on_dpll_set - set a state on TX clk pin + * @pin: pointer to a pin + * @pin_priv: private data pointer passed on pin registration + * @dpll: registered dpll pointer + * @dpll_priv: private data pointer passed on dpll registration + * @state: state to be set on pin + * @extack: error reporting + * + * Dpll subsystem callback, set a state of a Tx reference clock pin + * + * Return: + * * negative - failure + */ +static int +ice_dpll_txclk_state_on_dpll_set(const struct dpll_pin *pin, void *pin_pri= v, + const struct dpll_device *dpll, + void *dpll_priv, enum dpll_pin_state state, + struct netlink_ext_ack *extack) +{ + /* + * TODO: set HW accordingly to selected TX reference clock. + * To be added in the follow up patches. + */ + return -EOPNOTSUPP; +} + +/** + * ice_dpll_txclk_state_on_dpll_get - get a state of Tx clk reference pin + * @pin: pointer to a pin + * @pin_priv: private data pointer passed on pin registration + * @dpll: registered dpll pointer + * @dpll_priv: private data pointer passed on dpll registration + * @state: on success holds pin state on parent pin + * @extack: error reporting + * + * dpll subsystem callback, get a state of a TX clock reference pin. + * + * Return: + * * 0 - success + */ +static int +ice_dpll_txclk_state_on_dpll_get(const struct dpll_pin *pin, void *pin_pri= v, + const struct dpll_device *dpll, + void *dpll_priv, + enum dpll_pin_state *state, + struct netlink_ext_ack *extack) +{ + /* + * TODO: query HW status to determine if the TX reference is selected. + * To be added in the follow up patches. + */ + *state =3D DPLL_PIN_STATE_DISCONNECTED; + + return 0; +} + static const struct dpll_pin_ops ice_dpll_rclk_ops =3D { .state_on_pin_set =3D ice_dpll_rclk_state_on_pin_set, .state_on_pin_get =3D ice_dpll_rclk_state_on_pin_get, .direction_get =3D ice_dpll_input_direction, }; =20 +static const struct dpll_pin_ops ice_dpll_txclk_ops =3D { + .state_on_dpll_set =3D ice_dpll_txclk_state_on_dpll_set, + .state_on_dpll_get =3D ice_dpll_txclk_state_on_dpll_get, + .direction_get =3D ice_dpll_input_direction, +}; + static const struct dpll_pin_ops ice_dpll_pin_sma_ops =3D { .state_on_dpll_set =3D ice_dpll_sma_pin_state_set, .state_on_dpll_get =3D ice_dpll_sw_pin_state_get, @@ -3023,9 +3096,13 @@ ice_dpll_unregister_pins(struct dpll_device *dpll, s= truct ice_dpll_pin *pins, { int i; =20 - for (i =3D 0; i < count; i++) - if (!pins[i].hidden) - dpll_pin_unregister(dpll, pins[i].pin, ops, &pins[i]); + for (i =3D 0; i < count; i++) { + if (pins[i].hidden) + continue; + if (IS_ERR_OR_NULL(pins[i].pin)) + continue; + dpll_pin_unregister(dpll, pins[i].pin, ops, &pins[i]); + } } =20 /** @@ -3199,19 +3276,40 @@ static bool ice_dpll_is_fwnode_pin(struct ice_dpll_= pin *pin) return !IS_ERR_OR_NULL(pin->fwnode); } =20 +static bool ice_dpll_fwnode_eq(const struct fwnode_handle *a, + const struct fwnode_handle *b) +{ + return a && b && a =3D=3D b; +} + static void ice_dpll_pin_notify_work(struct work_struct *work) { struct ice_dpll_pin_work *w =3D container_of(work, struct ice_dpll_pin_work, work); struct ice_dpll_pin *pin, *parent =3D w->pin; + bool is_tx_synce_parent =3D false; struct ice_pf *pf =3D parent->pf; + bool is_rclk_parent =3D false; int ret; =20 wait_for_completion(&pf->dplls.dpll_init); if (!test_bit(ICE_FLAG_DPLL, pf->flags)) goto out; /* DPLL initialization failed */ =20 + /* Decide which parent we are handling, defensively checking FWNs */ + is_rclk_parent =3D + ice_dpll_fwnode_eq(parent->fwnode, + pf->dplls.inputs[E825_RCLK_PARENT_0_PIN_IDX].fwnode) || + ice_dpll_fwnode_eq(parent->fwnode, + pf->dplls.inputs[E825_RCLK_PARENT_1_PIN_IDX].fwnode); + + is_tx_synce_parent =3D + ice_dpll_fwnode_eq(parent->fwnode, + pf->dplls.txclks[E825_EXT_SYNCE_PIN_IDX].fwnode); + if (!is_rclk_parent && !is_tx_synce_parent) + goto out; + switch (w->action) { case DPLL_PIN_CREATED: if (!IS_ERR_OR_NULL(parent->pin)) { @@ -3228,16 +3326,28 @@ static void ice_dpll_pin_notify_work(struct work_st= ruct *work) goto out; } =20 - /* Register rclk pin */ - pin =3D &pf->dplls.rclk; - ret =3D dpll_pin_on_pin_register(parent->pin, pin->pin, - &ice_dpll_rclk_ops, pin); - if (ret) { - dev_err(ice_pf_to_dev(pf), - "Failed to register pin: %pe\n", ERR_PTR(ret)); - dpll_pin_put(parent->pin, &parent->tracker); - parent->pin =3D NULL; - goto out; + if (is_rclk_parent) { + /* Register rclk pin via on-pin relationship */ + pin =3D &pf->dplls.rclk; + ret =3D dpll_pin_on_pin_register(parent->pin, pin->pin, + &ice_dpll_rclk_ops, pin); + if (ret) { + dev_err(ice_pf_to_dev(pf), + "RCLK pin register failed: %pe\n", + ERR_PTR(ret)); + goto drop_parent_ref; + } + } else if (is_tx_synce_parent) { + /* Register TX-CLK SYNCE pin directly to TXC DPLL */ + pin =3D &pf->dplls.txclks[E825_EXT_SYNCE_PIN_IDX]; + ret =3D dpll_pin_register(pf->dplls.txc.dpll, pin->pin, + &ice_dpll_txclk_ops, pin); + if (ret) { + dev_err(ice_pf_to_dev(pf), + "TX SYNCE pin register failed: %pe\n", + ERR_PTR(ret)); + goto drop_parent_ref; + } } break; case DPLL_PIN_DELETED: @@ -3246,11 +3356,18 @@ static void ice_dpll_pin_notify_work(struct work_st= ruct *work) goto out; } =20 - /* Unregister rclk pin */ - pin =3D &pf->dplls.rclk; - dpll_pin_on_pin_unregister(parent->pin, pin->pin, - &ice_dpll_rclk_ops, pin); - + if (is_rclk_parent) { + /* Unregister rclk pin */ + pin =3D &pf->dplls.rclk; + dpll_pin_on_pin_unregister(parent->pin, pin->pin, + &ice_dpll_rclk_ops, pin); + } else if (is_tx_synce_parent) { + /* Unregister TX-CLK SYNCE pin from TXC DPLL */ + pin =3D &pf->dplls.txclks[E825_EXT_SYNCE_PIN_IDX]; + dpll_pin_unregister(pf->dplls.txc.dpll, pin->pin, + &ice_dpll_txclk_ops, pin); + } +drop_parent_ref: /* Drop fwnode pin reference */ dpll_pin_put(parent->pin, &parent->tracker); parent->pin =3D NULL; @@ -3276,6 +3393,12 @@ static int ice_dpll_pin_notify(struct notifier_block= *nb, unsigned long action, if (pin->fwnode !=3D info->fwnode) return NOTIFY_DONE; /* Not this pin */ =20 + /* Ignore notification which are the outcome of internal pin + * registration/unregistration calls - synce pin case. + */ + if (info->src_clock_id =3D=3D pin->pf->dplls.clock_id) + return NOTIFY_DONE; + work =3D kzalloc_obj(*work); if (!work) return NOTIFY_DONE; @@ -3401,6 +3524,19 @@ ice_dpll_deinit_fwnode_pins(struct ice_pf *pf, struc= t ice_dpll_pin *pins, destroy_workqueue(pf->dplls.wq); } =20 +static int ice_dpll_deinit_txclk_pins(struct ice_pf *pf) +{ + struct ice_dpll_pin *synce_pin =3D &pf->dplls.txclks[E825_EXT_SYNCE_PIN_I= DX]; + struct ice_dpll *dt =3D &pf->dplls.txc; + + ice_dpll_unregister_pins(dt->dpll, pf->dplls.txclks, + &ice_dpll_txclk_ops, + ARRAY_SIZE(pf->dplls.txclks)); + ice_dpll_release_pins(&pf->dplls.txclks[E825_EXT_EREF_PIN_IDX], 1); + ice_dpll_deinit_fwnode_pin(synce_pin); + return 0; +} + /** * ice_dpll_deinit_pins - deinitialize direct pins * @pf: board private structure @@ -3420,8 +3556,10 @@ static void ice_dpll_deinit_pins(struct ice_pf *pf, = bool cgu) struct ice_dpll *dp =3D &d->pps; =20 ice_dpll_deinit_rclk_pin(pf); - if (pf->hw.mac_type =3D=3D ICE_MAC_GENERIC_3K_E825) + if (pf->hw.mac_type =3D=3D ICE_MAC_GENERIC_3K_E825) { + ice_dpll_deinit_txclk_pins(pf); ice_dpll_deinit_fwnode_pins(pf, pf->dplls.inputs, 0); + } if (cgu) { ice_dpll_unregister_pins(dp->dpll, inputs, &ice_dpll_input_ops, num_inputs); @@ -3552,6 +3690,58 @@ ice_dpll_init_fwnode_pins(struct ice_pf *pf, struct = ice_dpll_pin *pins, return ret; } =20 +static int ice_dpll_init_txclk_pins(struct ice_pf *pf, int start_idx) +{ + struct ice_dpll_pin *ref_pin =3D pf->dplls.txclks; + struct ice_dpll *txc =3D &pf->dplls.txc; + int ret; + + /* Configure EXT_EREF0 pin */ + ret =3D ice_dpll_get_pins(pf, ref_pin, start_idx, 1, pf->dplls.clock_id); + if (ret) + return ret; + ret =3D dpll_pin_register(txc->dpll, ref_pin->pin, &ice_dpll_txclk_ops, + ref_pin); + if (ret) + goto err_release_ext_eref; + + /* + * Configure EXT_SYNCE pin (fwnode-backed). + * The pin may not yet be available; in that case registration + * will be deferred via the notifier path. + */ + ref_pin++; + ret =3D ice_dpll_init_fwnode_pin(ref_pin, ice_dpll_fwnode_ext_synce); + if (ret) + goto err_unregister_ext_eref; + + if (IS_ERR_OR_NULL(ref_pin->pin)) { + dev_dbg(ice_pf_to_dev(pf), + "Tx-clk SYNCE pin not registered yet\n"); + return 0; + } + + ret =3D dpll_pin_register(txc->dpll, ref_pin->pin, &ice_dpll_txclk_ops, + ref_pin); + if (ret) + goto err_deinit_synce; + + return 0; + +err_deinit_synce: + ice_dpll_deinit_fwnode_pin(ref_pin); +err_unregister_ext_eref: + dpll_pin_unregister(txc->dpll, + pf->dplls.txclks[E825_EXT_EREF_PIN_IDX].pin, + &ice_dpll_txclk_ops, + &pf->dplls.txclks[E825_EXT_EREF_PIN_IDX]); + +err_release_ext_eref: + ice_dpll_release_pins(&pf->dplls.txclks[E825_EXT_EREF_PIN_IDX], 1); + + return ret; +} + /** * ice_dpll_init_pins_e825 - init pins and register pins with a dplls * @pf: board private structure @@ -3574,6 +3764,15 @@ static int ice_dpll_init_pins_e825(struct ice_pf *pf) =20 ret =3D ice_dpll_init_rclk_pin(pf, DPLL_PIN_IDX_UNSPEC, &ice_dpll_rclk_ops); + + if (ret) + goto unregister_pins; + + ret =3D ice_dpll_init_txclk_pins(pf, 0); + if (ret) + ice_dpll_deinit_rclk_pin(pf); + +unregister_pins: if (ret) { /* Inform DPLL notifier works that DPLL init was finished * unsuccessfully (ICE_DPLL_FLAG not set). @@ -3692,7 +3891,7 @@ static int ice_dpll_init_pins(struct ice_pf *pf, bool= cgu) static void ice_dpll_deinit_dpll(struct ice_pf *pf, struct ice_dpll *d, bool cgu) { - if (cgu) + if (cgu || pf->hw.mac_type =3D=3D ICE_MAC_GENERIC_3K_E825) dpll_device_unregister(d->dpll, d->ops, d); dpll_device_put(d->dpll, &d->tracker); } @@ -3727,12 +3926,13 @@ ice_dpll_init_dpll(struct ice_pf *pf, struct ice_dp= ll *d, bool cgu, return ret; } d->pf =3D pf; - if (cgu) { + if (cgu || pf->hw.mac_type =3D=3D ICE_MAC_GENERIC_3K_E825) { const struct dpll_device_ops *ops =3D &ice_dpll_ops; =20 if (type =3D=3D DPLL_TYPE_PPS && ice_dpll_is_pps_phase_monitor(pf)) ops =3D &ice_dpll_pom_ops; - ice_dpll_update_state(pf, d, true); + if (cgu) + ice_dpll_update_state(pf, d, true); ret =3D dpll_device_register(d->dpll, type, ops, d); if (ret) { dpll_device_put(d->dpll, &d->tracker); @@ -4081,6 +4281,36 @@ static int ice_dpll_init_info_sw_pins(struct ice_pf = *pf) return 0; } =20 +/** + * ice_dpll_init_info_txclk_pins_e825c - initializes tx-clk pins informati= on + * @pf: board private structure + * + * Init information for tx-clks pin, cache them in pf->dplls.txclks + * + * Return: + * * 0 - success + */ +static int ice_dpll_init_info_txclk_pins_e825c(struct ice_pf *pf) +{ + struct ice_dpll_pin *tx_pin; + + for (int i =3D 0; i < ICE_DPLL_TXCLK_NUM_MAX; i++) { + tx_pin =3D &pf->dplls.txclks[i]; + tx_pin->prop.type =3D DPLL_PIN_TYPE_EXT; + tx_pin->prop.capabilities |=3D + DPLL_PIN_CAPABILITIES_STATE_CAN_CHANGE; + tx_pin->pf =3D pf; + if (i =3D=3D E825_EXT_EREF_PIN_IDX) { + tx_pin->prop.board_label =3D ice_dpll_ext_eref_pin; + tx_pin->tx_ref_src =3D ICE_REF_CLK_EREF0; + } else if (i =3D=3D E825_EXT_SYNCE_PIN_IDX) { + tx_pin->tx_ref_src =3D ICE_REF_CLK_SYNCE; + } + } + + return 0; +} + /** * ice_dpll_init_pins_info - init pins info wrapper * @pf: board private structure @@ -4106,6 +4336,9 @@ ice_dpll_init_pins_info(struct ice_pf *pf, enum ice_d= pll_pin_type pin_type) return ice_dpll_init_info_rclk_pin(pf); case ICE_DPLL_PIN_TYPE_SOFTWARE: return ice_dpll_init_info_sw_pins(pf); + + case ICE_DPLL_PIN_TYPE_TXCLK: + return ice_dpll_init_info_txclk_pins_e825c(pf); default: return -EINVAL; } @@ -4139,11 +4372,15 @@ static void ice_dpll_deinit_info(struct ice_pf *pf) static int ice_dpll_init_info_e825c(struct ice_pf *pf) { struct ice_dplls *d =3D &pf->dplls; + struct ice_dpll *dt =3D &d->txc; int ret =3D 0; int i; =20 d->clock_id =3D ice_generate_clock_id(pf); d->num_inputs =3D ICE_SYNCE_CLK_NUM; + dt->dpll_state =3D DPLL_LOCK_STATUS_UNLOCKED; + dt->mode =3D DPLL_MODE_MANUAL; + dt->dpll_idx =3D pf->ptp.port.port_num; =20 d->inputs =3D kzalloc_objs(*d->inputs, d->num_inputs); if (!d->inputs) @@ -4160,6 +4397,11 @@ static int ice_dpll_init_info_e825c(struct ice_pf *p= f) ret =3D ice_dpll_init_pins_info(pf, ICE_DPLL_PIN_TYPE_RCLK_INPUT); if (ret) goto deinit_info; + + ret =3D ice_dpll_init_pins_info(pf, ICE_DPLL_PIN_TYPE_TXCLK); + if (ret) + goto deinit_info; + dev_dbg(ice_pf_to_dev(pf), "%s - success, inputs: %u, outputs: %u, rclk-parents: %u\n", __func__, d->num_inputs, d->num_outputs, d->rclk.num_parents); @@ -4292,6 +4534,9 @@ void ice_dpll_deinit(struct ice_pf *pf) ice_dpll_deinit_dpll(pf, &pf->dplls.pps, cgu); if (!IS_ERR_OR_NULL(pf->dplls.eec.dpll)) ice_dpll_deinit_dpll(pf, &pf->dplls.eec, cgu); + if (!IS_ERR_OR_NULL(pf->dplls.txc.dpll)) + ice_dpll_deinit_dpll(pf, &pf->dplls.txc, false); + ice_dpll_deinit_info(pf); mutex_destroy(&pf->dplls.lock); } @@ -4317,14 +4562,19 @@ static void ice_dpll_init_e825(struct ice_pf *pf) err =3D ice_dpll_init_info_e825c(pf); if (err) goto err_exit; - err =3D ice_dpll_init_pins_e825(pf); + err =3D ice_dpll_init_dpll(pf, &pf->dplls.txc, false, DPLL_TYPE_TXC); if (err) goto deinit_info; + err =3D ice_dpll_init_pins_e825(pf); + if (err) + goto deinit_txclk; set_bit(ICE_FLAG_DPLL, pf->flags); complete_all(&d->dpll_init); =20 return; =20 +deinit_txclk: + ice_dpll_deinit_dpll(pf, &pf->dplls.txc, false); deinit_info: ice_dpll_deinit_info(pf); err_exit: diff --git a/drivers/net/ethernet/intel/ice/ice_dpll.h b/drivers/net/ethern= et/intel/ice/ice_dpll.h index ae42cdea0ee1..23f9d4da73c5 100644 --- a/drivers/net/ethernet/intel/ice/ice_dpll.h +++ b/drivers/net/ethernet/intel/ice/ice_dpll.h @@ -7,6 +7,7 @@ #include "ice.h" =20 #define ICE_DPLL_RCLK_NUM_MAX 4 +#define ICE_DPLL_TXCLK_NUM_MAX 2 =20 /** * enum ice_dpll_pin_sw - enumerate ice software pin indices: @@ -63,6 +64,7 @@ struct ice_dpll_pin { u8 ref_sync; bool active; bool hidden; + enum ice_e825c_ref_clk tx_ref_src; }; =20 /** ice_dpll - store info required for DPLL control @@ -111,9 +113,11 @@ struct ice_dpll { * @lock: locks access to configuration of a dpll * @eec: pointer to EEC dpll dev * @pps: pointer to PPS dpll dev + * @txc: pointer to TXC dpll dev * @inputs: input pins pointer * @outputs: output pins pointer * @rclk: recovered pins pointer + * @txclks: TX clock reference pins pointer * @num_inputs: number of input pins available on dpll * @num_outputs: number of output pins available on dpll * @cgu_state_acq_err_num: number of errors returned during periodic work @@ -131,11 +135,13 @@ struct ice_dplls { struct completion dpll_init; struct ice_dpll eec; struct ice_dpll pps; + struct ice_dpll txc; struct ice_dpll_pin *inputs; struct ice_dpll_pin *outputs; struct ice_dpll_pin sma[ICE_DPLL_PIN_SW_NUM]; struct ice_dpll_pin ufl[ICE_DPLL_PIN_SW_NUM]; struct ice_dpll_pin rclk; + struct ice_dpll_pin txclks[ICE_DPLL_TXCLK_NUM_MAX]; u8 num_inputs; u8 num_outputs; u8 sma_data; diff --git a/drivers/net/ethernet/intel/ice/ice_ptp_hw.h b/drivers/net/ethe= rnet/intel/ice/ice_ptp_hw.h index 9bfd3e79c580..cbc9693179a1 100644 --- a/drivers/net/ethernet/intel/ice/ice_ptp_hw.h +++ b/drivers/net/ethernet/intel/ice/ice_ptp_hw.h @@ -265,6 +265,13 @@ struct ice_cgu_pin_desc { struct dpll_pin_frequency *freq_supp; }; =20 +enum ice_e825c_ref_clk { + ICE_REF_CLK_ENET, + ICE_REF_CLK_SYNCE, + ICE_REF_CLK_EREF0, + ICE_REF_CLK_MAX, +}; + #define E810C_QSFP_C827_0_HANDLE 2 #define E810C_QSFP_C827_1_HANDLE 3 =20 --=20 2.39.3