xref: /linux/drivers/dpll/zl3073x/core.h (revision 6aac2aa2dfae38b60f22c3dfe4103ceefbe2d761)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #ifndef _ZL3073X_CORE_H
4 #define _ZL3073X_CORE_H
5 
6 #include <linux/bitfield.h>
7 #include <linux/kthread.h>
8 #include <linux/list.h>
9 #include <linux/mutex.h>
10 #include <linux/types.h>
11 
12 #include "out.h"
13 #include "ref.h"
14 #include "regs.h"
15 #include "synth.h"
16 
17 struct device;
18 struct regmap;
19 struct zl3073x_dpll;
20 
21 /*
22  * Hardware limits for ZL3073x chip family
23  */
24 #define ZL3073X_MAX_CHANNELS	5
25 #define ZL3073X_NUM_REFS	10
26 #define ZL3073X_NUM_OUTS	10
27 #define ZL3073X_NUM_SYNTHS	5
28 #define ZL3073X_NUM_INPUT_PINS	ZL3073X_NUM_REFS
29 #define ZL3073X_NUM_OUTPUT_PINS	(ZL3073X_NUM_OUTS * 2)
30 #define ZL3073X_NUM_PINS	(ZL3073X_NUM_INPUT_PINS + \
31 				 ZL3073X_NUM_OUTPUT_PINS)
32 
33 /**
34  * struct zl3073x_dev - zl3073x device
35  * @dev: pointer to device
36  * @regmap: regmap to access device registers
37  * @multiop_lock: to serialize multiple register operations
38  * @ref: array of input references' invariants
39  * @out: array of outs' invariants
40  * @synth: array of synths' invariants
41  * @dplls: list of DPLLs
42  * @kworker: thread for periodic work
43  * @work: periodic work
44  * @clock_id: clock id of the device
45  * @phase_avg_factor: phase offset measurement averaging factor
46  */
47 struct zl3073x_dev {
48 	struct device		*dev;
49 	struct regmap		*regmap;
50 	struct mutex		multiop_lock;
51 
52 	/* Invariants */
53 	struct zl3073x_ref	ref[ZL3073X_NUM_REFS];
54 	struct zl3073x_out	out[ZL3073X_NUM_OUTS];
55 	struct zl3073x_synth	synth[ZL3073X_NUM_SYNTHS];
56 
57 	/* DPLL channels */
58 	struct list_head	dplls;
59 
60 	/* Monitor */
61 	struct kthread_worker		*kworker;
62 	struct kthread_delayed_work	work;
63 
64 	/* Devlink parameters */
65 	u64			clock_id;
66 	u8			phase_avg_factor;
67 };
68 
69 struct zl3073x_chip_info {
70 	const u16	*ids;
71 	size_t		num_ids;
72 	int		num_channels;
73 };
74 
75 extern const struct zl3073x_chip_info zl30731_chip_info;
76 extern const struct zl3073x_chip_info zl30732_chip_info;
77 extern const struct zl3073x_chip_info zl30733_chip_info;
78 extern const struct zl3073x_chip_info zl30734_chip_info;
79 extern const struct zl3073x_chip_info zl30735_chip_info;
80 extern const struct regmap_config zl3073x_regmap_config;
81 
82 struct zl3073x_dev *zl3073x_devm_alloc(struct device *dev);
83 int zl3073x_dev_probe(struct zl3073x_dev *zldev,
84 		      const struct zl3073x_chip_info *chip_info);
85 
86 int zl3073x_dev_start(struct zl3073x_dev *zldev, bool full);
87 void zl3073x_dev_stop(struct zl3073x_dev *zldev);
88 
89 static inline u8 zl3073x_dev_phase_avg_factor_get(struct zl3073x_dev *zldev)
90 {
91 	return zldev->phase_avg_factor;
92 }
93 
94 int zl3073x_dev_phase_avg_factor_set(struct zl3073x_dev *zldev, u8 factor);
95 
96 /**********************
97  * Registers operations
98  **********************/
99 
100 /**
101  * struct zl3073x_hwreg_seq_item - HW register write sequence item
102  * @addr: HW register to be written
103  * @value: value to be written to HW register
104  * @mask: bitmask indicating bits to be updated
105  * @wait: number of ms to wait after register write
106  */
107 struct zl3073x_hwreg_seq_item {
108 	u32	addr;
109 	u32	value;
110 	u32	mask;
111 	u32	wait;
112 };
113 
114 #define HWREG_SEQ_ITEM(_addr, _value, _mask, _wait)	\
115 {							\
116 	.addr	= _addr,				\
117 	.value	= FIELD_PREP_CONST(_mask, _value),	\
118 	.mask	= _mask,				\
119 	.wait	= _wait,				\
120 }
121 
122 int zl3073x_mb_op(struct zl3073x_dev *zldev, unsigned int op_reg, u8 op_val,
123 		  unsigned int mask_reg, u16 mask_val);
124 int zl3073x_poll_zero_u8(struct zl3073x_dev *zldev, unsigned int reg, u8 mask);
125 int zl3073x_read_u8(struct zl3073x_dev *zldev, unsigned int reg, u8 *val);
126 int zl3073x_read_u16(struct zl3073x_dev *zldev, unsigned int reg, u16 *val);
127 int zl3073x_read_u32(struct zl3073x_dev *zldev, unsigned int reg, u32 *val);
128 int zl3073x_read_u48(struct zl3073x_dev *zldev, unsigned int reg, u64 *val);
129 int zl3073x_write_u8(struct zl3073x_dev *zldev, unsigned int reg, u8 val);
130 int zl3073x_write_u16(struct zl3073x_dev *zldev, unsigned int reg, u16 val);
131 int zl3073x_write_u32(struct zl3073x_dev *zldev, unsigned int reg, u32 val);
132 int zl3073x_write_u48(struct zl3073x_dev *zldev, unsigned int reg, u64 val);
133 int zl3073x_read_hwreg(struct zl3073x_dev *zldev, u32 addr, u32 *value);
134 int zl3073x_write_hwreg(struct zl3073x_dev *zldev, u32 addr, u32 value);
135 int zl3073x_update_hwreg(struct zl3073x_dev *zldev, u32 addr, u32 value,
136 			 u32 mask);
137 int zl3073x_write_hwreg_seq(struct zl3073x_dev *zldev,
138 			    const struct zl3073x_hwreg_seq_item *seq,
139 			    size_t num_items);
140 
141 /*****************
142  * Misc operations
143  *****************/
144 
145 int zl3073x_ref_phase_offsets_update(struct zl3073x_dev *zldev, int channel);
146 
147 static inline bool
148 zl3073x_is_n_pin(u8 id)
149 {
150 	/* P-pins ids are even while N-pins are odd */
151 	return id & 1;
152 }
153 
154 static inline bool
155 zl3073x_is_p_pin(u8 id)
156 {
157 	return !zl3073x_is_n_pin(id);
158 }
159 
160 /**
161  * zl3073x_input_pin_ref_get - get reference for given input pin
162  * @id: input pin id
163  *
164  * Return: reference id for the given input pin
165  */
166 static inline u8
167 zl3073x_input_pin_ref_get(u8 id)
168 {
169 	return id;
170 }
171 
172 /**
173  * zl3073x_output_pin_out_get - get output for the given output pin
174  * @id: output pin id
175  *
176  * Return: output id for the given output pin
177  */
178 static inline u8
179 zl3073x_output_pin_out_get(u8 id)
180 {
181 	/* Output pin pair shares the single output */
182 	return id / 2;
183 }
184 
185 /**
186  * zl3073x_dev_ref_freq_get - get input reference frequency
187  * @zldev: pointer to zl3073x device
188  * @index: input reference index
189  *
190  * Return: frequency of given input reference
191  */
192 static inline u32
193 zl3073x_dev_ref_freq_get(struct zl3073x_dev *zldev, u8 index)
194 {
195 	const struct zl3073x_ref *ref = zl3073x_ref_state_get(zldev, index);
196 
197 	return zl3073x_ref_freq_get(ref);
198 }
199 
200 /**
201  * zl3073x_dev_ref_is_diff - check if the given input reference is differential
202  * @zldev: pointer to zl3073x device
203  * @index: input reference index
204  *
205  * Return: true if reference is differential, false if reference is single-ended
206  */
207 static inline bool
208 zl3073x_dev_ref_is_diff(struct zl3073x_dev *zldev, u8 index)
209 {
210 	const struct zl3073x_ref *ref = zl3073x_ref_state_get(zldev, index);
211 
212 	return zl3073x_ref_is_diff(ref);
213 }
214 
215 /*
216  * zl3073x_dev_ref_is_status_ok - check the given input reference status
217  * @zldev: pointer to zl3073x device
218  * @index: input reference index
219  *
220  * Return: true if the status is ok, false otherwise
221  */
222 static inline bool
223 zl3073x_dev_ref_is_status_ok(struct zl3073x_dev *zldev, u8 index)
224 {
225 	const struct zl3073x_ref *ref = zl3073x_ref_state_get(zldev, index);
226 
227 	return zl3073x_ref_is_status_ok(ref);
228 }
229 
230 /**
231  * zl3073x_dev_synth_freq_get - get synth current freq
232  * @zldev: pointer to zl3073x device
233  * @index: synth index
234  *
235  * Return: frequency of given synthetizer
236  */
237 static inline u32
238 zl3073x_dev_synth_freq_get(struct zl3073x_dev *zldev, u8 index)
239 {
240 	const struct zl3073x_synth *synth;
241 
242 	synth = zl3073x_synth_state_get(zldev, index);
243 	return zl3073x_synth_freq_get(synth);
244 }
245 
246 /**
247  * zl3073x_dev_out_synth_get - get synth connected to given output
248  * @zldev: pointer to zl3073x device
249  * @index: output index
250  *
251  * Return: index of synth connected to given output.
252  */
253 static inline u8
254 zl3073x_dev_out_synth_get(struct zl3073x_dev *zldev, u8 index)
255 {
256 	const struct zl3073x_out *out = zl3073x_out_state_get(zldev, index);
257 
258 	return zl3073x_out_synth_get(out);
259 }
260 
261 /**
262  * zl3073x_dev_out_is_enabled - check if the given output is enabled
263  * @zldev: pointer to zl3073x device
264  * @index: output index
265  *
266  * Return: true if the output is enabled, false otherwise
267  */
268 static inline bool
269 zl3073x_dev_out_is_enabled(struct zl3073x_dev *zldev, u8 index)
270 {
271 	const struct zl3073x_out *out = zl3073x_out_state_get(zldev, index);
272 	const struct zl3073x_synth *synth;
273 	u8 synth_id;
274 
275 	/* Output is enabled only if associated synth is enabled */
276 	synth_id = zl3073x_out_synth_get(out);
277 	synth = zl3073x_synth_state_get(zldev, synth_id);
278 
279 	return zl3073x_synth_is_enabled(synth) && zl3073x_out_is_enabled(out);
280 }
281 
282 /**
283  * zl3073x_dev_out_dpll_get - get DPLL ID the output is driven by
284  * @zldev: pointer to zl3073x device
285  * @index: output index
286  *
287  * Return: ID of DPLL the given output is driven by
288  */
289 static inline
290 u8 zl3073x_dev_out_dpll_get(struct zl3073x_dev *zldev, u8 index)
291 {
292 	const struct zl3073x_out *out = zl3073x_out_state_get(zldev, index);
293 	const struct zl3073x_synth *synth;
294 	u8 synth_id;
295 
296 	/* Get synthesizer connected to given output */
297 	synth_id = zl3073x_out_synth_get(out);
298 	synth = zl3073x_synth_state_get(zldev, synth_id);
299 
300 	/* Return DPLL that drives the synth */
301 	return zl3073x_synth_dpll_get(synth);
302 }
303 
304 /**
305  * zl3073x_dev_out_is_diff - check if the given output is differential
306  * @zldev: pointer to zl3073x device
307  * @index: output index
308  *
309  * Return: true if output is differential, false if output is single-ended
310  */
311 static inline bool
312 zl3073x_dev_out_is_diff(struct zl3073x_dev *zldev, u8 index)
313 {
314 	const struct zl3073x_out *out = zl3073x_out_state_get(zldev, index);
315 
316 	return zl3073x_out_is_diff(out);
317 }
318 
319 /**
320  * zl3073x_dev_output_pin_is_enabled - check if the given output pin is enabled
321  * @zldev: pointer to zl3073x device
322  * @id: output pin id
323  *
324  * Checks if the output of the given output pin is enabled and also that
325  * its signal format also enables the given pin.
326  *
327  * Return: true if output pin is enabled, false if output pin is disabled
328  */
329 static inline bool
330 zl3073x_dev_output_pin_is_enabled(struct zl3073x_dev *zldev, u8 id)
331 {
332 	u8 out_id = zl3073x_output_pin_out_get(id);
333 	const struct zl3073x_out *out;
334 
335 	out = zl3073x_out_state_get(zldev, out_id);
336 
337 	/* Check if the output is enabled - call _dev_ helper that
338 	 * additionally checks for attached synth enablement.
339 	 */
340 	if (!zl3073x_dev_out_is_enabled(zldev, out_id))
341 		return false;
342 
343 	/* Check signal format */
344 	switch (zl3073x_out_signal_format_get(out)) {
345 	case ZL_OUTPUT_MODE_SIGNAL_FORMAT_DISABLED:
346 		/* Both output pins are disabled by signal format */
347 		return false;
348 
349 	case ZL_OUTPUT_MODE_SIGNAL_FORMAT_1P:
350 		/* Output is one single ended P-pin output */
351 		if (zl3073x_is_n_pin(id))
352 			return false;
353 		break;
354 	case ZL_OUTPUT_MODE_SIGNAL_FORMAT_1N:
355 		/* Output is one single ended N-pin output */
356 		if (zl3073x_is_p_pin(id))
357 			return false;
358 		break;
359 	default:
360 		/* For other format both pins are enabled */
361 		break;
362 	}
363 
364 	return true;
365 }
366 
367 #endif /* _ZL3073X_CORE_H */
368