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