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 }; 23 24 enum s32cc_clk_source { 25 S32CC_FIRC, 26 S32CC_FXOSC, 27 S32CC_SIRC, 28 S32CC_ARM_PLL, 29 S32CC_CGM1, 30 }; 31 32 struct s32cc_clk_obj { 33 enum s32cc_clkm_type type; 34 uint32_t refcount; 35 }; 36 37 struct s32cc_osc { 38 struct s32cc_clk_obj desc; 39 enum s32cc_clk_source source; 40 unsigned long freq; 41 void *base; 42 }; 43 44 #define S32CC_OSC_INIT(SOURCE) \ 45 { \ 46 .desc = { \ 47 .type = s32cc_osc_t, \ 48 }, \ 49 .source = (SOURCE), \ 50 } 51 52 struct s32cc_clkmux { 53 struct s32cc_clk_obj desc; 54 enum s32cc_clk_source module; 55 uint8_t index; /* Mux index in parent module */ 56 unsigned long source_id; /* Selected source */ 57 uint8_t nclks; /* Number of input clocks */ 58 unsigned long clkids[5]; /* IDs of the input clocks */ 59 }; 60 61 #define S32CC_CLKMUX_TYPE_INIT(TYPE, MODULE, INDEX, NCLKS, ...) \ 62 { \ 63 .desc = { \ 64 .type = (TYPE), \ 65 }, \ 66 .module = (MODULE), \ 67 .index = (INDEX), \ 68 .nclks = (NCLKS), \ 69 .clkids = {__VA_ARGS__}, \ 70 } 71 72 #define S32CC_CLKMUX_INIT(MODULE, INDEX, NCLKS, ...) \ 73 S32CC_CLKMUX_TYPE_INIT(s32cc_clkmux_t, MODULE, \ 74 INDEX, NCLKS, __VA_ARGS__) 75 76 #define S32CC_SHARED_CLKMUX_INIT(MODULE, INDEX, NCLKS, ...) \ 77 S32CC_CLKMUX_TYPE_INIT(s32cc_shared_clkmux_t, MODULE, \ 78 INDEX, NCLKS, __VA_ARGS__) 79 80 struct s32cc_pll { 81 struct s32cc_clk_obj desc; 82 struct s32cc_clk_obj *source; 83 enum s32cc_clk_source instance; 84 unsigned long vco_freq; 85 uint32_t ndividers; 86 uintptr_t base; 87 }; 88 89 #define S32CC_PLL_INIT(PLL_MUX_CLK, INSTANCE, NDIVIDERS) \ 90 { \ 91 .desc = { \ 92 .type = s32cc_pll_t, \ 93 }, \ 94 .source = &(PLL_MUX_CLK).desc, \ 95 .instance = (INSTANCE), \ 96 .ndividers = (NDIVIDERS), \ 97 } 98 99 struct s32cc_pll_out_div { 100 struct s32cc_clk_obj desc; 101 struct s32cc_clk_obj *parent; 102 uint32_t index; 103 unsigned long freq; 104 }; 105 106 #define S32CC_PLL_OUT_DIV_INIT(PARENT, INDEX) \ 107 { \ 108 .desc = { \ 109 .type = s32cc_pll_out_div_t, \ 110 }, \ 111 .parent = &(PARENT).desc, \ 112 .index = (INDEX), \ 113 } 114 115 struct s32cc_clk { 116 struct s32cc_clk_obj desc; 117 struct s32cc_clk_obj *module; 118 struct s32cc_clk *pclock; 119 unsigned long min_freq; 120 unsigned long max_freq; 121 }; 122 123 struct s32cc_clk_array { 124 unsigned long type_mask; 125 struct s32cc_clk **clks; 126 size_t n_clks; 127 }; 128 129 #define S32CC_FREQ_MODULE(PARENT_MODULE, MIN_F, MAX_F) \ 130 { \ 131 .desc = { \ 132 .type = s32cc_clk_t, \ 133 }, \ 134 .module = &(PARENT_MODULE).desc, \ 135 .min_freq = (MIN_F), \ 136 .max_freq = (MAX_F), \ 137 } 138 139 #define S32CC_FREQ_MODULE_CLK(PARENT_MODULE, MIN_F, MAX_F) \ 140 S32CC_FREQ_MODULE(PARENT_MODULE, MIN_F, MAX_F) 141 142 #define S32CC_MODULE_CLK(PARENT_MODULE) \ 143 S32CC_FREQ_MODULE_CLK(PARENT_MODULE, 0, 0) 144 145 static inline struct s32cc_osc *s32cc_obj2osc(const struct s32cc_clk_obj *mod) 146 { 147 uintptr_t osc_addr; 148 149 osc_addr = ((uintptr_t)mod) - offsetof(struct s32cc_osc, desc); 150 return (struct s32cc_osc *)osc_addr; 151 } 152 153 static inline struct s32cc_clk *s32cc_obj2clk(const struct s32cc_clk_obj *mod) 154 { 155 uintptr_t clk_addr; 156 157 clk_addr = ((uintptr_t)mod) - offsetof(struct s32cc_clk, desc); 158 return (struct s32cc_clk *)clk_addr; 159 } 160 161 static inline bool is_s32cc_clk_mux(const struct s32cc_clk *clk) 162 { 163 const struct s32cc_clk_obj *module; 164 165 module = clk->module; 166 if (module == NULL) { 167 return false; 168 } 169 170 return (module->type == s32cc_clkmux_t) || 171 (module->type == s32cc_shared_clkmux_t); 172 } 173 174 static inline struct s32cc_clkmux *s32cc_obj2clkmux(const struct s32cc_clk_obj *mod) 175 { 176 uintptr_t cmux_addr; 177 178 cmux_addr = ((uintptr_t)mod) - offsetof(struct s32cc_clkmux, desc); 179 return (struct s32cc_clkmux *)cmux_addr; 180 } 181 182 static inline struct s32cc_clkmux *s32cc_clk2mux(const struct s32cc_clk *clk) 183 { 184 if (!is_s32cc_clk_mux(clk)) { 185 return NULL; 186 } 187 188 return s32cc_obj2clkmux(clk->module); 189 } 190 191 #endif /* S32CC_CLK_MODULES_H */ 192