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