1 /* SPDX-License-Identifier: BSD-3-Clause */
2 /*
3 * Copyright 2020-2025 NXP
4 */
5 #ifndef S32CC_CLK_MODULES_H
6 #define S32CC_CLK_MODULES_H
7
8 #include <inttypes.h>
9 #include <stdbool.h>
10 #include <stddef.h>
11
12 #define MHZ UL(1000000)
13 #define GHZ (UL(1000) * MHZ)
14
15 enum s32cc_clkm_type {
16 s32cc_osc_t,
17 s32cc_clk_t,
18 s32cc_pll_t,
19 s32cc_pll_out_div_t,
20 s32cc_dfs_t,
21 s32cc_dfs_div_t,
22 s32cc_cgm_div_t,
23 s32cc_clkmux_t,
24 s32cc_shared_clkmux_t,
25 s32cc_fixed_div_t,
26 s32cc_part_t,
27 s32cc_part_block_t,
28 s32cc_part_block_link_t,
29 };
30
31 enum s32cc_clk_source {
32 S32CC_FIRC,
33 S32CC_FXOSC,
34 S32CC_SIRC,
35 S32CC_ARM_PLL,
36 S32CC_ARM_DFS,
37 S32CC_PERIPH_PLL,
38 S32CC_CGM0,
39 S32CC_CGM1,
40 S32CC_DDR_PLL,
41 S32CC_PERIPH_DFS,
42 S32CC_CGM5,
43 };
44
45 struct s32cc_clk_obj {
46 enum s32cc_clkm_type type;
47 uint32_t refcount;
48 };
49
50 struct s32cc_osc {
51 struct s32cc_clk_obj desc;
52 enum s32cc_clk_source source;
53 unsigned long freq;
54 void *base;
55 };
56
57 #define S32CC_OSC_INIT_FREQ(SOURCE, FREQ) \
58 { \
59 .desc = { \
60 .type = s32cc_osc_t, \
61 }, \
62 .source = (SOURCE), \
63 .freq = (FREQ), \
64 }
65
66 #define S32CC_OSC_INIT(SOURCE) \
67 S32CC_OSC_INIT_FREQ(SOURCE, 0)
68
69 struct s32cc_clkmux {
70 struct s32cc_clk_obj desc;
71 enum s32cc_clk_source module;
72 uint8_t index; /* Mux index in parent module */
73 unsigned long source_id; /* Selected source */
74 uint8_t nclks; /* Number of input clocks */
75 unsigned long clkids[5]; /* IDs of the input clocks */
76 };
77
78 #define S32CC_CLKMUX_TYPE_INIT(TYPE, MODULE, INDEX, NCLKS, ...) \
79 { \
80 .desc = { \
81 .type = (TYPE), \
82 }, \
83 .module = (MODULE), \
84 .index = (INDEX), \
85 .nclks = (NCLKS), \
86 .clkids = {__VA_ARGS__}, \
87 }
88
89 #define S32CC_CLKMUX_INIT(MODULE, INDEX, NCLKS, ...) \
90 S32CC_CLKMUX_TYPE_INIT(s32cc_clkmux_t, MODULE, \
91 INDEX, NCLKS, __VA_ARGS__)
92
93 #define S32CC_SHARED_CLKMUX_INIT(MODULE, INDEX, NCLKS, ...) \
94 S32CC_CLKMUX_TYPE_INIT(s32cc_shared_clkmux_t, MODULE, \
95 INDEX, NCLKS, __VA_ARGS__)
96
97 struct s32cc_pll {
98 struct s32cc_clk_obj desc;
99 struct s32cc_clk_obj *source;
100 enum s32cc_clk_source instance;
101 unsigned long vco_freq;
102 uint32_t ndividers;
103 uintptr_t base;
104 };
105
106 #define S32CC_PLL_INIT(PLL_MUX_CLK, INSTANCE, NDIVIDERS) \
107 { \
108 .desc = { \
109 .type = s32cc_pll_t, \
110 }, \
111 .source = &(PLL_MUX_CLK).desc, \
112 .instance = (INSTANCE), \
113 .ndividers = (NDIVIDERS), \
114 }
115
116 struct s32cc_pll_out_div {
117 struct s32cc_clk_obj desc;
118 struct s32cc_clk_obj *parent;
119 uint32_t index;
120 unsigned long freq;
121 };
122
123 #define S32CC_PLL_OUT_DIV_INIT(PARENT, INDEX) \
124 { \
125 .desc = { \
126 .type = s32cc_pll_out_div_t, \
127 }, \
128 .parent = &(PARENT).desc, \
129 .index = (INDEX), \
130 }
131
132 #define S32CC_PLL_OUT_DIV_INIT(PARENT, INDEX) \
133 { \
134 .desc = { \
135 .type = s32cc_pll_out_div_t, \
136 }, \
137 .parent = &(PARENT).desc, \
138 .index = (INDEX), \
139 }
140
141 struct s32cc_dfs {
142 struct s32cc_clk_obj desc;
143 struct s32cc_clk_obj *parent;
144 enum s32cc_clk_source instance;
145 uintptr_t base;
146 };
147
148 #define S32CC_DFS_INIT(PARENT, INSTANCE) \
149 { \
150 .desc = { \
151 .type = s32cc_dfs_t, \
152 }, \
153 .parent = &(PARENT).desc, \
154 .instance = (INSTANCE), \
155 }
156
157 struct s32cc_dfs_div {
158 struct s32cc_clk_obj desc;
159 struct s32cc_clk_obj *parent;
160 uint32_t index;
161 unsigned long freq;
162 };
163
164 #define S32CC_DFS_DIV_INIT(PARENT, INDEX) \
165 { \
166 .desc = { \
167 .type = s32cc_dfs_div_t, \
168 }, \
169 .parent = &(PARENT).desc, \
170 .index = (INDEX), \
171 }
172
173 struct s32cc_fixed_div {
174 struct s32cc_clk_obj desc;
175 struct s32cc_clk_obj *parent;
176 uint32_t rate_div;
177 };
178
179 #define S32CC_FIXED_DIV_INIT(PARENT, RATE_DIV) \
180 { \
181 .desc = { \
182 .type = s32cc_fixed_div_t, \
183 }, \
184 .parent = &(PARENT).desc, \
185 .rate_div = (RATE_DIV), \
186 }
187
188 struct s32cc_clk {
189 struct s32cc_clk_obj desc;
190 struct s32cc_clk_obj *module;
191 struct s32cc_clk *pclock;
192 unsigned long min_freq;
193 unsigned long max_freq;
194 };
195
196 struct s32cc_clk_array {
197 unsigned long type_mask;
198 struct s32cc_clk **clks;
199 size_t n_clks;
200 };
201
202 #define S32CC_FREQ_CLK(PARENT_MODULE, PARENT, MIN_F, MAX_F) \
203 { \
204 .desc = { \
205 .type = s32cc_clk_t, \
206 }, \
207 .pclock = (PARENT), \
208 .module = (PARENT_MODULE), \
209 .min_freq = (MIN_F), \
210 .max_freq = (MAX_F), \
211 }
212
213 #define S32CC_FREQ_MODULE_CLK(PARENT_MODULE, MIN_F, MAX_F) \
214 S32CC_FREQ_CLK(&(PARENT_MODULE).desc, NULL, MIN_F, MAX_F)
215
216 #define S32CC_MODULE_CLK(PARENT_MODULE) \
217 S32CC_FREQ_MODULE_CLK(PARENT_MODULE, 0, 0)
218
219 #define S32CC_CHILD_CLK(PARENT, MIN_F, MAX_F) \
220 S32CC_FREQ_CLK(NULL, &(PARENT), MIN_F, MAX_F)
221
222 struct s32cc_part {
223 struct s32cc_clk_obj desc;
224 uint32_t partition_id;
225 };
226
227 #define S32CC_PART(PART_NUM) \
228 { \
229 .desc = { \
230 .type = s32cc_part_t, \
231 }, \
232 .partition_id = (PART_NUM), \
233 }
234
235 enum s32cc_part_block_type {
236 s32cc_part_block0,
237 s32cc_part_block1,
238 s32cc_part_block2,
239 s32cc_part_block3,
240 s32cc_part_block4,
241 s32cc_part_block5,
242 s32cc_part_block6,
243 s32cc_part_block7,
244 s32cc_part_block8,
245 s32cc_part_block9,
246 s32cc_part_block10,
247 s32cc_part_block11,
248 s32cc_part_block12,
249 s32cc_part_block13,
250 s32cc_part_block14,
251 s32cc_part_block15,
252 };
253
254 struct s32cc_part_block {
255 struct s32cc_clk_obj desc;
256 struct s32cc_part *part;
257 enum s32cc_part_block_type block;
258 bool status;
259 };
260
261 #define S32CC_PART_BLOCK_STATUS(PART_META, BLOCK_TYPE, STATUS) \
262 { \
263 .desc = { \
264 .type = s32cc_part_block_t, \
265 }, \
266 .part = (PART_META), \
267 .block = (BLOCK_TYPE), \
268 .status = (STATUS), \
269 }
270
271 #define S32CC_PART_BLOCK(PARENT, BLOCK_TYPE) \
272 S32CC_PART_BLOCK_STATUS(PARENT, BLOCK_TYPE, true)
273
274 #define S32CC_PART_BLOCK_NO_STATUS(PARENT, BLOCK_TYPE) \
275 S32CC_PART_BLOCK_STATUS(PARENT, BLOCK_TYPE, false)
276
277 struct s32cc_part_block_link {
278 struct s32cc_clk_obj desc;
279 struct s32cc_clk_obj *parent;
280 struct s32cc_part_block *block;
281 };
282
283 #define S32CC_PART_BLOCK_LINK(PARENT, BLOCK) \
284 { \
285 .desc = { \
286 .type = s32cc_part_block_link_t, \
287 }, \
288 .parent = &(PARENT).desc, \
289 .block = (BLOCK), \
290 }
291
292 struct s32cc_cgm_div {
293 struct s32cc_clk_obj desc;
294 struct s32cc_clk_obj *parent;
295 unsigned long freq;
296 uint32_t index;
297 };
298
299 #define S32CC_CGM_DIV_INIT(PARENT, INDEX) \
300 { \
301 .desc = { \
302 .type = s32cc_cgm_div_t, \
303 }, \
304 .parent = &(PARENT).desc, \
305 .index = (INDEX), \
306 }
307
s32cc_obj2osc(const struct s32cc_clk_obj * mod)308 static inline struct s32cc_osc *s32cc_obj2osc(const struct s32cc_clk_obj *mod)
309 {
310 uintptr_t osc_addr;
311
312 osc_addr = ((uintptr_t)mod) - offsetof(struct s32cc_osc, desc);
313 return (struct s32cc_osc *)osc_addr;
314 }
315
s32cc_obj2clk(const struct s32cc_clk_obj * mod)316 static inline struct s32cc_clk *s32cc_obj2clk(const struct s32cc_clk_obj *mod)
317 {
318 uintptr_t clk_addr;
319
320 clk_addr = ((uintptr_t)mod) - offsetof(struct s32cc_clk, desc);
321 return (struct s32cc_clk *)clk_addr;
322 }
323
is_s32cc_clk_mux(const struct s32cc_clk * clk)324 static inline bool is_s32cc_clk_mux(const struct s32cc_clk *clk)
325 {
326 const struct s32cc_clk_obj *module;
327
328 module = clk->module;
329 if (module == NULL) {
330 return false;
331 }
332
333 return (module->type == s32cc_clkmux_t) ||
334 (module->type == s32cc_shared_clkmux_t);
335 }
336
s32cc_obj2clkmux(const struct s32cc_clk_obj * mod)337 static inline struct s32cc_clkmux *s32cc_obj2clkmux(const struct s32cc_clk_obj *mod)
338 {
339 uintptr_t cmux_addr;
340
341 cmux_addr = ((uintptr_t)mod) - offsetof(struct s32cc_clkmux, desc);
342 return (struct s32cc_clkmux *)cmux_addr;
343 }
344
s32cc_clk2mux(const struct s32cc_clk * clk)345 static inline struct s32cc_clkmux *s32cc_clk2mux(const struct s32cc_clk *clk)
346 {
347 if (!is_s32cc_clk_mux(clk)) {
348 return NULL;
349 }
350
351 return s32cc_obj2clkmux(clk->module);
352 }
353
s32cc_obj2pll(const struct s32cc_clk_obj * mod)354 static inline struct s32cc_pll *s32cc_obj2pll(const struct s32cc_clk_obj *mod)
355 {
356 uintptr_t pll_addr;
357
358 pll_addr = ((uintptr_t)mod) - offsetof(struct s32cc_pll, desc);
359 return (struct s32cc_pll *)pll_addr;
360 }
361
s32cc_obj2plldiv(const struct s32cc_clk_obj * mod)362 static inline struct s32cc_pll_out_div *s32cc_obj2plldiv(const struct s32cc_clk_obj *mod)
363 {
364 uintptr_t plldiv_addr;
365
366 plldiv_addr = ((uintptr_t)mod) - offsetof(struct s32cc_pll_out_div, desc);
367 return (struct s32cc_pll_out_div *)plldiv_addr;
368 }
369
s32cc_obj2fixeddiv(const struct s32cc_clk_obj * mod)370 static inline struct s32cc_fixed_div *s32cc_obj2fixeddiv(const struct s32cc_clk_obj *mod)
371 {
372 uintptr_t fdiv_addr;
373
374 fdiv_addr = ((uintptr_t)mod) - offsetof(struct s32cc_fixed_div, desc);
375 return (struct s32cc_fixed_div *)fdiv_addr;
376 }
377
s32cc_obj2dfs(const struct s32cc_clk_obj * mod)378 static inline struct s32cc_dfs *s32cc_obj2dfs(const struct s32cc_clk_obj *mod)
379 {
380 uintptr_t dfs_addr;
381
382 dfs_addr = ((uintptr_t)mod) - offsetof(struct s32cc_dfs, desc);
383 return (struct s32cc_dfs *)dfs_addr;
384 }
385
s32cc_obj2dfsdiv(const struct s32cc_clk_obj * mod)386 static inline struct s32cc_dfs_div *s32cc_obj2dfsdiv(const struct s32cc_clk_obj *mod)
387 {
388 uintptr_t dfs_div_addr;
389
390 dfs_div_addr = ((uintptr_t)mod) - offsetof(struct s32cc_dfs_div, desc);
391 return (struct s32cc_dfs_div *)dfs_div_addr;
392 }
393
s32cc_obj2part(const struct s32cc_clk_obj * mod)394 static inline struct s32cc_part *s32cc_obj2part(const struct s32cc_clk_obj *mod)
395 {
396 uintptr_t part_addr;
397
398 part_addr = ((uintptr_t)mod) - offsetof(struct s32cc_part, desc);
399 return (struct s32cc_part *)part_addr;
400 }
401
402 static inline struct s32cc_part_block *
s32cc_obj2partblock(const struct s32cc_clk_obj * mod)403 s32cc_obj2partblock(const struct s32cc_clk_obj *mod)
404 {
405 uintptr_t part_blk_addr;
406
407 part_blk_addr = ((uintptr_t)mod) - offsetof(struct s32cc_part_block, desc);
408 return (struct s32cc_part_block *)part_blk_addr;
409 }
410
411 static inline struct s32cc_part_block_link *
s32cc_obj2partblocklink(const struct s32cc_clk_obj * mod)412 s32cc_obj2partblocklink(const struct s32cc_clk_obj *mod)
413 {
414 uintptr_t blk_link;
415
416 blk_link = ((uintptr_t)mod) - offsetof(struct s32cc_part_block_link, desc);
417 return (struct s32cc_part_block_link *)blk_link;
418 }
419
s32cc_obj2cgmdiv(const struct s32cc_clk_obj * mod)420 static inline struct s32cc_cgm_div *s32cc_obj2cgmdiv(const struct s32cc_clk_obj *mod)
421 {
422 uintptr_t cgm_div_addr;
423
424 cgm_div_addr = ((uintptr_t)mod) - offsetof(struct s32cc_cgm_div, desc);
425 return (struct s32cc_cgm_div *)cgm_div_addr;
426 }
427
428 #endif /* S32CC_CLK_MODULES_H */
429