Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/arm/mv/clk/periph.h
39537 views
1
/*-
2
* SPDX-License-Identifier: BSD-2-Clause
3
*
4
* Copyright (c) 2021 Semihalf.
5
*
6
* Redistribution and use in source and binary forms, with or without
7
* modification, are permitted provided that the following conditions
8
* are met:
9
* 1. Redistributions of source code must retain the above copyright
10
* notice, this list of conditions and the following disclaimer.
11
* 2. Redistributions in binary form must reproduce the above copyright
12
* notice, this list of conditions and the following disclaimer in the
13
* documentation and/or other materials provided with the distribution.
14
*
15
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25
* SUCH DAMAGE.
26
*
27
*/
28
29
#ifndef _PERIPH_H_
30
#define _PERIPH_H_
31
32
#include <dev/clk/clk.h>
33
#include <dev/clk/clk_mux.h>
34
#include <dev/clk/clk_div.h>
35
#include <dev/clk/clk_gate.h>
36
37
#define TBG_SEL 0x0
38
#define DIV_SEL0 0x4
39
#define DIV_SEL1 0x8
40
#define DIV_SEL2 0xC
41
#define CLK_SEL 0x10
42
#define CLK_DIS 0x14
43
#define DIV_MASK 0x7
44
45
#define MUX_POS 1
46
#define DIV1_POS 2
47
#define DIV2_POS 3
48
#define GATE_POS 4
49
#define FIXED1_POS 5
50
#define FIXED2_POS 6
51
#define CLK_MUX_POS 7
52
53
#define RD4(_clk, offset, val) \
54
CLKDEV_READ_4(clknode_get_device(_clk), offset, val)
55
56
#define A37x0_INTERNAL_CLK_ID(_base, _pos) \
57
((_base * 10) + (_pos))
58
59
#define CLK_FULL_DD(_name, _id, _gate_shift, _tbg_mux_shift, \
60
_clk_mux_shift, _div1_reg, _div2_reg, _div1_shift, _div2_shift, \
61
_tbg_mux_name, _div1_name, _div2_name, _clk_mux_name) \
62
{ \
63
.type = CLK_FULL_DD, \
64
.common_def.device_name = _name, \
65
.common_def.device_id = _id, \
66
.clk_def.full_dd.tbg_mux.clkdef.name = _tbg_mux_name, \
67
.clk_def.full_dd.tbg_mux.offset = TBG_SEL, \
68
.clk_def.full_dd.tbg_mux.shift = _tbg_mux_shift, \
69
.clk_def.full_dd.tbg_mux.width = 0x2, \
70
.clk_def.full_dd.tbg_mux.mux_flags = 0x0, \
71
.clk_def.full_dd.div1.clkdef.name = _div1_name, \
72
.clk_def.full_dd.div1.offset = _div1_reg, \
73
.clk_def.full_dd.div1.i_shift = _div1_shift, \
74
.clk_def.full_dd.div1.i_width = 0x3, \
75
.clk_def.full_dd.div1.f_shift = 0x0, \
76
.clk_def.full_dd.div1.f_width = 0x0, \
77
.clk_def.full_dd.div1.div_flags = 0x0, \
78
.clk_def.full_dd.div1.div_table = NULL, \
79
.clk_def.full_dd.div2.clkdef.name = _div2_name, \
80
.clk_def.full_dd.div2.offset = _div2_reg, \
81
.clk_def.full_dd.div2.i_shift = _div2_shift, \
82
.clk_def.full_dd.div2.i_width = 0x3, \
83
.clk_def.full_dd.div2.f_shift = 0x0, \
84
.clk_def.full_dd.div2.f_width = 0x0, \
85
.clk_def.full_dd.div2.div_flags = 0x0, \
86
.clk_def.full_dd.div2.div_table = NULL, \
87
.clk_def.full_dd.clk_mux.clkdef.name = _clk_mux_name, \
88
.clk_def.full_dd.clk_mux.offset = CLK_SEL, \
89
.clk_def.full_dd.clk_mux.shift = _clk_mux_shift, \
90
.clk_def.full_dd.clk_mux.width = 0x1, \
91
.clk_def.full_dd.clk_mux.mux_flags = 0x0, \
92
.clk_def.full_dd.gate.clkdef.name = _name, \
93
.clk_def.full_dd.gate.offset = CLK_DIS, \
94
.clk_def.full_dd.gate.shift = _gate_shift, \
95
.clk_def.full_dd.gate.on_value = 0, \
96
.clk_def.full_dd.gate.off_value = 1, \
97
.clk_def.full_dd.gate.mask = 0x1, \
98
.clk_def.full_dd.gate.gate_flags = 0x0 \
99
}
100
101
#define CLK_FULL(_name, _id, _gate_shift, _tbg_mux_shift, \
102
_clk_mux_shift, _div1_reg, _div1_shift, _div_table, _tbg_mux_name, \
103
_div1_name, _clk_mux_name) \
104
{ \
105
.type = CLK_FULL, \
106
.common_def.device_name = _name, \
107
.common_def.device_id = _id, \
108
.clk_def.full_d.tbg_mux.clkdef.name = _tbg_mux_name, \
109
.clk_def.full_d.tbg_mux.offset = TBG_SEL, \
110
.clk_def.full_d.tbg_mux.shift = _tbg_mux_shift, \
111
.clk_def.full_d.tbg_mux.width = 0x2, \
112
.clk_def.full_d.tbg_mux.mux_flags = 0x0, \
113
.clk_def.full_d.div.clkdef.name = _div1_name, \
114
.clk_def.full_d.div.offset = _div1_reg, \
115
.clk_def.full_d.div.i_shift = _div1_shift, \
116
.clk_def.full_d.div.i_width = 0x3, \
117
.clk_def.full_d.div.f_shift = 0x0, \
118
.clk_def.full_d.div.f_width = 0x0, \
119
.clk_def.full_d.div.div_flags = 0x0, \
120
.clk_def.full_d.div.div_table = _div_table, \
121
.clk_def.full_d.clk_mux.clkdef.name = _clk_mux_name, \
122
.clk_def.full_d.clk_mux.offset = CLK_SEL, \
123
.clk_def.full_d.clk_mux.shift = _clk_mux_shift, \
124
.clk_def.full_d.clk_mux.width = 0x1, \
125
.clk_def.full_d.clk_mux.mux_flags = 0x0, \
126
.clk_def.full_d.gate.clkdef.name = _name, \
127
.clk_def.full_d.gate.offset = CLK_DIS, \
128
.clk_def.full_d.gate.shift = _gate_shift, \
129
.clk_def.full_d.gate.on_value = 0, \
130
.clk_def.full_d.gate.off_value = 1, \
131
.clk_def.full_d.gate.mask = 0x1, \
132
.clk_def.full_d.gate.gate_flags = 0x0 \
133
}
134
135
#define CLK_CPU(_name, _id, _tbg_mux_shift, _clk_mux_shift, _div1_reg, \
136
_div1_shift, _div_table, _tbg_mux_name, _div1_name) \
137
{ \
138
.type = CLK_CPU, \
139
.common_def.device_name = _name, \
140
.common_def.device_id = _id, \
141
.clk_def.cpu.tbg_mux.clkdef.name = _tbg_mux_name, \
142
.clk_def.cpu.tbg_mux.offset = TBG_SEL, \
143
.clk_def.cpu.tbg_mux.shift = _tbg_mux_shift, \
144
.clk_def.cpu.tbg_mux.width = 0x2, \
145
.clk_def.cpu.tbg_mux.mux_flags = 0x0, \
146
.clk_def.cpu.div.clkdef.name = _div1_name, \
147
.clk_def.cpu.div.offset = _div1_reg, \
148
.clk_def.cpu.div.i_shift = _div1_shift, \
149
.clk_def.cpu.div.i_width = 0x3, \
150
.clk_def.cpu.div.f_shift = 0x0, \
151
.clk_def.cpu.div.f_width = 0x0, \
152
.clk_def.cpu.div.div_flags = 0x0, \
153
.clk_def.cpu.div.div_table = _div_table, \
154
.clk_def.cpu.clk_mux.clkdef.name = _name, \
155
.clk_def.cpu.clk_mux.offset = CLK_SEL, \
156
.clk_def.cpu.clk_mux.shift = _clk_mux_shift, \
157
.clk_def.cpu.clk_mux.width = 0x1, \
158
.clk_def.cpu.clk_mux.mux_flags = 0x0, \
159
}
160
161
#define CLK_GATE(_name, _id, _gate_shift, _pname) \
162
{ \
163
.type = CLK_GATE, \
164
.common_def.device_name = _name, \
165
.common_def.device_id = _id, \
166
.common_def.pname = _pname, \
167
.clk_def.gate.gate.clkdef.name = _name, \
168
.clk_def.gate.gate.clkdef.parent_cnt = 1, \
169
.clk_def.gate.gate.offset = CLK_DIS, \
170
.clk_def.gate.gate.shift = _gate_shift, \
171
.clk_def.gate.gate.on_value = 0, \
172
.clk_def.gate.gate.off_value = 1, \
173
.clk_def.gate.gate.mask = 0x1, \
174
.clk_def.gate.gate.gate_flags = 0x0 \
175
}
176
177
#define CLK_MDD(_name, _id, _tbg_mux_shift, _clk_mux_shift, _div1_reg, \
178
_div2_reg, _div1_shift, _div2_shift, _tbg_mux_name, _div1_name, \
179
_div2_name) \
180
{ \
181
.type = CLK_MDD, \
182
.common_def.device_name = _name, \
183
.common_def.device_id = _id, \
184
.clk_def.mdd.tbg_mux.clkdef.name = _tbg_mux_name, \
185
.clk_def.mdd.tbg_mux.offset = TBG_SEL, \
186
.clk_def.mdd.tbg_mux.shift = _tbg_mux_shift, \
187
.clk_def.mdd.tbg_mux.width = 0x2, \
188
.clk_def.mdd.tbg_mux.mux_flags = 0x0, \
189
.clk_def.mdd.div1.clkdef.name = _div1_name, \
190
.clk_def.mdd.div1.offset = _div1_reg, \
191
.clk_def.mdd.div1.i_shift = _div1_shift, \
192
.clk_def.mdd.div1.i_width = 0x3, \
193
.clk_def.mdd.div1.f_shift = 0x0, \
194
.clk_def.mdd.div1.f_width = 0x0, \
195
.clk_def.mdd.div1.div_flags = 0x0, \
196
.clk_def.mdd.div1.div_table = NULL, \
197
.clk_def.mdd.div2.clkdef.name = _div2_name, \
198
.clk_def.mdd.div2.offset = _div2_reg, \
199
.clk_def.mdd.div2.i_shift = _div2_shift, \
200
.clk_def.mdd.div2.i_width = 0x3, \
201
.clk_def.mdd.div2.f_shift = 0x0, \
202
.clk_def.mdd.div2.f_width = 0x0, \
203
.clk_def.mdd.div2.div_flags = 0x0, \
204
.clk_def.mdd.div2.div_table = NULL, \
205
.clk_def.mdd.clk_mux.clkdef.name = _name, \
206
.clk_def.mdd.clk_mux.offset = CLK_SEL, \
207
.clk_def.mdd.clk_mux.shift = _clk_mux_shift, \
208
.clk_def.mdd.clk_mux.width = 0x1, \
209
.clk_def.mdd.clk_mux.mux_flags = 0x0 \
210
}
211
212
#define CLK_MUX_GATE(_name, _id, _gate_shift, _mux_shift, _pname, \
213
_mux_name, _fixed_name) \
214
{ \
215
.type = CLK_MUX_GATE, \
216
.common_def.device_name = _name, \
217
.common_def.device_id = _id, \
218
.common_def.pname = _pname, \
219
.clk_def.mux_gate.mux.clkdef.name = _mux_name, \
220
.clk_def.mux_gate.mux.offset = TBG_SEL, \
221
.clk_def.mux_gate.mux.shift = _mux_shift, \
222
.clk_def.mux_gate.mux.width = 0x1, \
223
.clk_def.mux_gate.mux.mux_flags = 0x0, \
224
.clk_def.mux_gate.gate.clkdef.name = _name, \
225
.clk_def.mux_gate.gate.offset = CLK_DIS, \
226
.clk_def.mux_gate.gate.shift = _gate_shift, \
227
.clk_def.mux_gate.gate.on_value = 0, \
228
.clk_def.mux_gate.gate.off_value = 1, \
229
.clk_def.mux_gate.gate.mask = 0x1, \
230
.clk_def.mux_gate.gate.gate_flags = 0x0, \
231
.clk_def.mux_gate.fixed.clkdef.name = _fixed_name \
232
}
233
234
#define CLK_MUX_GATE_FIXED(_name, _id, _gate_shift, _mux_shift, \
235
_mux_name, _gate_name, _fixed1_name) \
236
{ \
237
.type = CLK_MUX_GATE_FIXED, \
238
.common_def.device_name = _name, \
239
.common_def.device_id = _id, \
240
.clk_def.mux_gate_fixed.mux.clkdef.name = _mux_name, \
241
.clk_def.mux_gate_fixed.mux.offset = TBG_SEL, \
242
.clk_def.mux_gate_fixed.mux.shift = _mux_shift, \
243
.clk_def.mux_gate_fixed.mux.width = 0x1, \
244
.clk_def.mux_gate_fixed.mux.mux_flags = 0x0, \
245
.clk_def.mux_gate_fixed.gate.clkdef.name = _gate_name, \
246
.clk_def.mux_gate_fixed.gate.offset = CLK_DIS, \
247
.clk_def.mux_gate_fixed.gate.shift = _gate_shift, \
248
.clk_def.mux_gate_fixed.gate.on_value = 0, \
249
.clk_def.mux_gate_fixed.gate.off_value = 1, \
250
.clk_def.mux_gate_fixed.gate.mask = 0x1, \
251
.clk_def.mux_gate_fixed.gate.gate_flags = 0x0, \
252
.clk_def.mux_gate_fixed.fixed1.clkdef.name = _fixed1_name, \
253
.clk_def.mux_gate_fixed.fixed2.clkdef.name = _name \
254
}
255
256
#define CLK_FIXED(_name, _id, _gate_shift, _mux_shift, _mux_name, \
257
_fixed_name) \
258
{ \
259
.type = CLK_FIXED, \
260
.common_def.device_name = _name, \
261
.common_def.device_id = _id, \
262
.clk_def.fixed.mux.clkdef.name = _mux_name, \
263
.clk_def.fixed.mux.offset = TBG_SEL, \
264
.clk_def.fixed.mux.shift = _mux_shift, \
265
.clk_def.fixed.mux.width = 0x1, \
266
.clk_def.fixed.mux.mux_flags = 0x0, \
267
.clk_def.fixed.gate.clkdef.name = _name, \
268
.clk_def.fixed.gate.offset = CLK_DIS, \
269
.clk_def.fixed.gate.shift = _gate_shift, \
270
.clk_def.fixed.gate.on_value = 0, \
271
.clk_def.fixed.gate.off_value = 1, \
272
.clk_def.fixed.gate.mask = 0x1, \
273
.clk_def.fixed.gate.gate_flags = 0x0, \
274
.clk_def.fixed.fixed.clkdef.name = _fixed_name \
275
}
276
277
struct a37x0_periph_clk_softc {
278
device_t dev;
279
struct resource *res;
280
struct clkdom *clkdom;
281
struct mtx mtx;
282
struct a37x0_periph_clknode_def *devices;
283
int device_count;
284
};
285
286
struct a37x0_periph_clk_dd_def {
287
struct clk_mux_def tbg_mux;
288
struct clk_div_def div1;
289
struct clk_div_def div2;
290
struct clk_mux_def clk_mux;
291
struct clk_gate_def gate;
292
};
293
294
struct a37x0_periph_clk_cpu_def {
295
struct clk_mux_def tbg_mux;
296
struct clk_div_def div;
297
struct clk_mux_def clk_mux;
298
};
299
300
struct a37x0_periph_clk_d_def {
301
struct clk_mux_def tbg_mux;
302
struct clk_div_def div;
303
struct clk_mux_def clk_mux;
304
struct clk_gate_def gate;
305
};
306
307
struct a37x0_periph_clk_fixed_def {
308
struct clk_mux_def mux;
309
struct clk_fixed_def fixed;
310
struct clk_gate_def gate;
311
};
312
313
struct a37x0_periph_clk_gate_def {
314
struct clk_gate_def gate;
315
};
316
317
struct a37x0_periph_clk_mux_dd_def {
318
struct clk_mux_def tbg_mux;
319
struct clk_div_def div1;
320
struct clk_div_def div2;
321
struct clk_mux_def clk_mux;
322
};
323
324
struct a37x0_periph_clk_mux_div_def {
325
struct clk_mux_def mux;
326
struct clk_div_def div;
327
};
328
329
struct a37x0_periph_clk_mux_gate_def {
330
struct clk_mux_def mux;
331
struct clk_fixed_def fixed;
332
struct clk_gate_def gate;
333
};
334
335
struct a37x0_periph_clk_mux_gate_fixed_def {
336
struct clk_fixed_def fixed1;
337
struct clk_mux_def mux;
338
struct clk_gate_def gate;
339
struct clk_fixed_def fixed2;
340
};
341
342
enum a37x0_periph_clk_type {
343
/* Double divider clock */
344
CLK_FULL_DD,
345
/* Single divider clock */
346
CLK_FULL,
347
/* Gate clock */
348
CLK_GATE,
349
/* Mux, gate clock */
350
CLK_MUX_GATE,
351
/* CPU clock */
352
CLK_CPU,
353
/* Clock with fixed frequency divider */
354
CLK_FIXED,
355
/* Clock with double divider, without gate */
356
CLK_MDD,
357
/* Clock with two fixed frequency dividers */
358
CLK_MUX_GATE_FIXED
359
};
360
361
struct a37x0_periph_common_defs {
362
char *device_name;
363
int device_id;
364
int tbg_cnt;
365
const char *pname;
366
const char **tbgs;
367
const char *xtal;
368
};
369
370
union a37x0_periph_clocks_defs {
371
struct a37x0_periph_clk_dd_def full_dd;
372
struct a37x0_periph_clk_d_def full_d;
373
struct a37x0_periph_clk_gate_def gate;
374
struct a37x0_periph_clk_mux_gate_def mux_gate;
375
struct a37x0_periph_clk_cpu_def cpu;
376
struct a37x0_periph_clk_fixed_def fixed;
377
struct a37x0_periph_clk_mux_dd_def mdd;
378
struct a37x0_periph_clk_mux_gate_fixed_def mux_gate_fixed;
379
};
380
381
struct a37x0_periph_clknode_def {
382
enum a37x0_periph_clk_type type;
383
struct a37x0_periph_common_defs common_def;
384
union a37x0_periph_clocks_defs clk_def;
385
};
386
387
int a37x0_periph_create_mux(struct clkdom *,
388
struct clk_mux_def *, int);
389
int a37x0_periph_create_div(struct clkdom *,
390
struct clk_div_def *, int);
391
int a37x0_periph_create_gate(struct clkdom *,
392
struct clk_gate_def *, int);
393
void a37x0_periph_set_props(struct clknode_init_def *, const char **,
394
unsigned int);
395
int a37x0_periph_d_register_full_clk_dd(struct clkdom *,
396
struct a37x0_periph_clknode_def *);
397
int a37x0_periph_d_register_full_clk(struct clkdom *,
398
struct a37x0_periph_clknode_def *);
399
int a37x0_periph_d_register_periph_cpu(struct clkdom *,
400
struct a37x0_periph_clknode_def *);
401
int a37x0_periph_fixed_register_fixed(struct clkdom*,
402
struct a37x0_periph_clknode_def *);
403
int a37x0_periph_gate_register_gate(struct clkdom *,
404
struct a37x0_periph_clknode_def *);
405
int a37x0_periph_d_register_mdd(struct clkdom *,
406
struct a37x0_periph_clknode_def *);
407
int a37x0_periph_d_register_mux_div_clk(struct clkdom *,
408
struct a37x0_periph_clknode_def *);
409
int a37x0_periph_register_mux_gate(struct clkdom *,
410
struct a37x0_periph_clknode_def *);
411
int a37x0_periph_register_mux_gate_fixed(struct clkdom *,
412
struct a37x0_periph_clknode_def *);
413
414
int a37x0_periph_clk_read_4(device_t, bus_addr_t, uint32_t *);
415
void a37x0_periph_clk_device_unlock(device_t);
416
void a37x0_periph_clk_device_lock(device_t);
417
int a37x0_periph_clk_attach(device_t);
418
int a37x0_periph_clk_detach(device_t);
419
420
#endif
421
422