Commit 055a01b2 authored by Ivan Vecera's avatar Ivan Vecera Committed by Jakub Kicinski
Browse files

dpll: zl3073x: Specify phase adjustment granularity for pins



Output pins phase adjustment values in the device are expressed
in half synth clock cycles. Use this number of cycles as output
pins' phase adjust granularity and simplify both get/set callbacks.

Reviewed-by: default avatarMichal Schmidt <mschmidt@redhat.com>
Reviewed-by: default avatarPetr Oros <poros@redhat.com>
Tested-by: default avatarPrathosh Satish <Prathosh.Satish@microchip.com>
Signed-off-by: default avatarIvan Vecera <ivecera@redhat.com>
Reviewed-by: default avatarArkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
Link: https://patch.msgid.link/20251029153207.178448-3-ivecera@redhat.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 30176bf7
Loading
Loading
Loading
Loading
+14 −44
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@
 * @prio: pin priority <0, 14>
 * @selectable: pin is selectable in automatic mode
 * @esync_control: embedded sync is controllable
 * @phase_gran: phase adjustment granularity
 * @pin_state: last saved pin state
 * @phase_offset: last saved pin phase offset
 * @freq_offset: last saved fractional frequency offset
@@ -49,6 +50,7 @@ struct zl3073x_dpll_pin {
	u8			prio;
	bool			selectable;
	bool			esync_control;
	s32			phase_gran;
	enum dpll_pin_state	pin_state;
	s64			phase_offset;
	s64			freq_offset;
@@ -1388,25 +1390,14 @@ zl3073x_dpll_output_pin_phase_adjust_get(const struct dpll_pin *dpll_pin,
	struct zl3073x_dpll *zldpll = dpll_priv;
	struct zl3073x_dev *zldev = zldpll->dev;
	struct zl3073x_dpll_pin *pin = pin_priv;
	u32 synth_freq;
	s32 phase_comp;
	u8 out, synth;
	u8 out;
	int rc;

	out = zl3073x_output_pin_out_get(pin->id);
	synth = zl3073x_out_synth_get(zldev, out);
	synth_freq = zl3073x_synth_freq_get(zldev, synth);

	/* Check synth freq for zero */
	if (!synth_freq) {
		dev_err(zldev->dev, "Got zero synth frequency for output %u\n",
			out);
		return -EINVAL;
	}

	guard(mutex)(&zldev->multiop_lock);

	/* Read output configuration */
	out = zl3073x_output_pin_out_get(pin->id);
	rc = zl3073x_mb_op(zldev, ZL_REG_OUTPUT_MB_SEM, ZL_OUTPUT_MB_SEM_RD,
			   ZL_REG_OUTPUT_MB_MASK, BIT(out));
	if (rc)
@@ -1417,11 +1408,10 @@ zl3073x_dpll_output_pin_phase_adjust_get(const struct dpll_pin *dpll_pin,
	if (rc)
		return rc;

	/* Value in register is expressed in half synth clock cycles */
	phase_comp *= (int)div_u64(PSEC_PER_SEC, 2 * synth_freq);

	/* Reverse two's complement negation applied during 'set' */
	*phase_adjust = -phase_comp;
	/* Convert value to ps and reverse two's complement negation applied
	 * during 'set'
	 */
	*phase_adjust = -phase_comp * pin->phase_gran;

	return rc;
}
@@ -1437,39 +1427,18 @@ zl3073x_dpll_output_pin_phase_adjust_set(const struct dpll_pin *dpll_pin,
	struct zl3073x_dpll *zldpll = dpll_priv;
	struct zl3073x_dev *zldev = zldpll->dev;
	struct zl3073x_dpll_pin *pin = pin_priv;
	int half_synth_cycle;
	u32 synth_freq;
	u8 out, synth;
	u8 out;
	int rc;

	/* Get attached synth */
	out = zl3073x_output_pin_out_get(pin->id);
	synth = zl3073x_out_synth_get(zldev, out);

	/* Get synth's frequency */
	synth_freq = zl3073x_synth_freq_get(zldev, synth);

	/* Value in register is expressed in half synth clock cycles so
	 * the given phase adjustment a multiple of half synth clock.
	 */
	half_synth_cycle = (int)div_u64(PSEC_PER_SEC, 2 * synth_freq);

	if ((phase_adjust % half_synth_cycle) != 0) {
		NL_SET_ERR_MSG_FMT(extack,
				   "Phase adjustment value has to be multiple of %d",
				   half_synth_cycle);
		return -EINVAL;
	}
	phase_adjust /= half_synth_cycle;

	/* The value in the register is stored as two's complement negation
	 * of requested value.
	 * of requested value and expressed in half synth clock cycles.
	 */
	phase_adjust = -phase_adjust;
	phase_adjust = -phase_adjust / pin->phase_gran;

	guard(mutex)(&zldev->multiop_lock);

	/* Read output configuration */
	out = zl3073x_output_pin_out_get(pin->id);
	rc = zl3073x_mb_op(zldev, ZL_REG_OUTPUT_MB_SEM, ZL_OUTPUT_MB_SEM_RD,
			   ZL_REG_OUTPUT_MB_MASK, BIT(out));
	if (rc)
@@ -1758,9 +1727,10 @@ zl3073x_dpll_pin_register(struct zl3073x_dpll_pin *pin, u32 index)
	if (IS_ERR(props))
		return PTR_ERR(props);

	/* Save package label & esync capability */
	/* Save package label, esync capability and phase adjust granularity */
	strscpy(pin->label, props->package_label);
	pin->esync_control = props->esync_control;
	pin->phase_gran = props->dpll_props.phase_gran;

	if (zl3073x_dpll_is_input_pin(pin)) {
		rc = zl3073x_dpll_ref_prio_get(pin, &pin->prio);
+11 −0
Original line number Diff line number Diff line
@@ -208,7 +208,18 @@ struct zl3073x_pin_props *zl3073x_pin_props_get(struct zl3073x_dev *zldev,
			DPLL_PIN_CAPABILITIES_PRIORITY_CAN_CHANGE |
			DPLL_PIN_CAPABILITIES_STATE_CAN_CHANGE;
	} else {
		u8 out, synth;
		u32 f;

		props->dpll_props.type = DPLL_PIN_TYPE_GNSS;

		/* The output pin phase adjustment granularity equals half of
		 * the synth frequency count.
		 */
		out = zl3073x_output_pin_out_get(index);
		synth = zl3073x_out_synth_get(zldev, out);
		f = 2 * zl3073x_synth_freq_get(zldev, synth);
		props->dpll_props.phase_gran = f ? div_u64(PSEC_PER_SEC, f) : 1;
	}

	props->dpll_props.phase_range.min = S32_MIN;