mirror of
https://github.com/torvalds/linux.git
synced 2026-08-01 20:22:08 +02:00
ice: add ref-sync dpll pins
Implement reference sync input pin get/set callbacks, allow user space control over dpll pin pairs capable of reference sync support. Reviewed-by: Milena Olech <milena.olech@intel.com> Signed-off-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com> Link: https://patch.msgid.link/20250626135219.1769350-4-arkadiusz.kubalewski@intel.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
58256a26bf
commit
5bcea24133
|
|
@ -2304,6 +2304,8 @@ struct ice_aqc_get_cgu_abilities {
|
|||
u8 rsvd[3];
|
||||
};
|
||||
|
||||
#define ICE_AQC_CGU_IN_CFG_FLG2_REFSYNC_EN BIT(7)
|
||||
|
||||
/* Set CGU input config (direct 0x0C62) */
|
||||
struct ice_aqc_set_cgu_input_config {
|
||||
u8 input_idx;
|
||||
|
|
|
|||
|
|
@ -36,6 +36,19 @@
|
|||
#define ICE_DPLL_PIN_SW_2_OUTPUT_ABS_IDX \
|
||||
(ICE_DPLL_PIN_SW_OUTPUT_ABS(ICE_DPLL_PIN_SW_2_IDX))
|
||||
|
||||
#define ICE_SR_PFA_DPLL_DEFAULTS 0x152
|
||||
#define ICE_DPLL_PFA_REF_SYNC_TYPE 0x2420
|
||||
#define ICE_DPLL_PFA_REF_SYNC_TYPE2 0x2424
|
||||
#define ICE_DPLL_PFA_END 0xFFFF
|
||||
#define ICE_DPLL_PFA_HEADER_LEN 4
|
||||
#define ICE_DPLL_PFA_ENTRY_LEN 3
|
||||
#define ICE_DPLL_PFA_MAILBOX_REF_SYNC_PIN_S 4
|
||||
#define ICE_DPLL_PFA_MASK_OFFSET 1
|
||||
#define ICE_DPLL_PFA_VALUE_OFFSET 2
|
||||
|
||||
#define ICE_DPLL_E810C_SFP_NC_PINS 2
|
||||
#define ICE_DPLL_E810C_SFP_NC_START 4
|
||||
|
||||
/**
|
||||
* enum ice_dpll_pin_type - enumerate ice pin types:
|
||||
* @ICE_DPLL_PIN_INVALID: invalid pin type
|
||||
|
|
@ -2107,6 +2120,149 @@ ice_dpll_sw_esync_get(const struct dpll_pin *pin, void *pin_priv,
|
|||
extack);
|
||||
}
|
||||
|
||||
/*
|
||||
* ice_dpll_input_ref_sync_set - callback for setting reference sync feature
|
||||
* @pin: pointer to a pin
|
||||
* @pin_priv: private data pointer passed on pin registration
|
||||
* @ref_pin: pin pointer for reference sync pair
|
||||
* @ref_pin_priv: private data pointer of ref_pin
|
||||
* @state: requested state for reference sync for pin pair
|
||||
* @extack: error reporting
|
||||
*
|
||||
* Dpll subsystem callback. Handler for setting reference sync frequency
|
||||
* feature for input pin.
|
||||
*
|
||||
* Context: Acquires and releases pf->dplls.lock
|
||||
* Return:
|
||||
* * 0 - success
|
||||
* * negative - error
|
||||
*/
|
||||
static int
|
||||
ice_dpll_input_ref_sync_set(const struct dpll_pin *pin, void *pin_priv,
|
||||
const struct dpll_pin *ref_pin, void *ref_pin_priv,
|
||||
const enum dpll_pin_state state,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct ice_dpll_pin *p = pin_priv;
|
||||
struct ice_pf *pf = p->pf;
|
||||
u8 flags_en = 0;
|
||||
int ret;
|
||||
|
||||
if (ice_dpll_is_reset(pf, extack))
|
||||
return -EBUSY;
|
||||
mutex_lock(&pf->dplls.lock);
|
||||
|
||||
if (p->flags[0] & ICE_AQC_GET_CGU_IN_CFG_FLG2_INPUT_EN)
|
||||
flags_en = ICE_AQC_SET_CGU_IN_CFG_FLG2_INPUT_EN;
|
||||
if (state == DPLL_PIN_STATE_CONNECTED)
|
||||
flags_en |= ICE_AQC_CGU_IN_CFG_FLG2_REFSYNC_EN;
|
||||
ret = ice_aq_set_input_pin_cfg(&pf->hw, p->idx, 0, flags_en, 0, 0);
|
||||
if (!ret)
|
||||
ret = ice_dpll_pin_state_update(pf, p, ICE_DPLL_PIN_TYPE_INPUT,
|
||||
extack);
|
||||
mutex_unlock(&pf->dplls.lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_dpll_input_ref_sync_get - callback for getting reference sync config
|
||||
* @pin: pointer to a pin
|
||||
* @pin_priv: private data pointer passed on pin registration
|
||||
* @ref_pin: pin pointer for reference sync pair
|
||||
* @ref_pin_priv: private data pointer of ref_pin
|
||||
* @state: on success holds reference sync state for pin pair
|
||||
* @extack: error reporting
|
||||
*
|
||||
* Dpll subsystem callback. Handler for setting reference sync frequency
|
||||
* feature for input pin.
|
||||
*
|
||||
* Context: Acquires and releases pf->dplls.lock
|
||||
* Return:
|
||||
* * 0 - success
|
||||
* * negative - error
|
||||
*/
|
||||
static int
|
||||
ice_dpll_input_ref_sync_get(const struct dpll_pin *pin, void *pin_priv,
|
||||
const struct dpll_pin *ref_pin, void *ref_pin_priv,
|
||||
enum dpll_pin_state *state,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct ice_dpll_pin *p = pin_priv;
|
||||
struct ice_pf *pf = p->pf;
|
||||
|
||||
if (ice_dpll_is_reset(pf, extack))
|
||||
return -EBUSY;
|
||||
mutex_lock(&pf->dplls.lock);
|
||||
if (p->flags[0] & ICE_AQC_CGU_IN_CFG_FLG2_REFSYNC_EN)
|
||||
*state = DPLL_PIN_STATE_CONNECTED;
|
||||
else
|
||||
*state = DPLL_PIN_STATE_DISCONNECTED;
|
||||
mutex_unlock(&pf->dplls.lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* ice_dpll_sw_input_ref_sync_set - callback for setting reference sync feature
|
||||
* @pin: pointer to a pin
|
||||
* @pin_priv: private data pointer passed on pin registration
|
||||
* @ref_pin: pin pointer for reference sync pair
|
||||
* @ref_pin_priv: private data pointer of ref_pin
|
||||
* @state: requested state for reference sync for pin pair
|
||||
* @extack: error reporting
|
||||
*
|
||||
* Dpll subsystem callback. Handler for setting reference sync
|
||||
* feature for input pins.
|
||||
*
|
||||
* Context: Calls a function which acquires and releases pf->dplls.lock
|
||||
* Return:
|
||||
* * 0 - success
|
||||
* * negative - error
|
||||
*/
|
||||
static int
|
||||
ice_dpll_sw_input_ref_sync_set(const struct dpll_pin *pin, void *pin_priv,
|
||||
const struct dpll_pin *ref_pin,
|
||||
void *ref_pin_priv,
|
||||
const enum dpll_pin_state state,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct ice_dpll_pin *p = pin_priv;
|
||||
|
||||
return ice_dpll_input_ref_sync_set(pin, p->input, ref_pin, ref_pin_priv,
|
||||
state, extack);
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_dpll_sw_input_ref_sync_get - callback for getting reference sync config
|
||||
* @pin: pointer to a pin
|
||||
* @pin_priv: private data pointer passed on pin registration
|
||||
* @ref_pin: pin pointer for reference sync pair
|
||||
* @ref_pin_priv: private data pointer of ref_pin
|
||||
* @state: on success holds reference sync state for pin pair
|
||||
* @extack: error reporting
|
||||
*
|
||||
* Dpll subsystem callback. Handler for setting reference sync feature for
|
||||
* input pins.
|
||||
*
|
||||
* Context: Calls a function which acquires and releases pf->dplls.lock
|
||||
* Return:
|
||||
* * 0 - success
|
||||
* * negative - error
|
||||
*/
|
||||
static int
|
||||
ice_dpll_sw_input_ref_sync_get(const struct dpll_pin *pin, void *pin_priv,
|
||||
const struct dpll_pin *ref_pin,
|
||||
void *ref_pin_priv,
|
||||
enum dpll_pin_state *state,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct ice_dpll_pin *p = pin_priv;
|
||||
|
||||
return ice_dpll_input_ref_sync_get(pin, p->input, ref_pin, ref_pin_priv,
|
||||
state, extack);
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_dpll_rclk_state_on_pin_set - set a state on rclk pin
|
||||
* @pin: pointer to a pin
|
||||
|
|
@ -2234,6 +2390,8 @@ static const struct dpll_pin_ops ice_dpll_pin_sma_ops = {
|
|||
.phase_offset_get = ice_dpll_phase_offset_get,
|
||||
.esync_set = ice_dpll_sw_esync_set,
|
||||
.esync_get = ice_dpll_sw_esync_get,
|
||||
.ref_sync_set = ice_dpll_sw_input_ref_sync_set,
|
||||
.ref_sync_get = ice_dpll_sw_input_ref_sync_get,
|
||||
};
|
||||
|
||||
static const struct dpll_pin_ops ice_dpll_pin_ufl_ops = {
|
||||
|
|
@ -2262,6 +2420,8 @@ static const struct dpll_pin_ops ice_dpll_input_ops = {
|
|||
.phase_offset_get = ice_dpll_phase_offset_get,
|
||||
.esync_set = ice_dpll_input_esync_set,
|
||||
.esync_get = ice_dpll_input_esync_get,
|
||||
.ref_sync_set = ice_dpll_input_ref_sync_set,
|
||||
.ref_sync_get = ice_dpll_input_ref_sync_get,
|
||||
};
|
||||
|
||||
static const struct dpll_pin_ops ice_dpll_output_ops = {
|
||||
|
|
@ -2560,6 +2720,88 @@ static void ice_dpll_periodic_work(struct kthread_work *work)
|
|||
msecs_to_jiffies(500));
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_dpll_init_ref_sync_inputs - initialize reference sync pin pairs
|
||||
* @pf: pf private structure
|
||||
*
|
||||
* Read DPLL TLV capabilities and initialize reference sync pin pairs in
|
||||
* dpll subsystem.
|
||||
*
|
||||
* Return:
|
||||
* * 0 - success or nothing to do (no ref-sync tlv are present)
|
||||
* * negative - AQ failure
|
||||
*/
|
||||
static int ice_dpll_init_ref_sync_inputs(struct ice_pf *pf)
|
||||
{
|
||||
struct ice_dpll_pin *inputs = pf->dplls.inputs;
|
||||
struct ice_hw *hw = &pf->hw;
|
||||
u16 addr, len, end, hdr;
|
||||
int ret;
|
||||
|
||||
ret = ice_get_pfa_module_tlv(hw, &hdr, &len, ICE_SR_PFA_DPLL_DEFAULTS);
|
||||
if (ret) {
|
||||
dev_err(ice_pf_to_dev(pf),
|
||||
"Failed to read PFA dpll defaults TLV ret=%d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
end = hdr + len;
|
||||
|
||||
for (addr = hdr + ICE_DPLL_PFA_HEADER_LEN; addr < end;
|
||||
addr += ICE_DPLL_PFA_ENTRY_LEN) {
|
||||
unsigned long bit, ul_mask, offset;
|
||||
u16 pin, mask, buf;
|
||||
bool valid = false;
|
||||
|
||||
ret = ice_read_sr_word(hw, addr, &buf);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
switch (buf) {
|
||||
case ICE_DPLL_PFA_REF_SYNC_TYPE:
|
||||
case ICE_DPLL_PFA_REF_SYNC_TYPE2:
|
||||
{
|
||||
u16 mask_addr = addr + ICE_DPLL_PFA_MASK_OFFSET;
|
||||
u16 val_addr = addr + ICE_DPLL_PFA_VALUE_OFFSET;
|
||||
|
||||
ret = ice_read_sr_word(hw, mask_addr, &mask);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = ice_read_sr_word(hw, val_addr, &pin);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (buf == ICE_DPLL_PFA_REF_SYNC_TYPE)
|
||||
pin >>= ICE_DPLL_PFA_MAILBOX_REF_SYNC_PIN_S;
|
||||
valid = true;
|
||||
break;
|
||||
}
|
||||
case ICE_DPLL_PFA_END:
|
||||
addr = end;
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
if (!valid)
|
||||
continue;
|
||||
|
||||
ul_mask = mask;
|
||||
offset = 0;
|
||||
for_each_set_bit(bit, &ul_mask, BITS_PER_TYPE(u16)) {
|
||||
int i, j;
|
||||
|
||||
if (hw->device_id == ICE_DEV_ID_E810C_SFP &&
|
||||
pin > ICE_DPLL_E810C_SFP_NC_START)
|
||||
offset = -ICE_DPLL_E810C_SFP_NC_PINS;
|
||||
i = pin + offset;
|
||||
j = bit + offset;
|
||||
if (i < 0 || j < 0)
|
||||
return -ERANGE;
|
||||
inputs[i].ref_sync = j;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_dpll_release_pins - release pins resources from dpll subsystem
|
||||
* @pins: pointer to pins array
|
||||
|
|
@ -2634,6 +2876,36 @@ ice_dpll_unregister_pins(struct dpll_device *dpll, struct ice_dpll_pin *pins,
|
|||
dpll_pin_unregister(dpll, pins[i].pin, ops, &pins[i]);
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_dpll_pin_ref_sync_register - register reference sync pins
|
||||
* @pins: pointer to pins array
|
||||
* @count: number of pins
|
||||
*
|
||||
* Register reference sync pins in dpll subsystem.
|
||||
*
|
||||
* Return:
|
||||
* * 0 - success
|
||||
* * negative - registration failure reason
|
||||
*/
|
||||
static int
|
||||
ice_dpll_pin_ref_sync_register(struct ice_dpll_pin *pins, int count)
|
||||
{
|
||||
int ret, i;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
if (!pins[i].hidden && pins[i].ref_sync) {
|
||||
int j = pins[i].ref_sync;
|
||||
|
||||
ret = dpll_pin_ref_sync_pair_add(pins[i].pin,
|
||||
pins[j].pin);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_dpll_register_pins - register pins with a dpll
|
||||
* @dpll: dpll pointer to register pins with
|
||||
|
|
@ -2922,6 +3194,14 @@ static int ice_dpll_init_pins(struct ice_pf *pf, bool cgu)
|
|||
goto deinit_sma;
|
||||
count += ICE_DPLL_PIN_SW_NUM;
|
||||
}
|
||||
ret = ice_dpll_pin_ref_sync_register(pf->dplls.inputs,
|
||||
pf->dplls.num_inputs);
|
||||
if (ret)
|
||||
goto deinit_ufl;
|
||||
ret = ice_dpll_pin_ref_sync_register(pf->dplls.sma,
|
||||
ICE_DPLL_PIN_SW_NUM);
|
||||
if (ret)
|
||||
goto deinit_ufl;
|
||||
} else {
|
||||
count += pf->dplls.num_outputs + 2 * ICE_DPLL_PIN_SW_NUM;
|
||||
}
|
||||
|
|
@ -3219,6 +3499,8 @@ ice_dpll_init_info_direct_pins(struct ice_pf *pf,
|
|||
pins[i].prop.freq_supported_num = freq_supp_num;
|
||||
pins[i].pf = pf;
|
||||
}
|
||||
if (input)
|
||||
ret = ice_dpll_init_ref_sync_inputs(pf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -3284,6 +3566,8 @@ static int ice_dpll_init_info_sw_pins(struct ice_pf *pf)
|
|||
pin->pf = pf;
|
||||
pin->prop.board_label = ice_dpll_sw_pin_sma[i];
|
||||
pin->input = &d->inputs[pin_abs_idx];
|
||||
if (pin->input->ref_sync)
|
||||
pin->ref_sync = pin->input->ref_sync - pin_abs_idx;
|
||||
pin->output = &d->outputs[ICE_DPLL_PIN_SW_OUTPUT_ABS(i)];
|
||||
ice_dpll_phase_range_set(&pin->prop.phase_range, phase_adj_max);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ enum ice_dpll_pin_sw {
|
|||
* @freq: current frequency of a pin
|
||||
* @phase_adjust: current phase adjust value
|
||||
* @phase_offset: monitored phase offset value
|
||||
* @ref_sync: store id of reference sync pin
|
||||
*/
|
||||
struct ice_dpll_pin {
|
||||
struct dpll_pin *pin;
|
||||
|
|
@ -49,6 +50,7 @@ struct ice_dpll_pin {
|
|||
enum dpll_pin_direction direction;
|
||||
s64 phase_offset;
|
||||
u8 status;
|
||||
u8 ref_sync;
|
||||
bool active;
|
||||
bool hidden;
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user