1 /* 2 * Copyright 2024 NXP 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 #include <errno.h> 7 8 #include <common/debug.h> 9 #include <drivers/clk.h> 10 #include <s32cc-clk-modules.h> 11 #include <s32cc-clk-utils.h> 12 13 #define MAX_STACK_DEPTH (15U) 14 15 static int update_stack_depth(unsigned int *depth) 16 { 17 if (*depth == 0U) { 18 return -ENOMEM; 19 } 20 21 (*depth)--; 22 return 0; 23 } 24 25 static int s32cc_clk_enable(unsigned long id) 26 { 27 return -ENOTSUP; 28 } 29 30 static void s32cc_clk_disable(unsigned long id) 31 { 32 } 33 34 static bool s32cc_clk_is_enabled(unsigned long id) 35 { 36 return false; 37 } 38 39 static unsigned long s32cc_clk_get_rate(unsigned long id) 40 { 41 return 0; 42 } 43 44 static int set_module_rate(const struct s32cc_clk_obj *module, 45 unsigned long rate, unsigned long *orate, 46 unsigned int *depth); 47 48 static int set_osc_freq(const struct s32cc_clk_obj *module, unsigned long rate, 49 unsigned long *orate, unsigned int *depth) 50 { 51 struct s32cc_osc *osc = s32cc_obj2osc(module); 52 int ret; 53 54 ret = update_stack_depth(depth); 55 if (ret != 0) { 56 return ret; 57 } 58 59 if ((osc->freq != 0UL) && (rate != osc->freq)) { 60 ERROR("Already initialized oscillator. freq = %lu\n", 61 osc->freq); 62 return -EINVAL; 63 } 64 65 osc->freq = rate; 66 *orate = osc->freq; 67 68 return 0; 69 } 70 71 static int set_clk_freq(const struct s32cc_clk_obj *module, unsigned long rate, 72 unsigned long *orate, unsigned int *depth) 73 { 74 const struct s32cc_clk *clk = s32cc_obj2clk(module); 75 int ret; 76 77 ret = update_stack_depth(depth); 78 if (ret != 0) { 79 return ret; 80 } 81 82 if ((clk->min_freq != 0UL) && (clk->max_freq != 0UL) && 83 ((rate < clk->min_freq) || (rate > clk->max_freq))) { 84 ERROR("%lu frequency is out of the allowed range: [%lu:%lu]\n", 85 rate, clk->min_freq, clk->max_freq); 86 return -EINVAL; 87 } 88 89 if (clk->module != NULL) { 90 return set_module_rate(clk->module, rate, orate, depth); 91 } 92 93 if (clk->pclock != NULL) { 94 return set_clk_freq(&clk->pclock->desc, rate, orate, depth); 95 } 96 97 return -EINVAL; 98 } 99 100 static int set_module_rate(const struct s32cc_clk_obj *module, 101 unsigned long rate, unsigned long *orate, 102 unsigned int *depth) 103 { 104 int ret = 0; 105 106 ret = update_stack_depth(depth); 107 if (ret != 0) { 108 return ret; 109 } 110 111 switch (module->type) { 112 case s32cc_clk_t: 113 ret = set_clk_freq(module, rate, orate, depth); 114 break; 115 case s32cc_osc_t: 116 ret = set_osc_freq(module, rate, orate, depth); 117 break; 118 default: 119 ret = -EINVAL; 120 break; 121 } 122 123 return ret; 124 } 125 126 static int s32cc_clk_set_rate(unsigned long id, unsigned long rate, 127 unsigned long *orate) 128 { 129 unsigned int depth = MAX_STACK_DEPTH; 130 const struct s32cc_clk *clk; 131 int ret; 132 133 clk = s32cc_get_arch_clk(id); 134 if (clk == NULL) { 135 return -EINVAL; 136 } 137 138 ret = set_module_rate(&clk->desc, rate, orate, &depth); 139 if (ret != 0) { 140 ERROR("Failed to set frequency (%lu MHz) for clock %lu\n", 141 rate, id); 142 } 143 144 return ret; 145 } 146 147 static int s32cc_clk_get_parent(unsigned long id) 148 { 149 return -ENOTSUP; 150 } 151 152 static int s32cc_clk_set_parent(unsigned long id, unsigned long parent_id) 153 { 154 return -ENOTSUP; 155 } 156 157 void s32cc_clk_register_drv(void) 158 { 159 static const struct clk_ops s32cc_clk_ops = { 160 .enable = s32cc_clk_enable, 161 .disable = s32cc_clk_disable, 162 .is_enabled = s32cc_clk_is_enabled, 163 .get_rate = s32cc_clk_get_rate, 164 .set_rate = s32cc_clk_set_rate, 165 .get_parent = s32cc_clk_get_parent, 166 .set_parent = s32cc_clk_set_parent, 167 }; 168 169 clk_register(&s32cc_clk_ops); 170 } 171 172