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_clkmux_t, 21 s32cc_shared_clkmux_t, 22 s32cc_fixed_div_t, 23 }; 24 25 enum s32cc_clk_source { 26 S32CC_FIRC, 27 S32CC_FXOSC, 28 S32CC_SIRC, 29 S32CC_ARM_PLL, 30 S32CC_CGM1, 31 }; 32 33 struct s32cc_clk_obj { 34 enum s32cc_clkm_type type; 35 uint32_t refcount; 36 }; 37 38 struct s32cc_osc { 39 struct s32cc_clk_obj desc; 40 enum s32cc_clk_source source; 41 unsigned long freq; 42 void *base; 43 }; 44 45 #define S32CC_OSC_INIT(SOURCE) \ 46 { \ 47 .desc = { \ 48 .type = s32cc_osc_t, \ 49 }, \ 50 .source = (SOURCE), \ 51 } 52 53 struct s32cc_clkmux { 54 struct s32cc_clk_obj desc; 55 enum s32cc_clk_source module; 56 uint8_t index; /* Mux index in parent module */ 57 unsigned long source_id; /* Selected source */ 58 uint8_t nclks; /* Number of input clocks */ 59 unsigned long clkids[5]; /* IDs of the input clocks */ 60 }; 61 62 #define S32CC_CLKMUX_TYPE_INIT(TYPE, MODULE, INDEX, NCLKS, ...) \ 63 { \ 64 .desc = { \ 65 .type = (TYPE), \ 66 }, \ 67 .module = (MODULE), \ 68 .index = (INDEX), \ 69 .nclks = (NCLKS), \ 70 .clkids = {__VA_ARGS__}, \ 71 } 72 73 #define S32CC_CLKMUX_INIT(MODULE, INDEX, NCLKS, ...) \ 74 S32CC_CLKMUX_TYPE_INIT(s32cc_clkmux_t, MODULE, \ 75 INDEX, NCLKS, __VA_ARGS__) 76 77 #define S32CC_SHARED_CLKMUX_INIT(MODULE, INDEX, NCLKS, ...) \ 78 S32CC_CLKMUX_TYPE_INIT(s32cc_shared_clkmux_t, MODULE, \ 79 INDEX, NCLKS, __VA_ARGS__) 80 81 struct s32cc_pll { 82 struct s32cc_clk_obj desc; 83 struct s32cc_clk_obj *source; 84 enum s32cc_clk_source instance; 85 unsigned long vco_freq; 86 uint32_t ndividers; 87 uintptr_t base; 88 }; 89 90 #define S32CC_PLL_INIT(PLL_MUX_CLK, INSTANCE, NDIVIDERS) \ 91 { \ 92 .desc = { \ 93 .type = s32cc_pll_t, \ 94 }, \ 95 .source = &(PLL_MUX_CLK).desc, \ 96 .instance = (INSTANCE), \ 97 .ndividers = (NDIVIDERS), \ 98 } 99 100 struct s32cc_pll_out_div { 101 struct s32cc_clk_obj desc; 102 struct s32cc_clk_obj *parent; 103 uint32_t index; 104 unsigned long freq; 105 }; 106 107 #define S32CC_PLL_OUT_DIV_INIT(PARENT, INDEX) \ 108 { \ 109 .desc = { \ 110 .type = s32cc_pll_out_div_t, \ 111 }, \ 112 .parent = &(PARENT).desc, \ 113 .index = (INDEX), \ 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 struct s32cc_fixed_div { 126 struct s32cc_clk_obj desc; 127 struct s32cc_clk_obj *parent; 128 uint32_t rate_div; 129 }; 130 131 #define S32CC_FIXED_DIV_INIT(PARENT, RATE_DIV) \ 132 { \ 133 .desc = { \ 134 .type = s32cc_fixed_div_t, \ 135 }, \ 136 .parent = &(PARENT).desc, \ 137 .rate_div = (RATE_DIV), \ 138 } 139 140 struct s32cc_clk { 141 struct s32cc_clk_obj desc; 142 struct s32cc_clk_obj *module; 143 struct s32cc_clk *pclock; 144 unsigned long min_freq; 145 unsigned long max_freq; 146 }; 147 148 struct s32cc_clk_array { 149 unsigned long type_mask; 150 struct s32cc_clk **clks; 151 size_t n_clks; 152 }; 153 154 #define S32CC_FREQ_MODULE(PARENT_MODULE, MIN_F, MAX_F) \ 155 { \ 156 .desc = { \ 157 .type = s32cc_clk_t, \ 158 }, \ 159 .module = &(PARENT_MODULE).desc, \ 160 .min_freq = (MIN_F), \ 161 .max_freq = (MAX_F), \ 162 } 163 164 #define S32CC_FREQ_MODULE_CLK(PARENT_MODULE, MIN_F, MAX_F) \ 165 S32CC_FREQ_MODULE(PARENT_MODULE, MIN_F, MAX_F) 166 167 #define S32CC_MODULE_CLK(PARENT_MODULE) \ 168 S32CC_FREQ_MODULE_CLK(PARENT_MODULE, 0, 0) 169 170 static inline struct s32cc_osc *s32cc_obj2osc(const struct s32cc_clk_obj *mod) 171 { 172 uintptr_t osc_addr; 173 174 osc_addr = ((uintptr_t)mod) - offsetof(struct s32cc_osc, desc); 175 return (struct s32cc_osc *)osc_addr; 176 } 177 178 static inline struct s32cc_clk *s32cc_obj2clk(const struct s32cc_clk_obj *mod) 179 { 180 uintptr_t clk_addr; 181 182 clk_addr = ((uintptr_t)mod) - offsetof(struct s32cc_clk, desc); 183 return (struct s32cc_clk *)clk_addr; 184 } 185 186 static inline bool is_s32cc_clk_mux(const struct s32cc_clk *clk) 187 { 188 const struct s32cc_clk_obj *module; 189 190 module = clk->module; 191 if (module == NULL) { 192 return false; 193 } 194 195 return (module->type == s32cc_clkmux_t) || 196 (module->type == s32cc_shared_clkmux_t); 197 } 198 199 static inline struct s32cc_clkmux *s32cc_obj2clkmux(const struct s32cc_clk_obj *mod) 200 { 201 uintptr_t cmux_addr; 202 203 cmux_addr = ((uintptr_t)mod) - offsetof(struct s32cc_clkmux, desc); 204 return (struct s32cc_clkmux *)cmux_addr; 205 } 206 207 static inline struct s32cc_clkmux *s32cc_clk2mux(const struct s32cc_clk *clk) 208 { 209 if (!is_s32cc_clk_mux(clk)) { 210 return NULL; 211 } 212 213 return s32cc_obj2clkmux(clk->module); 214 } 215 216 static inline struct s32cc_pll *s32cc_obj2pll(const struct s32cc_clk_obj *mod) 217 { 218 uintptr_t pll_addr; 219 220 pll_addr = ((uintptr_t)mod) - offsetof(struct s32cc_pll, desc); 221 return (struct s32cc_pll *)pll_addr; 222 } 223 224 static inline struct s32cc_pll_out_div *s32cc_obj2plldiv(const struct s32cc_clk_obj *mod) 225 { 226 uintptr_t plldiv_addr; 227 228 plldiv_addr = ((uintptr_t)mod) - offsetof(struct s32cc_pll_out_div, desc); 229 return (struct s32cc_pll_out_div *)plldiv_addr; 230 } 231 232 static inline struct s32cc_fixed_div *s32cc_obj2fixeddiv(const struct s32cc_clk_obj *mod) 233 { 234 uintptr_t fdiv_addr; 235 236 fdiv_addr = ((uintptr_t)mod) - offsetof(struct s32cc_fixed_div, desc); 237 return (struct s32cc_fixed_div *)fdiv_addr; 238 } 239 240 #endif /* S32CC_CLK_MODULES_H */ 241