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 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 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 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 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 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 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 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 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 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 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 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 * 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 * 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 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