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