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