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 * @meas_freq: measured input frequency in Hz 27 * @mon_status: reference monitor status 28 */ 29 struct zl3073x_ref { 30 struct_group(cfg, /* Configuration */ 31 u64 phase_comp; 32 u32 esync_n_div; 33 u16 freq_base; 34 u16 freq_mult; 35 u16 freq_ratio_m; 36 u16 freq_ratio_n; 37 u8 sync_ctrl; 38 ); 39 struct_group(inv, /* Invariants */ 40 u8 config; 41 ); 42 struct_group(stat, /* Status */ 43 s64 ffo; 44 u32 meas_freq; 45 u8 mon_status; 46 ); 47 }; 48 49 int zl3073x_ref_state_fetch(struct zl3073x_dev *zldev, u8 index); 50 51 const struct zl3073x_ref *zl3073x_ref_state_get(struct zl3073x_dev *zldev, 52 u8 index); 53 54 int zl3073x_ref_state_set(struct zl3073x_dev *zldev, u8 index, 55 const struct zl3073x_ref *ref); 56 57 int zl3073x_ref_state_update(struct zl3073x_dev *zldev, u8 index); 58 59 int zl3073x_ref_freq_factorize(u32 freq, u16 *base, u16 *mult); 60 61 /** 62 * zl3073x_ref_ffo_get - get current fractional frequency offset 63 * @ref: pointer to ref state 64 * 65 * Return: the latest measured fractional frequency offset 66 */ 67 static inline s64 68 zl3073x_ref_ffo_get(const struct zl3073x_ref *ref) 69 { 70 return ref->ffo; 71 } 72 73 /** 74 * zl3073x_ref_meas_freq_get - get measured input frequency 75 * @ref: pointer to ref state 76 * 77 * Return: measured input frequency in Hz 78 */ 79 static inline u32 80 zl3073x_ref_meas_freq_get(const struct zl3073x_ref *ref) 81 { 82 return ref->meas_freq; 83 } 84 85 /** 86 * zl3073x_ref_freq_get - get given input reference frequency 87 * @ref: pointer to ref state 88 * 89 * Return: frequency of the given input reference 90 */ 91 static inline u32 92 zl3073x_ref_freq_get(const struct zl3073x_ref *ref) 93 { 94 return mul_u64_u32_div(ref->freq_base * ref->freq_mult, 95 ref->freq_ratio_m, ref->freq_ratio_n); 96 } 97 98 /** 99 * zl3073x_ref_freq_set - set given input reference frequency 100 * @ref: pointer to ref state 101 * @freq: frequency to be set 102 * 103 * Return: 0 on success, <0 when frequency cannot be factorized 104 */ 105 static inline int 106 zl3073x_ref_freq_set(struct zl3073x_ref *ref, u32 freq) 107 { 108 u16 base, mult; 109 int rc; 110 111 rc = zl3073x_ref_freq_factorize(freq, &base, &mult); 112 if (rc) 113 return rc; 114 115 ref->freq_base = base; 116 ref->freq_mult = mult; 117 ref->freq_ratio_m = 1; 118 ref->freq_ratio_n = 1; 119 120 return 0; 121 } 122 123 /** 124 * zl3073x_ref_sync_mode_get - get sync control mode 125 * @ref: pointer to ref state 126 * 127 * Return: sync control mode (ZL_REF_SYNC_CTRL_MODE_*) 128 */ 129 static inline u8 130 zl3073x_ref_sync_mode_get(const struct zl3073x_ref *ref) 131 { 132 return FIELD_GET(ZL_REF_SYNC_CTRL_MODE, ref->sync_ctrl); 133 } 134 135 /** 136 * zl3073x_ref_sync_mode_set - set sync control mode 137 * @ref: pointer to ref state 138 * @mode: sync control mode (ZL_REF_SYNC_CTRL_MODE_*) 139 */ 140 static inline void 141 zl3073x_ref_sync_mode_set(struct zl3073x_ref *ref, u8 mode) 142 { 143 FIELD_MODIFY(ZL_REF_SYNC_CTRL_MODE, &ref->sync_ctrl, mode); 144 } 145 146 /** 147 * zl3073x_ref_sync_pair_get - get sync pair reference index 148 * @ref: pointer to ref state 149 * 150 * Return: paired reference index 151 */ 152 static inline u8 153 zl3073x_ref_sync_pair_get(const struct zl3073x_ref *ref) 154 { 155 return FIELD_GET(ZL_REF_SYNC_CTRL_PAIR, ref->sync_ctrl); 156 } 157 158 /** 159 * zl3073x_ref_sync_pair_set - set sync pair reference index 160 * @ref: pointer to ref state 161 * @pair: paired reference index 162 */ 163 static inline void 164 zl3073x_ref_sync_pair_set(struct zl3073x_ref *ref, u8 pair) 165 { 166 FIELD_MODIFY(ZL_REF_SYNC_CTRL_PAIR, &ref->sync_ctrl, pair); 167 } 168 169 /** 170 * zl3073x_ref_is_diff - check if the given input reference is differential 171 * @ref: pointer to ref state 172 * 173 * Return: true if reference is differential, false if reference is single-ended 174 */ 175 static inline bool 176 zl3073x_ref_is_diff(const struct zl3073x_ref *ref) 177 { 178 return !!FIELD_GET(ZL_REF_CONFIG_DIFF_EN, ref->config); 179 } 180 181 /** 182 * zl3073x_ref_is_enabled - check if the given input reference is enabled 183 * @ref: pointer to ref state 184 * 185 * Return: true if input refernce is enabled, false otherwise 186 */ 187 static inline bool 188 zl3073x_ref_is_enabled(const struct zl3073x_ref *ref) 189 { 190 return !!FIELD_GET(ZL_REF_CONFIG_ENABLE, ref->config); 191 } 192 193 /** 194 * zl3073x_ref_is_status_ok - check the given input reference status 195 * @ref: pointer to ref state 196 * 197 * Return: true if the status is ok, false otherwise 198 */ 199 static inline bool 200 zl3073x_ref_is_status_ok(const struct zl3073x_ref *ref) 201 { 202 return ref->mon_status == ZL_REF_MON_STATUS_OK; 203 } 204 205 #endif /* _ZL3073X_REF_H */ 206