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