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