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