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