xref: /linux/drivers/dpll/zl3073x/chan.h (revision 3a2c4d55e32ad65efebdb6de44eef3bfa08bb49d)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #ifndef _ZL3073X_CHAN_H
4 #define _ZL3073X_CHAN_H
5 
6 #include <linux/bitfield.h>
7 #include <linux/stddef.h>
8 #include <linux/time64.h>
9 #include <linux/types.h>
10 
11 #include "regs.h"
12 
13 struct ptp_system_timestamp;
14 struct zl3073x_dev;
15 
16 /**
17  * struct zl3073x_chan - DPLL channel state
18  * @ctrl: DPLL control register value
19  * @mode_refsel: mode and reference selection register value
20  * @ref_prio: reference priority registers (4 bits per ref, P/N packed)
21  * @mon_status: monitor status register value
22  * @refsel_status: reference selection status register value
23  * @df_offset: frequency offset vs tracked reference in 2^-48 steps
24  */
25 struct zl3073x_chan {
26 	struct_group(cfg,
27 		u8	ctrl;
28 		u8	mode_refsel;
29 		u8	ref_prio[ZL3073X_NUM_REFS / 2];
30 	);
31 	struct_group(stat,
32 		u8	mon_status;
33 		u8	refsel_status;
34 		s64	df_offset;
35 	);
36 };
37 
38 int zl3073x_chan_state_fetch(struct zl3073x_dev *zldev, u8 index);
39 const struct zl3073x_chan *zl3073x_chan_state_get(struct zl3073x_dev *zldev,
40 						 u8 index);
41 int zl3073x_chan_state_set(struct zl3073x_dev *zldev, u8 index,
42 			   const struct zl3073x_chan *chan);
43 
44 int zl3073x_chan_state_update(struct zl3073x_dev *zldev, u8 index);
45 int zl3073x_chan_nco_mode_set(struct zl3073x_dev *zldev, u8 index);
46 
47 int zl3073x_chan_tod_ready_wait(struct zl3073x_dev *zldev, u8 ch);
48 int zl3073x_chan_tod_read(struct zl3073x_dev *zldev, u8 ch,
49 			  bool next_hz, struct timespec64 *ts,
50 			  struct ptp_system_timestamp *sts);
51 int zl3073x_chan_tod_write(struct zl3073x_dev *zldev, u8 ch,
52 			   struct timespec64 ts);
53 int zl3073x_chan_tod_adjust(struct zl3073x_dev *zldev, u8 ch,
54 			    struct timespec64 delta);
55 int zl3073x_chan_phase_step(struct zl3073x_dev *zldev, u8 ch,
56 			    u16 out_mask, s32 step_cycles, bool tod_step);
57 
58 int zl3073x_chan_df_offset_set(struct zl3073x_dev *zldev, u8 ch, s64 offset);
59 
60 int zl3073x_chan_tie_write(struct zl3073x_dev *zldev, u8 ch, s64 delta_ns);
61 
62 /**
63  * zl3073x_chan_df_offset_get - get cached df_offset vs tracked reference
64  * @chan: pointer to channel state
65  *
66  * Return: frequency offset in 2^-48 steps
67  */
68 static inline s64
69 zl3073x_chan_df_offset_get(const struct zl3073x_chan *chan)
70 {
71 	return chan->df_offset;
72 }
73 
74 /**
75  * zl3073x_chan_mode_get - get DPLL channel operating mode
76  * @chan: pointer to channel state
77  *
78  * Return: reference selection mode of the given DPLL channel
79  */
80 static inline u8 zl3073x_chan_mode_get(const struct zl3073x_chan *chan)
81 {
82 	return FIELD_GET(ZL_DPLL_MODE_REFSEL_MODE, chan->mode_refsel);
83 }
84 
85 /**
86  * zl3073x_chan_ref_get - get manually selected reference
87  * @chan: pointer to channel state
88  *
89  * Return: reference selected in forced reference lock mode
90  */
91 static inline u8 zl3073x_chan_ref_get(const struct zl3073x_chan *chan)
92 {
93 	return FIELD_GET(ZL_DPLL_MODE_REFSEL_REF, chan->mode_refsel);
94 }
95 
96 /**
97  * zl3073x_chan_mode_set - set DPLL channel operating mode
98  * @chan: pointer to channel state
99  * @mode: mode to set
100  */
101 static inline void zl3073x_chan_mode_set(struct zl3073x_chan *chan, u8 mode)
102 {
103 	FIELD_MODIFY(ZL_DPLL_MODE_REFSEL_MODE, &chan->mode_refsel, mode);
104 }
105 
106 /**
107  * zl3073x_chan_ref_set - set manually selected reference
108  * @chan: pointer to channel state
109  * @ref: reference to set
110  */
111 static inline void zl3073x_chan_ref_set(struct zl3073x_chan *chan, u8 ref)
112 {
113 	FIELD_MODIFY(ZL_DPLL_MODE_REFSEL_REF, &chan->mode_refsel, ref);
114 }
115 
116 /**
117  * zl3073x_chan_ref_prio_get - get reference priority
118  * @chan: pointer to channel state
119  * @ref: input reference index
120  *
121  * Return: priority of the given reference <0, 15>
122  */
123 static inline u8
124 zl3073x_chan_ref_prio_get(const struct zl3073x_chan *chan, u8 ref)
125 {
126 	u8 val = chan->ref_prio[ref / 2];
127 
128 	if (!(ref & 1))
129 		return FIELD_GET(ZL_DPLL_REF_PRIO_REF_P, val);
130 	else
131 		return FIELD_GET(ZL_DPLL_REF_PRIO_REF_N, val);
132 }
133 
134 /**
135  * zl3073x_chan_ref_prio_set - set reference priority
136  * @chan: pointer to channel state
137  * @ref: input reference index
138  * @prio: priority to set
139  */
140 static inline void
141 zl3073x_chan_ref_prio_set(struct zl3073x_chan *chan, u8 ref, u8 prio)
142 {
143 	u8 *val = &chan->ref_prio[ref / 2];
144 
145 	if (!(ref & 1))
146 		FIELD_MODIFY(ZL_DPLL_REF_PRIO_REF_P, val, prio);
147 	else
148 		FIELD_MODIFY(ZL_DPLL_REF_PRIO_REF_N, val, prio);
149 }
150 
151 /**
152  * zl3073x_chan_ref_is_selectable - check if reference is selectable
153  * @chan: pointer to channel state
154  * @ref: input reference index
155  *
156  * Return: true if the reference priority is not NONE, false otherwise
157  */
158 static inline bool
159 zl3073x_chan_ref_is_selectable(const struct zl3073x_chan *chan, u8 ref)
160 {
161 	return zl3073x_chan_ref_prio_get(chan, ref) != ZL_DPLL_REF_PRIO_NONE;
162 }
163 
164 /**
165  * zl3073x_chan_lock_state_get - get DPLL channel lock state
166  * @chan: pointer to channel state
167  *
168  * Return: lock state of the given DPLL channel
169  */
170 static inline u8 zl3073x_chan_lock_state_get(const struct zl3073x_chan *chan)
171 {
172 	return FIELD_GET(ZL_DPLL_MON_STATUS_STATE, chan->mon_status);
173 }
174 
175 /**
176  * zl3073x_chan_is_locked - check if channel is locked to a reference
177  * @chan: pointer to channel state
178  *
179  * Return: true if channel is locked, false otherwise
180  */
181 static inline bool zl3073x_chan_is_locked(const struct zl3073x_chan *chan)
182 {
183 	u8 lock_state = zl3073x_chan_lock_state_get(chan);
184 	return lock_state == ZL_DPLL_MON_STATUS_STATE_LOCK;
185 }
186 
187 /**
188  * zl3073x_chan_mode_is_auto - check if channel is in automatic mode
189  * @chan: pointer to channel state
190  *
191  * Return: true if channel is in automatic mode, false otherwise
192  */
193 static inline bool zl3073x_chan_mode_is_auto(const struct zl3073x_chan *chan)
194 {
195 	return zl3073x_chan_mode_get(chan) == ZL_DPLL_MODE_REFSEL_MODE_AUTO;
196 }
197 
198 /**
199  * zl3073x_chan_mode_is_nco - check if channel is in NCO mode
200  * @chan: pointer to channel state
201  *
202  * Return: true if channel is in NCO mode, false otherwise
203  */
204 static inline bool zl3073x_chan_mode_is_nco(const struct zl3073x_chan *chan)
205 {
206 	return zl3073x_chan_mode_get(chan) == ZL_DPLL_MODE_REFSEL_MODE_NCO;
207 }
208 
209 /**
210  * zl3073x_chan_mode_is_reflock - check if channel is in reflock mode
211  * @chan: pointer to channel state
212  *
213  * Return: true if channel is in reflock mode, false otherwise
214  */
215 static inline bool zl3073x_chan_mode_is_reflock(const struct zl3073x_chan *chan)
216 {
217 	return zl3073x_chan_mode_get(chan) == ZL_DPLL_MODE_REFSEL_MODE_REFLOCK;
218 }
219 
220 /**
221  * zl3073x_chan_mode_supports_tie - check if channel mode supports TIE write
222  * @chan: pointer to channel state
223  *
224  * TIE write is supported in AUTO and REFLOCK modes regardless of lock state.
225  *
226  * Return: true if TIE write is supported, false otherwise
227  */
228 static inline bool
229 zl3073x_chan_mode_supports_tie(const struct zl3073x_chan *chan)
230 {
231 	return zl3073x_chan_mode_is_auto(chan) ||
232 		zl3073x_chan_mode_is_reflock(chan);
233 }
234 
235 /**
236  * zl3073x_chan_is_ho_ready - check if holdover is ready
237  * @chan: pointer to channel state
238  *
239  * Return: true if holdover is ready, false otherwise
240  */
241 static inline bool zl3073x_chan_is_ho_ready(const struct zl3073x_chan *chan)
242 {
243 	return !!FIELD_GET(ZL_DPLL_MON_STATUS_HO_READY, chan->mon_status);
244 }
245 
246 /**
247  * zl3073x_chan_refsel_state_get - get reference selection state
248  * @chan: pointer to channel state
249  *
250  * Return: reference selection state of the given DPLL channel
251  */
252 static inline u8 zl3073x_chan_refsel_state_get(const struct zl3073x_chan *chan)
253 {
254 	return FIELD_GET(ZL_DPLL_REFSEL_STATUS_STATE, chan->refsel_status);
255 }
256 
257 /**
258  * zl3073x_chan_refsel_ref_get - get currently selected reference in auto mode
259  * @chan: pointer to channel state
260  *
261  * Return: reference selected by the DPLL in automatic mode
262  */
263 static inline u8 zl3073x_chan_refsel_ref_get(const struct zl3073x_chan *chan)
264 {
265 	return FIELD_GET(ZL_DPLL_REFSEL_STATUS_REFSEL, chan->refsel_status);
266 }
267 
268 #endif /* _ZL3073X_CHAN_H */
269