hpm_clock_drv.c 17 KB

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