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 }; 26 27 enum s32cc_clk_source { 28 S32CC_FIRC, 29 S32CC_FXOSC, 30 S32CC_SIRC, 31 S32CC_ARM_PLL, 32 S32CC_ARM_DFS, 33 S32CC_PERIPH_PLL, 34 S32CC_CGM0, 35 S32CC_CGM1, 36 }; 37 38 struct s32cc_clk_obj { 39 enum s32cc_clkm_type type; 40 uint32_t refcount; 41 }; 42 43 struct s32cc_osc { 44 struct s32cc_clk_obj desc; 45 enum s32cc_clk_source source; 46 unsigned long freq; 47 void *base; 48 }; 49 50 #define S32CC_OSC_INIT(SOURCE) \ 51 { \ 52 .desc = { \ 53 .type = s32cc_osc_t, \ 54 }, \ 55 .source = (SOURCE), \ 56 } 57 58 struct s32cc_clkmux { 59 struct s32cc_clk_obj desc; 60 enum s32cc_clk_source module; 61 uint8_t index; /* Mux index in parent module */ 62 unsigned long source_id; /* Selected source */ 63 uint8_t nclks; /* Number of input clocks */ 64 unsigned long clkids[5]; /* IDs of the input clocks */ 65 }; 66 67 #define S32CC_CLKMUX_TYPE_INIT(TYPE, MODULE, INDEX, NCLKS, ...) \ 68 { \ 69 .desc = { \ 70 .type = (TYPE), \ 71 }, \ 72 .module = (MODULE), \ 73 .index = (INDEX), \ 74 .nclks = (NCLKS), \ 75 .clkids = {__VA_ARGS__}, \ 76 } 77 78 #define S32CC_CLKMUX_INIT(MODULE, INDEX, NCLKS, ...) \ 79 S32CC_CLKMUX_TYPE_INIT(s32cc_clkmux_t, MODULE, \ 80 INDEX, NCLKS, __VA_ARGS__) 81 82 #define S32CC_SHARED_CLKMUX_INIT(MODULE, INDEX, NCLKS, ...) \ 83 S32CC_CLKMUX_TYPE_INIT(s32cc_shared_clkmux_t, MODULE, \ 84 INDEX, NCLKS, __VA_ARGS__) 85 86 struct s32cc_pll { 87 struct s32cc_clk_obj desc; 88 struct s32cc_clk_obj *source; 89 enum s32cc_clk_source instance; 90 unsigned long vco_freq; 91 uint32_t ndividers; 92 uintptr_t base; 93 }; 94 95 #define S32CC_PLL_INIT(PLL_MUX_CLK, INSTANCE, NDIVIDERS) \ 96 { \ 97 .desc = { \ 98 .type = s32cc_pll_t, \ 99 }, \ 100 .source = &(PLL_MUX_CLK).desc, \ 101 .instance = (INSTANCE), \ 102 .ndividers = (NDIVIDERS), \ 103 } 104 105 struct s32cc_pll_out_div { 106 struct s32cc_clk_obj desc; 107 struct s32cc_clk_obj *parent; 108 uint32_t index; 109 unsigned long freq; 110 }; 111 112 #define S32CC_PLL_OUT_DIV_INIT(PARENT, INDEX) \ 113 { \ 114 .desc = { \ 115 .type = s32cc_pll_out_div_t, \ 116 }, \ 117 .parent = &(PARENT).desc, \ 118 .index = (INDEX), \ 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 struct s32cc_dfs { 131 struct s32cc_clk_obj desc; 132 struct s32cc_clk_obj *parent; 133 enum s32cc_clk_source instance; 134 uintptr_t base; 135 }; 136 137 #define S32CC_DFS_INIT(PARENT, INSTANCE) \ 138 { \ 139 .desc = { \ 140 .type = s32cc_dfs_t, \ 141 }, \ 142 .parent = &(PARENT).desc, \ 143 .instance = (INSTANCE), \ 144 } 145 146 struct s32cc_dfs_div { 147 struct s32cc_clk_obj desc; 148 struct s32cc_clk_obj *parent; 149 uint32_t index; 150 unsigned long freq; 151 }; 152 153 #define S32CC_DFS_DIV_INIT(PARENT, INDEX) \ 154 { \ 155 .desc = { \ 156 .type = s32cc_dfs_div_t, \ 157 }, \ 158 .parent = &(PARENT).desc, \ 159 .index = (INDEX), \ 160 } 161 162 struct s32cc_fixed_div { 163 struct s32cc_clk_obj desc; 164 struct s32cc_clk_obj *parent; 165 uint32_t rate_div; 166 }; 167 168 #define S32CC_FIXED_DIV_INIT(PARENT, RATE_DIV) \ 169 { \ 170 .desc = { \ 171 .type = s32cc_fixed_div_t, \ 172 }, \ 173 .parent = &(PARENT).desc, \ 174 .rate_div = (RATE_DIV), \ 175 } 176 177 struct s32cc_clk { 178 struct s32cc_clk_obj desc; 179 struct s32cc_clk_obj *module; 180 struct s32cc_clk *pclock; 181 unsigned long min_freq; 182 unsigned long max_freq; 183 }; 184 185 struct s32cc_clk_array { 186 unsigned long type_mask; 187 struct s32cc_clk **clks; 188 size_t n_clks; 189 }; 190 191 #define S32CC_FREQ_CLK(PARENT_MODULE, PARENT, MIN_F, MAX_F) \ 192 { \ 193 .desc = { \ 194 .type = s32cc_clk_t, \ 195 }, \ 196 .pclock = (PARENT), \ 197 .module = (PARENT_MODULE), \ 198 .min_freq = (MIN_F), \ 199 .max_freq = (MAX_F), \ 200 } 201 202 #define S32CC_FREQ_MODULE_CLK(PARENT_MODULE, MIN_F, MAX_F) \ 203 S32CC_FREQ_CLK(&(PARENT_MODULE).desc, NULL, MIN_F, MAX_F) 204 205 #define S32CC_MODULE_CLK(PARENT_MODULE) \ 206 S32CC_FREQ_MODULE_CLK(PARENT_MODULE, 0, 0) 207 208 #define S32CC_CHILD_CLK(PARENT, MIN_F, MAX_F) \ 209 S32CC_FREQ_CLK(NULL, &(PARENT), MIN_F, MAX_F) 210 211 static inline struct s32cc_osc *s32cc_obj2osc(const struct s32cc_clk_obj *mod) 212 { 213 uintptr_t osc_addr; 214 215 osc_addr = ((uintptr_t)mod) - offsetof(struct s32cc_osc, desc); 216 return (struct s32cc_osc *)osc_addr; 217 } 218 219 static inline struct s32cc_clk *s32cc_obj2clk(const struct s32cc_clk_obj *mod) 220 { 221 uintptr_t clk_addr; 222 223 clk_addr = ((uintptr_t)mod) - offsetof(struct s32cc_clk, desc); 224 return (struct s32cc_clk *)clk_addr; 225 } 226 227 static inline bool is_s32cc_clk_mux(const struct s32cc_clk *clk) 228 { 229 const struct s32cc_clk_obj *module; 230 231 module = clk->module; 232 if (module == NULL) { 233 return false; 234 } 235 236 return (module->type == s32cc_clkmux_t) || 237 (module->type == s32cc_shared_clkmux_t); 238 } 239 240 static inline struct s32cc_clkmux *s32cc_obj2clkmux(const struct s32cc_clk_obj *mod) 241 { 242 uintptr_t cmux_addr; 243 244 cmux_addr = ((uintptr_t)mod) - offsetof(struct s32cc_clkmux, desc); 245 return (struct s32cc_clkmux *)cmux_addr; 246 } 247 248 static inline struct s32cc_clkmux *s32cc_clk2mux(const struct s32cc_clk *clk) 249 { 250 if (!is_s32cc_clk_mux(clk)) { 251 return NULL; 252 } 253 254 return s32cc_obj2clkmux(clk->module); 255 } 256 257 static inline struct s32cc_pll *s32cc_obj2pll(const struct s32cc_clk_obj *mod) 258 { 259 uintptr_t pll_addr; 260 261 pll_addr = ((uintptr_t)mod) - offsetof(struct s32cc_pll, desc); 262 return (struct s32cc_pll *)pll_addr; 263 } 264 265 static inline struct s32cc_pll_out_div *s32cc_obj2plldiv(const struct s32cc_clk_obj *mod) 266 { 267 uintptr_t plldiv_addr; 268 269 plldiv_addr = ((uintptr_t)mod) - offsetof(struct s32cc_pll_out_div, desc); 270 return (struct s32cc_pll_out_div *)plldiv_addr; 271 } 272 273 static inline struct s32cc_fixed_div *s32cc_obj2fixeddiv(const struct s32cc_clk_obj *mod) 274 { 275 uintptr_t fdiv_addr; 276 277 fdiv_addr = ((uintptr_t)mod) - offsetof(struct s32cc_fixed_div, desc); 278 return (struct s32cc_fixed_div *)fdiv_addr; 279 } 280 281 static inline struct s32cc_dfs *s32cc_obj2dfs(const struct s32cc_clk_obj *mod) 282 { 283 uintptr_t dfs_addr; 284 285 dfs_addr = ((uintptr_t)mod) - offsetof(struct s32cc_dfs, desc); 286 return (struct s32cc_dfs *)dfs_addr; 287 } 288 289 static inline struct s32cc_dfs_div *s32cc_obj2dfsdiv(const struct s32cc_clk_obj *mod) 290 { 291 uintptr_t dfs_div_addr; 292 293 dfs_div_addr = ((uintptr_t)mod) - offsetof(struct s32cc_dfs_div, desc); 294 return (struct s32cc_dfs_div *)dfs_div_addr; 295 } 296 297 #endif /* S32CC_CLK_MODULES_H */ 298