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