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