brintos

brintos / linux-shallow public Read only

0
0
Text · 67.5 KiB · d5ad6d8 Raw
2448 lines · c
1// SPDX-License-Identifier: GPL-2.02/* Copyright (C) 2022, Intel Corporation. */3 4#include "ice.h"5#include "ice_lib.h"6#include "ice_trace.h"7#include <linux/dpll.h>8 9#define ICE_CGU_STATE_ACQ_ERR_THRESHOLD		5010#define ICE_DPLL_PIN_IDX_INVALID		0xff11#define ICE_DPLL_RCLK_NUM_PER_PF		112#define ICE_DPLL_PIN_ESYNC_PULSE_HIGH_PERCENT	2513#define ICE_DPLL_PIN_GEN_RCLK_FREQ		195312514 15/**16 * enum ice_dpll_pin_type - enumerate ice pin types:17 * @ICE_DPLL_PIN_INVALID: invalid pin type18 * @ICE_DPLL_PIN_TYPE_INPUT: input pin19 * @ICE_DPLL_PIN_TYPE_OUTPUT: output pin20 * @ICE_DPLL_PIN_TYPE_RCLK_INPUT: recovery clock input pin21 */22enum ice_dpll_pin_type {23	ICE_DPLL_PIN_INVALID,24	ICE_DPLL_PIN_TYPE_INPUT,25	ICE_DPLL_PIN_TYPE_OUTPUT,26	ICE_DPLL_PIN_TYPE_RCLK_INPUT,27};28 29static const char * const pin_type_name[] = {30	[ICE_DPLL_PIN_TYPE_INPUT] = "input",31	[ICE_DPLL_PIN_TYPE_OUTPUT] = "output",32	[ICE_DPLL_PIN_TYPE_RCLK_INPUT] = "rclk-input",33};34 35static const struct dpll_pin_frequency ice_esync_range[] = {36	DPLL_PIN_FREQUENCY_RANGE(0, DPLL_PIN_FREQUENCY_1_HZ),37};38 39/**40 * ice_dpll_is_reset - check if reset is in progress41 * @pf: private board structure42 * @extack: error reporting43 *44 * If reset is in progress, fill extack with error.45 *46 * Return:47 * * false - no reset in progress48 * * true - reset in progress49 */50static bool ice_dpll_is_reset(struct ice_pf *pf, struct netlink_ext_ack *extack)51{52	if (ice_is_reset_in_progress(pf->state)) {53		NL_SET_ERR_MSG(extack, "PF reset in progress");54		return true;55	}56	return false;57}58 59/**60 * ice_dpll_pin_freq_set - set pin's frequency61 * @pf: private board structure62 * @pin: pointer to a pin63 * @pin_type: type of pin being configured64 * @freq: frequency to be set65 * @extack: error reporting66 *67 * Set requested frequency on a pin.68 *69 * Context: Called under pf->dplls.lock70 * Return:71 * * 0 - success72 * * negative - error on AQ or wrong pin type given73 */74static int75ice_dpll_pin_freq_set(struct ice_pf *pf, struct ice_dpll_pin *pin,76		      enum ice_dpll_pin_type pin_type, const u32 freq,77		      struct netlink_ext_ack *extack)78{79	u8 flags;80	int ret;81 82	switch (pin_type) {83	case ICE_DPLL_PIN_TYPE_INPUT:84		flags = ICE_AQC_SET_CGU_IN_CFG_FLG1_UPDATE_FREQ;85		ret = ice_aq_set_input_pin_cfg(&pf->hw, pin->idx, flags,86					       pin->flags[0], freq, 0);87		break;88	case ICE_DPLL_PIN_TYPE_OUTPUT:89		flags = ICE_AQC_SET_CGU_OUT_CFG_UPDATE_FREQ;90		ret = ice_aq_set_output_pin_cfg(&pf->hw, pin->idx, flags,91						0, freq, 0);92		break;93	default:94		return -EINVAL;95	}96	if (ret) {97		NL_SET_ERR_MSG_FMT(extack,98				   "err:%d %s failed to set pin freq:%u on pin:%u\n",99				   ret,100				   ice_aq_str(pf->hw.adminq.sq_last_status),101				   freq, pin->idx);102		return ret;103	}104	pin->freq = freq;105 106	return 0;107}108 109/**110 * ice_dpll_frequency_set - wrapper for pin callback for set frequency111 * @pin: pointer to a pin112 * @pin_priv: private data pointer passed on pin registration113 * @dpll: pointer to dpll114 * @dpll_priv: private data pointer passed on dpll registration115 * @frequency: frequency to be set116 * @extack: error reporting117 * @pin_type: type of pin being configured118 *119 * Wraps internal set frequency command on a pin.120 *121 * Context: Acquires pf->dplls.lock122 * Return:123 * * 0 - success124 * * negative - error pin not found or couldn't set in hw125 */126static int127ice_dpll_frequency_set(const struct dpll_pin *pin, void *pin_priv,128		       const struct dpll_device *dpll, void *dpll_priv,129		       const u32 frequency,130		       struct netlink_ext_ack *extack,131		       enum ice_dpll_pin_type pin_type)132{133	struct ice_dpll_pin *p = pin_priv;134	struct ice_dpll *d = dpll_priv;135	struct ice_pf *pf = d->pf;136	int ret;137 138	if (ice_dpll_is_reset(pf, extack))139		return -EBUSY;140 141	mutex_lock(&pf->dplls.lock);142	ret = ice_dpll_pin_freq_set(pf, p, pin_type, frequency, extack);143	mutex_unlock(&pf->dplls.lock);144 145	return ret;146}147 148/**149 * ice_dpll_input_frequency_set - input pin callback for set frequency150 * @pin: pointer to a pin151 * @pin_priv: private data pointer passed on pin registration152 * @dpll: pointer to dpll153 * @dpll_priv: private data pointer passed on dpll registration154 * @frequency: frequency to be set155 * @extack: error reporting156 *157 * Wraps internal set frequency command on a pin.158 *159 * Context: Calls a function which acquires pf->dplls.lock160 * Return:161 * * 0 - success162 * * negative - error pin not found or couldn't set in hw163 */164static int165ice_dpll_input_frequency_set(const struct dpll_pin *pin, void *pin_priv,166			     const struct dpll_device *dpll, void *dpll_priv,167			     u64 frequency, struct netlink_ext_ack *extack)168{169	return ice_dpll_frequency_set(pin, pin_priv, dpll, dpll_priv, frequency,170				      extack, ICE_DPLL_PIN_TYPE_INPUT);171}172 173/**174 * ice_dpll_output_frequency_set - output pin callback for set frequency175 * @pin: pointer to a pin176 * @pin_priv: private data pointer passed on pin registration177 * @dpll: pointer to dpll178 * @dpll_priv: private data pointer passed on dpll registration179 * @frequency: frequency to be set180 * @extack: error reporting181 *182 * Wraps internal set frequency command on a pin.183 *184 * Context: Calls a function which acquires pf->dplls.lock185 * Return:186 * * 0 - success187 * * negative - error pin not found or couldn't set in hw188 */189static int190ice_dpll_output_frequency_set(const struct dpll_pin *pin, void *pin_priv,191			      const struct dpll_device *dpll, void *dpll_priv,192			      u64 frequency, struct netlink_ext_ack *extack)193{194	return ice_dpll_frequency_set(pin, pin_priv, dpll, dpll_priv, frequency,195				      extack, ICE_DPLL_PIN_TYPE_OUTPUT);196}197 198/**199 * ice_dpll_frequency_get - wrapper for pin callback for get frequency200 * @pin: pointer to a pin201 * @pin_priv: private data pointer passed on pin registration202 * @dpll: pointer to dpll203 * @dpll_priv: private data pointer passed on dpll registration204 * @frequency: on success holds pin's frequency205 * @extack: error reporting206 * @pin_type: type of pin being configured207 *208 * Wraps internal get frequency command of a pin.209 *210 * Context: Acquires pf->dplls.lock211 * Return:212 * * 0 - success213 * * negative - error pin not found or couldn't get from hw214 */215static int216ice_dpll_frequency_get(const struct dpll_pin *pin, void *pin_priv,217		       const struct dpll_device *dpll, void *dpll_priv,218		       u64 *frequency, struct netlink_ext_ack *extack,219		       enum ice_dpll_pin_type pin_type)220{221	struct ice_dpll_pin *p = pin_priv;222	struct ice_dpll *d = dpll_priv;223	struct ice_pf *pf = d->pf;224 225	mutex_lock(&pf->dplls.lock);226	*frequency = p->freq;227	mutex_unlock(&pf->dplls.lock);228 229	return 0;230}231 232/**233 * ice_dpll_input_frequency_get - input pin callback for get frequency234 * @pin: pointer to a pin235 * @pin_priv: private data pointer passed on pin registration236 * @dpll: pointer to dpll237 * @dpll_priv: private data pointer passed on dpll registration238 * @frequency: on success holds pin's frequency239 * @extack: error reporting240 *241 * Wraps internal get frequency command of a input pin.242 *243 * Context: Calls a function which acquires pf->dplls.lock244 * Return:245 * * 0 - success246 * * negative - error pin not found or couldn't get from hw247 */248static int249ice_dpll_input_frequency_get(const struct dpll_pin *pin, void *pin_priv,250			     const struct dpll_device *dpll, void *dpll_priv,251			     u64 *frequency, struct netlink_ext_ack *extack)252{253	return ice_dpll_frequency_get(pin, pin_priv, dpll, dpll_priv, frequency,254				      extack, ICE_DPLL_PIN_TYPE_INPUT);255}256 257/**258 * ice_dpll_output_frequency_get - output pin callback for get frequency259 * @pin: pointer to a pin260 * @pin_priv: private data pointer passed on pin registration261 * @dpll: pointer to dpll262 * @dpll_priv: private data pointer passed on dpll registration263 * @frequency: on success holds pin's frequency264 * @extack: error reporting265 *266 * Wraps internal get frequency command of a pin.267 *268 * Context: Calls a function which acquires pf->dplls.lock269 * Return:270 * * 0 - success271 * * negative - error pin not found or couldn't get from hw272 */273static int274ice_dpll_output_frequency_get(const struct dpll_pin *pin, void *pin_priv,275			      const struct dpll_device *dpll, void *dpll_priv,276			      u64 *frequency, struct netlink_ext_ack *extack)277{278	return ice_dpll_frequency_get(pin, pin_priv, dpll, dpll_priv, frequency,279				      extack, ICE_DPLL_PIN_TYPE_OUTPUT);280}281 282/**283 * ice_dpll_pin_enable - enable a pin on dplls284 * @hw: board private hw structure285 * @pin: pointer to a pin286 * @dpll_idx: dpll index to connect to output pin287 * @pin_type: type of pin being enabled288 * @extack: error reporting289 *290 * Enable a pin on both dplls. Store current state in pin->flags.291 *292 * Context: Called under pf->dplls.lock293 * Return:294 * * 0 - OK295 * * negative - error296 */297static int298ice_dpll_pin_enable(struct ice_hw *hw, struct ice_dpll_pin *pin,299		    u8 dpll_idx, enum ice_dpll_pin_type pin_type,300		    struct netlink_ext_ack *extack)301{302	u8 flags = 0;303	int ret;304 305	switch (pin_type) {306	case ICE_DPLL_PIN_TYPE_INPUT:307		if (pin->flags[0] & ICE_AQC_GET_CGU_IN_CFG_FLG2_ESYNC_EN)308			flags |= ICE_AQC_SET_CGU_IN_CFG_FLG2_ESYNC_EN;309		flags |= ICE_AQC_SET_CGU_IN_CFG_FLG2_INPUT_EN;310		ret = ice_aq_set_input_pin_cfg(hw, pin->idx, 0, flags, 0, 0);311		break;312	case ICE_DPLL_PIN_TYPE_OUTPUT:313		flags = ICE_AQC_SET_CGU_OUT_CFG_UPDATE_SRC_SEL;314		if (pin->flags[0] & ICE_AQC_GET_CGU_OUT_CFG_ESYNC_EN)315			flags |= ICE_AQC_SET_CGU_OUT_CFG_ESYNC_EN;316		flags |= ICE_AQC_SET_CGU_OUT_CFG_OUT_EN;317		ret = ice_aq_set_output_pin_cfg(hw, pin->idx, flags, dpll_idx,318						0, 0);319		break;320	default:321		return -EINVAL;322	}323	if (ret)324		NL_SET_ERR_MSG_FMT(extack,325				   "err:%d %s failed to enable %s pin:%u\n",326				   ret, ice_aq_str(hw->adminq.sq_last_status),327				   pin_type_name[pin_type], pin->idx);328 329	return ret;330}331 332/**333 * ice_dpll_pin_disable - disable a pin on dplls334 * @hw: board private hw structure335 * @pin: pointer to a pin336 * @pin_type: type of pin being disabled337 * @extack: error reporting338 *339 * Disable a pin on both dplls. Store current state in pin->flags.340 *341 * Context: Called under pf->dplls.lock342 * Return:343 * * 0 - OK344 * * negative - error345 */346static int347ice_dpll_pin_disable(struct ice_hw *hw, struct ice_dpll_pin *pin,348		     enum ice_dpll_pin_type pin_type,349		     struct netlink_ext_ack *extack)350{351	u8 flags = 0;352	int ret;353 354	switch (pin_type) {355	case ICE_DPLL_PIN_TYPE_INPUT:356		if (pin->flags[0] & ICE_AQC_GET_CGU_IN_CFG_FLG2_ESYNC_EN)357			flags |= ICE_AQC_SET_CGU_IN_CFG_FLG2_ESYNC_EN;358		ret = ice_aq_set_input_pin_cfg(hw, pin->idx, 0, flags, 0, 0);359		break;360	case ICE_DPLL_PIN_TYPE_OUTPUT:361		if (pin->flags[0] & ICE_AQC_GET_CGU_OUT_CFG_ESYNC_EN)362			flags |= ICE_AQC_SET_CGU_OUT_CFG_ESYNC_EN;363		ret = ice_aq_set_output_pin_cfg(hw, pin->idx, flags, 0, 0, 0);364		break;365	default:366		return -EINVAL;367	}368	if (ret)369		NL_SET_ERR_MSG_FMT(extack,370				   "err:%d %s failed to disable %s pin:%u\n",371				   ret, ice_aq_str(hw->adminq.sq_last_status),372				   pin_type_name[pin_type], pin->idx);373 374	return ret;375}376 377/**378 * ice_dpll_pin_state_update - update pin's state379 * @pf: private board struct380 * @pin: structure with pin attributes to be updated381 * @pin_type: type of pin being updated382 * @extack: error reporting383 *384 * Determine pin current state and frequency, then update struct385 * holding the pin info. For input pin states are separated for each386 * dpll, for rclk pins states are separated for each parent.387 *388 * Context: Called under pf->dplls.lock389 * Return:390 * * 0 - OK391 * * negative - error392 */393static int394ice_dpll_pin_state_update(struct ice_pf *pf, struct ice_dpll_pin *pin,395			  enum ice_dpll_pin_type pin_type,396			  struct netlink_ext_ack *extack)397{398	u8 parent, port_num = ICE_AQC_SET_PHY_REC_CLK_OUT_CURR_PORT;399	int ret;400 401	switch (pin_type) {402	case ICE_DPLL_PIN_TYPE_INPUT:403		ret = ice_aq_get_input_pin_cfg(&pf->hw, pin->idx, &pin->status,404					       NULL, NULL, &pin->flags[0],405					       &pin->freq, &pin->phase_adjust);406		if (ret)407			goto err;408		if (ICE_AQC_GET_CGU_IN_CFG_FLG2_INPUT_EN & pin->flags[0]) {409			if (pin->pin) {410				pin->state[pf->dplls.eec.dpll_idx] =411					pin->pin == pf->dplls.eec.active_input ?412					DPLL_PIN_STATE_CONNECTED :413					DPLL_PIN_STATE_SELECTABLE;414				pin->state[pf->dplls.pps.dpll_idx] =415					pin->pin == pf->dplls.pps.active_input ?416					DPLL_PIN_STATE_CONNECTED :417					DPLL_PIN_STATE_SELECTABLE;418			} else {419				pin->state[pf->dplls.eec.dpll_idx] =420					DPLL_PIN_STATE_SELECTABLE;421				pin->state[pf->dplls.pps.dpll_idx] =422					DPLL_PIN_STATE_SELECTABLE;423			}424		} else {425			pin->state[pf->dplls.eec.dpll_idx] =426				DPLL_PIN_STATE_DISCONNECTED;427			pin->state[pf->dplls.pps.dpll_idx] =428				DPLL_PIN_STATE_DISCONNECTED;429		}430		break;431	case ICE_DPLL_PIN_TYPE_OUTPUT:432		ret = ice_aq_get_output_pin_cfg(&pf->hw, pin->idx,433						&pin->flags[0], &parent,434						&pin->freq, NULL);435		if (ret)436			goto err;437 438		parent &= ICE_AQC_GET_CGU_OUT_CFG_DPLL_SRC_SEL;439		if (ICE_AQC_GET_CGU_OUT_CFG_OUT_EN & pin->flags[0]) {440			pin->state[pf->dplls.eec.dpll_idx] =441				parent == pf->dplls.eec.dpll_idx ?442				DPLL_PIN_STATE_CONNECTED :443				DPLL_PIN_STATE_DISCONNECTED;444			pin->state[pf->dplls.pps.dpll_idx] =445				parent == pf->dplls.pps.dpll_idx ?446				DPLL_PIN_STATE_CONNECTED :447				DPLL_PIN_STATE_DISCONNECTED;448		} else {449			pin->state[pf->dplls.eec.dpll_idx] =450				DPLL_PIN_STATE_DISCONNECTED;451			pin->state[pf->dplls.pps.dpll_idx] =452				DPLL_PIN_STATE_DISCONNECTED;453		}454		break;455	case ICE_DPLL_PIN_TYPE_RCLK_INPUT:456		for (parent = 0; parent < pf->dplls.rclk.num_parents;457		     parent++) {458			u8 p = parent;459 460			ret = ice_aq_get_phy_rec_clk_out(&pf->hw, &p,461							 &port_num,462							 &pin->flags[parent],463							 NULL);464			if (ret)465				goto err;466			if (ICE_AQC_GET_PHY_REC_CLK_OUT_OUT_EN &467			    pin->flags[parent])468				pin->state[parent] = DPLL_PIN_STATE_CONNECTED;469			else470				pin->state[parent] =471					DPLL_PIN_STATE_DISCONNECTED;472		}473		break;474	default:475		return -EINVAL;476	}477 478	return 0;479err:480	if (extack)481		NL_SET_ERR_MSG_FMT(extack,482				   "err:%d %s failed to update %s pin:%u\n",483				   ret,484				   ice_aq_str(pf->hw.adminq.sq_last_status),485				   pin_type_name[pin_type], pin->idx);486	else487		dev_err_ratelimited(ice_pf_to_dev(pf),488				    "err:%d %s failed to update %s pin:%u\n",489				    ret,490				    ice_aq_str(pf->hw.adminq.sq_last_status),491				    pin_type_name[pin_type], pin->idx);492	return ret;493}494 495/**496 * ice_dpll_hw_input_prio_set - set input priority value in hardware497 * @pf: board private structure498 * @dpll: ice dpll pointer499 * @pin: ice pin pointer500 * @prio: priority value being set on a dpll501 * @extack: error reporting502 *503 * Internal wrapper for setting the priority in the hardware.504 *505 * Context: Called under pf->dplls.lock506 * Return:507 * * 0 - success508 * * negative - failure509 */510static int511ice_dpll_hw_input_prio_set(struct ice_pf *pf, struct ice_dpll *dpll,512			   struct ice_dpll_pin *pin, const u32 prio,513			   struct netlink_ext_ack *extack)514{515	int ret;516 517	ret = ice_aq_set_cgu_ref_prio(&pf->hw, dpll->dpll_idx, pin->idx,518				      (u8)prio);519	if (ret)520		NL_SET_ERR_MSG_FMT(extack,521				   "err:%d %s failed to set pin prio:%u on pin:%u\n",522				   ret,523				   ice_aq_str(pf->hw.adminq.sq_last_status),524				   prio, pin->idx);525	else526		dpll->input_prio[pin->idx] = prio;527 528	return ret;529}530 531/**532 * ice_dpll_lock_status_get - get dpll lock status callback533 * @dpll: registered dpll pointer534 * @dpll_priv: private data pointer passed on dpll registration535 * @status: on success holds dpll's lock status536 * @status_error: status error value537 * @extack: error reporting538 *539 * Dpll subsystem callback, provides dpll's lock status.540 *541 * Context: Acquires pf->dplls.lock542 * Return:543 * * 0 - success544 * * negative - failure545 */546static int547ice_dpll_lock_status_get(const struct dpll_device *dpll, void *dpll_priv,548			 enum dpll_lock_status *status,549			 enum dpll_lock_status_error *status_error,550			 struct netlink_ext_ack *extack)551{552	struct ice_dpll *d = dpll_priv;553	struct ice_pf *pf = d->pf;554 555	mutex_lock(&pf->dplls.lock);556	*status = d->dpll_state;557	mutex_unlock(&pf->dplls.lock);558 559	return 0;560}561 562/**563 * ice_dpll_mode_get - get dpll's working mode564 * @dpll: registered dpll pointer565 * @dpll_priv: private data pointer passed on dpll registration566 * @mode: on success holds current working mode of dpll567 * @extack: error reporting568 *569 * Dpll subsystem callback. Provides working mode of dpll.570 *571 * Context: Acquires pf->dplls.lock572 * Return:573 * * 0 - success574 * * negative - failure575 */576static int ice_dpll_mode_get(const struct dpll_device *dpll, void *dpll_priv,577			     enum dpll_mode *mode,578			     struct netlink_ext_ack *extack)579{580	struct ice_dpll *d = dpll_priv;581	struct ice_pf *pf = d->pf;582 583	mutex_lock(&pf->dplls.lock);584	*mode = d->mode;585	mutex_unlock(&pf->dplls.lock);586 587	return 0;588}589 590/**591 * ice_dpll_pin_state_set - set pin's state on dpll592 * @pin: pointer to a pin593 * @pin_priv: private data pointer passed on pin registration594 * @dpll: registered dpll pointer595 * @dpll_priv: private data pointer passed on dpll registration596 * @enable: if pin shalll be enabled597 * @extack: error reporting598 * @pin_type: type of a pin599 *600 * Set pin state on a pin.601 *602 * Context: Acquires pf->dplls.lock603 * Return:604 * * 0 - OK or no change required605 * * negative - error606 */607static int608ice_dpll_pin_state_set(const struct dpll_pin *pin, void *pin_priv,609		       const struct dpll_device *dpll, void *dpll_priv,610		       bool enable, struct netlink_ext_ack *extack,611		       enum ice_dpll_pin_type pin_type)612{613	struct ice_dpll_pin *p = pin_priv;614	struct ice_dpll *d = dpll_priv;615	struct ice_pf *pf = d->pf;616	int ret;617 618	if (ice_dpll_is_reset(pf, extack))619		return -EBUSY;620 621	mutex_lock(&pf->dplls.lock);622	if (enable)623		ret = ice_dpll_pin_enable(&pf->hw, p, d->dpll_idx, pin_type,624					  extack);625	else626		ret = ice_dpll_pin_disable(&pf->hw, p, pin_type, extack);627	if (!ret)628		ret = ice_dpll_pin_state_update(pf, p, pin_type, extack);629	mutex_unlock(&pf->dplls.lock);630 631	return ret;632}633 634/**635 * ice_dpll_output_state_set - enable/disable output pin on dpll device636 * @pin: pointer to a pin637 * @pin_priv: private data pointer passed on pin registration638 * @dpll: dpll being configured639 * @dpll_priv: private data pointer passed on dpll registration640 * @state: state of pin to be set641 * @extack: error reporting642 *643 * Dpll subsystem callback. Set given state on output type pin.644 *645 * Context: Calls a function which acquires pf->dplls.lock646 * Return:647 * * 0 - successfully enabled mode648 * * negative - failed to enable mode649 */650static int651ice_dpll_output_state_set(const struct dpll_pin *pin, void *pin_priv,652			  const struct dpll_device *dpll, void *dpll_priv,653			  enum dpll_pin_state state,654			  struct netlink_ext_ack *extack)655{656	bool enable = state == DPLL_PIN_STATE_CONNECTED;657	struct ice_dpll_pin *p = pin_priv;658	struct ice_dpll *d = dpll_priv;659 660	if (state == DPLL_PIN_STATE_SELECTABLE)661		return -EINVAL;662	if (!enable && p->state[d->dpll_idx] == DPLL_PIN_STATE_DISCONNECTED)663		return 0;664 665	return ice_dpll_pin_state_set(pin, pin_priv, dpll, dpll_priv, enable,666				      extack, ICE_DPLL_PIN_TYPE_OUTPUT);667}668 669/**670 * ice_dpll_input_state_set - enable/disable input pin on dpll levice671 * @pin: pointer to a pin672 * @pin_priv: private data pointer passed on pin registration673 * @dpll: dpll being configured674 * @dpll_priv: private data pointer passed on dpll registration675 * @state: state of pin to be set676 * @extack: error reporting677 *678 * Dpll subsystem callback. Enables given mode on input type pin.679 *680 * Context: Calls a function which acquires pf->dplls.lock681 * Return:682 * * 0 - successfully enabled mode683 * * negative - failed to enable mode684 */685static int686ice_dpll_input_state_set(const struct dpll_pin *pin, void *pin_priv,687			 const struct dpll_device *dpll, void *dpll_priv,688			 enum dpll_pin_state state,689			 struct netlink_ext_ack *extack)690{691	bool enable = state == DPLL_PIN_STATE_SELECTABLE;692 693	return ice_dpll_pin_state_set(pin, pin_priv, dpll, dpll_priv, enable,694				      extack, ICE_DPLL_PIN_TYPE_INPUT);695}696 697/**698 * ice_dpll_pin_state_get - set pin's state on dpll699 * @pin: pointer to a pin700 * @pin_priv: private data pointer passed on pin registration701 * @dpll: registered dpll pointer702 * @dpll_priv: private data pointer passed on dpll registration703 * @state: on success holds state of the pin704 * @extack: error reporting705 * @pin_type: type of questioned pin706 *707 * Determine pin state set it on a pin.708 *709 * Context: Acquires pf->dplls.lock710 * Return:711 * * 0 - success712 * * negative - failed to get state713 */714static int715ice_dpll_pin_state_get(const struct dpll_pin *pin, void *pin_priv,716		       const struct dpll_device *dpll, void *dpll_priv,717		       enum dpll_pin_state *state,718		       struct netlink_ext_ack *extack,719		       enum ice_dpll_pin_type pin_type)720{721	struct ice_dpll_pin *p = pin_priv;722	struct ice_dpll *d = dpll_priv;723	struct ice_pf *pf = d->pf;724	int ret;725 726	if (ice_dpll_is_reset(pf, extack))727		return -EBUSY;728 729	mutex_lock(&pf->dplls.lock);730	ret = ice_dpll_pin_state_update(pf, p, pin_type, extack);731	if (ret)732		goto unlock;733	if (pin_type == ICE_DPLL_PIN_TYPE_INPUT ||734	    pin_type == ICE_DPLL_PIN_TYPE_OUTPUT)735		*state = p->state[d->dpll_idx];736	ret = 0;737unlock:738	mutex_unlock(&pf->dplls.lock);739 740	return ret;741}742 743/**744 * ice_dpll_output_state_get - get output pin state on dpll device745 * @pin: pointer to a pin746 * @pin_priv: private data pointer passed on pin registration747 * @dpll: registered dpll pointer748 * @dpll_priv: private data pointer passed on dpll registration749 * @state: on success holds state of the pin750 * @extack: error reporting751 *752 * Dpll subsystem callback. Check state of a pin.753 *754 * Context: Calls a function which acquires pf->dplls.lock755 * Return:756 * * 0 - success757 * * negative - failed to get state758 */759static int760ice_dpll_output_state_get(const struct dpll_pin *pin, void *pin_priv,761			  const struct dpll_device *dpll, void *dpll_priv,762			  enum dpll_pin_state *state,763			  struct netlink_ext_ack *extack)764{765	return ice_dpll_pin_state_get(pin, pin_priv, dpll, dpll_priv, state,766				      extack, ICE_DPLL_PIN_TYPE_OUTPUT);767}768 769/**770 * ice_dpll_input_state_get - get input pin state on dpll device771 * @pin: pointer to a pin772 * @pin_priv: private data pointer passed on pin registration773 * @dpll: registered dpll pointer774 * @dpll_priv: private data pointer passed on dpll registration775 * @state: on success holds state of the pin776 * @extack: error reporting777 *778 * Dpll subsystem callback. Check state of a input pin.779 *780 * Context: Calls a function which acquires pf->dplls.lock781 * Return:782 * * 0 - success783 * * negative - failed to get state784 */785static int786ice_dpll_input_state_get(const struct dpll_pin *pin, void *pin_priv,787			 const struct dpll_device *dpll, void *dpll_priv,788			 enum dpll_pin_state *state,789			 struct netlink_ext_ack *extack)790{791	return ice_dpll_pin_state_get(pin, pin_priv, dpll, dpll_priv, state,792				      extack, ICE_DPLL_PIN_TYPE_INPUT);793}794 795/**796 * ice_dpll_input_prio_get - get dpll's input prio797 * @pin: pointer to a pin798 * @pin_priv: private data pointer passed on pin registration799 * @dpll: registered dpll pointer800 * @dpll_priv: private data pointer passed on dpll registration801 * @prio: on success - returns input priority on dpll802 * @extack: error reporting803 *804 * Dpll subsystem callback. Handler for getting priority of a input pin.805 *806 * Context: Acquires pf->dplls.lock807 * Return:808 * * 0 - success809 * * negative - failure810 */811static int812ice_dpll_input_prio_get(const struct dpll_pin *pin, void *pin_priv,813			const struct dpll_device *dpll, void *dpll_priv,814			u32 *prio, struct netlink_ext_ack *extack)815{816	struct ice_dpll_pin *p = pin_priv;817	struct ice_dpll *d = dpll_priv;818	struct ice_pf *pf = d->pf;819 820	mutex_lock(&pf->dplls.lock);821	*prio = d->input_prio[p->idx];822	mutex_unlock(&pf->dplls.lock);823 824	return 0;825}826 827/**828 * ice_dpll_input_prio_set - set dpll input prio829 * @pin: pointer to a pin830 * @pin_priv: private data pointer passed on pin registration831 * @dpll: registered dpll pointer832 * @dpll_priv: private data pointer passed on dpll registration833 * @prio: input priority to be set on dpll834 * @extack: error reporting835 *836 * Dpll subsystem callback. Handler for setting priority of a input pin.837 *838 * Context: Acquires pf->dplls.lock839 * Return:840 * * 0 - success841 * * negative - failure842 */843static int844ice_dpll_input_prio_set(const struct dpll_pin *pin, void *pin_priv,845			const struct dpll_device *dpll, void *dpll_priv,846			u32 prio, struct netlink_ext_ack *extack)847{848	struct ice_dpll_pin *p = pin_priv;849	struct ice_dpll *d = dpll_priv;850	struct ice_pf *pf = d->pf;851	int ret;852 853	if (ice_dpll_is_reset(pf, extack))854		return -EBUSY;855 856	mutex_lock(&pf->dplls.lock);857	ret = ice_dpll_hw_input_prio_set(pf, d, p, prio, extack);858	mutex_unlock(&pf->dplls.lock);859 860	return ret;861}862 863/**864 * ice_dpll_input_direction - callback for get input pin direction865 * @pin: pointer to a pin866 * @pin_priv: private data pointer passed on pin registration867 * @dpll: registered dpll pointer868 * @dpll_priv: private data pointer passed on dpll registration869 * @direction: holds input pin direction870 * @extack: error reporting871 *872 * Dpll subsystem callback. Handler for getting direction of a input pin.873 *874 * Return:875 * * 0 - success876 */877static int878ice_dpll_input_direction(const struct dpll_pin *pin, void *pin_priv,879			 const struct dpll_device *dpll, void *dpll_priv,880			 enum dpll_pin_direction *direction,881			 struct netlink_ext_ack *extack)882{883	*direction = DPLL_PIN_DIRECTION_INPUT;884 885	return 0;886}887 888/**889 * ice_dpll_output_direction - callback for get output pin direction890 * @pin: pointer to a pin891 * @pin_priv: private data pointer passed on pin registration892 * @dpll: registered dpll pointer893 * @dpll_priv: private data pointer passed on dpll registration894 * @direction: holds output pin direction895 * @extack: error reporting896 *897 * Dpll subsystem callback. Handler for getting direction of an output pin.898 *899 * Return:900 * * 0 - success901 */902static int903ice_dpll_output_direction(const struct dpll_pin *pin, void *pin_priv,904			  const struct dpll_device *dpll, void *dpll_priv,905			  enum dpll_pin_direction *direction,906			  struct netlink_ext_ack *extack)907{908	*direction = DPLL_PIN_DIRECTION_OUTPUT;909 910	return 0;911}912 913/**914 * ice_dpll_pin_phase_adjust_get - callback for get pin phase adjust value915 * @pin: pointer to a pin916 * @pin_priv: private data pointer passed on pin registration917 * @dpll: registered dpll pointer918 * @dpll_priv: private data pointer passed on dpll registration919 * @phase_adjust: on success holds pin phase_adjust value920 * @extack: error reporting921 *922 * Dpll subsystem callback. Handler for getting phase adjust value of a pin.923 *924 * Context: Acquires pf->dplls.lock925 * Return:926 * * 0 - success927 * * negative - error928 */929static int930ice_dpll_pin_phase_adjust_get(const struct dpll_pin *pin, void *pin_priv,931			      const struct dpll_device *dpll, void *dpll_priv,932			      s32 *phase_adjust,933			      struct netlink_ext_ack *extack)934{935	struct ice_dpll_pin *p = pin_priv;936	struct ice_pf *pf = p->pf;937 938	mutex_lock(&pf->dplls.lock);939	*phase_adjust = p->phase_adjust;940	mutex_unlock(&pf->dplls.lock);941 942	return 0;943}944 945/**946 * ice_dpll_pin_phase_adjust_set - helper for setting a pin phase adjust value947 * @pin: pointer to a pin948 * @pin_priv: private data pointer passed on pin registration949 * @dpll: registered dpll pointer950 * @dpll_priv: private data pointer passed on dpll registration951 * @phase_adjust: phase_adjust to be set952 * @extack: error reporting953 * @type: type of a pin954 *955 * Helper for dpll subsystem callback. Handler for setting phase adjust value956 * of a pin.957 *958 * Context: Acquires pf->dplls.lock959 * Return:960 * * 0 - success961 * * negative - error962 */963static int964ice_dpll_pin_phase_adjust_set(const struct dpll_pin *pin, void *pin_priv,965			      const struct dpll_device *dpll, void *dpll_priv,966			      s32 phase_adjust,967			      struct netlink_ext_ack *extack,968			      enum ice_dpll_pin_type type)969{970	struct ice_dpll_pin *p = pin_priv;971	struct ice_dpll *d = dpll_priv;972	struct ice_pf *pf = d->pf;973	u8 flag, flags_en = 0;974	int ret;975 976	if (ice_dpll_is_reset(pf, extack))977		return -EBUSY;978 979	mutex_lock(&pf->dplls.lock);980	switch (type) {981	case ICE_DPLL_PIN_TYPE_INPUT:982		flag = ICE_AQC_SET_CGU_IN_CFG_FLG1_UPDATE_DELAY;983		if (p->flags[0] & ICE_AQC_GET_CGU_IN_CFG_FLG2_ESYNC_EN)984			flags_en |= ICE_AQC_SET_CGU_IN_CFG_FLG2_ESYNC_EN;985		if (p->flags[0] & ICE_AQC_GET_CGU_IN_CFG_FLG2_INPUT_EN)986			flags_en |= ICE_AQC_SET_CGU_IN_CFG_FLG2_INPUT_EN;987		ret = ice_aq_set_input_pin_cfg(&pf->hw, p->idx, flag, flags_en,988					       0, phase_adjust);989		break;990	case ICE_DPLL_PIN_TYPE_OUTPUT:991		flag = ICE_AQC_SET_CGU_OUT_CFG_UPDATE_PHASE;992		if (p->flags[0] & ICE_AQC_GET_CGU_OUT_CFG_OUT_EN)993			flag |= ICE_AQC_SET_CGU_OUT_CFG_OUT_EN;994		if (p->flags[0] & ICE_AQC_GET_CGU_OUT_CFG_ESYNC_EN)995			flag |= ICE_AQC_SET_CGU_OUT_CFG_ESYNC_EN;996		ret = ice_aq_set_output_pin_cfg(&pf->hw, p->idx, flag, 0, 0,997						phase_adjust);998		break;999	default:1000		ret = -EINVAL;1001	}1002	if (!ret)1003		p->phase_adjust = phase_adjust;1004	mutex_unlock(&pf->dplls.lock);1005	if (ret)1006		NL_SET_ERR_MSG_FMT(extack,1007				   "err:%d %s failed to set pin phase_adjust:%d for pin:%u on dpll:%u\n",1008				   ret,1009				   ice_aq_str(pf->hw.adminq.sq_last_status),1010				   phase_adjust, p->idx, d->dpll_idx);1011 1012	return ret;1013}1014 1015/**1016 * ice_dpll_input_phase_adjust_set - callback for set input pin phase adjust1017 * @pin: pointer to a pin1018 * @pin_priv: private data pointer passed on pin registration1019 * @dpll: registered dpll pointer1020 * @dpll_priv: private data pointer passed on dpll registration1021 * @phase_adjust: phase_adjust to be set1022 * @extack: error reporting1023 *1024 * Dpll subsystem callback. Wraps a handler for setting phase adjust on input1025 * pin.1026 *1027 * Context: Calls a function which acquires pf->dplls.lock1028 * Return:1029 * * 0 - success1030 * * negative - error1031 */1032static int1033ice_dpll_input_phase_adjust_set(const struct dpll_pin *pin, void *pin_priv,1034				const struct dpll_device *dpll, void *dpll_priv,1035				s32 phase_adjust,1036				struct netlink_ext_ack *extack)1037{1038	return ice_dpll_pin_phase_adjust_set(pin, pin_priv, dpll, dpll_priv,1039					     phase_adjust, extack,1040					     ICE_DPLL_PIN_TYPE_INPUT);1041}1042 1043/**1044 * ice_dpll_output_phase_adjust_set - callback for set output pin phase adjust1045 * @pin: pointer to a pin1046 * @pin_priv: private data pointer passed on pin registration1047 * @dpll: registered dpll pointer1048 * @dpll_priv: private data pointer passed on dpll registration1049 * @phase_adjust: phase_adjust to be set1050 * @extack: error reporting1051 *1052 * Dpll subsystem callback. Wraps a handler for setting phase adjust on output1053 * pin.1054 *1055 * Context: Calls a function which acquires pf->dplls.lock1056 * Return:1057 * * 0 - success1058 * * negative - error1059 */1060static int1061ice_dpll_output_phase_adjust_set(const struct dpll_pin *pin, void *pin_priv,1062				 const struct dpll_device *dpll, void *dpll_priv,1063				 s32 phase_adjust,1064				 struct netlink_ext_ack *extack)1065{1066	return ice_dpll_pin_phase_adjust_set(pin, pin_priv, dpll, dpll_priv,1067					     phase_adjust, extack,1068					     ICE_DPLL_PIN_TYPE_OUTPUT);1069}1070 1071#define ICE_DPLL_PHASE_OFFSET_DIVIDER	1001072#define ICE_DPLL_PHASE_OFFSET_FACTOR		\1073	(DPLL_PHASE_OFFSET_DIVIDER / ICE_DPLL_PHASE_OFFSET_DIVIDER)1074/**1075 * ice_dpll_phase_offset_get - callback for get dpll phase shift value1076 * @pin: pointer to a pin1077 * @pin_priv: private data pointer passed on pin registration1078 * @dpll: registered dpll pointer1079 * @dpll_priv: private data pointer passed on dpll registration1080 * @phase_offset: on success holds pin phase_offset value1081 * @extack: error reporting1082 *1083 * Dpll subsystem callback. Handler for getting phase shift value between1084 * dpll's input and output.1085 *1086 * Context: Acquires pf->dplls.lock1087 * Return:1088 * * 0 - success1089 * * negative - error1090 */1091static int1092ice_dpll_phase_offset_get(const struct dpll_pin *pin, void *pin_priv,1093			  const struct dpll_device *dpll, void *dpll_priv,1094			  s64 *phase_offset, struct netlink_ext_ack *extack)1095{1096	struct ice_dpll *d = dpll_priv;1097	struct ice_pf *pf = d->pf;1098 1099	mutex_lock(&pf->dplls.lock);1100	if (d->active_input == pin)1101		*phase_offset = d->phase_offset * ICE_DPLL_PHASE_OFFSET_FACTOR;1102	else1103		*phase_offset = 0;1104	mutex_unlock(&pf->dplls.lock);1105 1106	return 0;1107}1108 1109/**1110 * ice_dpll_output_esync_set - callback for setting embedded sync1111 * @pin: pointer to a pin1112 * @pin_priv: private data pointer passed on pin registration1113 * @dpll: registered dpll pointer1114 * @dpll_priv: private data pointer passed on dpll registration1115 * @freq: requested embedded sync frequency1116 * @extack: error reporting1117 *1118 * Dpll subsystem callback. Handler for setting embedded sync frequency value1119 * on output pin.1120 *1121 * Context: Acquires pf->dplls.lock1122 * Return:1123 * * 0 - success1124 * * negative - error1125 */1126static int1127ice_dpll_output_esync_set(const struct dpll_pin *pin, void *pin_priv,1128			  const struct dpll_device *dpll, void *dpll_priv,1129			  u64 freq, struct netlink_ext_ack *extack)1130{1131	struct ice_dpll_pin *p = pin_priv;1132	struct ice_dpll *d = dpll_priv;1133	struct ice_pf *pf = d->pf;1134	u8 flags = 0;1135	int ret;1136 1137	if (ice_dpll_is_reset(pf, extack))1138		return -EBUSY;1139	mutex_lock(&pf->dplls.lock);1140	if (p->flags[0] & ICE_AQC_GET_CGU_OUT_CFG_OUT_EN)1141		flags = ICE_AQC_SET_CGU_OUT_CFG_OUT_EN;1142	if (freq == DPLL_PIN_FREQUENCY_1_HZ) {1143		if (p->flags[0] & ICE_AQC_GET_CGU_OUT_CFG_ESYNC_EN) {1144			ret = 0;1145		} else {1146			flags |= ICE_AQC_SET_CGU_OUT_CFG_ESYNC_EN;1147			ret = ice_aq_set_output_pin_cfg(&pf->hw, p->idx, flags,1148							0, 0, 0);1149		}1150	} else {1151		if (!(p->flags[0] & ICE_AQC_GET_CGU_OUT_CFG_ESYNC_EN)) {1152			ret = 0;1153		} else {1154			flags &= ~ICE_AQC_SET_CGU_OUT_CFG_ESYNC_EN;1155			ret = ice_aq_set_output_pin_cfg(&pf->hw, p->idx, flags,1156							0, 0, 0);1157		}1158	}1159	mutex_unlock(&pf->dplls.lock);1160 1161	return ret;1162}1163 1164/**1165 * ice_dpll_output_esync_get - callback for getting embedded sync config1166 * @pin: pointer to a pin1167 * @pin_priv: private data pointer passed on pin registration1168 * @dpll: registered dpll pointer1169 * @dpll_priv: private data pointer passed on dpll registration1170 * @esync: on success holds embedded sync pin properties1171 * @extack: error reporting1172 *1173 * Dpll subsystem callback. Handler for getting embedded sync frequency value1174 * and capabilities on output pin.1175 *1176 * Context: Acquires pf->dplls.lock1177 * Return:1178 * * 0 - success1179 * * negative - error1180 */1181static int1182ice_dpll_output_esync_get(const struct dpll_pin *pin, void *pin_priv,1183			  const struct dpll_device *dpll, void *dpll_priv,1184			  struct dpll_pin_esync *esync,1185			  struct netlink_ext_ack *extack)1186{1187	struct ice_dpll_pin *p = pin_priv;1188	struct ice_dpll *d = dpll_priv;1189	struct ice_pf *pf = d->pf;1190 1191	if (ice_dpll_is_reset(pf, extack))1192		return -EBUSY;1193	mutex_lock(&pf->dplls.lock);1194	if (!(p->flags[0] & ICE_AQC_GET_CGU_OUT_CFG_ESYNC_ABILITY) ||1195	    p->freq != DPLL_PIN_FREQUENCY_10_MHZ) {1196		mutex_unlock(&pf->dplls.lock);1197		return -EOPNOTSUPP;1198	}1199	esync->range = ice_esync_range;1200	esync->range_num = ARRAY_SIZE(ice_esync_range);1201	if (p->flags[0] & ICE_AQC_GET_CGU_OUT_CFG_ESYNC_EN) {1202		esync->freq = DPLL_PIN_FREQUENCY_1_HZ;1203		esync->pulse = ICE_DPLL_PIN_ESYNC_PULSE_HIGH_PERCENT;1204	} else {1205		esync->freq = 0;1206		esync->pulse = 0;1207	}1208	mutex_unlock(&pf->dplls.lock);1209 1210	return 0;1211}1212 1213/**1214 * ice_dpll_input_esync_set - callback for setting embedded sync1215 * @pin: pointer to a pin1216 * @pin_priv: private data pointer passed on pin registration1217 * @dpll: registered dpll pointer1218 * @dpll_priv: private data pointer passed on dpll registration1219 * @freq: requested embedded sync frequency1220 * @extack: error reporting1221 *1222 * Dpll subsystem callback. Handler for setting embedded sync frequency value1223 * on input pin.1224 *1225 * Context: Acquires pf->dplls.lock1226 * Return:1227 * * 0 - success1228 * * negative - error1229 */1230static int1231ice_dpll_input_esync_set(const struct dpll_pin *pin, void *pin_priv,1232			 const struct dpll_device *dpll, void *dpll_priv,1233			 u64 freq, struct netlink_ext_ack *extack)1234{1235	struct ice_dpll_pin *p = pin_priv;1236	struct ice_dpll *d = dpll_priv;1237	struct ice_pf *pf = d->pf;1238	u8 flags_en = 0;1239	int ret;1240 1241	if (ice_dpll_is_reset(pf, extack))1242		return -EBUSY;1243	mutex_lock(&pf->dplls.lock);1244	if (p->flags[0] & ICE_AQC_GET_CGU_IN_CFG_FLG2_INPUT_EN)1245		flags_en = ICE_AQC_SET_CGU_IN_CFG_FLG2_INPUT_EN;1246	if (freq == DPLL_PIN_FREQUENCY_1_HZ) {1247		if (p->flags[0] & ICE_AQC_GET_CGU_IN_CFG_FLG2_ESYNC_EN) {1248			ret = 0;1249		} else {1250			flags_en |= ICE_AQC_SET_CGU_IN_CFG_FLG2_ESYNC_EN;1251			ret = ice_aq_set_input_pin_cfg(&pf->hw, p->idx, 0,1252						       flags_en, 0, 0);1253		}1254	} else {1255		if (!(p->flags[0] & ICE_AQC_GET_CGU_IN_CFG_FLG2_ESYNC_EN)) {1256			ret = 0;1257		} else {1258			flags_en &= ~ICE_AQC_SET_CGU_IN_CFG_FLG2_ESYNC_EN;1259			ret = ice_aq_set_input_pin_cfg(&pf->hw, p->idx, 0,1260						       flags_en, 0, 0);1261		}1262	}1263	mutex_unlock(&pf->dplls.lock);1264 1265	return ret;1266}1267 1268/**1269 * ice_dpll_input_esync_get - callback for getting embedded sync config1270 * @pin: pointer to a pin1271 * @pin_priv: private data pointer passed on pin registration1272 * @dpll: registered dpll pointer1273 * @dpll_priv: private data pointer passed on dpll registration1274 * @esync: on success holds embedded sync pin properties1275 * @extack: error reporting1276 *1277 * Dpll subsystem callback. Handler for getting embedded sync frequency value1278 * and capabilities on input pin.1279 *1280 * Context: Acquires pf->dplls.lock1281 * Return:1282 * * 0 - success1283 * * negative - error1284 */1285static int1286ice_dpll_input_esync_get(const struct dpll_pin *pin, void *pin_priv,1287			 const struct dpll_device *dpll, void *dpll_priv,1288			 struct dpll_pin_esync *esync,1289			 struct netlink_ext_ack *extack)1290{1291	struct ice_dpll_pin *p = pin_priv;1292	struct ice_dpll *d = dpll_priv;1293	struct ice_pf *pf = d->pf;1294 1295	if (ice_dpll_is_reset(pf, extack))1296		return -EBUSY;1297	mutex_lock(&pf->dplls.lock);1298	if (!(p->status & ICE_AQC_GET_CGU_IN_CFG_STATUS_ESYNC_CAP) ||1299	    p->freq != DPLL_PIN_FREQUENCY_10_MHZ) {1300		mutex_unlock(&pf->dplls.lock);1301		return -EOPNOTSUPP;1302	}1303	esync->range = ice_esync_range;1304	esync->range_num = ARRAY_SIZE(ice_esync_range);1305	if (p->flags[0] & ICE_AQC_GET_CGU_IN_CFG_FLG2_ESYNC_EN) {1306		esync->freq = DPLL_PIN_FREQUENCY_1_HZ;1307		esync->pulse = ICE_DPLL_PIN_ESYNC_PULSE_HIGH_PERCENT;1308	} else {1309		esync->freq = 0;1310		esync->pulse = 0;1311	}1312	mutex_unlock(&pf->dplls.lock);1313 1314	return 0;1315}1316 1317/**1318 * ice_dpll_rclk_state_on_pin_set - set a state on rclk pin1319 * @pin: pointer to a pin1320 * @pin_priv: private data pointer passed on pin registration1321 * @parent_pin: pin parent pointer1322 * @parent_pin_priv: parent private data pointer passed on pin registration1323 * @state: state to be set on pin1324 * @extack: error reporting1325 *1326 * Dpll subsystem callback, set a state of a rclk pin on a parent pin1327 *1328 * Context: Acquires pf->dplls.lock1329 * Return:1330 * * 0 - success1331 * * negative - failure1332 */1333static int1334ice_dpll_rclk_state_on_pin_set(const struct dpll_pin *pin, void *pin_priv,1335			       const struct dpll_pin *parent_pin,1336			       void *parent_pin_priv,1337			       enum dpll_pin_state state,1338			       struct netlink_ext_ack *extack)1339{1340	struct ice_dpll_pin *p = pin_priv, *parent = parent_pin_priv;1341	bool enable = state == DPLL_PIN_STATE_CONNECTED;1342	struct ice_pf *pf = p->pf;1343	int ret = -EINVAL;1344	u32 hw_idx;1345 1346	if (ice_dpll_is_reset(pf, extack))1347		return -EBUSY;1348 1349	mutex_lock(&pf->dplls.lock);1350	hw_idx = parent->idx - pf->dplls.base_rclk_idx;1351	if (hw_idx >= pf->dplls.num_inputs)1352		goto unlock;1353 1354	if ((enable && p->state[hw_idx] == DPLL_PIN_STATE_CONNECTED) ||1355	    (!enable && p->state[hw_idx] == DPLL_PIN_STATE_DISCONNECTED)) {1356		NL_SET_ERR_MSG_FMT(extack,1357				   "pin:%u state:%u on parent:%u already set",1358				   p->idx, state, parent->idx);1359		goto unlock;1360	}1361	ret = ice_aq_set_phy_rec_clk_out(&pf->hw, hw_idx, enable,1362					 &p->freq);1363	if (ret)1364		NL_SET_ERR_MSG_FMT(extack,1365				   "err:%d %s failed to set pin state:%u for pin:%u on parent:%u\n",1366				   ret,1367				   ice_aq_str(pf->hw.adminq.sq_last_status),1368				   state, p->idx, parent->idx);1369unlock:1370	mutex_unlock(&pf->dplls.lock);1371 1372	return ret;1373}1374 1375/**1376 * ice_dpll_rclk_state_on_pin_get - get a state of rclk pin1377 * @pin: pointer to a pin1378 * @pin_priv: private data pointer passed on pin registration1379 * @parent_pin: pin parent pointer1380 * @parent_pin_priv: pin parent priv data pointer passed on pin registration1381 * @state: on success holds pin state on parent pin1382 * @extack: error reporting1383 *1384 * dpll subsystem callback, get a state of a recovered clock pin.1385 *1386 * Context: Acquires pf->dplls.lock1387 * Return:1388 * * 0 - success1389 * * negative - failure1390 */1391static int1392ice_dpll_rclk_state_on_pin_get(const struct dpll_pin *pin, void *pin_priv,1393			       const struct dpll_pin *parent_pin,1394			       void *parent_pin_priv,1395			       enum dpll_pin_state *state,1396			       struct netlink_ext_ack *extack)1397{1398	struct ice_dpll_pin *p = pin_priv, *parent = parent_pin_priv;1399	struct ice_pf *pf = p->pf;1400	int ret = -EINVAL;1401	u32 hw_idx;1402 1403	if (ice_dpll_is_reset(pf, extack))1404		return -EBUSY;1405 1406	mutex_lock(&pf->dplls.lock);1407	hw_idx = parent->idx - pf->dplls.base_rclk_idx;1408	if (hw_idx >= pf->dplls.num_inputs)1409		goto unlock;1410 1411	ret = ice_dpll_pin_state_update(pf, p, ICE_DPLL_PIN_TYPE_RCLK_INPUT,1412					extack);1413	if (ret)1414		goto unlock;1415 1416	*state = p->state[hw_idx];1417	ret = 0;1418unlock:1419	mutex_unlock(&pf->dplls.lock);1420 1421	return ret;1422}1423 1424static const struct dpll_pin_ops ice_dpll_rclk_ops = {1425	.state_on_pin_set = ice_dpll_rclk_state_on_pin_set,1426	.state_on_pin_get = ice_dpll_rclk_state_on_pin_get,1427	.direction_get = ice_dpll_input_direction,1428};1429 1430static const struct dpll_pin_ops ice_dpll_input_ops = {1431	.frequency_get = ice_dpll_input_frequency_get,1432	.frequency_set = ice_dpll_input_frequency_set,1433	.state_on_dpll_get = ice_dpll_input_state_get,1434	.state_on_dpll_set = ice_dpll_input_state_set,1435	.prio_get = ice_dpll_input_prio_get,1436	.prio_set = ice_dpll_input_prio_set,1437	.direction_get = ice_dpll_input_direction,1438	.phase_adjust_get = ice_dpll_pin_phase_adjust_get,1439	.phase_adjust_set = ice_dpll_input_phase_adjust_set,1440	.phase_offset_get = ice_dpll_phase_offset_get,1441	.esync_set = ice_dpll_input_esync_set,1442	.esync_get = ice_dpll_input_esync_get,1443};1444 1445static const struct dpll_pin_ops ice_dpll_output_ops = {1446	.frequency_get = ice_dpll_output_frequency_get,1447	.frequency_set = ice_dpll_output_frequency_set,1448	.state_on_dpll_get = ice_dpll_output_state_get,1449	.state_on_dpll_set = ice_dpll_output_state_set,1450	.direction_get = ice_dpll_output_direction,1451	.phase_adjust_get = ice_dpll_pin_phase_adjust_get,1452	.phase_adjust_set = ice_dpll_output_phase_adjust_set,1453	.esync_set = ice_dpll_output_esync_set,1454	.esync_get = ice_dpll_output_esync_get,1455};1456 1457static const struct dpll_device_ops ice_dpll_ops = {1458	.lock_status_get = ice_dpll_lock_status_get,1459	.mode_get = ice_dpll_mode_get,1460};1461 1462/**1463 * ice_generate_clock_id - generates unique clock_id for registering dpll.1464 * @pf: board private structure1465 *1466 * Generates unique (per board) clock_id for allocation and search of dpll1467 * devices in Linux dpll subsystem.1468 *1469 * Return: generated clock id for the board1470 */1471static u64 ice_generate_clock_id(struct ice_pf *pf)1472{1473	return pci_get_dsn(pf->pdev);1474}1475 1476/**1477 * ice_dpll_notify_changes - notify dpll subsystem about changes1478 * @d: pointer do dpll1479 *1480 * Once change detected appropriate event is submitted to the dpll subsystem.1481 */1482static void ice_dpll_notify_changes(struct ice_dpll *d)1483{1484	bool pin_notified = false;1485 1486	if (d->prev_dpll_state != d->dpll_state) {1487		d->prev_dpll_state = d->dpll_state;1488		dpll_device_change_ntf(d->dpll);1489	}1490	if (d->prev_input != d->active_input) {1491		if (d->prev_input)1492			dpll_pin_change_ntf(d->prev_input);1493		d->prev_input = d->active_input;1494		if (d->active_input) {1495			dpll_pin_change_ntf(d->active_input);1496			pin_notified = true;1497		}1498	}1499	if (d->prev_phase_offset != d->phase_offset) {1500		d->prev_phase_offset = d->phase_offset;1501		if (!pin_notified && d->active_input)1502			dpll_pin_change_ntf(d->active_input);1503	}1504}1505 1506/**1507 * ice_dpll_update_state - update dpll state1508 * @pf: pf private structure1509 * @d: pointer to queried dpll device1510 * @init: if function called on initialization of ice dpll1511 *1512 * Poll current state of dpll from hw and update ice_dpll struct.1513 *1514 * Context: Called by kworker under pf->dplls.lock1515 * Return:1516 * * 0 - success1517 * * negative - AQ failure1518 */1519static int1520ice_dpll_update_state(struct ice_pf *pf, struct ice_dpll *d, bool init)1521{1522	struct ice_dpll_pin *p = NULL;1523	int ret;1524 1525	ret = ice_get_cgu_state(&pf->hw, d->dpll_idx, d->prev_dpll_state,1526				&d->input_idx, &d->ref_state, &d->eec_mode,1527				&d->phase_offset, &d->dpll_state);1528 1529	dev_dbg(ice_pf_to_dev(pf),1530		"update dpll=%d, prev_src_idx:%u, src_idx:%u, state:%d, prev:%d mode:%d\n",1531		d->dpll_idx, d->prev_input_idx, d->input_idx,1532		d->dpll_state, d->prev_dpll_state, d->mode);1533	if (ret) {1534		dev_err(ice_pf_to_dev(pf),1535			"update dpll=%d state failed, ret=%d %s\n",1536			d->dpll_idx, ret,1537			ice_aq_str(pf->hw.adminq.sq_last_status));1538		return ret;1539	}1540	if (init) {1541		if (d->dpll_state == DPLL_LOCK_STATUS_LOCKED ||1542		    d->dpll_state == DPLL_LOCK_STATUS_LOCKED_HO_ACQ)1543			d->active_input = pf->dplls.inputs[d->input_idx].pin;1544		p = &pf->dplls.inputs[d->input_idx];1545		return ice_dpll_pin_state_update(pf, p,1546						 ICE_DPLL_PIN_TYPE_INPUT, NULL);1547	}1548	if (d->dpll_state == DPLL_LOCK_STATUS_HOLDOVER ||1549	    d->dpll_state == DPLL_LOCK_STATUS_UNLOCKED) {1550		d->active_input = NULL;1551		if (d->input_idx != ICE_DPLL_PIN_IDX_INVALID)1552			p = &pf->dplls.inputs[d->input_idx];1553		d->prev_input_idx = ICE_DPLL_PIN_IDX_INVALID;1554		d->input_idx = ICE_DPLL_PIN_IDX_INVALID;1555		if (!p)1556			return 0;1557		ret = ice_dpll_pin_state_update(pf, p,1558						ICE_DPLL_PIN_TYPE_INPUT, NULL);1559	} else if (d->input_idx != d->prev_input_idx) {1560		if (d->prev_input_idx != ICE_DPLL_PIN_IDX_INVALID) {1561			p = &pf->dplls.inputs[d->prev_input_idx];1562			ice_dpll_pin_state_update(pf, p,1563						  ICE_DPLL_PIN_TYPE_INPUT,1564						  NULL);1565		}1566		if (d->input_idx != ICE_DPLL_PIN_IDX_INVALID) {1567			p = &pf->dplls.inputs[d->input_idx];1568			d->active_input = p->pin;1569			ice_dpll_pin_state_update(pf, p,1570						  ICE_DPLL_PIN_TYPE_INPUT,1571						  NULL);1572		}1573		d->prev_input_idx = d->input_idx;1574	}1575 1576	return ret;1577}1578 1579/**1580 * ice_dpll_periodic_work - DPLLs periodic worker1581 * @work: pointer to kthread_work structure1582 *1583 * DPLLs periodic worker is responsible for polling state of dpll.1584 * Context: Holds pf->dplls.lock1585 */1586static void ice_dpll_periodic_work(struct kthread_work *work)1587{1588	struct ice_dplls *d = container_of(work, struct ice_dplls, work.work);1589	struct ice_pf *pf = container_of(d, struct ice_pf, dplls);1590	struct ice_dpll *de = &pf->dplls.eec;1591	struct ice_dpll *dp = &pf->dplls.pps;1592	int ret = 0;1593 1594	if (ice_is_reset_in_progress(pf->state))1595		goto resched;1596	mutex_lock(&pf->dplls.lock);1597	ret = ice_dpll_update_state(pf, de, false);1598	if (!ret)1599		ret = ice_dpll_update_state(pf, dp, false);1600	if (ret) {1601		d->cgu_state_acq_err_num++;1602		/* stop rescheduling this worker */1603		if (d->cgu_state_acq_err_num >1604		    ICE_CGU_STATE_ACQ_ERR_THRESHOLD) {1605			dev_err(ice_pf_to_dev(pf),1606				"EEC/PPS DPLLs periodic work disabled\n");1607			mutex_unlock(&pf->dplls.lock);1608			return;1609		}1610	}1611	mutex_unlock(&pf->dplls.lock);1612	ice_dpll_notify_changes(de);1613	ice_dpll_notify_changes(dp);1614 1615resched:1616	/* Run twice a second or reschedule if update failed */1617	kthread_queue_delayed_work(d->kworker, &d->work,1618				   ret ? msecs_to_jiffies(10) :1619				   msecs_to_jiffies(500));1620}1621 1622/**1623 * ice_dpll_release_pins - release pins resources from dpll subsystem1624 * @pins: pointer to pins array1625 * @count: number of pins1626 *1627 * Release resources of given pins array in the dpll subsystem.1628 */1629static void ice_dpll_release_pins(struct ice_dpll_pin *pins, int count)1630{1631	int i;1632 1633	for (i = 0; i < count; i++)1634		dpll_pin_put(pins[i].pin);1635}1636 1637/**1638 * ice_dpll_get_pins - get pins from dpll subsystem1639 * @pf: board private structure1640 * @pins: pointer to pins array1641 * @start_idx: get starts from this pin idx value1642 * @count: number of pins1643 * @clock_id: clock_id of dpll device1644 *1645 * Get pins - allocate - in dpll subsystem, store them in pin field of given1646 * pins array.1647 *1648 * Return:1649 * * 0 - success1650 * * negative - allocation failure reason1651 */1652static int1653ice_dpll_get_pins(struct ice_pf *pf, struct ice_dpll_pin *pins,1654		  int start_idx, int count, u64 clock_id)1655{1656	int i, ret;1657 1658	for (i = 0; i < count; i++) {1659		pins[i].pin = dpll_pin_get(clock_id, i + start_idx, THIS_MODULE,1660					   &pins[i].prop);1661		if (IS_ERR(pins[i].pin)) {1662			ret = PTR_ERR(pins[i].pin);1663			goto release_pins;1664		}1665	}1666 1667	return 0;1668 1669release_pins:1670	while (--i >= 0)1671		dpll_pin_put(pins[i].pin);1672	return ret;1673}1674 1675/**1676 * ice_dpll_unregister_pins - unregister pins from a dpll1677 * @dpll: dpll device pointer1678 * @pins: pointer to pins array1679 * @ops: callback ops registered with the pins1680 * @count: number of pins1681 *1682 * Unregister pins of a given array of pins from given dpll device registered in1683 * dpll subsystem.1684 */1685static void1686ice_dpll_unregister_pins(struct dpll_device *dpll, struct ice_dpll_pin *pins,1687			 const struct dpll_pin_ops *ops, int count)1688{1689	int i;1690 1691	for (i = 0; i < count; i++)1692		dpll_pin_unregister(dpll, pins[i].pin, ops, &pins[i]);1693}1694 1695/**1696 * ice_dpll_register_pins - register pins with a dpll1697 * @dpll: dpll pointer to register pins with1698 * @pins: pointer to pins array1699 * @ops: callback ops registered with the pins1700 * @count: number of pins1701 *1702 * Register pins of a given array with given dpll in dpll subsystem.1703 *1704 * Return:1705 * * 0 - success1706 * * negative - registration failure reason1707 */1708static int1709ice_dpll_register_pins(struct dpll_device *dpll, struct ice_dpll_pin *pins,1710		       const struct dpll_pin_ops *ops, int count)1711{1712	int ret, i;1713 1714	for (i = 0; i < count; i++) {1715		ret = dpll_pin_register(dpll, pins[i].pin, ops, &pins[i]);1716		if (ret)1717			goto unregister_pins;1718	}1719 1720	return 0;1721 1722unregister_pins:1723	while (--i >= 0)1724		dpll_pin_unregister(dpll, pins[i].pin, ops, &pins[i]);1725	return ret;1726}1727 1728/**1729 * ice_dpll_deinit_direct_pins - deinitialize direct pins1730 * @cgu: if cgu is present and controlled by this NIC1731 * @pins: pointer to pins array1732 * @count: number of pins1733 * @ops: callback ops registered with the pins1734 * @first: dpll device pointer1735 * @second: dpll device pointer1736 *1737 * If cgu is owned unregister pins from given dplls.1738 * Release pins resources to the dpll subsystem.1739 */1740static void1741ice_dpll_deinit_direct_pins(bool cgu, struct ice_dpll_pin *pins, int count,1742			    const struct dpll_pin_ops *ops,1743			    struct dpll_device *first,1744			    struct dpll_device *second)1745{1746	if (cgu) {1747		ice_dpll_unregister_pins(first, pins, ops, count);1748		ice_dpll_unregister_pins(second, pins, ops, count);1749	}1750	ice_dpll_release_pins(pins, count);1751}1752 1753/**1754 * ice_dpll_init_direct_pins - initialize direct pins1755 * @pf: board private structure1756 * @cgu: if cgu is present and controlled by this NIC1757 * @pins: pointer to pins array1758 * @start_idx: on which index shall allocation start in dpll subsystem1759 * @count: number of pins1760 * @ops: callback ops registered with the pins1761 * @first: dpll device pointer1762 * @second: dpll device pointer1763 *1764 * Allocate directly connected pins of a given array in dpll subsystem.1765 * If cgu is owned register allocated pins with given dplls.1766 *1767 * Return:1768 * * 0 - success1769 * * negative - registration failure reason1770 */1771static int1772ice_dpll_init_direct_pins(struct ice_pf *pf, bool cgu,1773			  struct ice_dpll_pin *pins, int start_idx, int count,1774			  const struct dpll_pin_ops *ops,1775			  struct dpll_device *first, struct dpll_device *second)1776{1777	int ret;1778 1779	ret = ice_dpll_get_pins(pf, pins, start_idx, count, pf->dplls.clock_id);1780	if (ret)1781		return ret;1782	if (cgu) {1783		ret = ice_dpll_register_pins(first, pins, ops, count);1784		if (ret)1785			goto release_pins;1786		ret = ice_dpll_register_pins(second, pins, ops, count);1787		if (ret)1788			goto unregister_first;1789	}1790 1791	return 0;1792 1793unregister_first:1794	ice_dpll_unregister_pins(first, pins, ops, count);1795release_pins:1796	ice_dpll_release_pins(pins, count);1797	return ret;1798}1799 1800/**1801 * ice_dpll_deinit_rclk_pin - release rclk pin resources1802 * @pf: board private structure1803 *1804 * Deregister rclk pin from parent pins and release resources in dpll subsystem.1805 */1806static void ice_dpll_deinit_rclk_pin(struct ice_pf *pf)1807{1808	struct ice_dpll_pin *rclk = &pf->dplls.rclk;1809	struct ice_vsi *vsi = ice_get_main_vsi(pf);1810	struct dpll_pin *parent;1811	int i;1812 1813	for (i = 0; i < rclk->num_parents; i++) {1814		parent = pf->dplls.inputs[rclk->parent_idx[i]].pin;1815		if (!parent)1816			continue;1817		dpll_pin_on_pin_unregister(parent, rclk->pin,1818					   &ice_dpll_rclk_ops, rclk);1819	}1820	if (WARN_ON_ONCE(!vsi || !vsi->netdev))1821		return;1822	dpll_netdev_pin_clear(vsi->netdev);1823	dpll_pin_put(rclk->pin);1824}1825 1826/**1827 * ice_dpll_init_rclk_pins - initialize recovered clock pin1828 * @pf: board private structure1829 * @pin: pin to register1830 * @start_idx: on which index shall allocation start in dpll subsystem1831 * @ops: callback ops registered with the pins1832 *1833 * Allocate resource for recovered clock pin in dpll subsystem. Register the1834 * pin with the parents it has in the info. Register pin with the pf's main vsi1835 * netdev.1836 *1837 * Return:1838 * * 0 - success1839 * * negative - registration failure reason1840 */1841static int1842ice_dpll_init_rclk_pins(struct ice_pf *pf, struct ice_dpll_pin *pin,1843			int start_idx, const struct dpll_pin_ops *ops)1844{1845	struct ice_vsi *vsi = ice_get_main_vsi(pf);1846	struct dpll_pin *parent;1847	int ret, i;1848 1849	if (WARN_ON((!vsi || !vsi->netdev)))1850		return -EINVAL;1851	ret = ice_dpll_get_pins(pf, pin, start_idx, ICE_DPLL_RCLK_NUM_PER_PF,1852				pf->dplls.clock_id);1853	if (ret)1854		return ret;1855	for (i = 0; i < pf->dplls.rclk.num_parents; i++) {1856		parent = pf->dplls.inputs[pf->dplls.rclk.parent_idx[i]].pin;1857		if (!parent) {1858			ret = -ENODEV;1859			goto unregister_pins;1860		}1861		ret = dpll_pin_on_pin_register(parent, pf->dplls.rclk.pin,1862					       ops, &pf->dplls.rclk);1863		if (ret)1864			goto unregister_pins;1865	}1866	dpll_netdev_pin_set(vsi->netdev, pf->dplls.rclk.pin);1867 1868	return 0;1869 1870unregister_pins:1871	while (i) {1872		parent = pf->dplls.inputs[pf->dplls.rclk.parent_idx[--i]].pin;1873		dpll_pin_on_pin_unregister(parent, pf->dplls.rclk.pin,1874					   &ice_dpll_rclk_ops, &pf->dplls.rclk);1875	}1876	ice_dpll_release_pins(pin, ICE_DPLL_RCLK_NUM_PER_PF);1877	return ret;1878}1879 1880/**1881 * ice_dpll_deinit_pins - deinitialize direct pins1882 * @pf: board private structure1883 * @cgu: if cgu is controlled by this pf1884 *1885 * If cgu is owned unregister directly connected pins from the dplls.1886 * Release resources of directly connected pins from the dpll subsystem.1887 */1888static void ice_dpll_deinit_pins(struct ice_pf *pf, bool cgu)1889{1890	struct ice_dpll_pin *outputs = pf->dplls.outputs;1891	struct ice_dpll_pin *inputs = pf->dplls.inputs;1892	int num_outputs = pf->dplls.num_outputs;1893	int num_inputs = pf->dplls.num_inputs;1894	struct ice_dplls *d = &pf->dplls;1895	struct ice_dpll *de = &d->eec;1896	struct ice_dpll *dp = &d->pps;1897 1898	ice_dpll_deinit_rclk_pin(pf);1899	if (cgu) {1900		ice_dpll_unregister_pins(dp->dpll, inputs, &ice_dpll_input_ops,1901					 num_inputs);1902		ice_dpll_unregister_pins(de->dpll, inputs, &ice_dpll_input_ops,1903					 num_inputs);1904	}1905	ice_dpll_release_pins(inputs, num_inputs);1906	if (cgu) {1907		ice_dpll_unregister_pins(dp->dpll, outputs,1908					 &ice_dpll_output_ops, num_outputs);1909		ice_dpll_unregister_pins(de->dpll, outputs,1910					 &ice_dpll_output_ops, num_outputs);1911		ice_dpll_release_pins(outputs, num_outputs);1912	}1913}1914 1915/**1916 * ice_dpll_init_pins - init pins and register pins with a dplls1917 * @pf: board private structure1918 * @cgu: if cgu is present and controlled by this NIC1919 *1920 * Initialize directly connected pf's pins within pf's dplls in a Linux dpll1921 * subsystem.1922 *1923 * Return:1924 * * 0 - success1925 * * negative - initialization failure reason1926 */1927static int ice_dpll_init_pins(struct ice_pf *pf, bool cgu)1928{1929	u32 rclk_idx;1930	int ret;1931 1932	ret = ice_dpll_init_direct_pins(pf, cgu, pf->dplls.inputs, 0,1933					pf->dplls.num_inputs,1934					&ice_dpll_input_ops,1935					pf->dplls.eec.dpll, pf->dplls.pps.dpll);1936	if (ret)1937		return ret;1938	if (cgu) {1939		ret = ice_dpll_init_direct_pins(pf, cgu, pf->dplls.outputs,1940						pf->dplls.num_inputs,1941						pf->dplls.num_outputs,1942						&ice_dpll_output_ops,1943						pf->dplls.eec.dpll,1944						pf->dplls.pps.dpll);1945		if (ret)1946			goto deinit_inputs;1947	}1948	rclk_idx = pf->dplls.num_inputs + pf->dplls.num_outputs + pf->hw.pf_id;1949	ret = ice_dpll_init_rclk_pins(pf, &pf->dplls.rclk, rclk_idx,1950				      &ice_dpll_rclk_ops);1951	if (ret)1952		goto deinit_outputs;1953 1954	return 0;1955deinit_outputs:1956	ice_dpll_deinit_direct_pins(cgu, pf->dplls.outputs,1957				    pf->dplls.num_outputs,1958				    &ice_dpll_output_ops, pf->dplls.pps.dpll,1959				    pf->dplls.eec.dpll);1960deinit_inputs:1961	ice_dpll_deinit_direct_pins(cgu, pf->dplls.inputs, pf->dplls.num_inputs,1962				    &ice_dpll_input_ops, pf->dplls.pps.dpll,1963				    pf->dplls.eec.dpll);1964	return ret;1965}1966 1967/**1968 * ice_dpll_deinit_dpll - deinitialize dpll device1969 * @pf: board private structure1970 * @d: pointer to ice_dpll1971 * @cgu: if cgu is present and controlled by this NIC1972 *1973 * If cgu is owned unregister the dpll from dpll subsystem.1974 * Release resources of dpll device from dpll subsystem.1975 */1976static void1977ice_dpll_deinit_dpll(struct ice_pf *pf, struct ice_dpll *d, bool cgu)1978{1979	if (cgu)1980		dpll_device_unregister(d->dpll, &ice_dpll_ops, d);1981	dpll_device_put(d->dpll);1982}1983 1984/**1985 * ice_dpll_init_dpll - initialize dpll device in dpll subsystem1986 * @pf: board private structure1987 * @d: dpll to be initialized1988 * @cgu: if cgu is present and controlled by this NIC1989 * @type: type of dpll being initialized1990 *1991 * Allocate dpll instance for this board in dpll subsystem, if cgu is controlled1992 * by this NIC, register dpll with the callback ops.1993 *1994 * Return:1995 * * 0 - success1996 * * negative - initialization failure reason1997 */1998static int1999ice_dpll_init_dpll(struct ice_pf *pf, struct ice_dpll *d, bool cgu,2000		   enum dpll_type type)2001{2002	u64 clock_id = pf->dplls.clock_id;2003	int ret;2004 2005	d->dpll = dpll_device_get(clock_id, d->dpll_idx, THIS_MODULE);2006	if (IS_ERR(d->dpll)) {2007		ret = PTR_ERR(d->dpll);2008		dev_err(ice_pf_to_dev(pf),2009			"dpll_device_get failed (%p) err=%d\n", d, ret);2010		return ret;2011	}2012	d->pf = pf;2013	if (cgu) {2014		ice_dpll_update_state(pf, d, true);2015		ret = dpll_device_register(d->dpll, type, &ice_dpll_ops, d);2016		if (ret) {2017			dpll_device_put(d->dpll);2018			return ret;2019		}2020	}2021 2022	return 0;2023}2024 2025/**2026 * ice_dpll_deinit_worker - deinitialize dpll kworker2027 * @pf: board private structure2028 *2029 * Stop dpll's kworker, release it's resources.2030 */2031static void ice_dpll_deinit_worker(struct ice_pf *pf)2032{2033	struct ice_dplls *d = &pf->dplls;2034 2035	kthread_cancel_delayed_work_sync(&d->work);2036	kthread_destroy_worker(d->kworker);2037}2038 2039/**2040 * ice_dpll_init_worker - Initialize DPLLs periodic worker2041 * @pf: board private structure2042 *2043 * Create and start DPLLs periodic worker.2044 *2045 * Context: Shall be called after pf->dplls.lock is initialized.2046 * Return:2047 * * 0 - success2048 * * negative - create worker failure2049 */2050static int ice_dpll_init_worker(struct ice_pf *pf)2051{2052	struct ice_dplls *d = &pf->dplls;2053	struct kthread_worker *kworker;2054 2055	kthread_init_delayed_work(&d->work, ice_dpll_periodic_work);2056	kworker = kthread_create_worker(0, "ice-dplls-%s",2057					dev_name(ice_pf_to_dev(pf)));2058	if (IS_ERR(kworker))2059		return PTR_ERR(kworker);2060	d->kworker = kworker;2061	d->cgu_state_acq_err_num = 0;2062	kthread_queue_delayed_work(d->kworker, &d->work, 0);2063 2064	return 0;2065}2066 2067/**2068 * ice_dpll_init_info_pins_generic - initializes generic pins info2069 * @pf: board private structure2070 * @input: if input pins initialized2071 *2072 * Init information for generic pins, cache them in PF's pins structures.2073 *2074 * Return:2075 * * 0 - success2076 * * negative - init failure reason2077 */2078static int ice_dpll_init_info_pins_generic(struct ice_pf *pf, bool input)2079{2080	struct ice_dpll *de = &pf->dplls.eec, *dp = &pf->dplls.pps;2081	static const char labels[][sizeof("99")] = {2082		"0", "1", "2", "3", "4", "5", "6", "7", "8",2083		"9", "10", "11", "12", "13", "14", "15" };2084	u32 cap = DPLL_PIN_CAPABILITIES_STATE_CAN_CHANGE;2085	enum ice_dpll_pin_type pin_type;2086	int i, pin_num, ret = -EINVAL;2087	struct ice_dpll_pin *pins;2088	u32 phase_adj_max;2089 2090	if (input) {2091		pin_num = pf->dplls.num_inputs;2092		pins = pf->dplls.inputs;2093		phase_adj_max = pf->dplls.input_phase_adj_max;2094		pin_type = ICE_DPLL_PIN_TYPE_INPUT;2095		cap |= DPLL_PIN_CAPABILITIES_PRIORITY_CAN_CHANGE;2096	} else {2097		pin_num = pf->dplls.num_outputs;2098		pins = pf->dplls.outputs;2099		phase_adj_max = pf->dplls.output_phase_adj_max;2100		pin_type = ICE_DPLL_PIN_TYPE_OUTPUT;2101	}2102	if (pin_num > ARRAY_SIZE(labels))2103		return ret;2104 2105	for (i = 0; i < pin_num; i++) {2106		pins[i].idx = i;2107		pins[i].prop.board_label = labels[i];2108		pins[i].prop.phase_range.min = phase_adj_max;2109		pins[i].prop.phase_range.max = -phase_adj_max;2110		pins[i].prop.capabilities = cap;2111		pins[i].pf = pf;2112		ret = ice_dpll_pin_state_update(pf, &pins[i], pin_type, NULL);2113		if (ret)2114			break;2115		if (input && pins[i].freq == ICE_DPLL_PIN_GEN_RCLK_FREQ)2116			pins[i].prop.type = DPLL_PIN_TYPE_MUX;2117		else2118			pins[i].prop.type = DPLL_PIN_TYPE_EXT;2119		if (!input)2120			continue;2121		ret = ice_aq_get_cgu_ref_prio(&pf->hw, de->dpll_idx, i,2122					      &de->input_prio[i]);2123		if (ret)2124			break;2125		ret = ice_aq_get_cgu_ref_prio(&pf->hw, dp->dpll_idx, i,2126					      &dp->input_prio[i]);2127		if (ret)2128			break;2129	}2130 2131	return ret;2132}2133 2134/**2135 * ice_dpll_init_info_direct_pins - initializes direct pins info2136 * @pf: board private structure2137 * @pin_type: type of pins being initialized2138 *2139 * Init information for directly connected pins, cache them in pf's pins2140 * structures.2141 *2142 * Return:2143 * * 0 - success2144 * * negative - init failure reason2145 */2146static int2147ice_dpll_init_info_direct_pins(struct ice_pf *pf,2148			       enum ice_dpll_pin_type pin_type)2149{2150	struct ice_dpll *de = &pf->dplls.eec, *dp = &pf->dplls.pps;2151	int num_pins, i, ret = -EINVAL;2152	struct ice_hw *hw = &pf->hw;2153	struct ice_dpll_pin *pins;2154	unsigned long caps;2155	u8 freq_supp_num;2156	bool input;2157 2158	switch (pin_type) {2159	case ICE_DPLL_PIN_TYPE_INPUT:2160		pins = pf->dplls.inputs;2161		num_pins = pf->dplls.num_inputs;2162		input = true;2163		break;2164	case ICE_DPLL_PIN_TYPE_OUTPUT:2165		pins = pf->dplls.outputs;2166		num_pins = pf->dplls.num_outputs;2167		input = false;2168		break;2169	default:2170		return -EINVAL;2171	}2172	if (num_pins != ice_cgu_get_num_pins(hw, input))2173		return ice_dpll_init_info_pins_generic(pf, input);2174 2175	for (i = 0; i < num_pins; i++) {2176		caps = 0;2177		pins[i].idx = i;2178		pins[i].prop.board_label = ice_cgu_get_pin_name(hw, i, input);2179		pins[i].prop.type = ice_cgu_get_pin_type(hw, i, input);2180		if (input) {2181			ret = ice_aq_get_cgu_ref_prio(hw, de->dpll_idx, i,2182						      &de->input_prio[i]);2183			if (ret)2184				return ret;2185			ret = ice_aq_get_cgu_ref_prio(hw, dp->dpll_idx, i,2186						      &dp->input_prio[i]);2187			if (ret)2188				return ret;2189			caps |= (DPLL_PIN_CAPABILITIES_PRIORITY_CAN_CHANGE |2190				 DPLL_PIN_CAPABILITIES_STATE_CAN_CHANGE);2191			pins[i].prop.phase_range.min =2192				pf->dplls.input_phase_adj_max;2193			pins[i].prop.phase_range.max =2194				-pf->dplls.input_phase_adj_max;2195		} else {2196			pins[i].prop.phase_range.min =2197				pf->dplls.output_phase_adj_max;2198			pins[i].prop.phase_range.max =2199				-pf->dplls.output_phase_adj_max;2200			ret = ice_cgu_get_output_pin_state_caps(hw, i, &caps);2201			if (ret)2202				return ret;2203		}2204		pins[i].prop.capabilities = caps;2205		ret = ice_dpll_pin_state_update(pf, &pins[i], pin_type, NULL);2206		if (ret)2207			return ret;2208		pins[i].prop.freq_supported =2209			ice_cgu_get_pin_freq_supp(hw, i, input, &freq_supp_num);2210		pins[i].prop.freq_supported_num = freq_supp_num;2211		pins[i].pf = pf;2212	}2213 2214	return ret;2215}2216 2217/**2218 * ice_dpll_init_info_rclk_pin - initializes rclk pin information2219 * @pf: board private structure2220 *2221 * Init information for rclk pin, cache them in pf->dplls.rclk.2222 *2223 * Return:2224 * * 0 - success2225 * * negative - init failure reason2226 */2227static int ice_dpll_init_info_rclk_pin(struct ice_pf *pf)2228{2229	struct ice_dpll_pin *pin = &pf->dplls.rclk;2230 2231	pin->prop.type = DPLL_PIN_TYPE_SYNCE_ETH_PORT;2232	pin->prop.capabilities |= DPLL_PIN_CAPABILITIES_STATE_CAN_CHANGE;2233	pin->pf = pf;2234 2235	return ice_dpll_pin_state_update(pf, pin,2236					 ICE_DPLL_PIN_TYPE_RCLK_INPUT, NULL);2237}2238 2239/**2240 * ice_dpll_init_pins_info - init pins info wrapper2241 * @pf: board private structure2242 * @pin_type: type of pins being initialized2243 *2244 * Wraps functions for pin initialization.2245 *2246 * Return:2247 * * 0 - success2248 * * negative - init failure reason2249 */2250static int2251ice_dpll_init_pins_info(struct ice_pf *pf, enum ice_dpll_pin_type pin_type)2252{2253	switch (pin_type) {2254	case ICE_DPLL_PIN_TYPE_INPUT:2255	case ICE_DPLL_PIN_TYPE_OUTPUT:2256		return ice_dpll_init_info_direct_pins(pf, pin_type);2257	case ICE_DPLL_PIN_TYPE_RCLK_INPUT:2258		return ice_dpll_init_info_rclk_pin(pf);2259	default:2260		return -EINVAL;2261	}2262}2263 2264/**2265 * ice_dpll_deinit_info - release memory allocated for pins info2266 * @pf: board private structure2267 *2268 * Release memory allocated for pins by ice_dpll_init_info function.2269 */2270static void ice_dpll_deinit_info(struct ice_pf *pf)2271{2272	kfree(pf->dplls.inputs);2273	kfree(pf->dplls.outputs);2274	kfree(pf->dplls.eec.input_prio);2275	kfree(pf->dplls.pps.input_prio);2276}2277 2278/**2279 * ice_dpll_init_info - prepare pf's dpll information structure2280 * @pf: board private structure2281 * @cgu: if cgu is present and controlled by this NIC2282 *2283 * Acquire (from HW) and set basic dpll information (on pf->dplls struct).2284 *2285 * Return:2286 * * 0 - success2287 * * negative - init failure reason2288 */2289static int ice_dpll_init_info(struct ice_pf *pf, bool cgu)2290{2291	struct ice_aqc_get_cgu_abilities abilities;2292	struct ice_dpll *de = &pf->dplls.eec;2293	struct ice_dpll *dp = &pf->dplls.pps;2294	struct ice_dplls *d = &pf->dplls;2295	struct ice_hw *hw = &pf->hw;2296	int ret, alloc_size, i;2297 2298	d->clock_id = ice_generate_clock_id(pf);2299	ret = ice_aq_get_cgu_abilities(hw, &abilities);2300	if (ret) {2301		dev_err(ice_pf_to_dev(pf),2302			"err:%d %s failed to read cgu abilities\n",2303			ret, ice_aq_str(hw->adminq.sq_last_status));2304		return ret;2305	}2306 2307	de->dpll_idx = abilities.eec_dpll_idx;2308	dp->dpll_idx = abilities.pps_dpll_idx;2309	d->num_inputs = abilities.num_inputs;2310	d->num_outputs = abilities.num_outputs;2311	d->input_phase_adj_max = le32_to_cpu(abilities.max_in_phase_adj);2312	d->output_phase_adj_max = le32_to_cpu(abilities.max_out_phase_adj);2313 2314	alloc_size = sizeof(*d->inputs) * d->num_inputs;2315	d->inputs = kzalloc(alloc_size, GFP_KERNEL);2316	if (!d->inputs)2317		return -ENOMEM;2318 2319	alloc_size = sizeof(*de->input_prio) * d->num_inputs;2320	de->input_prio = kzalloc(alloc_size, GFP_KERNEL);2321	if (!de->input_prio)2322		return -ENOMEM;2323 2324	dp->input_prio = kzalloc(alloc_size, GFP_KERNEL);2325	if (!dp->input_prio)2326		return -ENOMEM;2327 2328	ret = ice_dpll_init_pins_info(pf, ICE_DPLL_PIN_TYPE_INPUT);2329	if (ret)2330		goto deinit_info;2331 2332	if (cgu) {2333		alloc_size = sizeof(*d->outputs) * d->num_outputs;2334		d->outputs = kzalloc(alloc_size, GFP_KERNEL);2335		if (!d->outputs) {2336			ret = -ENOMEM;2337			goto deinit_info;2338		}2339 2340		ret = ice_dpll_init_pins_info(pf, ICE_DPLL_PIN_TYPE_OUTPUT);2341		if (ret)2342			goto deinit_info;2343	}2344 2345	ret = ice_get_cgu_rclk_pin_info(&pf->hw, &d->base_rclk_idx,2346					&pf->dplls.rclk.num_parents);2347	if (ret)2348		return ret;2349	for (i = 0; i < pf->dplls.rclk.num_parents; i++)2350		pf->dplls.rclk.parent_idx[i] = d->base_rclk_idx + i;2351	ret = ice_dpll_init_pins_info(pf, ICE_DPLL_PIN_TYPE_RCLK_INPUT);2352	if (ret)2353		return ret;2354	de->mode = DPLL_MODE_AUTOMATIC;2355	dp->mode = DPLL_MODE_AUTOMATIC;2356 2357	dev_dbg(ice_pf_to_dev(pf),2358		"%s - success, inputs:%u, outputs:%u rclk-parents:%u\n",2359		__func__, d->num_inputs, d->num_outputs, d->rclk.num_parents);2360 2361	return 0;2362 2363deinit_info:2364	dev_err(ice_pf_to_dev(pf),2365		"%s - fail: d->inputs:%p, de->input_prio:%p, dp->input_prio:%p, d->outputs:%p\n",2366		__func__, d->inputs, de->input_prio,2367		dp->input_prio, d->outputs);2368	ice_dpll_deinit_info(pf);2369	return ret;2370}2371 2372/**2373 * ice_dpll_deinit - Disable the driver/HW support for dpll subsystem2374 * the dpll device.2375 * @pf: board private structure2376 *2377 * Handles the cleanup work required after dpll initialization, freeing2378 * resources and unregistering the dpll, pin and all resources used for2379 * handling them.2380 *2381 * Context: Destroys pf->dplls.lock mutex. Call only if ICE_FLAG_DPLL was set.2382 */2383void ice_dpll_deinit(struct ice_pf *pf)2384{2385	bool cgu = ice_is_feature_supported(pf, ICE_F_CGU);2386 2387	clear_bit(ICE_FLAG_DPLL, pf->flags);2388	if (cgu)2389		ice_dpll_deinit_worker(pf);2390 2391	ice_dpll_deinit_pins(pf, cgu);2392	ice_dpll_deinit_dpll(pf, &pf->dplls.pps, cgu);2393	ice_dpll_deinit_dpll(pf, &pf->dplls.eec, cgu);2394	ice_dpll_deinit_info(pf);2395	mutex_destroy(&pf->dplls.lock);2396}2397 2398/**2399 * ice_dpll_init - initialize support for dpll subsystem2400 * @pf: board private structure2401 *2402 * Set up the device dplls, register them and pins connected within Linux dpll2403 * subsystem. Allow userspace to obtain state of DPLL and handling of DPLL2404 * configuration requests.2405 *2406 * Context: Initializes pf->dplls.lock mutex.2407 */2408void ice_dpll_init(struct ice_pf *pf)2409{2410	bool cgu = ice_is_feature_supported(pf, ICE_F_CGU);2411	struct ice_dplls *d = &pf->dplls;2412	int err = 0;2413 2414	mutex_init(&d->lock);2415	err = ice_dpll_init_info(pf, cgu);2416	if (err)2417		goto err_exit;2418	err = ice_dpll_init_dpll(pf, &pf->dplls.eec, cgu, DPLL_TYPE_EEC);2419	if (err)2420		goto deinit_info;2421	err = ice_dpll_init_dpll(pf, &pf->dplls.pps, cgu, DPLL_TYPE_PPS);2422	if (err)2423		goto deinit_eec;2424	err = ice_dpll_init_pins(pf, cgu);2425	if (err)2426		goto deinit_pps;2427	if (cgu) {2428		err = ice_dpll_init_worker(pf);2429		if (err)2430			goto deinit_pins;2431	}2432	set_bit(ICE_FLAG_DPLL, pf->flags);2433 2434	return;2435 2436deinit_pins:2437	ice_dpll_deinit_pins(pf, cgu);2438deinit_pps:2439	ice_dpll_deinit_dpll(pf, &pf->dplls.pps, cgu);2440deinit_eec:2441	ice_dpll_deinit_dpll(pf, &pf->dplls.eec, cgu);2442deinit_info:2443	ice_dpll_deinit_info(pf);2444err_exit:2445	mutex_destroy(&d->lock);2446	dev_warn(ice_pf_to_dev(pf), "DPLLs init failure err:%d\n", err);2447}2448