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