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