1 /* 2 * Copyright 2024 NXP 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 #include <errno.h> 7 8 #include <s32cc-clk-regs.h> 9 10 #include <common/debug.h> 11 #include <drivers/clk.h> 12 #include <lib/mmio.h> 13 #include <s32cc-clk-modules.h> 14 #include <s32cc-clk-utils.h> 15 16 #define MAX_STACK_DEPTH (15U) 17 18 struct s32cc_clk_drv { 19 uintptr_t fxosc_base; 20 }; 21 22 static int update_stack_depth(unsigned int *depth) 23 { 24 if (*depth == 0U) { 25 return -ENOMEM; 26 } 27 28 (*depth)--; 29 return 0; 30 } 31 32 static struct s32cc_clk_drv *get_drv(void) 33 { 34 static struct s32cc_clk_drv driver = { 35 .fxosc_base = FXOSC_BASE_ADDR, 36 }; 37 38 return &driver; 39 } 40 41 static int enable_module(const struct s32cc_clk_obj *module, unsigned int *depth); 42 43 static int enable_clk_module(const struct s32cc_clk_obj *module, 44 const struct s32cc_clk_drv *drv, 45 unsigned int *depth) 46 { 47 const struct s32cc_clk *clk = s32cc_obj2clk(module); 48 int ret; 49 50 ret = update_stack_depth(depth); 51 if (ret != 0) { 52 return ret; 53 } 54 55 if (clk == NULL) { 56 return -EINVAL; 57 } 58 59 if (clk->module != NULL) { 60 return enable_module(clk->module, depth); 61 } 62 63 if (clk->pclock != NULL) { 64 return enable_clk_module(&clk->pclock->desc, drv, depth); 65 } 66 67 return -EINVAL; 68 } 69 70 static void enable_fxosc(const struct s32cc_clk_drv *drv) 71 { 72 uintptr_t fxosc_base = drv->fxosc_base; 73 uint32_t ctrl; 74 75 ctrl = mmio_read_32(FXOSC_CTRL(fxosc_base)); 76 if ((ctrl & FXOSC_CTRL_OSCON) != U(0)) { 77 return; 78 } 79 80 ctrl = FXOSC_CTRL_COMP_EN; 81 ctrl &= ~FXOSC_CTRL_OSC_BYP; 82 ctrl |= FXOSC_CTRL_EOCV(0x1); 83 ctrl |= FXOSC_CTRL_GM_SEL(0x7); 84 mmio_write_32(FXOSC_CTRL(fxosc_base), ctrl); 85 86 /* Switch ON the crystal oscillator. */ 87 mmio_setbits_32(FXOSC_CTRL(fxosc_base), FXOSC_CTRL_OSCON); 88 89 /* Wait until the clock is stable. */ 90 while ((mmio_read_32(FXOSC_STAT(fxosc_base)) & FXOSC_STAT_OSC_STAT) == U(0)) { 91 } 92 } 93 94 static int enable_osc(const struct s32cc_clk_obj *module, 95 const struct s32cc_clk_drv *drv, 96 unsigned int *depth) 97 { 98 const struct s32cc_osc *osc = s32cc_obj2osc(module); 99 int ret = 0; 100 101 ret = update_stack_depth(depth); 102 if (ret != 0) { 103 return ret; 104 } 105 106 switch (osc->source) { 107 case S32CC_FXOSC: 108 enable_fxosc(drv); 109 break; 110 /* FIRC and SIRC oscillators are enabled by default */ 111 case S32CC_FIRC: 112 break; 113 case S32CC_SIRC: 114 break; 115 default: 116 ERROR("Invalid oscillator %d\n", osc->source); 117 ret = -EINVAL; 118 break; 119 }; 120 121 return ret; 122 } 123 124 static int enable_module(const struct s32cc_clk_obj *module, unsigned int *depth) 125 { 126 const struct s32cc_clk_drv *drv = get_drv(); 127 int ret = 0; 128 129 ret = update_stack_depth(depth); 130 if (ret != 0) { 131 return ret; 132 } 133 134 if (drv == NULL) { 135 return -EINVAL; 136 } 137 138 switch (module->type) { 139 case s32cc_osc_t: 140 ret = enable_osc(module, drv, depth); 141 break; 142 case s32cc_clk_t: 143 ret = enable_clk_module(module, drv, depth); 144 break; 145 default: 146 ret = -EINVAL; 147 break; 148 } 149 150 return ret; 151 } 152 153 static int s32cc_clk_enable(unsigned long id) 154 { 155 unsigned int depth = MAX_STACK_DEPTH; 156 const struct s32cc_clk *clk; 157 158 clk = s32cc_get_arch_clk(id); 159 if (clk == NULL) { 160 return -EINVAL; 161 } 162 163 return enable_module(&clk->desc, &depth); 164 } 165 166 static void s32cc_clk_disable(unsigned long id) 167 { 168 } 169 170 static bool s32cc_clk_is_enabled(unsigned long id) 171 { 172 return false; 173 } 174 175 static unsigned long s32cc_clk_get_rate(unsigned long id) 176 { 177 return 0; 178 } 179 180 static int set_module_rate(const struct s32cc_clk_obj *module, 181 unsigned long rate, unsigned long *orate, 182 unsigned int *depth); 183 184 static int set_osc_freq(const struct s32cc_clk_obj *module, unsigned long rate, 185 unsigned long *orate, unsigned int *depth) 186 { 187 struct s32cc_osc *osc = s32cc_obj2osc(module); 188 int ret; 189 190 ret = update_stack_depth(depth); 191 if (ret != 0) { 192 return ret; 193 } 194 195 if ((osc->freq != 0UL) && (rate != osc->freq)) { 196 ERROR("Already initialized oscillator. freq = %lu\n", 197 osc->freq); 198 return -EINVAL; 199 } 200 201 osc->freq = rate; 202 *orate = osc->freq; 203 204 return 0; 205 } 206 207 static int set_clk_freq(const struct s32cc_clk_obj *module, unsigned long rate, 208 unsigned long *orate, unsigned int *depth) 209 { 210 const struct s32cc_clk *clk = s32cc_obj2clk(module); 211 int ret; 212 213 ret = update_stack_depth(depth); 214 if (ret != 0) { 215 return ret; 216 } 217 218 if ((clk->min_freq != 0UL) && (clk->max_freq != 0UL) && 219 ((rate < clk->min_freq) || (rate > clk->max_freq))) { 220 ERROR("%lu frequency is out of the allowed range: [%lu:%lu]\n", 221 rate, clk->min_freq, clk->max_freq); 222 return -EINVAL; 223 } 224 225 if (clk->module != NULL) { 226 return set_module_rate(clk->module, rate, orate, depth); 227 } 228 229 if (clk->pclock != NULL) { 230 return set_clk_freq(&clk->pclock->desc, rate, orate, depth); 231 } 232 233 return -EINVAL; 234 } 235 236 static int set_module_rate(const struct s32cc_clk_obj *module, 237 unsigned long rate, unsigned long *orate, 238 unsigned int *depth) 239 { 240 int ret = 0; 241 242 ret = update_stack_depth(depth); 243 if (ret != 0) { 244 return ret; 245 } 246 247 switch (module->type) { 248 case s32cc_clk_t: 249 ret = set_clk_freq(module, rate, orate, depth); 250 break; 251 case s32cc_osc_t: 252 ret = set_osc_freq(module, rate, orate, depth); 253 break; 254 default: 255 ret = -EINVAL; 256 break; 257 } 258 259 return ret; 260 } 261 262 static int s32cc_clk_set_rate(unsigned long id, unsigned long rate, 263 unsigned long *orate) 264 { 265 unsigned int depth = MAX_STACK_DEPTH; 266 const struct s32cc_clk *clk; 267 int ret; 268 269 clk = s32cc_get_arch_clk(id); 270 if (clk == NULL) { 271 return -EINVAL; 272 } 273 274 ret = set_module_rate(&clk->desc, rate, orate, &depth); 275 if (ret != 0) { 276 ERROR("Failed to set frequency (%lu MHz) for clock %lu\n", 277 rate, id); 278 } 279 280 return ret; 281 } 282 283 static int s32cc_clk_get_parent(unsigned long id) 284 { 285 return -ENOTSUP; 286 } 287 288 static int s32cc_clk_set_parent(unsigned long id, unsigned long parent_id) 289 { 290 return -ENOTSUP; 291 } 292 293 void s32cc_clk_register_drv(void) 294 { 295 static const struct clk_ops s32cc_clk_ops = { 296 .enable = s32cc_clk_enable, 297 .disable = s32cc_clk_disable, 298 .is_enabled = s32cc_clk_is_enabled, 299 .get_rate = s32cc_clk_get_rate, 300 .set_rate = s32cc_clk_set_rate, 301 .get_parent = s32cc_clk_get_parent, 302 .set_parent = s32cc_clk_set_parent, 303 }; 304 305 clk_register(&s32cc_clk_ops); 306 } 307 308