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