1 /*
2 * Copyright (c) 2022-2024 HPMicro
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7 #include "hpm_clock_drv.h"
8 #include "hpm_sysctl_drv.h"
9 #include "hpm_soc.h"
10 #include "hpm_common.h"
11 #include "hpm_pllctlv2_drv.h"
12 /***********************************************************************************************************************
13 * Definitions
14 **********************************************************************************************************************/
15
16 /* Clock preset values */
17 #define FREQ_PRESET1_OSC0_CLK0 (24000000UL)
18 #define FREQ_PRESET1_PLL0_CLK0 (400000000UL)
19 #define FREQ_PRESET1_PLL0_CLK1 (333333333UL)
20 #define FREQ_PRESET1_PLL1_CLK2 (250000000UL)
21 #define FREQ_PRESET1_PLL1_CLK0 (480000000UL)
22 #define FREQ_PRESET1_PLL1_CLK1 (320000000UL)
23 #define FREQ_PRESET1_PLL2_CLK0 (516096000UL)
24 #define FREQ_PRESET1_PLL2_CLK1 (451584000UL)
25 #define FREQ_32KHz (32768UL)
26 #define ADC_INSTANCE_NUM ARRAY_SIZE(HPM_SYSCTL->ADCCLK)
27 #define DAC_INSTANCE_NUM ARRAY_SIZE(HPM_SYSCTL->DACCLK)
28 #define WDG_INSTANCE_NUM (2U)
29 #define BUS_FREQ_MAX (200000000UL)
30 #define FREQ_1MHz (1000000UL)
31
32 /* Clock On/Off definitions */
33 #define CLOCK_ON (true)
34 #define CLOCK_OFF (false)
35
36
37 /***********************************************************************************************************************
38 * Prototypes
39 **********************************************************************************************************************/
40
41
42
43 /**
44 * @brief Get Clock frequency for IP in common group
45 */
46 static uint32_t get_frequency_for_ip_in_common_group(clock_node_t node);
47
48 /**
49 * @brief Get Clock frequency for ADC
50 */
51 static uint32_t get_frequency_for_adc(uint32_t clk_src_type, uint32_t instance);
52
53 /**
54 * @brief Get Clock frequency for DAC
55 */
56 static uint32_t get_frequency_for_dac(uint32_t instance);
57
58 /**
59 * @brief Get Clock frequency for WDG
60 */
61 static uint32_t get_frequency_for_wdg(uint32_t instance);
62
63 /**
64 * @brief Get Clock frequency for PWDG
65 */
66 static uint32_t get_frequency_for_pwdg(void);
67
68 /**
69 * @brief Turn on/off the IP clock
70 */
71 static void switch_ip_clock(clock_name_t clock_name, bool on);
72
73 static uint32_t get_frequency_for_cpu(void);
74 static uint32_t get_frequency_for_axi(void);
75 static uint32_t get_frequency_for_ahb(void);
76
77 /***********************************************************************************************************************
78 * Variables
79 **********************************************************************************************************************/
80 static const clock_node_t s_adc_clk_mux_node[] = {
81 clock_node_ana0, clock_node_ahb,
82 };
83
84 static const clock_node_t s_dac_clk_mux_node[] = {
85 clock_node_ana3, clock_node_ahb
86 };
87
88 static WDG_Type *const s_wdgs[] = { HPM_WDG0, HPM_WDG1 };
89
90 uint32_t hpm_core_clock;
91
92 /***********************************************************************************************************************
93 * Codes
94 **********************************************************************************************************************/
clock_get_frequency(clock_name_t clock_name)95 uint32_t clock_get_frequency(clock_name_t clock_name)
96 {
97 uint32_t clk_freq;
98 uint32_t clk_src_type = GET_CLK_SRC_GROUP_FROM_NAME(clock_name);
99 uint32_t node_or_instance = GET_CLK_NODE_FROM_NAME(clock_name);
100 switch (clk_src_type) {
101 case CLK_SRC_GROUP_COMMON:
102 clk_freq = get_frequency_for_ip_in_common_group((clock_node_t) node_or_instance);
103 break;
104 case CLK_SRC_GROUP_ADC:
105 clk_freq = get_frequency_for_adc(CLK_SRC_GROUP_ADC, node_or_instance);
106 break;
107 case CLK_SRC_GROUP_DAC:
108 clk_freq = get_frequency_for_dac(node_or_instance);
109 break;
110 case CLK_SRC_GROUP_WDG:
111 clk_freq = get_frequency_for_wdg(node_or_instance);
112 break;
113 case CLK_SRC_GROUP_PWDG:
114 clk_freq = get_frequency_for_pwdg();
115 break;
116 case CLK_SRC_GROUP_PMIC:
117 clk_freq = FREQ_PRESET1_OSC0_CLK0;
118 break;
119 case CLK_SRC_GROUP_CPU0:
120 clk_freq = get_frequency_for_cpu();
121 break;
122 case CLK_SRC_GROUP_AHB:
123 clk_freq = get_frequency_for_ahb();
124 break;
125 case CLK_SRC_GROUP_AXI:
126 clk_freq = get_frequency_for_axi();
127 break;
128 case CLK_SRC_GROUP_SRC:
129 clk_freq = get_frequency_for_source((clock_source_t) node_or_instance);
130 break;
131 default:
132 clk_freq = 0UL;
133 break;
134 }
135 return clk_freq;
136 }
137
get_frequency_for_source(clock_source_t source)138 uint32_t get_frequency_for_source(clock_source_t source)
139 {
140 uint32_t clk_freq;
141 switch (source) {
142 case clock_source_osc0_clk0:
143 clk_freq = FREQ_PRESET1_OSC0_CLK0;
144 break;
145 case clock_source_pll0_clk0:
146 clk_freq = pllctlv2_get_pll_postdiv_freq_in_hz(HPM_PLLCTLV2, 0U, 0U);
147 break;
148 case clock_source_pll0_clk1:
149 clk_freq = pllctlv2_get_pll_postdiv_freq_in_hz(HPM_PLLCTLV2, 0U, 1U);
150 break;
151 case clock_source_pll0_clk2:
152 clk_freq = pllctlv2_get_pll_postdiv_freq_in_hz(HPM_PLLCTLV2, 0U, 2U);
153 break;
154 case clock_source_pll1_clk0:
155 clk_freq = pllctlv2_get_pll_postdiv_freq_in_hz(HPM_PLLCTLV2, 1U, 0U);
156 break;
157 case clock_source_pll1_clk1:
158 clk_freq = pllctlv2_get_pll_postdiv_freq_in_hz(HPM_PLLCTLV2, 1U, 1U);
159 break;
160 case clock_source_pll2_clk0:
161 clk_freq = pllctlv2_get_pll_postdiv_freq_in_hz(HPM_PLLCTLV2, 2U, 0U);
162 break;
163 case clock_source_pll2_clk1:
164 clk_freq = pllctlv2_get_pll_postdiv_freq_in_hz(HPM_PLLCTLV2, 2U, 1U);
165 break;
166 default:
167 clk_freq = 0UL;
168 break;
169 }
170
171 return clk_freq;
172 }
173
get_frequency_for_ip_in_common_group(clock_node_t node)174 static uint32_t get_frequency_for_ip_in_common_group(clock_node_t node)
175 {
176 uint32_t clk_freq = 0UL;
177 uint32_t node_or_instance = GET_CLK_NODE_FROM_NAME(node);
178
179 if (node_or_instance < clock_node_end) {
180 uint32_t clk_node = (uint32_t) node_or_instance;
181
182 uint32_t clk_div = 1UL + SYSCTL_CLOCK_DIV_GET(HPM_SYSCTL->CLOCK[clk_node]);
183 clock_source_t clk_mux = (clock_source_t) SYSCTL_CLOCK_MUX_GET(HPM_SYSCTL->CLOCK[clk_node]);
184 clk_freq = get_frequency_for_source(clk_mux) / clk_div;
185 }
186 return clk_freq;
187 }
188
get_frequency_for_adc(uint32_t clk_src_type,uint32_t instance)189 static uint32_t get_frequency_for_adc(uint32_t clk_src_type, uint32_t instance)
190 {
191 uint32_t clk_freq = 0UL;
192 bool is_mux_valid = false;
193 clock_node_t node = clock_node_end;
194 uint32_t adc_index = instance;
195
196 (void) clk_src_type;
197
198 if (adc_index < ADC_INSTANCE_NUM) {
199 uint32_t mux_in_reg = SYSCTL_ADCCLK_MUX_GET(HPM_SYSCTL->ADCCLK[adc_index]);
200 if (mux_in_reg < ARRAY_SIZE(s_adc_clk_mux_node)) {
201 node = s_adc_clk_mux_node[mux_in_reg];
202 is_mux_valid = true;
203 }
204 }
205
206 if (is_mux_valid) {
207 if (node != clock_node_ahb) {
208 node += instance;
209 clk_freq = get_frequency_for_ip_in_common_group(node);
210 } else {
211 clk_freq = get_frequency_for_ahb();
212 }
213 }
214 return clk_freq;
215 }
216
get_frequency_for_dac(uint32_t instance)217 static uint32_t get_frequency_for_dac(uint32_t instance)
218 {
219 uint32_t clk_freq = 0UL;
220 bool is_mux_valid = false;
221 clock_node_t node = clock_node_end;
222 if (instance < DAC_INSTANCE_NUM) {
223 uint32_t mux_in_reg = SYSCTL_DACCLK_MUX_GET(HPM_SYSCTL->DACCLK[instance]);
224 if (mux_in_reg < ARRAY_SIZE(s_dac_clk_mux_node)) {
225 node = s_dac_clk_mux_node[mux_in_reg];
226 is_mux_valid = true;
227 }
228 }
229
230 if (is_mux_valid) {
231 if (node == clock_node_ahb) {
232 clk_freq = get_frequency_for_ahb();
233 } else {
234 node += instance;
235 clk_freq = get_frequency_for_ip_in_common_group(node);
236 }
237 }
238
239 return clk_freq;
240 }
241
get_frequency_for_wdg(uint32_t instance)242 static uint32_t get_frequency_for_wdg(uint32_t instance)
243 {
244 uint32_t freq_in_hz;
245 /* EXT clock is chosen */
246 if (WDG_CTRL_CLKSEL_GET(s_wdgs[instance]->CTRL) == 0) {
247 freq_in_hz = get_frequency_for_ahb();
248 }
249 /* PCLK is chosen */
250 else {
251 freq_in_hz = FREQ_32KHz;
252 }
253
254 return freq_in_hz;
255 }
256
get_frequency_for_pwdg(void)257 static uint32_t get_frequency_for_pwdg(void)
258 {
259 uint32_t freq_in_hz;
260 if (WDG_CTRL_CLKSEL_GET(HPM_PWDG->CTRL) == 0) {
261 freq_in_hz = FREQ_PRESET1_OSC0_CLK0;
262 } else {
263 freq_in_hz = FREQ_32KHz;
264 }
265
266 return freq_in_hz;
267 }
268
get_frequency_for_cpu(void)269 static uint32_t get_frequency_for_cpu(void)
270 {
271 uint32_t mux = SYSCTL_CLOCK_CPU_MUX_GET(HPM_SYSCTL->CLOCK_CPU[0]);
272 uint32_t div = SYSCTL_CLOCK_CPU_DIV_GET(HPM_SYSCTL->CLOCK_CPU[0]) + 1U;
273 return (get_frequency_for_source(mux) / div);
274 }
275
get_frequency_for_axi(void)276 static uint32_t get_frequency_for_axi(void)
277 {
278 uint32_t div = SYSCTL_CLOCK_CPU_SUB0_DIV_GET(HPM_SYSCTL->CLOCK_CPU[0]) + 1U;
279 return (get_frequency_for_cpu() / div);
280 }
281
get_frequency_for_ahb(void)282 static uint32_t get_frequency_for_ahb(void)
283 {
284 uint32_t div = SYSCTL_CLOCK_CPU_SUB1_DIV_GET(HPM_SYSCTL->CLOCK_CPU[0]) + 1U;
285 return (get_frequency_for_cpu() / div);
286 }
287
clock_get_source(clock_name_t clock_name)288 clk_src_t clock_get_source(clock_name_t clock_name)
289 {
290 uint8_t clk_src_group = CLK_SRC_GROUP_INVALID;
291 uint8_t clk_src_index = 0xFU;
292 uint32_t clk_src_type = GET_CLK_SRC_GROUP_FROM_NAME(clock_name);
293 uint32_t node_or_instance = GET_CLK_NODE_FROM_NAME(clock_name);
294 switch (clk_src_type) {
295 case CLK_SRC_GROUP_COMMON:
296 clk_src_group = CLK_SRC_GROUP_COMMON;
297 clk_src_index = SYSCTL_CLOCK_MUX_GET(HPM_SYSCTL->CLOCK[node_or_instance]);
298 break;
299 case CLK_SRC_GROUP_ADC:
300 if (node_or_instance < ADC_INSTANCE_NUM) {
301 clk_src_group = CLK_SRC_GROUP_ADC;
302 clk_src_index = SYSCTL_ADCCLK_MUX_GET(HPM_SYSCTL->ADCCLK[node_or_instance]);
303 }
304 break;
305 case CLK_SRC_GROUP_DAC:
306 if (node_or_instance < DAC_INSTANCE_NUM) {
307 clk_src_group = CLK_SRC_GROUP_DAC;
308 clk_src_index = SYSCTL_DACCLK_MUX_GET(HPM_SYSCTL->DACCLK[node_or_instance]);
309 }
310 break;
311 case CLK_SRC_GROUP_WDG:
312 if (node_or_instance < WDG_INSTANCE_NUM) {
313 clk_src_group = CLK_SRC_GROUP_WDG;
314 clk_src_index = WDG_CTRL_CLKSEL_GET(s_wdgs[node_or_instance]->CTRL);
315 }
316 break;
317 case CLK_SRC_GROUP_PWDG:
318 clk_src_group = CLK_SRC_GROUP_PWDG;
319 clk_src_index = WDG_CTRL_CLKSEL_GET(HPM_PWDG->CTRL);
320 break;
321 case CLK_SRC_GROUP_PMIC:
322 clk_src_group = CLK_SRC_GROUP_COMMON;
323 clk_src_index = clock_source_osc0_clk0;
324 break;
325 case CLK_SRC_GROUP_CPU0:
326 case CLK_SRC_GROUP_AHB:
327 case CLK_SRC_GROUP_AXI:
328 clk_src_group = CLK_SRC_GROUP_CPU0;
329 clk_src_index = SYSCTL_CLOCK_CPU_MUX_GET(HPM_SYSCTL->CLOCK_CPU[0]);
330 break;
331 case CLK_SRC_GROUP_SRC:
332 clk_src_index = (clk_src_t) node_or_instance;
333 break;
334 default:
335 clk_src_group = CLK_SRC_GROUP_INVALID;
336 break;
337 }
338
339 clk_src_t clk_src;
340 if (clk_src_group != CLK_SRC_GROUP_INVALID) {
341 clk_src = MAKE_CLK_SRC(clk_src_group, clk_src_index);
342 } else {
343 clk_src = clk_src_invalid;
344 }
345
346 return clk_src;
347 }
348
clock_get_divider(clock_name_t clock_name)349 uint32_t clock_get_divider(clock_name_t clock_name)
350 {
351 uint32_t clk_divider = CLOCK_DIV_INVALID;
352 uint32_t clk_src_type = GET_CLK_SRC_GROUP_FROM_NAME(clock_name);
353 uint32_t node_or_instance = GET_CLK_NODE_FROM_NAME(clock_name);
354 switch (clk_src_type) {
355 case CLK_SRC_GROUP_COMMON:
356 clk_divider = 1UL + SYSCTL_CLOCK_DIV_GET(HPM_SYSCTL->CLOCK[node_or_instance]);
357 break;
358 case CLK_SRC_GROUP_WDG:
359 if (node_or_instance < WDG_INSTANCE_NUM) {
360 clk_divider = 1UL;
361 }
362 break;
363 case CLK_SRC_GROUP_PWDG:
364 clk_divider = 1UL;
365 break;
366 case CLK_SRC_GROUP_PMIC:
367 clk_divider = 1UL;
368 break;
369 case CLK_SRC_GROUP_CPU0:
370 clk_divider = 1UL + SYSCTL_CLOCK_CPU_DIV_GET(HPM_SYSCTL->CLOCK_CPU[0]);
371 break;
372 case CLK_SRC_GROUP_AHB:
373 clk_divider = 1UL + SYSCTL_CLOCK_CPU_SUB1_DIV_GET(HPM_SYSCTL->CLOCK_CPU[0]);
374 break;
375 case CLK_SRC_GROUP_AXI:
376 clk_divider = 1UL + SYSCTL_CLOCK_CPU_SUB0_DIV_GET(HPM_SYSCTL->CLOCK_CPU[0]);
377 break;
378 default:
379 clk_divider = CLOCK_DIV_INVALID;
380 break;
381 }
382 return clk_divider;
383 }
384
clock_set_adc_source(clock_name_t clock_name,clk_src_t src)385 hpm_stat_t clock_set_adc_source(clock_name_t clock_name, clk_src_t src)
386 {
387 uint32_t clk_src_type = GET_CLK_SRC_GROUP_FROM_NAME(clock_name);
388 uint32_t node_or_instance = GET_CLK_NODE_FROM_NAME(clock_name);
389
390 if ((clk_src_type != CLK_SRC_GROUP_ADC) || (node_or_instance >= ADC_INSTANCE_NUM)) {
391 return status_clk_invalid;
392 }
393
394 if ((src < clk_adc_src_ana0) || (src > clk_adc_src_ahb0)) {
395 return status_clk_src_invalid;
396 }
397
398 uint32_t clk_src_index = GET_CLK_SRC_INDEX(src);
399 HPM_SYSCTL->ADCCLK[node_or_instance] =
400 (HPM_SYSCTL->ADCCLK[node_or_instance] & ~SYSCTL_ADCCLK_MUX_MASK) | SYSCTL_ADCCLK_MUX_SET(clk_src_index);
401
402 return status_success;
403 }
404
clock_set_dac_source(clock_name_t clock_name,clk_src_t src)405 hpm_stat_t clock_set_dac_source(clock_name_t clock_name, clk_src_t src)
406 {
407 uint32_t clk_src_type = GET_CLK_SRC_GROUP_FROM_NAME(clock_name);
408 uint32_t node_or_instance = GET_CLK_NODE_FROM_NAME(clock_name);
409
410 if ((clk_src_type != CLK_SRC_GROUP_DAC) || (node_or_instance >= DAC_INSTANCE_NUM)) {
411 return status_clk_invalid;
412 }
413
414 if ((src < clk_dac_src_ana3) || (src > clk_dac_src_ahb0)) {
415 return status_clk_src_invalid;
416 }
417
418 uint32_t clk_src_index = GET_CLK_SRC_INDEX(src);
419 HPM_SYSCTL->DACCLK[node_or_instance] =
420 (HPM_SYSCTL->DACCLK[node_or_instance] & ~SYSCTL_DACCLK_MUX_MASK) | SYSCTL_DACCLK_MUX_SET(clk_src_index);
421
422 return status_success;
423 }
424
clock_set_wdg_source(clock_name_t clock_name,clk_src_t src)425 hpm_stat_t clock_set_wdg_source(clock_name_t clock_name, clk_src_t src)
426 {
427 uint32_t clk_src_grp = GET_CLK_SRC_GROUP(clock_name);
428 if ((clk_src_grp != CLK_SRC_GROUP_WDG) && (clk_src_grp != CLK_SRC_GROUP_PWDG)) {
429 return status_invalid_argument;
430 }
431 if (clock_name == clock_pwdg) {
432 if ((src == clk_pwdg_src_osc24m) || (src == clk_pwdg_src_osc32k)) {
433 uint32_t wdg_clk_src_in_ip = (uint32_t)(src - clk_pwdg_src_osc24m);
434 HPM_PWDG->CTRL = (HPM_PWDG->CTRL & ~WDG_CTRL_CLKSEL_MASK) | WDG_CTRL_CLKSEL_SET(wdg_clk_src_in_ip);
435 } else {
436 return status_invalid_argument;
437 }
438 } else {
439 uint32_t instance = GET_CLK_SRC_INDEX(clock_name);
440 if ((src == clk_wdg_src_ahb0) || (src == clk_wdg_src_osc32k)) {
441 uint32_t wdg_clk_src_in_ip = (uint32_t)(src - clk_wdg_src_ahb0);
442 s_wdgs[instance]->CTRL = (s_wdgs[instance]->CTRL & ~WDG_CTRL_CLKSEL_MASK) | WDG_CTRL_CLKSEL_SET(wdg_clk_src_in_ip);
443 } else {
444 return status_invalid_argument;
445 }
446 }
447 return status_success;
448 }
449
clock_set_source_divider(clock_name_t clock_name,clk_src_t src,uint32_t div)450 hpm_stat_t clock_set_source_divider(clock_name_t clock_name, clk_src_t src, uint32_t div)
451 {
452 hpm_stat_t status = status_success;
453 uint32_t clk_src_type = GET_CLK_SRC_GROUP_FROM_NAME(clock_name);
454 uint32_t node_or_instance = GET_CLK_NODE_FROM_NAME(clock_name);
455 switch (clk_src_type) {
456 case CLK_SRC_GROUP_COMMON:
457 if ((div < 1U) || (div > 256U)) {
458 status = status_clk_div_invalid;
459 } else {
460 clock_source_t clk_src = GET_CLOCK_SOURCE_FROM_CLK_SRC(src);
461 sysctl_config_clock(HPM_SYSCTL, (clock_node_t) node_or_instance, clk_src, div);
462 }
463 break;
464 case CLK_SRC_GROUP_ADC:
465 case CLK_SRC_GROUP_DAC:
466 case CLK_SRC_GROUP_WDG:
467 case CLK_SRC_GROUP_PWDG:
468 case CLK_SRC_GROUP_SRC:
469 status = status_clk_operation_unsupported;
470 break;
471 case CLK_SRC_GROUP_PMIC:
472 status = status_clk_fixed;
473 break;
474 case CLK_SRC_GROUP_AHB:
475 status = status_clk_shared_cpu0;
476 break;
477 case CLK_SRC_GROUP_AXI:
478 status = status_clk_shared_cpu0;
479 break;
480 case CLK_SRC_GROUP_CPU0:
481 if (node_or_instance == clock_node_cpu0) {
482 /* Note: the AXI and AHB BUS share the same CPU clock, once the CPU clock frequency
483 * changes, the AXI and AHB clock changes accordingly, here the driver ensures the
484 * AXI and AHB bus clock frequency is in valid range.
485 */
486 uint32_t expected_freq = get_frequency_for_source((clock_source_t) src) / div;
487 uint32_t axi_sub_div = (expected_freq + BUS_FREQ_MAX - 1U) / BUS_FREQ_MAX;
488 uint32_t ahb_sub_div = (expected_freq + BUS_FREQ_MAX - 1U) / BUS_FREQ_MAX;
489 sysctl_config_cpu0_domain_clock(HPM_SYSCTL, (clock_source_t) src, div, axi_sub_div, ahb_sub_div);
490 } else {
491 status = status_clk_shared_cpu0;
492 }
493 break;
494 default:
495 status = status_clk_src_invalid;
496 break;
497 }
498
499 return status;
500 }
501
switch_ip_clock(clock_name_t clock_name,bool on)502 static void switch_ip_clock(clock_name_t clock_name, bool on)
503 {
504 uint32_t resource = GET_CLK_RESOURCE_FROM_NAME(clock_name);
505
506 if (resource < sysctl_resource_end) {
507 uint32_t mode = on ? 1UL : 2UL;
508 HPM_SYSCTL->RESOURCE[resource] =
509 (HPM_SYSCTL->RESOURCE[resource] & ~SYSCTL_RESOURCE_MODE_MASK) | SYSCTL_RESOURCE_MODE_SET(mode);
510 }
511 }
512
clock_enable(clock_name_t clock_name)513 void clock_enable(clock_name_t clock_name)
514 {
515 switch_ip_clock(clock_name, CLOCK_ON);
516 }
517
clock_disable(clock_name_t clock_name)518 void clock_disable(clock_name_t clock_name)
519 {
520 switch_ip_clock(clock_name, CLOCK_OFF);
521 }
522
clock_add_to_group(clock_name_t clock_name,uint32_t group)523 void clock_add_to_group(clock_name_t clock_name, uint32_t group)
524 {
525 uint32_t resource = GET_CLK_RESOURCE_FROM_NAME(clock_name);
526
527 if (resource < sysctl_resource_end) {
528 sysctl_enable_group_resource(HPM_SYSCTL, group, resource, true);
529 }
530 }
531
clock_remove_from_group(clock_name_t clock_name,uint32_t group)532 void clock_remove_from_group(clock_name_t clock_name, uint32_t group)
533 {
534 uint32_t resource = GET_CLK_RESOURCE_FROM_NAME(clock_name);
535
536 if (resource < sysctl_resource_end) {
537 sysctl_enable_group_resource(HPM_SYSCTL, group, resource, false);
538 }
539 }
540
clock_check_in_group(clock_name_t clock_name,uint32_t group)541 bool clock_check_in_group(clock_name_t clock_name, uint32_t group)
542 {
543 uint32_t resource = GET_CLK_RESOURCE_FROM_NAME(clock_name);
544
545 return sysctl_check_group_resource_enable(HPM_SYSCTL, group, resource);
546 }
547
clock_connect_group_to_cpu(uint32_t group,uint32_t cpu)548 void clock_connect_group_to_cpu(uint32_t group, uint32_t cpu)
549 {
550 if (cpu < 2U) {
551 HPM_SYSCTL->AFFILIATE[cpu].SET = (1UL << group);
552 }
553 }
554
clock_disconnect_group_from_cpu(uint32_t group,uint32_t cpu)555 void clock_disconnect_group_from_cpu(uint32_t group, uint32_t cpu)
556 {
557 if (cpu < 2U) {
558 HPM_SYSCTL->AFFILIATE[cpu].CLEAR = (1UL << group);
559 }
560 }
561
clock_cpu_delay_us(uint32_t us)562 void clock_cpu_delay_us(uint32_t us)
563 {
564 uint32_t ticks_per_us = (hpm_core_clock + FREQ_1MHz - 1U) / FREQ_1MHz;
565 uint64_t expected_ticks = hpm_csr_get_core_cycle() + ticks_per_us * us;
566 while (hpm_csr_get_core_cycle() < expected_ticks) {
567 }
568 }
569
clock_cpu_delay_ms(uint32_t ms)570 void clock_cpu_delay_ms(uint32_t ms)
571 {
572 uint32_t ticks_per_us = (hpm_core_clock + FREQ_1MHz - 1U) / FREQ_1MHz;
573 uint64_t expected_ticks = hpm_csr_get_core_cycle() + (uint64_t) ticks_per_us * 1000UL * ms;
574 while (hpm_csr_get_core_cycle() < expected_ticks) {
575 }
576 }
577
clock_update_core_clock(void)578 void clock_update_core_clock(void)
579 {
580 uint32_t hart_id = read_csr(CSR_MHARTID);
581 clock_name_t cpu_clk_name = (hart_id == 1U) ? clock_cpu1 : clock_cpu0;
582 hpm_core_clock = clock_get_frequency(cpu_clk_name);
583 }
584