13a580e9eSGhennadi Procopciuc /* 23a580e9eSGhennadi Procopciuc * Copyright 2024 NXP 33a580e9eSGhennadi Procopciuc * 43a580e9eSGhennadi Procopciuc * SPDX-License-Identifier: BSD-3-Clause 53a580e9eSGhennadi Procopciuc */ 63a580e9eSGhennadi Procopciuc #include <errno.h> 73a580e9eSGhennadi Procopciuc 8*d9373519SGhennadi Procopciuc #include <common/debug.h> 93a580e9eSGhennadi Procopciuc #include <drivers/clk.h> 10*d9373519SGhennadi Procopciuc #include <s32cc-clk-modules.h> 11*d9373519SGhennadi Procopciuc #include <s32cc-clk-utils.h> 12*d9373519SGhennadi Procopciuc 13*d9373519SGhennadi Procopciuc #define MAX_STACK_DEPTH (15U) 14*d9373519SGhennadi Procopciuc 15*d9373519SGhennadi Procopciuc static int update_stack_depth(unsigned int *depth) 16*d9373519SGhennadi Procopciuc { 17*d9373519SGhennadi Procopciuc if (*depth == 0U) { 18*d9373519SGhennadi Procopciuc return -ENOMEM; 19*d9373519SGhennadi Procopciuc } 20*d9373519SGhennadi Procopciuc 21*d9373519SGhennadi Procopciuc (*depth)--; 22*d9373519SGhennadi Procopciuc return 0; 23*d9373519SGhennadi Procopciuc } 243a580e9eSGhennadi Procopciuc 253a580e9eSGhennadi Procopciuc static int s32cc_clk_enable(unsigned long id) 263a580e9eSGhennadi Procopciuc { 273a580e9eSGhennadi Procopciuc return -ENOTSUP; 283a580e9eSGhennadi Procopciuc } 293a580e9eSGhennadi Procopciuc 303a580e9eSGhennadi Procopciuc static void s32cc_clk_disable(unsigned long id) 313a580e9eSGhennadi Procopciuc { 323a580e9eSGhennadi Procopciuc } 333a580e9eSGhennadi Procopciuc 343a580e9eSGhennadi Procopciuc static bool s32cc_clk_is_enabled(unsigned long id) 353a580e9eSGhennadi Procopciuc { 363a580e9eSGhennadi Procopciuc return false; 373a580e9eSGhennadi Procopciuc } 383a580e9eSGhennadi Procopciuc 393a580e9eSGhennadi Procopciuc static unsigned long s32cc_clk_get_rate(unsigned long id) 403a580e9eSGhennadi Procopciuc { 413a580e9eSGhennadi Procopciuc return 0; 423a580e9eSGhennadi Procopciuc } 433a580e9eSGhennadi Procopciuc 44*d9373519SGhennadi Procopciuc static int set_module_rate(const struct s32cc_clk_obj *module, 45*d9373519SGhennadi Procopciuc unsigned long rate, unsigned long *orate, 46*d9373519SGhennadi Procopciuc unsigned int *depth); 47*d9373519SGhennadi Procopciuc 48*d9373519SGhennadi Procopciuc static int set_osc_freq(const struct s32cc_clk_obj *module, unsigned long rate, 49*d9373519SGhennadi Procopciuc unsigned long *orate, unsigned int *depth) 50*d9373519SGhennadi Procopciuc { 51*d9373519SGhennadi Procopciuc struct s32cc_osc *osc = s32cc_obj2osc(module); 52*d9373519SGhennadi Procopciuc int ret; 53*d9373519SGhennadi Procopciuc 54*d9373519SGhennadi Procopciuc ret = update_stack_depth(depth); 55*d9373519SGhennadi Procopciuc if (ret != 0) { 56*d9373519SGhennadi Procopciuc return ret; 57*d9373519SGhennadi Procopciuc } 58*d9373519SGhennadi Procopciuc 59*d9373519SGhennadi Procopciuc if ((osc->freq != 0UL) && (rate != osc->freq)) { 60*d9373519SGhennadi Procopciuc ERROR("Already initialized oscillator. freq = %lu\n", 61*d9373519SGhennadi Procopciuc osc->freq); 62*d9373519SGhennadi Procopciuc return -EINVAL; 63*d9373519SGhennadi Procopciuc } 64*d9373519SGhennadi Procopciuc 65*d9373519SGhennadi Procopciuc osc->freq = rate; 66*d9373519SGhennadi Procopciuc *orate = osc->freq; 67*d9373519SGhennadi Procopciuc 68*d9373519SGhennadi Procopciuc return 0; 69*d9373519SGhennadi Procopciuc } 70*d9373519SGhennadi Procopciuc 71*d9373519SGhennadi Procopciuc static int set_clk_freq(const struct s32cc_clk_obj *module, unsigned long rate, 72*d9373519SGhennadi Procopciuc unsigned long *orate, unsigned int *depth) 73*d9373519SGhennadi Procopciuc { 74*d9373519SGhennadi Procopciuc const struct s32cc_clk *clk = s32cc_obj2clk(module); 75*d9373519SGhennadi Procopciuc int ret; 76*d9373519SGhennadi Procopciuc 77*d9373519SGhennadi Procopciuc ret = update_stack_depth(depth); 78*d9373519SGhennadi Procopciuc if (ret != 0) { 79*d9373519SGhennadi Procopciuc return ret; 80*d9373519SGhennadi Procopciuc } 81*d9373519SGhennadi Procopciuc 82*d9373519SGhennadi Procopciuc if ((clk->min_freq != 0UL) && (clk->max_freq != 0UL) && 83*d9373519SGhennadi Procopciuc ((rate < clk->min_freq) || (rate > clk->max_freq))) { 84*d9373519SGhennadi Procopciuc ERROR("%lu frequency is out of the allowed range: [%lu:%lu]\n", 85*d9373519SGhennadi Procopciuc rate, clk->min_freq, clk->max_freq); 86*d9373519SGhennadi Procopciuc return -EINVAL; 87*d9373519SGhennadi Procopciuc } 88*d9373519SGhennadi Procopciuc 89*d9373519SGhennadi Procopciuc if (clk->module != NULL) { 90*d9373519SGhennadi Procopciuc return set_module_rate(clk->module, rate, orate, depth); 91*d9373519SGhennadi Procopciuc } 92*d9373519SGhennadi Procopciuc 93*d9373519SGhennadi Procopciuc if (clk->pclock != NULL) { 94*d9373519SGhennadi Procopciuc return set_clk_freq(&clk->pclock->desc, rate, orate, depth); 95*d9373519SGhennadi Procopciuc } 96*d9373519SGhennadi Procopciuc 97*d9373519SGhennadi Procopciuc return -EINVAL; 98*d9373519SGhennadi Procopciuc } 99*d9373519SGhennadi Procopciuc 100*d9373519SGhennadi Procopciuc static int set_module_rate(const struct s32cc_clk_obj *module, 101*d9373519SGhennadi Procopciuc unsigned long rate, unsigned long *orate, 102*d9373519SGhennadi Procopciuc unsigned int *depth) 103*d9373519SGhennadi Procopciuc { 104*d9373519SGhennadi Procopciuc int ret = 0; 105*d9373519SGhennadi Procopciuc 106*d9373519SGhennadi Procopciuc ret = update_stack_depth(depth); 107*d9373519SGhennadi Procopciuc if (ret != 0) { 108*d9373519SGhennadi Procopciuc return ret; 109*d9373519SGhennadi Procopciuc } 110*d9373519SGhennadi Procopciuc 111*d9373519SGhennadi Procopciuc switch (module->type) { 112*d9373519SGhennadi Procopciuc case s32cc_clk_t: 113*d9373519SGhennadi Procopciuc ret = set_clk_freq(module, rate, orate, depth); 114*d9373519SGhennadi Procopciuc break; 115*d9373519SGhennadi Procopciuc case s32cc_osc_t: 116*d9373519SGhennadi Procopciuc ret = set_osc_freq(module, rate, orate, depth); 117*d9373519SGhennadi Procopciuc break; 118*d9373519SGhennadi Procopciuc default: 119*d9373519SGhennadi Procopciuc ret = -EINVAL; 120*d9373519SGhennadi Procopciuc break; 121*d9373519SGhennadi Procopciuc } 122*d9373519SGhennadi Procopciuc 123*d9373519SGhennadi Procopciuc return ret; 124*d9373519SGhennadi Procopciuc } 125*d9373519SGhennadi Procopciuc 1263a580e9eSGhennadi Procopciuc static int s32cc_clk_set_rate(unsigned long id, unsigned long rate, 1273a580e9eSGhennadi Procopciuc unsigned long *orate) 1283a580e9eSGhennadi Procopciuc { 129*d9373519SGhennadi Procopciuc unsigned int depth = MAX_STACK_DEPTH; 130*d9373519SGhennadi Procopciuc const struct s32cc_clk *clk; 131*d9373519SGhennadi Procopciuc int ret; 132*d9373519SGhennadi Procopciuc 133*d9373519SGhennadi Procopciuc clk = s32cc_get_arch_clk(id); 134*d9373519SGhennadi Procopciuc if (clk == NULL) { 135*d9373519SGhennadi Procopciuc return -EINVAL; 136*d9373519SGhennadi Procopciuc } 137*d9373519SGhennadi Procopciuc 138*d9373519SGhennadi Procopciuc ret = set_module_rate(&clk->desc, rate, orate, &depth); 139*d9373519SGhennadi Procopciuc if (ret != 0) { 140*d9373519SGhennadi Procopciuc ERROR("Failed to set frequency (%lu MHz) for clock %lu\n", 141*d9373519SGhennadi Procopciuc rate, id); 142*d9373519SGhennadi Procopciuc } 143*d9373519SGhennadi Procopciuc 144*d9373519SGhennadi Procopciuc return ret; 1453a580e9eSGhennadi Procopciuc } 1463a580e9eSGhennadi Procopciuc 1473a580e9eSGhennadi Procopciuc static int s32cc_clk_get_parent(unsigned long id) 1483a580e9eSGhennadi Procopciuc { 1493a580e9eSGhennadi Procopciuc return -ENOTSUP; 1503a580e9eSGhennadi Procopciuc } 1513a580e9eSGhennadi Procopciuc 1523a580e9eSGhennadi Procopciuc static int s32cc_clk_set_parent(unsigned long id, unsigned long parent_id) 1533a580e9eSGhennadi Procopciuc { 1543a580e9eSGhennadi Procopciuc return -ENOTSUP; 1553a580e9eSGhennadi Procopciuc } 1563a580e9eSGhennadi Procopciuc 1573a580e9eSGhennadi Procopciuc void s32cc_clk_register_drv(void) 1583a580e9eSGhennadi Procopciuc { 1593a580e9eSGhennadi Procopciuc static const struct clk_ops s32cc_clk_ops = { 1603a580e9eSGhennadi Procopciuc .enable = s32cc_clk_enable, 1613a580e9eSGhennadi Procopciuc .disable = s32cc_clk_disable, 1623a580e9eSGhennadi Procopciuc .is_enabled = s32cc_clk_is_enabled, 1633a580e9eSGhennadi Procopciuc .get_rate = s32cc_clk_get_rate, 1643a580e9eSGhennadi Procopciuc .set_rate = s32cc_clk_set_rate, 1653a580e9eSGhennadi Procopciuc .get_parent = s32cc_clk_get_parent, 1663a580e9eSGhennadi Procopciuc .set_parent = s32cc_clk_set_parent, 1673a580e9eSGhennadi Procopciuc }; 1683a580e9eSGhennadi Procopciuc 1693a580e9eSGhennadi Procopciuc clk_register(&s32cc_clk_ops); 1703a580e9eSGhennadi Procopciuc } 1713a580e9eSGhennadi Procopciuc 172