Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/dpll/zl3073x/core.h
29268 views
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
429