xref: /linux/drivers/dpll/zl3073x/ref.h (revision 84318277d6334c6981ab326d4acc87c6a6ddc9b8)
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/types.h>
9 
10 #include "regs.h"
11 
12 struct zl3073x_dev;
13 
14 /**
15  * struct zl3073x_ref - input reference state
16  * @ffo: current fractional frequency offset
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  * @config: reference config
24  * @sync_ctrl: reference sync control
25  * @mon_status: reference monitor status
26  */
27 struct zl3073x_ref {
28 	s64	ffo;
29 	u64	phase_comp;
30 	u32	esync_n_div;
31 	u16	freq_base;
32 	u16	freq_mult;
33 	u16	freq_ratio_m;
34 	u16	freq_ratio_n;
35 	u8	config;
36 	u8	sync_ctrl;
37 	u8	mon_status;
38 };
39 
40 int zl3073x_ref_state_fetch(struct zl3073x_dev *zldev, u8 index);
41 
42 const struct zl3073x_ref *zl3073x_ref_state_get(struct zl3073x_dev *zldev,
43 						u8 index);
44 
45 int zl3073x_ref_state_set(struct zl3073x_dev *zldev, u8 index,
46 			  const struct zl3073x_ref *ref);
47 
48 int zl3073x_ref_freq_factorize(u32 freq, u16 *base, u16 *mult);
49 
50 /**
51  * zl3073x_ref_ffo_get - get current fractional frequency offset
52  * @ref: pointer to ref state
53  *
54  * Return: the latest measured fractional frequency offset
55  */
56 static inline s64
57 zl3073x_ref_ffo_get(const struct zl3073x_ref *ref)
58 {
59 	return ref->ffo;
60 }
61 
62 /**
63  * zl3073x_ref_freq_get - get given input reference frequency
64  * @ref: pointer to ref state
65  *
66  * Return: frequency of the given input reference
67  */
68 static inline u32
69 zl3073x_ref_freq_get(const struct zl3073x_ref *ref)
70 {
71 	return mul_u64_u32_div(ref->freq_base * ref->freq_mult,
72 			       ref->freq_ratio_m, ref->freq_ratio_n);
73 }
74 
75 /**
76  * zl3073x_ref_freq_set - set given input reference frequency
77  * @ref: pointer to ref state
78  * @freq: frequency to be set
79  *
80  * Return: 0 on success, <0 when frequency cannot be factorized
81  */
82 static inline int
83 zl3073x_ref_freq_set(struct zl3073x_ref *ref, u32 freq)
84 {
85 	u16 base, mult;
86 	int rc;
87 
88 	rc = zl3073x_ref_freq_factorize(freq, &base, &mult);
89 	if (rc)
90 		return rc;
91 
92 	ref->freq_base = base;
93 	ref->freq_mult = mult;
94 
95 	return 0;
96 }
97 
98 /**
99  * zl3073x_ref_is_diff - check if the given input reference is differential
100  * @ref: pointer to ref state
101  *
102  * Return: true if reference is differential, false if reference is single-ended
103  */
104 static inline bool
105 zl3073x_ref_is_diff(const struct zl3073x_ref *ref)
106 {
107 	return !!FIELD_GET(ZL_REF_CONFIG_DIFF_EN, ref->config);
108 }
109 
110 /**
111  * zl3073x_ref_is_enabled - check if the given input reference is enabled
112  * @ref: pointer to ref state
113  *
114  * Return: true if input refernce is enabled, false otherwise
115  */
116 static inline bool
117 zl3073x_ref_is_enabled(const struct zl3073x_ref *ref)
118 {
119 	return !!FIELD_GET(ZL_REF_CONFIG_ENABLE, ref->config);
120 }
121 
122 /**
123  * zl3073x_ref_is_status_ok - check the given input reference status
124  * @ref: pointer to ref state
125  *
126  * Return: true if the status is ok, false otherwise
127  */
128 static inline bool
129 zl3073x_ref_is_status_ok(const struct zl3073x_ref *ref)
130 {
131 	return ref->mon_status == ZL_REF_MON_STATUS_OK;
132 }
133 
134 #endif /* _ZL3073X_REF_H */
135