1 /* 2 * Copyright (c) 2021-2023 HPMicro 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 * 6 */ 7 #ifndef HPM_CLOCK_DRV_H 8 #define HPM_CLOCK_DRV_H 9 10 #include "hpm_common.h" 11 #include "hpm_sysctl_drv.h" 12 #include "hpm_csr_drv.h" 13 14 15 /** 16 * @brief Error codes for clock driver 17 */ 18 enum { 19 status_clk_div_invalid = MAKE_STATUS(status_group_clk, 0), 20 status_clk_src_invalid = MAKE_STATUS(status_group_clk, 1), 21 status_clk_invalid = MAKE_STATUS(status_group_clk, 2), 22 status_clk_operation_unsupported = MAKE_STATUS(status_group_clk, 3), 23 status_clk_shared_ahb = MAKE_STATUS(status_group_clk, 4), 24 status_clk_shared_axi0 = MAKE_STATUS(status_group_clk, 5), 25 status_clk_shared_axi1 = MAKE_STATUS(status_group_clk, 6), 26 status_clk_shared_axi2 = MAKE_STATUS(status_group_clk, 7), 27 status_clk_shared_cpu0 = MAKE_STATUS(status_group_clk, 8), 28 status_clk_shared_cpu1 = MAKE_STATUS(status_group_clk, 9), 29 status_clk_fixed = MAKE_STATUS(status_group_clk, 10), 30 31 }; 32 33 34 35 /** 36 * @brief Clock source group definitions 37 */ 38 #define CLK_SRC_GROUP_COMMON (0U) 39 #define CLK_SRC_GROUP_ADC (1U) 40 #define CLK_SRC_GROUP_I2S (2U) 41 #define CLK_SRC_GROUP_WDG (3U) 42 #define CLK_SRC_GROUP_PMIC (4U) 43 #define CLK_SRC_GROUP_AHB (5U) 44 #define CLK_SRC_GROUP_AXI (6U) 45 #define CLK_SRC_GROUP_DAC (7U) 46 #define CLK_SRC_GROUP_CPU0 (9U) 47 #define CLK_SRC_GROUP_SRC (10U) 48 #define CLK_SRC_GROUP_PWDG (11U) 49 #define CLK_SRC_GROUP_INVALID (15U) 50 51 #define MAKE_CLK_SRC(src_grp, index) (((uint8_t)(src_grp)<<4) | (index)) 52 #define GET_CLK_SRC_GROUP(src) (((uint8_t)(src)>>4) & 0x0FU) 53 #define GET_CLK_SRC_INDEX(src) ((uint8_t)(src) & 0x0FU) 54 55 /** 56 * @brief Clock source definitions 57 */ 58 typedef enum _clock_sources { 59 clk_src_osc24m = MAKE_CLK_SRC(CLK_SRC_GROUP_COMMON, 0), 60 clk_src_pll0_clk0 = MAKE_CLK_SRC(CLK_SRC_GROUP_COMMON, 1), 61 clk_src_pll0_clk1 = MAKE_CLK_SRC(CLK_SRC_GROUP_COMMON, 2), 62 clk_src_pll0_clk2 = MAKE_CLK_SRC(CLK_SRC_GROUP_COMMON, 3), 63 clk_src_pll1_clk0 = MAKE_CLK_SRC(CLK_SRC_GROUP_COMMON, 4), 64 clk_src_pll1_clk1 = MAKE_CLK_SRC(CLK_SRC_GROUP_COMMON, 5), 65 clk_src_pll2_clk0 = MAKE_CLK_SRC(CLK_SRC_GROUP_COMMON, 6), 66 clk_src_pll2_clk1 = MAKE_CLK_SRC(CLK_SRC_GROUP_COMMON, 7), 67 clk_src_osc32k = MAKE_CLK_SRC(CLK_SRC_GROUP_COMMON, 8), 68 69 clk_adc_src_ana0 = MAKE_CLK_SRC(CLK_SRC_GROUP_ADC, 0), 70 clk_adc_src_ana1 = MAKE_CLK_SRC(CLK_SRC_GROUP_ADC, 0), 71 clk_adc_src_ana2 = MAKE_CLK_SRC(CLK_SRC_GROUP_ADC, 0), 72 clk_adc_src_ahb0 = MAKE_CLK_SRC(CLK_SRC_GROUP_ADC, 1), 73 74 clk_dac_src_ana3 = MAKE_CLK_SRC(CLK_SRC_GROUP_DAC, 0), 75 clk_dac_src_ahb0 = MAKE_CLK_SRC(CLK_SRC_GROUP_DAC, 1), 76 77 clk_i2s_src_aud0 = MAKE_CLK_SRC(CLK_SRC_GROUP_I2S, 0), 78 clk_i2s_src_aud1 = MAKE_CLK_SRC(CLK_SRC_GROUP_I2S, 1), 79 80 clk_wdg_src_ahb0 = MAKE_CLK_SRC(CLK_SRC_GROUP_WDG, 0), 81 clk_wdg_src_osc32k = MAKE_CLK_SRC(CLK_SRC_GROUP_WDG, 1), 82 83 clk_pwdg_src_osc24m = MAKE_CLK_SRC(CLK_SRC_GROUP_PWDG, 0), 84 clk_pwdg_src_osc32k = MAKE_CLK_SRC(CLK_SRC_GROUP_PWDG, 1), 85 86 clk_src_invalid = MAKE_CLK_SRC(CLK_SRC_GROUP_INVALID, 15), 87 } clk_src_t; 88 89 90 #define RESOURCE_INVALID (0xFFFFU) 91 #define RESOURCE_SHARED_PTPC (0xFFFEU) 92 #define RESOURCE_SHARED_CPU0 (0xFFFDU) 93 94 #define GET_CLOCK_SOURCE_FROM_CLK_SRC(clk_src) (clock_source_t)((uint32_t)(clk_src) & 0xFU) 95 96 /* Clock NAME related Macros */ 97 #define MAKE_CLOCK_NAME(resource, src_type, node) (((uint32_t)(resource) << 16) | ((uint32_t)(src_type) << 8) | ((uint32_t)node)) 98 #define GET_CLK_SRC_GROUP_FROM_NAME(name) (((uint32_t)(name) >> 8) & 0xFFUL) 99 #define GET_CLK_NODE_FROM_NAME(name) ((uint32_t)(name) & 0xFFUL) 100 #define GET_CLK_RESOURCE_FROM_NAME(name) ((uint32_t)(name) >> 16) 101 102 /** 103 * @brief Peripheral Clock Type Description 104 */ 105 typedef enum _clock_name { 106 clock_cpu0 = MAKE_CLOCK_NAME(sysctl_resource_cpu0, CLK_SRC_GROUP_CPU0, clock_node_cpu0), 107 clock_mchtmr0 = MAKE_CLOCK_NAME(sysctl_resource_mchtmr0, CLK_SRC_GROUP_COMMON, clock_node_mchtmr0), 108 clock_femc = MAKE_CLOCK_NAME(sysctl_resource_femc, CLK_SRC_GROUP_COMMON, clock_node_femc), 109 clock_xpi0 = MAKE_CLOCK_NAME(sysctl_resource_xpi0, CLK_SRC_GROUP_COMMON, clock_node_xpi0), 110 clock_xpi1 = MAKE_CLOCK_NAME(sysctl_resource_xpi1, CLK_SRC_GROUP_COMMON, clock_node_xpi1), 111 clock_gptmr0 = MAKE_CLOCK_NAME(sysctl_resource_gptmr0, CLK_SRC_GROUP_COMMON, clock_node_gptmr0), 112 clock_gptmr1 = MAKE_CLOCK_NAME(sysctl_resource_gptmr1, CLK_SRC_GROUP_COMMON, clock_node_gptmr1), 113 clock_gptmr2 = MAKE_CLOCK_NAME(sysctl_resource_gptmr2, CLK_SRC_GROUP_COMMON, clock_node_gptmr2), 114 clock_gptmr3 = MAKE_CLOCK_NAME(sysctl_resource_gptmr3, CLK_SRC_GROUP_COMMON, clock_node_gptmr3), 115 clock_uart0 = MAKE_CLOCK_NAME(sysctl_resource_uart0, CLK_SRC_GROUP_COMMON, clock_node_uart0), 116 clock_uart1 = MAKE_CLOCK_NAME(sysctl_resource_uart1, CLK_SRC_GROUP_COMMON, clock_node_uart1), 117 clock_uart2 = MAKE_CLOCK_NAME(sysctl_resource_uart2, CLK_SRC_GROUP_COMMON, clock_node_uart2), 118 clock_uart3 = MAKE_CLOCK_NAME(sysctl_resource_uart3, CLK_SRC_GROUP_COMMON, clock_node_uart3), 119 clock_uart4 = MAKE_CLOCK_NAME(sysctl_resource_uart4, CLK_SRC_GROUP_COMMON, clock_node_uart4), 120 clock_uart5 = MAKE_CLOCK_NAME(sysctl_resource_uart5, CLK_SRC_GROUP_COMMON, clock_node_uart5), 121 clock_uart6 = MAKE_CLOCK_NAME(sysctl_resource_uart6, CLK_SRC_GROUP_COMMON, clock_node_uart6), 122 clock_uart7 = MAKE_CLOCK_NAME(sysctl_resource_uart7, CLK_SRC_GROUP_COMMON, clock_node_uart7), 123 clock_i2c0 = MAKE_CLOCK_NAME(sysctl_resource_i2c0, CLK_SRC_GROUP_COMMON, clock_node_i2c0), 124 clock_i2c1 = MAKE_CLOCK_NAME(sysctl_resource_i2c1, CLK_SRC_GROUP_COMMON, clock_node_i2c1), 125 clock_i2c2 = MAKE_CLOCK_NAME(sysctl_resource_i2c2, CLK_SRC_GROUP_COMMON, clock_node_i2c2), 126 clock_i2c3 = MAKE_CLOCK_NAME(sysctl_resource_i2c3, CLK_SRC_GROUP_COMMON, clock_node_i2c3), 127 clock_spi0 = MAKE_CLOCK_NAME(sysctl_resource_spi0, CLK_SRC_GROUP_COMMON, clock_node_spi0), 128 clock_spi1 = MAKE_CLOCK_NAME(sysctl_resource_spi1, CLK_SRC_GROUP_COMMON, clock_node_spi1), 129 clock_spi2 = MAKE_CLOCK_NAME(sysctl_resource_spi2, CLK_SRC_GROUP_COMMON, clock_node_spi2), 130 clock_spi3 = MAKE_CLOCK_NAME(sysctl_resource_spi3, CLK_SRC_GROUP_COMMON, clock_node_spi3), 131 clock_can0 = MAKE_CLOCK_NAME(sysctl_resource_can0, CLK_SRC_GROUP_COMMON, clock_node_can0), 132 clock_can1 = MAKE_CLOCK_NAME(sysctl_resource_can1, CLK_SRC_GROUP_COMMON, clock_node_can1), 133 clock_sdxc0 = MAKE_CLOCK_NAME(sysctl_resource_sdxc0, CLK_SRC_GROUP_COMMON, clock_node_sdxc0), 134 clock_ntmr0 = MAKE_CLOCK_NAME(sysctl_resource_ntmr0, CLK_SRC_GROUP_COMMON, clock_node_ntmr0), 135 clock_ahb = MAKE_CLOCK_NAME(RESOURCE_SHARED_CPU0, CLK_SRC_GROUP_AHB, clock_node_ahb), 136 clock_axi = MAKE_CLOCK_NAME(RESOURCE_SHARED_CPU0, CLK_SRC_GROUP_AXI, clock_node_axi), 137 clock_axic = MAKE_CLOCK_NAME(sysctl_resource_axic, CLK_SRC_GROUP_AXI, clock_node_axi), 138 clock_axis = MAKE_CLOCK_NAME(sysctl_resource_axis, CLK_SRC_GROUP_AXI, clock_node_axi), 139 clock_ahbp = MAKE_CLOCK_NAME(sysctl_resource_ahbp, CLK_SRC_GROUP_AHB, clock_node_ahb), 140 141 clock_ptpc = MAKE_CLOCK_NAME(sysctl_resource_ptpc, CLK_SRC_GROUP_COMMON, clock_node_ptpc), 142 clock_ptp0 = MAKE_CLOCK_NAME(RESOURCE_SHARED_PTPC, CLK_SRC_GROUP_COMMON, clock_node_ptp0), 143 clock_ref0 = MAKE_CLOCK_NAME(sysctl_resource_ref0, CLK_SRC_GROUP_COMMON, clock_node_ref0), 144 clock_ref1 = MAKE_CLOCK_NAME(sysctl_resource_ref1, CLK_SRC_GROUP_COMMON, clock_node_ref0), 145 clock_watchdog0 = MAKE_CLOCK_NAME(sysctl_resource_wdg0, CLK_SRC_GROUP_WDG, 0), 146 clock_watchdog1 = MAKE_CLOCK_NAME(sysctl_resource_wdg1, CLK_SRC_GROUP_WDG, 1), 147 clock_puart = MAKE_CLOCK_NAME(RESOURCE_INVALID, CLK_SRC_GROUP_PMIC, 0), 148 clock_pwdg = MAKE_CLOCK_NAME(RESOURCE_INVALID, CLK_SRC_GROUP_PWDG, 0), 149 clock_eth0 = MAKE_CLOCK_NAME(sysctl_resource_eth0, CLK_SRC_GROUP_COMMON, clock_node_eth0), 150 clock_sdp = MAKE_CLOCK_NAME(sysctl_resource_sdp0, CLK_SRC_GROUP_AXI, 0), 151 clock_xdma = MAKE_CLOCK_NAME(sysctl_resource_dma1, CLK_SRC_GROUP_AXI, 1), 152 clock_rom = MAKE_CLOCK_NAME(sysctl_resource_rom0, CLK_SRC_GROUP_AXI, 2), 153 clock_ram0 = MAKE_CLOCK_NAME(sysctl_resource_ram0, CLK_SRC_GROUP_AXI, 3), 154 clock_usb0 = MAKE_CLOCK_NAME(sysctl_resource_usb0, CLK_SRC_GROUP_AXI, 4), 155 clock_kman = MAKE_CLOCK_NAME(sysctl_resource_kman, CLK_SRC_GROUP_AHB, 0), 156 clock_gpio = MAKE_CLOCK_NAME(sysctl_resource_gpio, CLK_SRC_GROUP_AHB, 1), 157 clock_mbx0 = MAKE_CLOCK_NAME(sysctl_resource_mbx0, CLK_SRC_GROUP_AHB, 2), 158 clock_hdma = MAKE_CLOCK_NAME(sysctl_resource_dma0, CLK_SRC_GROUP_AHB, 4), 159 clock_rng = MAKE_CLOCK_NAME(sysctl_resource_rng0, CLK_SRC_GROUP_AHB, 5), 160 clock_mot0 = MAKE_CLOCK_NAME(sysctl_resource_mot0, CLK_SRC_GROUP_AHB, 6), 161 clock_mot1 = MAKE_CLOCK_NAME(sysctl_resource_mot1, CLK_SRC_GROUP_AHB, 7), 162 clock_acmp = MAKE_CLOCK_NAME(sysctl_resource_acmp, CLK_SRC_GROUP_AHB, 10), 163 clock_pdm = MAKE_CLOCK_NAME(sysctl_resource_i2spdm0, CLK_SRC_GROUP_I2S, 0), 164 clock_dao = MAKE_CLOCK_NAME(sysctl_resource_i2sdao, CLK_SRC_GROUP_I2S, 1), 165 clock_msyn = MAKE_CLOCK_NAME(sysctl_resource_msyn, CLK_SRC_GROUP_AHB, 13), 166 clock_ffa0 = MAKE_CLOCK_NAME(sysctl_resource_ffa0, CLK_SRC_GROUP_AHB, 14), 167 clock_lmm0 = MAKE_CLOCK_NAME(sysctl_resource_lmm0, CLK_SRC_GROUP_CPU0, 0), 168 clock_tsns = MAKE_CLOCK_NAME(sysctl_resource_tsns, CLK_SRC_GROUP_CPU0, 0), 169 170 171 /* For ADC, there are 2-stage clock source and divider configurations */ 172 clock_ana0 = MAKE_CLOCK_NAME(RESOURCE_INVALID, CLK_SRC_GROUP_COMMON, clock_node_ana0), 173 clock_ana1 = MAKE_CLOCK_NAME(RESOURCE_INVALID, CLK_SRC_GROUP_COMMON, clock_node_ana1), 174 clock_ana2 = MAKE_CLOCK_NAME(RESOURCE_INVALID, CLK_SRC_GROUP_COMMON, clock_node_ana2), 175 clock_adc0 = MAKE_CLOCK_NAME(sysctl_resource_adc0, CLK_SRC_GROUP_ADC, 0), 176 clock_adc1 = MAKE_CLOCK_NAME(sysctl_resource_adc1, CLK_SRC_GROUP_ADC, 1), 177 clock_adc2 = MAKE_CLOCK_NAME(sysctl_resource_adc2, CLK_SRC_GROUP_ADC, 2), 178 179 /* For DAC, there are 2-stage clock source and divider configurations */ 180 clock_ana3 = MAKE_CLOCK_NAME(RESOURCE_INVALID, CLK_SRC_GROUP_COMMON, clock_node_ana3), 181 clock_dac0 = MAKE_CLOCK_NAME(sysctl_resource_dac0, CLK_SRC_GROUP_DAC, 0), 182 183 /* For I2S, there are 2-stage clock source and divider configurations */ 184 clock_aud0 = MAKE_CLOCK_NAME(RESOURCE_INVALID, CLK_SRC_GROUP_COMMON, clock_node_aud0), 185 clock_aud1 = MAKE_CLOCK_NAME(RESOURCE_INVALID, CLK_SRC_GROUP_COMMON, clock_node_aud1), 186 clock_i2s0 = MAKE_CLOCK_NAME(sysctl_resource_i2s0, CLK_SRC_GROUP_I2S, 0), 187 clock_i2s1 = MAKE_CLOCK_NAME(sysctl_resource_i2s1, CLK_SRC_GROUP_I2S, 1), 188 189 /* Clock sources */ 190 clk_osc0clk0 = MAKE_CLOCK_NAME(sysctl_resource_xtal, CLK_SRC_GROUP_SRC, 0), 191 clk_pll0clk0 = MAKE_CLOCK_NAME(sysctl_resource_clk0_pll1, CLK_SRC_GROUP_SRC, 1), 192 clk_pll0clk1 = MAKE_CLOCK_NAME(sysctl_resource_clk1_pll0, CLK_SRC_GROUP_SRC, 2), 193 clk_pll0clk2 = MAKE_CLOCK_NAME(sysctl_resource_clk2_pll0, CLK_SRC_GROUP_SRC, 3), 194 clk_pll1clk0 = MAKE_CLOCK_NAME(sysctl_resource_clk0_pll1, CLK_SRC_GROUP_SRC, 4), 195 clk_pll1clk1 = MAKE_CLOCK_NAME(sysctl_resource_clk1_pll1, CLK_SRC_GROUP_SRC, 5), 196 clk_pll2clk0 = MAKE_CLOCK_NAME(sysctl_resource_clk0_pll2, CLK_SRC_GROUP_SRC, 6), 197 clk_pll2clk1 = MAKE_CLOCK_NAME(sysctl_resource_clk1_pll2, CLK_SRC_GROUP_SRC, 7), 198 } clock_name_t; 199 200 #ifdef __cplusplus 201 extern "C" { 202 #endif 203 204 /** 205 * @brief Get specified IP frequency 206 * @param[in] clock_name IP clock name 207 * 208 * @return IP clock frequency in Hz 209 */ 210 uint32_t clock_get_frequency(clock_name_t clock_name); 211 212 213 /** 214 * @brief Get Clock frequency for selected clock source 215 * @param [in] source clock source 216 * @return clock frequency for selected clock source 217 */ 218 uint32_t get_frequency_for_source(clock_source_t source); 219 220 /** 221 * @brief Get the IP clock source 222 * Note: This API return the direct clock source 223 * @param [in] clock_name clock name 224 * @return IP clock source 225 */ 226 clk_src_t clock_get_source(clock_name_t clock_name); 227 228 /** 229 * @brief Set ADC clock source 230 * @param[in] clock_name ADC clock name 231 * @param[in] src ADC clock source 232 * 233 * @return #status_success Setting ADC clock source is successful 234 * #status_clk_invalid Invalid ADC clock 235 * #status_clk_src_invalid Invalid ADC clock source 236 */ 237 hpm_stat_t clock_set_adc_source(clock_name_t clock_name, clk_src_t src); 238 239 /** 240 * @brief Set DAC clock source 241 * @param[in] clock_name DAC clock name 242 * @param[in] src DAC clock source 243 * 244 * @return #status_success Setting DAC clock source is successful 245 * #status_clk_invalid Invalid DAC clock 246 * #status_clk_src_invalid Invalid DAC clock source 247 */ 248 hpm_stat_t clock_set_dac_source(clock_name_t clock_name, clk_src_t src); 249 250 /** 251 * @brief Set I2S clock source 252 * @param[in] clock_name I2S clock name 253 * @param[in] src I2S clock source 254 * 255 * @return #status_success Setting I2S clock source is successful 256 * #status_clk_invalid Invalid I2S clock 257 * #status_clk_src_invalid Invalid I2S clock source 258 */ 259 hpm_stat_t clock_set_i2s_source(clock_name_t clock_name, clk_src_t src); 260 261 /** 262 * @brief Set the IP clock source and divider 263 * @param[in] clock_name clock name 264 * @param[in] src clock source 265 * @param[in] div clock divider, valid range (1 - 256) 266 * 267 * @return #status_success Setting Clock source and divider is successful. 268 * #status_clk_src_invalid clock source is invalid. 269 * #status_clk_fixed clock source and divider is a fixed value 270 * #status_clk_shared_ahb Clock is shared with the AHB clock 271 * #status_clk_shared_axi0 Clock is shared with the AXI0 clock 272 * #status_clk_shared_axi1 CLock is shared with the AXI1 clock 273 * #status_clk_shared_axi2 Clock is shared with the AXI2 clock 274 * #status_clk_shared_cpu0 Clock is shared with the CPU0 clock 275 * #status_clk_shared_cpu1 Clock is shared with the CPU1 clock 276 */ 277 hpm_stat_t clock_set_source_divider(clock_name_t clock_name, clk_src_t src, uint32_t div); 278 279 /** 280 * @brief Enable IP clock 281 * @param[in] clock_name IP clock name 282 */ 283 void clock_enable(clock_name_t clock_name); 284 285 /** 286 * @brief Disable IP clock 287 * @param[in] clock_name IP clock name 288 */ 289 void clock_disable(clock_name_t clock_name); 290 291 /** 292 * @brief Add IP to specified group 293 * @param[in] clock_name IP clock name 294 * @param[in] group resource group index, valid value: 0/1/2/3 295 */ 296 void clock_add_to_group(clock_name_t clock_name, uint32_t group); 297 298 /** 299 * @brief Remove IP from specified group 300 * @param[in] clock_name IP clock name 301 * @param[in] group resource group index, valid value: 0/1/2/3 302 */ 303 void clock_remove_from_group(clock_name_t clock_name, uint32_t group); 304 305 /** 306 * @brief Check IP in specified group 307 * @param[in] clock_name IP clock name 308 * @return true if in group, false if not in group 309 */ 310 bool clock_check_in_group(clock_name_t clock_name, uint32_t group); 311 312 /** 313 * @brief Disconnect the clock group from specified CPU 314 * @param[in] group clock group index, value value is 0/1/2/3 315 * @param[in] cpu CPU index, valid value is 0/1 316 */ 317 void clock_connect_group_to_cpu(uint32_t group, uint32_t cpu); 318 319 /** 320 * @brief Disconnect the clock group from specified CPU 321 * @param[in] group clock group index, value value is 0/1/2/3 322 * @param[in] cpu CPU index, valid value is 0/1 323 */ 324 void clock_disconnect_group_from_cpu(uint32_t group, uint32_t cpu); 325 326 /** 327 * @brief Delay specified microseconds 328 * 329 * @param [in] us expected delay interval in microseconds 330 */ 331 void clock_cpu_delay_us(uint32_t us); 332 333 /** 334 * @brief Delay specified milliseconds 335 * 336 * @param [in] ms expected delay interval in milliseconds 337 */ 338 void clock_cpu_delay_ms(uint32_t ms); 339 340 /** 341 * @brief Update the Core clock frequency 342 */ 343 void clock_update_core_clock(void); 344 345 /** 346 * @brief HPM Core clock variable 347 */ 348 extern uint32_t hpm_core_clock; 349 350 #ifdef __cplusplus 351 } 352 #endif 353 354 #endif /* HPM_CLOCK_DRV_H */ 355