Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/dpll/zl3073x/core.h
26282 views
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
* @ffo: current fractional frequency offset
34
*/
35
struct zl3073x_ref {
36
bool enabled;
37
bool diff;
38
s64 ffo;
39
};
40
41
/**
42
* struct zl3073x_out - output invariant info
43
* @enabled: out is enabled or disabled
44
* @synth: synthesizer the out is connected to
45
* @signal_format: out signal format
46
*/
47
struct zl3073x_out {
48
bool enabled;
49
u8 synth;
50
u8 signal_format;
51
};
52
53
/**
54
* struct zl3073x_synth - synthesizer invariant info
55
* @freq: synthesizer frequency
56
* @dpll: ID of DPLL the synthesizer is driven by
57
* @enabled: synth is enabled or disabled
58
*/
59
struct zl3073x_synth {
60
u32 freq;
61
u8 dpll;
62
bool enabled;
63
};
64
65
/**
66
* struct zl3073x_dev - zl3073x device
67
* @dev: pointer to device
68
* @regmap: regmap to access device registers
69
* @multiop_lock: to serialize multiple register operations
70
* @clock_id: clock id of the device
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
*/
78
struct zl3073x_dev {
79
struct device *dev;
80
struct regmap *regmap;
81
struct mutex multiop_lock;
82
u64 clock_id;
83
84
/* Invariants */
85
struct zl3073x_ref ref[ZL3073X_NUM_REFS];
86
struct zl3073x_out out[ZL3073X_NUM_OUTS];
87
struct zl3073x_synth synth[ZL3073X_NUM_SYNTHS];
88
89
/* DPLL channels */
90
struct list_head dplls;
91
92
/* Monitor */
93
struct kthread_worker *kworker;
94
struct kthread_delayed_work work;
95
};
96
97
struct zl3073x_chip_info {
98
const u16 *ids;
99
size_t num_ids;
100
int num_channels;
101
};
102
103
extern const struct zl3073x_chip_info zl30731_chip_info;
104
extern const struct zl3073x_chip_info zl30732_chip_info;
105
extern const struct zl3073x_chip_info zl30733_chip_info;
106
extern const struct zl3073x_chip_info zl30734_chip_info;
107
extern const struct zl3073x_chip_info zl30735_chip_info;
108
extern const struct regmap_config zl3073x_regmap_config;
109
110
struct zl3073x_dev *zl3073x_devm_alloc(struct device *dev);
111
int zl3073x_dev_probe(struct zl3073x_dev *zldev,
112
const struct zl3073x_chip_info *chip_info);
113
114
/**********************
115
* Registers operations
116
**********************/
117
118
int zl3073x_mb_op(struct zl3073x_dev *zldev, unsigned int op_reg, u8 op_val,
119
unsigned int mask_reg, u16 mask_val);
120
int zl3073x_poll_zero_u8(struct zl3073x_dev *zldev, unsigned int reg, u8 mask);
121
int zl3073x_read_u8(struct zl3073x_dev *zldev, unsigned int reg, u8 *val);
122
int zl3073x_read_u16(struct zl3073x_dev *zldev, unsigned int reg, u16 *val);
123
int zl3073x_read_u32(struct zl3073x_dev *zldev, unsigned int reg, u32 *val);
124
int zl3073x_read_u48(struct zl3073x_dev *zldev, unsigned int reg, u64 *val);
125
int zl3073x_write_u8(struct zl3073x_dev *zldev, unsigned int reg, u8 val);
126
int zl3073x_write_u16(struct zl3073x_dev *zldev, unsigned int reg, u16 val);
127
int zl3073x_write_u32(struct zl3073x_dev *zldev, unsigned int reg, u32 val);
128
int zl3073x_write_u48(struct zl3073x_dev *zldev, unsigned int reg, u64 val);
129
130
/*****************
131
* Misc operations
132
*****************/
133
134
int zl3073x_ref_freq_factorize(u32 freq, u16 *base, u16 *mult);
135
int zl3073x_ref_phase_offsets_update(struct zl3073x_dev *zldev, int channel);
136
137
static inline bool
138
zl3073x_is_n_pin(u8 id)
139
{
140
/* P-pins ids are even while N-pins are odd */
141
return id & 1;
142
}
143
144
static inline bool
145
zl3073x_is_p_pin(u8 id)
146
{
147
return !zl3073x_is_n_pin(id);
148
}
149
150
/**
151
* zl3073x_input_pin_ref_get - get reference for given input pin
152
* @id: input pin id
153
*
154
* Return: reference id for the given input pin
155
*/
156
static inline u8
157
zl3073x_input_pin_ref_get(u8 id)
158
{
159
return id;
160
}
161
162
/**
163
* zl3073x_output_pin_out_get - get output for the given output pin
164
* @id: output pin id
165
*
166
* Return: output id for the given output pin
167
*/
168
static inline u8
169
zl3073x_output_pin_out_get(u8 id)
170
{
171
/* Output pin pair shares the single output */
172
return id / 2;
173
}
174
175
/**
176
* zl3073x_ref_ffo_get - get current fractional frequency offset
177
* @zldev: pointer to zl3073x device
178
* @index: input reference index
179
*
180
* Return: the latest measured fractional frequency offset
181
*/
182
static inline s64
183
zl3073x_ref_ffo_get(struct zl3073x_dev *zldev, u8 index)
184
{
185
return zldev->ref[index].ffo;
186
}
187
188
/**
189
* zl3073x_ref_is_diff - check if the given input reference is differential
190
* @zldev: pointer to zl3073x device
191
* @index: input reference index
192
*
193
* Return: true if reference is differential, false if reference is single-ended
194
*/
195
static inline bool
196
zl3073x_ref_is_diff(struct zl3073x_dev *zldev, u8 index)
197
{
198
return zldev->ref[index].diff;
199
}
200
201
/**
202
* zl3073x_ref_is_enabled - check if the given input reference is enabled
203
* @zldev: pointer to zl3073x device
204
* @index: input reference index
205
*
206
* Return: true if input refernce is enabled, false otherwise
207
*/
208
static inline bool
209
zl3073x_ref_is_enabled(struct zl3073x_dev *zldev, u8 index)
210
{
211
return zldev->ref[index].enabled;
212
}
213
214
/**
215
* zl3073x_synth_dpll_get - get DPLL ID the synth is driven by
216
* @zldev: pointer to zl3073x device
217
* @index: synth index
218
*
219
* Return: ID of DPLL the given synthetizer is driven by
220
*/
221
static inline u8
222
zl3073x_synth_dpll_get(struct zl3073x_dev *zldev, u8 index)
223
{
224
return zldev->synth[index].dpll;
225
}
226
227
/**
228
* zl3073x_synth_freq_get - get synth current freq
229
* @zldev: pointer to zl3073x device
230
* @index: synth index
231
*
232
* Return: frequency of given synthetizer
233
*/
234
static inline u32
235
zl3073x_synth_freq_get(struct zl3073x_dev *zldev, u8 index)
236
{
237
return zldev->synth[index].freq;
238
}
239
240
/**
241
* zl3073x_synth_is_enabled - check if the given synth is enabled
242
* @zldev: pointer to zl3073x device
243
* @index: synth index
244
*
245
* Return: true if synth is enabled, false otherwise
246
*/
247
static inline bool
248
zl3073x_synth_is_enabled(struct zl3073x_dev *zldev, u8 index)
249
{
250
return zldev->synth[index].enabled;
251
}
252
253
/**
254
* zl3073x_out_synth_get - get synth connected to given output
255
* @zldev: pointer to zl3073x device
256
* @index: output index
257
*
258
* Return: index of synth connected to given output.
259
*/
260
static inline u8
261
zl3073x_out_synth_get(struct zl3073x_dev *zldev, u8 index)
262
{
263
return zldev->out[index].synth;
264
}
265
266
/**
267
* zl3073x_out_is_enabled - check if the given output is enabled
268
* @zldev: pointer to zl3073x device
269
* @index: output index
270
*
271
* Return: true if the output is enabled, false otherwise
272
*/
273
static inline bool
274
zl3073x_out_is_enabled(struct zl3073x_dev *zldev, u8 index)
275
{
276
u8 synth;
277
278
/* Output is enabled only if associated synth is enabled */
279
synth = zl3073x_out_synth_get(zldev, index);
280
if (zl3073x_synth_is_enabled(zldev, synth))
281
return zldev->out[index].enabled;
282
283
return false;
284
}
285
286
/**
287
* zl3073x_out_signal_format_get - get output signal format
288
* @zldev: pointer to zl3073x device
289
* @index: output index
290
*
291
* Return: signal format of given output
292
*/
293
static inline u8
294
zl3073x_out_signal_format_get(struct zl3073x_dev *zldev, u8 index)
295
{
296
return zldev->out[index].signal_format;
297
}
298
299
/**
300
* zl3073x_out_dpll_get - get DPLL ID the output is driven by
301
* @zldev: pointer to zl3073x device
302
* @index: output index
303
*
304
* Return: ID of DPLL the given output is driven by
305
*/
306
static inline
307
u8 zl3073x_out_dpll_get(struct zl3073x_dev *zldev, u8 index)
308
{
309
u8 synth;
310
311
/* Get synthesizer connected to given output */
312
synth = zl3073x_out_synth_get(zldev, index);
313
314
/* Return DPLL that drives the synth */
315
return zl3073x_synth_dpll_get(zldev, synth);
316
}
317
318
/**
319
* zl3073x_out_is_diff - check if the given output is differential
320
* @zldev: pointer to zl3073x device
321
* @index: output index
322
*
323
* Return: true if output is differential, false if output is single-ended
324
*/
325
static inline bool
326
zl3073x_out_is_diff(struct zl3073x_dev *zldev, u8 index)
327
{
328
switch (zl3073x_out_signal_format_get(zldev, index)) {
329
case ZL_OUTPUT_MODE_SIGNAL_FORMAT_LVDS:
330
case ZL_OUTPUT_MODE_SIGNAL_FORMAT_DIFF:
331
case ZL_OUTPUT_MODE_SIGNAL_FORMAT_LOWVCM:
332
return true;
333
default:
334
break;
335
}
336
337
return false;
338
}
339
340
/**
341
* zl3073x_output_pin_is_enabled - check if the given output pin is enabled
342
* @zldev: pointer to zl3073x device
343
* @id: output pin id
344
*
345
* Checks if the output of the given output pin is enabled and also that
346
* its signal format also enables the given pin.
347
*
348
* Return: true if output pin is enabled, false if output pin is disabled
349
*/
350
static inline bool
351
zl3073x_output_pin_is_enabled(struct zl3073x_dev *zldev, u8 id)
352
{
353
u8 output = zl3073x_output_pin_out_get(id);
354
355
/* Check if the whole output is enabled */
356
if (!zl3073x_out_is_enabled(zldev, output))
357
return false;
358
359
/* Check signal format */
360
switch (zl3073x_out_signal_format_get(zldev, output)) {
361
case ZL_OUTPUT_MODE_SIGNAL_FORMAT_DISABLED:
362
/* Both output pins are disabled by signal format */
363
return false;
364
365
case ZL_OUTPUT_MODE_SIGNAL_FORMAT_1P:
366
/* Output is one single ended P-pin output */
367
if (zl3073x_is_n_pin(id))
368
return false;
369
break;
370
case ZL_OUTPUT_MODE_SIGNAL_FORMAT_1N:
371
/* Output is one single ended N-pin output */
372
if (zl3073x_is_p_pin(id))
373
return false;
374
break;
375
default:
376
/* For other format both pins are enabled */
377
break;
378
}
379
380
return true;
381
}
382
383
#endif /* _ZL3073X_CORE_H */
384
385