1 /* SPDX-License-Identifier: GPL-2.0-only */ 2 3 #ifndef _ZL3073X_REF_H 4 #define _ZL3073X_REF_H 5 6 #include <linux/bitfield.h> 7 #include <linux/math64.h> 8 #include <linux/stddef.h> 9 #include <linux/types.h> 10 11 #include "regs.h" 12 13 struct zl3073x_dev; 14 15 /** 16 * struct zl3073x_ref - input reference state 17 * @phase_comp: phase compensation 18 * @esync_n_div: divisor for embedded sync or n-divided signal formats 19 * @freq_base: frequency base 20 * @freq_mult: frequnecy multiplier 21 * @freq_ratio_m: FEC mode multiplier 22 * @freq_ratio_n: FEC mode divisor 23 * @sync_ctrl: reference sync control 24 * @config: reference config 25 * @ffo: current fractional frequency offset 26 * @mon_status: reference monitor status 27 */ 28 struct zl3073x_ref { 29 struct_group(cfg, /* Configuration */ 30 u64 phase_comp; 31 u32 esync_n_div; 32 u16 freq_base; 33 u16 freq_mult; 34 u16 freq_ratio_m; 35 u16 freq_ratio_n; 36 u8 sync_ctrl; 37 ); 38 struct_group(inv, /* Invariants */ 39 u8 config; 40 ); 41 struct_group(stat, /* Status */ 42 s64 ffo; 43 u8 mon_status; 44 ); 45 }; 46 47 int zl3073x_ref_state_fetch(struct zl3073x_dev *zldev, u8 index); 48 49 const struct zl3073x_ref *zl3073x_ref_state_get(struct zl3073x_dev *zldev, 50 u8 index); 51 52 int zl3073x_ref_state_set(struct zl3073x_dev *zldev, u8 index, 53 const struct zl3073x_ref *ref); 54 55 int zl3073x_ref_state_update(struct zl3073x_dev *zldev, u8 index); 56 57 int zl3073x_ref_freq_factorize(u32 freq, u16 *base, u16 *mult); 58 59 /** 60 * zl3073x_ref_ffo_get - get current fractional frequency offset 61 * @ref: pointer to ref state 62 * 63 * Return: the latest measured fractional frequency offset 64 */ 65 static inline s64 66 zl3073x_ref_ffo_get(const struct zl3073x_ref *ref) 67 { 68 return ref->ffo; 69 } 70 71 /** 72 * zl3073x_ref_freq_get - get given input reference frequency 73 * @ref: pointer to ref state 74 * 75 * Return: frequency of the given input reference 76 */ 77 static inline u32 78 zl3073x_ref_freq_get(const struct zl3073x_ref *ref) 79 { 80 return mul_u64_u32_div(ref->freq_base * ref->freq_mult, 81 ref->freq_ratio_m, ref->freq_ratio_n); 82 } 83 84 /** 85 * zl3073x_ref_freq_set - set given input reference frequency 86 * @ref: pointer to ref state 87 * @freq: frequency to be set 88 * 89 * Return: 0 on success, <0 when frequency cannot be factorized 90 */ 91 static inline int 92 zl3073x_ref_freq_set(struct zl3073x_ref *ref, u32 freq) 93 { 94 u16 base, mult; 95 int rc; 96 97 rc = zl3073x_ref_freq_factorize(freq, &base, &mult); 98 if (rc) 99 return rc; 100 101 ref->freq_base = base; 102 ref->freq_mult = mult; 103 ref->freq_ratio_m = 1; 104 ref->freq_ratio_n = 1; 105 106 return 0; 107 } 108 109 /** 110 * zl3073x_ref_is_diff - check if the given input reference is differential 111 * @ref: pointer to ref state 112 * 113 * Return: true if reference is differential, false if reference is single-ended 114 */ 115 static inline bool 116 zl3073x_ref_is_diff(const struct zl3073x_ref *ref) 117 { 118 return !!FIELD_GET(ZL_REF_CONFIG_DIFF_EN, ref->config); 119 } 120 121 /** 122 * zl3073x_ref_is_enabled - check if the given input reference is enabled 123 * @ref: pointer to ref state 124 * 125 * Return: true if input refernce is enabled, false otherwise 126 */ 127 static inline bool 128 zl3073x_ref_is_enabled(const struct zl3073x_ref *ref) 129 { 130 return !!FIELD_GET(ZL_REF_CONFIG_ENABLE, ref->config); 131 } 132 133 /** 134 * zl3073x_ref_is_status_ok - check the given input reference status 135 * @ref: pointer to ref state 136 * 137 * Return: true if the status is ok, false otherwise 138 */ 139 static inline bool 140 zl3073x_ref_is_status_ok(const struct zl3073x_ref *ref) 141 { 142 return ref->mon_status == ZL_REF_MON_STATUS_OK; 143 } 144 145 #endif /* _ZL3073X_REF_H */ 146