xref: /linux/drivers/dpll/zl3073x/chan.h (revision b2f1e6301efa4a80becdb0715416c3cbc693fbb4)
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/types.h>
9 
10 #include "regs.h"
11 
12 struct zl3073x_dev;
13 
14 /**
15  * struct zl3073x_chan - DPLL channel state
16  * @mode_refsel: mode and reference selection register value
17  * @ref_prio: reference priority registers (4 bits per ref, P/N packed)
18  * @mon_status: monitor status register value
19  * @refsel_status: reference selection status register value
20  * @df_offset: frequency offset vs tracked reference in 2^-48 steps
21  */
22 struct zl3073x_chan {
23 	struct_group(cfg,
24 		u8	mode_refsel;
25 		u8	ref_prio[ZL3073X_NUM_REFS / 2];
26 	);
27 	struct_group(stat,
28 		u8	mon_status;
29 		u8	refsel_status;
30 		s64	df_offset;
31 	);
32 };
33 
34 int zl3073x_chan_state_fetch(struct zl3073x_dev *zldev, u8 index);
35 const struct zl3073x_chan *zl3073x_chan_state_get(struct zl3073x_dev *zldev,
36 						 u8 index);
37 int zl3073x_chan_state_set(struct zl3073x_dev *zldev, u8 index,
38 			   const struct zl3073x_chan *chan);
39 
40 int zl3073x_chan_state_update(struct zl3073x_dev *zldev, u8 index);
41 
42 /**
43  * zl3073x_chan_df_offset_get - get cached df_offset vs tracked reference
44  * @chan: pointer to channel state
45  *
46  * Return: frequency offset in 2^-48 steps
47  */
48 static inline s64
49 zl3073x_chan_df_offset_get(const struct zl3073x_chan *chan)
50 {
51 	return chan->df_offset;
52 }
53 
54 /**
55  * zl3073x_chan_mode_get - get DPLL channel operating mode
56  * @chan: pointer to channel state
57  *
58  * Return: reference selection mode of the given DPLL channel
59  */
60 static inline u8 zl3073x_chan_mode_get(const struct zl3073x_chan *chan)
61 {
62 	return FIELD_GET(ZL_DPLL_MODE_REFSEL_MODE, chan->mode_refsel);
63 }
64 
65 /**
66  * zl3073x_chan_ref_get - get manually selected reference
67  * @chan: pointer to channel state
68  *
69  * Return: reference selected in forced reference lock mode
70  */
71 static inline u8 zl3073x_chan_ref_get(const struct zl3073x_chan *chan)
72 {
73 	return FIELD_GET(ZL_DPLL_MODE_REFSEL_REF, chan->mode_refsel);
74 }
75 
76 /**
77  * zl3073x_chan_mode_set - set DPLL channel operating mode
78  * @chan: pointer to channel state
79  * @mode: mode to set
80  */
81 static inline void zl3073x_chan_mode_set(struct zl3073x_chan *chan, u8 mode)
82 {
83 	FIELD_MODIFY(ZL_DPLL_MODE_REFSEL_MODE, &chan->mode_refsel, mode);
84 }
85 
86 /**
87  * zl3073x_chan_ref_set - set manually selected reference
88  * @chan: pointer to channel state
89  * @ref: reference to set
90  */
91 static inline void zl3073x_chan_ref_set(struct zl3073x_chan *chan, u8 ref)
92 {
93 	FIELD_MODIFY(ZL_DPLL_MODE_REFSEL_REF, &chan->mode_refsel, ref);
94 }
95 
96 /**
97  * zl3073x_chan_ref_prio_get - get reference priority
98  * @chan: pointer to channel state
99  * @ref: input reference index
100  *
101  * Return: priority of the given reference <0, 15>
102  */
103 static inline u8
104 zl3073x_chan_ref_prio_get(const struct zl3073x_chan *chan, u8 ref)
105 {
106 	u8 val = chan->ref_prio[ref / 2];
107 
108 	if (!(ref & 1))
109 		return FIELD_GET(ZL_DPLL_REF_PRIO_REF_P, val);
110 	else
111 		return FIELD_GET(ZL_DPLL_REF_PRIO_REF_N, val);
112 }
113 
114 /**
115  * zl3073x_chan_ref_prio_set - set reference priority
116  * @chan: pointer to channel state
117  * @ref: input reference index
118  * @prio: priority to set
119  */
120 static inline void
121 zl3073x_chan_ref_prio_set(struct zl3073x_chan *chan, u8 ref, u8 prio)
122 {
123 	u8 *val = &chan->ref_prio[ref / 2];
124 
125 	if (!(ref & 1))
126 		FIELD_MODIFY(ZL_DPLL_REF_PRIO_REF_P, val, prio);
127 	else
128 		FIELD_MODIFY(ZL_DPLL_REF_PRIO_REF_N, val, prio);
129 }
130 
131 /**
132  * zl3073x_chan_ref_is_selectable - check if reference is selectable
133  * @chan: pointer to channel state
134  * @ref: input reference index
135  *
136  * Return: true if the reference priority is not NONE, false otherwise
137  */
138 static inline bool
139 zl3073x_chan_ref_is_selectable(const struct zl3073x_chan *chan, u8 ref)
140 {
141 	return zl3073x_chan_ref_prio_get(chan, ref) != ZL_DPLL_REF_PRIO_NONE;
142 }
143 
144 /**
145  * zl3073x_chan_lock_state_get - get DPLL channel lock state
146  * @chan: pointer to channel state
147  *
148  * Return: lock state of the given DPLL channel
149  */
150 static inline u8 zl3073x_chan_lock_state_get(const struct zl3073x_chan *chan)
151 {
152 	return FIELD_GET(ZL_DPLL_MON_STATUS_STATE, chan->mon_status);
153 }
154 
155 /**
156  * zl3073x_chan_is_ho_ready - check if holdover is ready
157  * @chan: pointer to channel state
158  *
159  * Return: true if holdover is ready, false otherwise
160  */
161 static inline bool zl3073x_chan_is_ho_ready(const struct zl3073x_chan *chan)
162 {
163 	return !!FIELD_GET(ZL_DPLL_MON_STATUS_HO_READY, chan->mon_status);
164 }
165 
166 /**
167  * zl3073x_chan_refsel_state_get - get reference selection state
168  * @chan: pointer to channel state
169  *
170  * Return: reference selection state of the given DPLL channel
171  */
172 static inline u8 zl3073x_chan_refsel_state_get(const struct zl3073x_chan *chan)
173 {
174 	return FIELD_GET(ZL_DPLL_REFSEL_STATUS_STATE, chan->refsel_status);
175 }
176 
177 /**
178  * zl3073x_chan_refsel_ref_get - get currently selected reference in auto mode
179  * @chan: pointer to channel state
180  *
181  * Return: reference selected by the DPLL in automatic mode
182  */
183 static inline u8 zl3073x_chan_refsel_ref_get(const struct zl3073x_chan *chan)
184 {
185 	return FIELD_GET(ZL_DPLL_REFSEL_STATUS_REFSEL, chan->refsel_status);
186 }
187 
188 #endif /* _ZL3073X_CHAN_H */
189