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