mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-12-27 12:21:22 -05:00
Expand the zl3073x_ref structure to cache all reference-related hardware registers, including frequency components, embedded-sync settings and phase compensation. Previously, these registers were read on-demand from various functions in dpll.c leading to frequent mailbox operations. Modify zl3073x_ref_state_fetch() to read and populate all these new fields at once. Refactor all "getter" functions in dpll.c to read from this new cached state instead of performing direct register access. Remove the standalone zl3073x_dpll_input_ref_frequency_get() helper, as its functionality is now replaced by zl3073x_ref_freq_get() which operates on the cached state and add a corresponding zl3073x_dev_... wrapper. Introduce a new function, zl3073x_ref_state_set(), to handle writing changes back to the hardware. This function compares the provided state with the current cached state and writes *only* the modified register values to the device via a single mailbox sequence before updating the local cache. Refactor all dpll "setter" functions to modify a local copy of the ref state and then call zl3073x_ref_state_set() to commit the changes. As a cleanup, update callers in dpll.c that already have a struct zl3073x_ref * to use the direct helpers instead of the zl3073x_dev_... wrappers. This change centralizes all reference-related register I/O into ref.c, significantly reduces bus traffic, and simplifies the logic in dpll.c. Reviewed-by: Petr Oros <poros@redhat.com> Tested-by: Prathosh Satish <Prathosh.Satish@microchip.com> Signed-off-by: Ivan Vecera <ivecera@redhat.com> Link: https://patch.msgid.link/20251113074105.141379-5-ivecera@redhat.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
135 lines
3.1 KiB
C
135 lines
3.1 KiB
C
/* SPDX-License-Identifier: GPL-2.0-only */
|
|
|
|
#ifndef _ZL3073X_REF_H
|
|
#define _ZL3073X_REF_H
|
|
|
|
#include <linux/bitfield.h>
|
|
#include <linux/math64.h>
|
|
#include <linux/types.h>
|
|
|
|
#include "regs.h"
|
|
|
|
struct zl3073x_dev;
|
|
|
|
/**
|
|
* struct zl3073x_ref - input reference state
|
|
* @ffo: current fractional frequency offset
|
|
* @phase_comp: phase compensation
|
|
* @esync_n_div: divisor for embedded sync or n-divided signal formats
|
|
* @freq_base: frequency base
|
|
* @freq_mult: frequnecy multiplier
|
|
* @freq_ratio_m: FEC mode multiplier
|
|
* @freq_ratio_n: FEC mode divisor
|
|
* @config: reference config
|
|
* @sync_ctrl: reference sync control
|
|
* @mon_status: reference monitor status
|
|
*/
|
|
struct zl3073x_ref {
|
|
s64 ffo;
|
|
u64 phase_comp;
|
|
u32 esync_n_div;
|
|
u16 freq_base;
|
|
u16 freq_mult;
|
|
u16 freq_ratio_m;
|
|
u16 freq_ratio_n;
|
|
u8 config;
|
|
u8 sync_ctrl;
|
|
u8 mon_status;
|
|
};
|
|
|
|
int zl3073x_ref_state_fetch(struct zl3073x_dev *zldev, u8 index);
|
|
|
|
const struct zl3073x_ref *zl3073x_ref_state_get(struct zl3073x_dev *zldev,
|
|
u8 index);
|
|
|
|
int zl3073x_ref_state_set(struct zl3073x_dev *zldev, u8 index,
|
|
const struct zl3073x_ref *ref);
|
|
|
|
int zl3073x_ref_freq_factorize(u32 freq, u16 *base, u16 *mult);
|
|
|
|
/**
|
|
* zl3073x_ref_ffo_get - get current fractional frequency offset
|
|
* @ref: pointer to ref state
|
|
*
|
|
* Return: the latest measured fractional frequency offset
|
|
*/
|
|
static inline s64
|
|
zl3073x_ref_ffo_get(const struct zl3073x_ref *ref)
|
|
{
|
|
return ref->ffo;
|
|
}
|
|
|
|
/**
|
|
* zl3073x_ref_freq_get - get given input reference frequency
|
|
* @ref: pointer to ref state
|
|
*
|
|
* Return: frequency of the given input reference
|
|
*/
|
|
static inline u32
|
|
zl3073x_ref_freq_get(const struct zl3073x_ref *ref)
|
|
{
|
|
return mul_u64_u32_div(ref->freq_base * ref->freq_mult,
|
|
ref->freq_ratio_m, ref->freq_ratio_n);
|
|
}
|
|
|
|
/**
|
|
* zl3073x_ref_freq_set - set given input reference frequency
|
|
* @ref: pointer to ref state
|
|
* @freq: frequency to be set
|
|
*
|
|
* Return: 0 on success, <0 when frequency cannot be factorized
|
|
*/
|
|
static inline int
|
|
zl3073x_ref_freq_set(struct zl3073x_ref *ref, u32 freq)
|
|
{
|
|
u16 base, mult;
|
|
int rc;
|
|
|
|
rc = zl3073x_ref_freq_factorize(freq, &base, &mult);
|
|
if (rc)
|
|
return rc;
|
|
|
|
ref->freq_base = base;
|
|
ref->freq_mult = mult;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* zl3073x_ref_is_diff - check if the given input reference is differential
|
|
* @ref: pointer to ref state
|
|
*
|
|
* Return: true if reference is differential, false if reference is single-ended
|
|
*/
|
|
static inline bool
|
|
zl3073x_ref_is_diff(const struct zl3073x_ref *ref)
|
|
{
|
|
return !!FIELD_GET(ZL_REF_CONFIG_DIFF_EN, ref->config);
|
|
}
|
|
|
|
/**
|
|
* zl3073x_ref_is_enabled - check if the given input reference is enabled
|
|
* @ref: pointer to ref state
|
|
*
|
|
* Return: true if input refernce is enabled, false otherwise
|
|
*/
|
|
static inline bool
|
|
zl3073x_ref_is_enabled(const struct zl3073x_ref *ref)
|
|
{
|
|
return !!FIELD_GET(ZL_REF_CONFIG_ENABLE, ref->config);
|
|
}
|
|
|
|
/**
|
|
* zl3073x_ref_is_status_ok - check the given input reference status
|
|
* @ref: pointer to ref state
|
|
*
|
|
* Return: true if the status is ok, false otherwise
|
|
*/
|
|
static inline bool
|
|
zl3073x_ref_is_status_ok(const struct zl3073x_ref *ref)
|
|
{
|
|
return ref->mon_status == ZL_REF_MON_STATUS_OK;
|
|
}
|
|
|
|
#endif /* _ZL3073X_REF_H */
|