HPM SDK
HPMicro Software Development Kit
hpm_pllctl_drv.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2021,2025 HPMicro
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  *
6  */
7 
8 #ifndef HPM_PLLCTL_DRV_H
9 #define HPM_PLLCTL_DRV_H
10 #include "hpm_common.h"
11 #include "hpm_soc_feature.h"
12 #include "hpm_pllctl_regs.h"
13 
21 #define PLLCTL_PLL_VCO_FREQ_MIN (375000000U)
22 #define PLLCTL_PLL_VCO_FREQ_MAX (2200000000U)
23 
24 /*
25  * @brief PLL parts with lock
26  */
27 #define PLLCTL_PLL_LOCK_SS_RESET PLLCTL_PLL_LOCK_LOCK_SS_RSTPTR_MASK
28 #define PLLCTL_PLL_LOCK_REFDIV PLLCTL_PLL_LOCK_LOCK_REFDIV_MASK
29 #define PLLCTL_PLL_LOCK_POSTDIV1 PLLCTL_PLL_LOCK_LOCK_POSTDIV1_MASK
30 #define PLLCTL_PLL_LOCK_SS_SPREAD PLLCTL_PLL_LOCK_LOCK_SS_SPREAD_MASK
31 #define PLLCTL_PLL_LOCK_SS_DIVVAL PLLCTL_PLL_LOCK_LOCK_SS_DIVVAL_MASK
32 #define PLLCTL_PLL_LOCK_ALL (PLLCTL_PLL_LOCK_LOCK_SS_RSTPTR_MASK \
33  | PLLCTL_PLL_LOCK_LOCK_REFDIV_MASK \
34  | PLLCTL_PLL_LOCK_LOCK_POSTDIV1_MASK \
35  | PLLCTL_PLL_LOCK_LOCK_SS_SPREAD_MASK \
36  | PLLCTL_PLL_LOCK_LOCK_SS_DIVVAL_MASK \
37  | PLLCTL_PLL_LOCK_LOCK_SS_DIVVAL_MASK)
38 
39 /*
40  * @brief PLLCTL specific status
41  */
42 enum {
45 };
46 
47 /*
48  * @brief PLLCTL spread spectrum type
49  */
50 typedef enum {
54 
55 #ifdef __cplusplus
56 extern "C" {
57 #endif
58 
66 static inline hpm_stat_t pllctl_pll_ss_disable(PLLCTL_Type *ptr, uint8_t pll)
67 {
68  if (pll > (PLLCTL_SOC_PLL_MAX_COUNT - 1)) {
70  }
71 
75  return status_success;
76 }
77 
85 static inline hpm_stat_t pllctl_pll_powerdown(PLLCTL_Type *ptr, uint8_t pll)
86 {
87  if (pll > (PLLCTL_SOC_PLL_MAX_COUNT - 1)) {
89  }
90 
91  ptr->PLL[pll].CFG1 = (ptr->PLL[pll].CFG1 &
94  return status_success;
95 }
96 
104 static inline hpm_stat_t pllctl_pll_poweron(PLLCTL_Type *ptr, uint8_t pll)
105 {
106  uint32_t cfg;
107  if (pll > (PLLCTL_SOC_PLL_MAX_COUNT - 1)) {
109  }
110 
111  cfg = ptr->PLL[pll].CFG1;
112  if (!(cfg & PLLCTL_PLL_CFG1_PLLPD_SW_MASK)) {
113  return status_success;
114  }
115 
118  }
119 
120  ptr->PLL[pll].CFG1 &= ~PLLCTL_PLL_CFG1_PLLPD_SW_MASK;
121 
122  /*
123  * put back to hardware mode
124  */
126  return status_success;
127 }
128 
137 static inline hpm_stat_t pllctl_set_postdiv1(PLLCTL_Type *ptr, uint8_t pll, uint8_t div)
138 {
139  if ((pll > (PLLCTL_SOC_PLL_MAX_COUNT - 1))
140  || (!div)
143  }
144 
145  ptr->PLL[pll].CFG0 = ((ptr->PLL[pll].CFG0 & ~(PLLCTL_PLL_CFG0_POSTDIV1_MASK))) | PLLCTL_PLL_CFG0_POSTDIV1_SET(div);
146  return status_success;
147 }
148 
157 static inline hpm_stat_t pllctl_set_fbdiv_int(PLLCTL_Type *ptr, uint8_t pll, uint16_t fbdiv)
158 {
159  if ((pll > (PLLCTL_SOC_PLL_MAX_COUNT - 1))
160  || ((fbdiv - 1) > (uint16_t)(PLLCTL_PLL_CFG2_FBDIV_INT_MASK >> PLLCTL_PLL_CFG2_FBDIV_INT_SHIFT))) {
162  }
163 
164  ptr->PLL[pll].CFG2 = ((ptr->PLL[pll].CFG2 & ~(PLLCTL_PLL_CFG2_FBDIV_INT_MASK))) | PLLCTL_PLL_CFG2_FBDIV_INT_SET(fbdiv - 1);
165  return status_success;
166 }
167 
175 static inline hpm_stat_t pllctl_set_fbdiv_frac(PLLCTL_Type *ptr, uint8_t pll, uint16_t fbdiv)
176 {
177  if ((pll > (PLLCTL_SOC_PLL_MAX_COUNT - 1))
178  || ((fbdiv - 1) > (uint16_t) (PLLCTL_PLL_FREQ_FBDIV_FRAC_MASK >> PLLCTL_PLL_FREQ_FBDIV_FRAC_SHIFT))) {
180  }
181 
182  ptr->PLL[pll].FREQ = (ptr->PLL[pll].FREQ & ~(PLLCTL_PLL_FREQ_FBDIV_FRAC_MASK))
183  | PLLCTL_PLL_FREQ_FBDIV_FRAC_SET(fbdiv - 1);
184  return status_success;
185 }
186 
195 static inline hpm_stat_t pllctl_set_frac(PLLCTL_Type *ptr, uint8_t pll, uint32_t frac)
196 {
197  if ((pll > (PLLCTL_SOC_PLL_MAX_COUNT - 1))
200  }
201  ptr->PLL[pll].FREQ = (ptr->PLL[pll].FREQ & ~(PLLCTL_PLL_FREQ_FRAC_MASK))
202  | PLLCTL_PLL_FREQ_FRAC_SET(frac);
203  return status_success;
204 }
205 
213 static inline hpm_stat_t pllctl_get_div(PLLCTL_Type *ptr, uint8_t pll, uint8_t div_index)
214 {
215  if ((pll > (PLLCTL_SOC_PLL_MAX_COUNT - 1))
216  || !(PLLCTL_SOC_PLL_HAS_DIV0(pll))) {
218  }
219  if (div_index) {
220  return PLLCTL_PLL_DIV0_DIV_GET(ptr->PLL[pll].DIV1) + 1;
221  } else {
222  return PLLCTL_PLL_DIV0_DIV_GET(ptr->PLL[pll].DIV0) + 1;
223  }
224 }
225 
233 static inline bool pllctl_div_is_stable(PLLCTL_Type *ptr, uint8_t pll, uint8_t div_index)
234 {
235  uint32_t status;
236  if ((pll > (PLLCTL_SOC_PLL_MAX_COUNT - 1)) || !(PLLCTL_SOC_PLL_HAS_DIV0(pll))) {
237  return false;
238  }
239  if (div_index) {
240  status = ptr->PLL[pll].DIV1;
243  } else {
244  status = ptr->PLL[pll].DIV0;
247  }
248 }
249 
258 static inline hpm_stat_t pllctl_set_div(PLLCTL_Type *ptr, uint8_t pll, uint8_t div_index, uint16_t div)
259 {
260  if ((pll > (PLLCTL_SOC_PLL_MAX_COUNT - 1))
261  || !(PLLCTL_SOC_PLL_HAS_DIV0(pll))
262  || ((div - 1) > (uint16_t) (PLLCTL_PLL_DIV0_DIV_MASK >> PLLCTL_PLL_DIV0_DIV_SHIFT))) {
264  }
265 
266  if (div_index) {
267  ptr->PLL[pll].DIV1 = (ptr->PLL[pll].DIV1 & ~(PLLCTL_PLL_DIV1_DIV_MASK))
268  | PLLCTL_PLL_DIV1_DIV_SET(div - 1);
269  } else {
270  ptr->PLL[pll].DIV0 = (ptr->PLL[pll].DIV0 & ~(PLLCTL_PLL_DIV0_DIV_MASK))
271  | PLLCTL_PLL_DIV0_DIV_SET(div - 1);
272  }
273  while (!pllctl_div_is_stable(ptr, pll, div_index)) {
274  NOP();
275  }
276  return status_success;
277 }
278 
285 static inline bool pllctl_pll_is_enabled(PLLCTL_Type *ptr, uint8_t pll)
286 {
287  return (ptr->PLL[pll].STATUS & PLLCTL_PLL_STATUS_ENABLE_MASK);
288 }
289 
295 static inline bool pllctl_xtal_is_stable(PLLCTL_Type *ptr)
296 {
297  uint32_t status = ptr->XTAL;
300 }
301 
307 static inline bool pllctl_xtal_is_enabled(PLLCTL_Type *ptr)
308 {
309  return ptr->XTAL & PLLCTL_XTAL_ENABLE_MASK;
310 }
311 
318 static inline void pllctl_xtal_set_rampup_time(PLLCTL_Type *ptr, uint32_t cycles)
319 {
321 }
322 
329 static inline bool pllctl_pll_is_locked(PLLCTL_Type *ptr, uint8_t pll)
330 {
331  return ((ptr->PLL[pll].STATUS & PLLCTL_PLL_STATUS_PLL_LOCK_COMB_MASK));
332 }
333 
342 hpm_stat_t pllctl_set_pll_work_mode(PLLCTL_Type *ptr, uint8_t pll, bool int_mode);
343 
352 hpm_stat_t pllctl_set_refdiv(PLLCTL_Type *ptr, uint8_t pll, uint8_t div);
353 
362 hpm_stat_t pllctl_init_int_pll_with_freq(PLLCTL_Type *ptr, uint8_t pll, uint32_t freq_in_hz);
363 
372 hpm_stat_t pllctl_init_frac_pll_with_freq(PLLCTL_Type *ptr, uint8_t pll, uint32_t freq_in_hz);
373 
380 uint32_t pllctl_get_pll_freq_in_hz(PLLCTL_Type *ptr, uint8_t pll);
381 
391 hpm_stat_t pllctl_pll_ss_enable(PLLCTL_Type *ptr, uint8_t pll, uint8_t spread, uint8_t div, bool down_spread);
392 
402 hpm_stat_t pllctl_pll_setup_spread_spectrum(PLLCTL_Type *ptr, uint8_t pll, uint8_t ss_range, uint32_t modulation_freq, pllctl_ss_type ss_type);
403 #ifdef __cplusplus
404 }
405 #endif
409 #endif /* HPM_PLLCTL_DRV_H */
#define PLLCTL_SOC_PLL_HAS_DIV0(x)
Definition: hpm_soc_feature.h:59
#define PLLCTL_SOC_PLL_MAX_COUNT
Definition: hpm_soc_feature.h:55
uint32_t hpm_stat_t
Definition: hpm_common.h:135
#define IS_HPM_BITMASK_CLR(val, mask)
Definition: hpm_common.h:63
#define MAKE_STATUS(group, code)
Definition: hpm_common.h:144
#define IS_HPM_BITMASK_SET(val, mask)
Definition: hpm_common.h:61
@ status_invalid_argument
Definition: hpm_common.h:191
@ status_success
Definition: hpm_common.h:189
@ status_group_pllctl
Definition: hpm_common.h:170
hpm_stat_t pllctl_init_frac_pll_with_freq(PLLCTL_Type *ptr, uint8_t pll, uint32_t freq_in_hz)
Initializes a PLL in fractional mode for a specific frequency.
Definition: hpm_pllctl_drv.c:156
static hpm_stat_t pllctl_pll_powerdown(PLLCTL_Type *ptr, uint8_t pll)
Powers down a specified PLL.
Definition: hpm_pllctl_drv.h:85
static hpm_stat_t pllctl_pll_poweron(PLLCTL_Type *ptr, uint8_t pll)
Powers on a specified PLL.
Definition: hpm_pllctl_drv.h:104
hpm_stat_t pllctl_set_pll_work_mode(PLLCTL_Type *ptr, uint8_t pll, bool int_mode)
Sets the operating mode of a specified PLL.
Definition: hpm_pllctl_drv.c:26
static hpm_stat_t pllctl_set_postdiv1(PLLCTL_Type *ptr, uint8_t pll, uint8_t div)
Sets the post-divider (postdiv1) for a specified PLL.
Definition: hpm_pllctl_drv.h:137
static hpm_stat_t pllctl_set_div(PLLCTL_Type *ptr, uint8_t pll, uint8_t div_index, uint16_t div)
Sets the divider value for a specified PLL divider.
Definition: hpm_pllctl_drv.h:258
static void pllctl_xtal_set_rampup_time(PLLCTL_Type *ptr, uint32_t cycles)
Sets the ramp-up time for the crystal oscillator.
Definition: hpm_pllctl_drv.h:318
static bool pllctl_xtal_is_enabled(PLLCTL_Type *ptr)
Checks if the crystal oscillator is enabled.
Definition: hpm_pllctl_drv.h:307
uint32_t pllctl_get_pll_freq_in_hz(PLLCTL_Type *ptr, uint8_t pll)
Gets the current frequency of a specified PLL.
Definition: hpm_pllctl_drv.c:232
static hpm_stat_t pllctl_set_fbdiv_int(PLLCTL_Type *ptr, uint8_t pll, uint16_t fbdiv)
Sets the feedback divider for PLL integer mode.
Definition: hpm_pllctl_drv.h:157
pllctl_ss_type
Definition: hpm_pllctl_drv.h:50
static bool pllctl_pll_is_enabled(PLLCTL_Type *ptr, uint8_t pll)
Checks if a specified PLL is enabled.
Definition: hpm_pllctl_drv.h:285
static hpm_stat_t pllctl_get_div(PLLCTL_Type *ptr, uint8_t pll, uint8_t div_index)
Gets the current divider value for a specified PLL divider.
Definition: hpm_pllctl_drv.h:213
static hpm_stat_t pllctl_set_fbdiv_frac(PLLCTL_Type *ptr, uint8_t pll, uint16_t fbdiv)
Sets the feedback divider for PLL fraction mode.
Definition: hpm_pllctl_drv.h:175
hpm_stat_t pllctl_set_refdiv(PLLCTL_Type *ptr, uint8_t pll, uint8_t div)
Sets the reference divider for a specified PLL.
Definition: hpm_pllctl_drv.c:50
static bool pllctl_pll_is_locked(PLLCTL_Type *ptr, uint8_t pll)
Checks if a specified PLL is locked.
Definition: hpm_pllctl_drv.h:329
hpm_stat_t pllctl_pll_ss_enable(PLLCTL_Type *ptr, uint8_t pll, uint8_t spread, uint8_t div, bool down_spread)
Enables spread spectrum mode for a specified PLL.
Definition: hpm_pllctl_drv.c:260
static hpm_stat_t pllctl_pll_ss_disable(PLLCTL_Type *ptr, uint8_t pll)
Disables spread spectrum mode for a specified PLL.
Definition: hpm_pllctl_drv.h:66
static bool pllctl_xtal_is_stable(PLLCTL_Type *ptr)
Checks if the crystal oscillator has stabilized.
Definition: hpm_pllctl_drv.h:295
static hpm_stat_t pllctl_set_frac(PLLCTL_Type *ptr, uint8_t pll, uint32_t frac)
Sets the fractional part for PLL fraction mode.
Definition: hpm_pllctl_drv.h:195
static bool pllctl_div_is_stable(PLLCTL_Type *ptr, uint8_t pll, uint8_t div_index)
Checks if a specified PLL divider has stabilized.
Definition: hpm_pllctl_drv.h:233
hpm_stat_t pllctl_pll_setup_spread_spectrum(PLLCTL_Type *ptr, uint8_t pll, uint8_t ss_range, uint32_t modulation_freq, pllctl_ss_type ss_type)
Configures spread spectrum settings for a specified PLL.
Definition: hpm_pllctl_drv.c:291
hpm_stat_t pllctl_init_int_pll_with_freq(PLLCTL_Type *ptr, uint8_t pll, uint32_t freq_in_hz)
Initializes a PLL in integer mode for a specific frequency.
Definition: hpm_pllctl_drv.c:85
@ pllctl_ss_centerspread
Definition: hpm_pllctl_drv.h:51
@ pllctl_ss_downspread
Definition: hpm_pllctl_drv.h:52
@ status_pllctl_not_enabled
Definition: hpm_pllctl_drv.h:43
@ status_pllctl_out_of_range
Definition: hpm_pllctl_drv.h:44
#define PLLCTL_XTAL_ENABLE_MASK
Definition: hpm_pllctl_regs.h:50
#define PLLCTL_PLL_DIV0_DIV_MASK
Definition: hpm_pllctl_regs.h:383
#define PLLCTL_PLL_FREQ_FRAC_MASK
Definition: hpm_pllctl_regs.h:229
#define PLLCTL_PLL_FREQ_FBDIV_FRAC_SET(x)
Definition: hpm_pllctl_regs.h:241
#define PLLCTL_PLL_CFG0_POSTDIV1_SET(x)
Definition: hpm_pllctl_regs.h:96
#define PLLCTL_XTAL_RAMP_TIME_SET(x)
Definition: hpm_pllctl_regs.h:65
#define PLLCTL_PLL_CFG1_PLLCTRL_HW_EN_MASK
Definition: hpm_pllctl_regs.h:166
#define PLLCTL_PLL_DIV1_BUSY_MASK
Definition: hpm_pllctl_regs.h:396
#define PLLCTL_PLL_DIV0_DIV_SET(x)
Definition: hpm_pllctl_regs.h:385
#define PLLCTL_PLL_DIV1_ENABLE_MASK
Definition: hpm_pllctl_regs.h:418
#define PLLCTL_PLL_FREQ_FRAC_SET(x)
Definition: hpm_pllctl_regs.h:231
#define PLLCTL_PLL_DIV0_DIV_GET(x)
Definition: hpm_pllctl_regs.h:386
#define PLLCTL_PLL_DIV0_BUSY_MASK
Definition: hpm_pllctl_regs.h:348
#define PLLCTL_PLL_CFG2_FBDIV_INT_SET(x)
Definition: hpm_pllctl_regs.h:214
#define PLLCTL_XTAL_RAMP_TIME_MASK
Definition: hpm_pllctl_regs.h:63
#define PLLCTL_PLL_FREQ_FBDIV_FRAC_SHIFT
Definition: hpm_pllctl_regs.h:240
#define PLLCTL_PLL_CFG0_SS_RSTPTR_MASK
Definition: hpm_pllctl_regs.h:74
#define PLLCTL_PLL_CFG0_POSTDIV1_SHIFT
Definition: hpm_pllctl_regs.h:95
#define PLLCTL_XTAL_RESPONSE_MASK
Definition: hpm_pllctl_regs.h:39
#define PLLCTL_PLL_CFG1_PLLPD_SW_MASK
Definition: hpm_pllctl_regs.h:190
#define PLLCTL_PLL_CFG1_CLKEN_SW_MASK
Definition: hpm_pllctl_regs.h:177
#define PLLCTL_PLL_DIV0_RESPONSE_MASK
Definition: hpm_pllctl_regs.h:359
#define PLLCTL_PLL_CFG0_SS_RESET_MASK
Definition: hpm_pllctl_regs.h:135
#define PLLCTL_PLL_DIV1_DIV_SET(x)
Definition: hpm_pllctl_regs.h:433
#define PLLCTL_PLL_FREQ_FRAC_SHIFT
Definition: hpm_pllctl_regs.h:230
#define PLLCTL_PLL_STATUS_PLL_LOCK_COMB_MASK
Definition: hpm_pllctl_regs.h:328
#define PLLCTL_PLL_STATUS_ENABLE_MASK
Definition: hpm_pllctl_regs.h:311
#define PLLCTL_PLL_DIV1_DIV_MASK
Definition: hpm_pllctl_regs.h:431
#define PLLCTL_PLL_DIV0_DIV_SHIFT
Definition: hpm_pllctl_regs.h:384
#define PLLCTL_PLL_CFG2_FBDIV_INT_SHIFT
Definition: hpm_pllctl_regs.h:213
#define PLLCTL_PLL_DIV1_RESPONSE_MASK
Definition: hpm_pllctl_regs.h:407
#define PLLCTL_PLL_CFG0_POSTDIV1_MASK
Definition: hpm_pllctl_regs.h:94
#define PLLCTL_PLL_FREQ_FBDIV_FRAC_MASK
Definition: hpm_pllctl_regs.h:239
#define PLLCTL_PLL_CFG2_FBDIV_INT_MASK
Definition: hpm_pllctl_regs.h:212
#define PLLCTL_PLL_CFG0_SS_DISABLE_SSCG_MASK
Definition: hpm_pllctl_regs.h:144
#define PLLCTL_PLL_DIV0_ENABLE_MASK
Definition: hpm_pllctl_regs.h:370
Definition: hpm_pllctl_regs.h:12
__RW uint32_t XTAL
Definition: hpm_pllctl_regs.h:13
__RW uint32_t CFG0
Definition: hpm_pllctl_regs.h:16
__RW uint32_t CFG1
Definition: hpm_pllctl_regs.h:17
__R uint32_t STATUS
Definition: hpm_pllctl_regs.h:22
__RW uint32_t DIV1
Definition: hpm_pllctl_regs.h:25
__RW uint32_t CFG2
Definition: hpm_pllctl_regs.h:18
__RW uint32_t FREQ
Definition: hpm_pllctl_regs.h:19
struct PLLCTL_Type::@599 PLL[5]
__RW uint32_t DIV0
Definition: hpm_pllctl_regs.h:24