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 case s32cc_clkmux_t: 146 ret = -ENOTSUP; 147 break; 148 case s32cc_shared_clkmux_t: 149 ret = -ENOTSUP; 150 break; 151 case s32cc_pll_t: 152 ret = -ENOTSUP; 153 break; 154 case s32cc_pll_out_div_t: 155 case s32cc_fixed_div_t: 156 ret = -ENOTSUP; 157 break; 158 default: 159 ret = -EINVAL; 160 break; 161 } 162 163 return ret; 164 } 165 166 static int s32cc_clk_enable(unsigned long id) 167 { 168 unsigned int depth = MAX_STACK_DEPTH; 169 const struct s32cc_clk *clk; 170 171 clk = s32cc_get_arch_clk(id); 172 if (clk == NULL) { 173 return -EINVAL; 174 } 175 176 return enable_module(&clk->desc, &depth); 177 } 178 179 static void s32cc_clk_disable(unsigned long id) 180 { 181 } 182 183 static bool s32cc_clk_is_enabled(unsigned long id) 184 { 185 return false; 186 } 187 188 static unsigned long s32cc_clk_get_rate(unsigned long id) 189 { 190 return 0; 191 } 192 193 static int set_module_rate(const struct s32cc_clk_obj *module, 194 unsigned long rate, unsigned long *orate, 195 unsigned int *depth); 196 197 static int set_osc_freq(const struct s32cc_clk_obj *module, unsigned long rate, 198 unsigned long *orate, unsigned int *depth) 199 { 200 struct s32cc_osc *osc = s32cc_obj2osc(module); 201 int ret; 202 203 ret = update_stack_depth(depth); 204 if (ret != 0) { 205 return ret; 206 } 207 208 if ((osc->freq != 0UL) && (rate != osc->freq)) { 209 ERROR("Already initialized oscillator. freq = %lu\n", 210 osc->freq); 211 return -EINVAL; 212 } 213 214 osc->freq = rate; 215 *orate = osc->freq; 216 217 return 0; 218 } 219 220 static int set_clk_freq(const struct s32cc_clk_obj *module, unsigned long rate, 221 unsigned long *orate, unsigned int *depth) 222 { 223 const struct s32cc_clk *clk = s32cc_obj2clk(module); 224 int ret; 225 226 ret = update_stack_depth(depth); 227 if (ret != 0) { 228 return ret; 229 } 230 231 if ((clk->min_freq != 0UL) && (clk->max_freq != 0UL) && 232 ((rate < clk->min_freq) || (rate > clk->max_freq))) { 233 ERROR("%lu frequency is out of the allowed range: [%lu:%lu]\n", 234 rate, clk->min_freq, clk->max_freq); 235 return -EINVAL; 236 } 237 238 if (clk->module != NULL) { 239 return set_module_rate(clk->module, rate, orate, depth); 240 } 241 242 if (clk->pclock != NULL) { 243 return set_clk_freq(&clk->pclock->desc, rate, orate, depth); 244 } 245 246 return -EINVAL; 247 } 248 249 static int set_pll_freq(const struct s32cc_clk_obj *module, unsigned long rate, 250 unsigned long *orate, unsigned int *depth) 251 { 252 struct s32cc_pll *pll = s32cc_obj2pll(module); 253 int ret; 254 255 ret = update_stack_depth(depth); 256 if (ret != 0) { 257 return ret; 258 } 259 260 if ((pll->vco_freq != 0UL) && (pll->vco_freq != rate)) { 261 ERROR("PLL frequency was already set\n"); 262 return -EINVAL; 263 } 264 265 pll->vco_freq = rate; 266 *orate = pll->vco_freq; 267 268 return 0; 269 } 270 271 static int set_pll_div_freq(const struct s32cc_clk_obj *module, unsigned long rate, 272 unsigned long *orate, unsigned int *depth) 273 { 274 struct s32cc_pll_out_div *pdiv = s32cc_obj2plldiv(module); 275 const struct s32cc_pll *pll; 276 unsigned long prate, dc; 277 int ret; 278 279 ret = update_stack_depth(depth); 280 if (ret != 0) { 281 return ret; 282 } 283 284 if (pdiv->parent == NULL) { 285 ERROR("Failed to identify PLL divider's parent\n"); 286 return -EINVAL; 287 } 288 289 pll = s32cc_obj2pll(pdiv->parent); 290 if (pll == NULL) { 291 ERROR("The parent of the PLL DIV is invalid\n"); 292 return -EINVAL; 293 } 294 295 prate = pll->vco_freq; 296 297 /** 298 * The PLL is not initialized yet, so let's take a risk 299 * and accept the proposed rate. 300 */ 301 if (prate == 0UL) { 302 pdiv->freq = rate; 303 *orate = rate; 304 return 0; 305 } 306 307 /* Decline in case the rate cannot fit PLL's requirements. */ 308 dc = prate / rate; 309 if ((prate / dc) != rate) { 310 return -EINVAL; 311 } 312 313 pdiv->freq = rate; 314 *orate = pdiv->freq; 315 316 return 0; 317 } 318 319 static int set_fixed_div_freq(const struct s32cc_clk_obj *module, unsigned long rate, 320 unsigned long *orate, unsigned int *depth) 321 { 322 const struct s32cc_fixed_div *fdiv = s32cc_obj2fixeddiv(module); 323 int ret; 324 325 ret = update_stack_depth(depth); 326 if (ret != 0) { 327 return ret; 328 } 329 330 if (fdiv->parent == NULL) { 331 ERROR("The divider doesn't have a valid parent\b"); 332 return -EINVAL; 333 } 334 335 ret = set_module_rate(fdiv->parent, rate * fdiv->rate_div, orate, depth); 336 337 /* Update the output rate based on the parent's rate */ 338 *orate /= fdiv->rate_div; 339 340 return ret; 341 } 342 343 static int set_mux_freq(const struct s32cc_clk_obj *module, unsigned long rate, 344 unsigned long *orate, unsigned int *depth) 345 { 346 const struct s32cc_clkmux *mux = s32cc_obj2clkmux(module); 347 const struct s32cc_clk *clk = s32cc_get_arch_clk(mux->source_id); 348 int ret; 349 350 ret = update_stack_depth(depth); 351 if (ret != 0) { 352 return ret; 353 } 354 355 if (clk == NULL) { 356 ERROR("Mux (id:%" PRIu8 ") without a valid source (%lu)\n", 357 mux->index, mux->source_id); 358 return -EINVAL; 359 } 360 361 return set_module_rate(&clk->desc, rate, orate, depth); 362 } 363 364 static int set_module_rate(const struct s32cc_clk_obj *module, 365 unsigned long rate, unsigned long *orate, 366 unsigned int *depth) 367 { 368 int ret = 0; 369 370 ret = update_stack_depth(depth); 371 if (ret != 0) { 372 return ret; 373 } 374 375 switch (module->type) { 376 case s32cc_clk_t: 377 ret = set_clk_freq(module, rate, orate, depth); 378 break; 379 case s32cc_osc_t: 380 ret = set_osc_freq(module, rate, orate, depth); 381 break; 382 case s32cc_pll_t: 383 ret = set_pll_freq(module, rate, orate, depth); 384 break; 385 case s32cc_pll_out_div_t: 386 ret = set_pll_div_freq(module, rate, orate, depth); 387 break; 388 case s32cc_fixed_div_t: 389 ret = set_fixed_div_freq(module, rate, orate, depth); 390 break; 391 case s32cc_clkmux_t: 392 ret = set_mux_freq(module, rate, orate, depth); 393 break; 394 case s32cc_shared_clkmux_t: 395 ret = set_mux_freq(module, rate, orate, depth); 396 break; 397 default: 398 ret = -EINVAL; 399 break; 400 } 401 402 return ret; 403 } 404 405 static int s32cc_clk_set_rate(unsigned long id, unsigned long rate, 406 unsigned long *orate) 407 { 408 unsigned int depth = MAX_STACK_DEPTH; 409 const struct s32cc_clk *clk; 410 int ret; 411 412 clk = s32cc_get_arch_clk(id); 413 if (clk == NULL) { 414 return -EINVAL; 415 } 416 417 ret = set_module_rate(&clk->desc, rate, orate, &depth); 418 if (ret != 0) { 419 ERROR("Failed to set frequency (%lu MHz) for clock %lu\n", 420 rate, id); 421 } 422 423 return ret; 424 } 425 426 static int s32cc_clk_get_parent(unsigned long id) 427 { 428 return -ENOTSUP; 429 } 430 431 static int s32cc_clk_set_parent(unsigned long id, unsigned long parent_id) 432 { 433 const struct s32cc_clk *parent; 434 const struct s32cc_clk *clk; 435 bool valid_source = false; 436 struct s32cc_clkmux *mux; 437 uint8_t i; 438 439 clk = s32cc_get_arch_clk(id); 440 if (clk == NULL) { 441 return -EINVAL; 442 } 443 444 parent = s32cc_get_arch_clk(parent_id); 445 if (parent == NULL) { 446 return -EINVAL; 447 } 448 449 if (!is_s32cc_clk_mux(clk)) { 450 ERROR("Clock %lu is not a mux\n", id); 451 return -EINVAL; 452 } 453 454 mux = s32cc_clk2mux(clk); 455 if (mux == NULL) { 456 ERROR("Failed to cast clock %lu to clock mux\n", id); 457 return -EINVAL; 458 } 459 460 for (i = 0; i < mux->nclks; i++) { 461 if (mux->clkids[i] == parent_id) { 462 valid_source = true; 463 break; 464 } 465 } 466 467 if (!valid_source) { 468 ERROR("Clock %lu is not a valid clock for mux %lu\n", 469 parent_id, id); 470 return -EINVAL; 471 } 472 473 mux->source_id = parent_id; 474 475 return 0; 476 } 477 478 void s32cc_clk_register_drv(void) 479 { 480 static const struct clk_ops s32cc_clk_ops = { 481 .enable = s32cc_clk_enable, 482 .disable = s32cc_clk_disable, 483 .is_enabled = s32cc_clk_is_enabled, 484 .get_rate = s32cc_clk_get_rate, 485 .set_rate = s32cc_clk_set_rate, 486 .get_parent = s32cc_clk_get_parent, 487 .set_parent = s32cc_clk_set_parent, 488 }; 489 490 clk_register(&s32cc_clk_ops); 491 } 492 493