File Index
Files and directories
Sign in
FILE

core.h

File preview with syntax highlighting.

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