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