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