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