HPM SDK
HPMicro Software Development Kit
hpm_pllctl_drv.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2021 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 #ifdef __cplusplus
48 extern "C" {
49 #endif
50 
58 static inline void pllctl_pll_unlock(PLLCTL_Type *ptr, uint8_t pll, uint32_t lock_mask)
59 {
60  ptr->PLL[pll].LOCK &= ~lock_mask;
61 }
62 
71 static inline void pllctl_pll_lock(PLLCTL_Type *ptr, uint8_t pll, uint32_t lock_mask)
72 {
73  ptr->PLL[pll].LOCK = lock_mask;
74 }
75 
84 static inline hpm_stat_t pllctl_pll_ss_disable(PLLCTL_Type *ptr, uint8_t pll)
85 {
86  if (pll > (PLLCTL_SOC_PLL_MAX_COUNT - 1)) {
88  }
89 
93  return status_success;
94 }
95 
104 static inline hpm_stat_t pllctl_pll_powerdown(PLLCTL_Type *ptr, uint8_t pll)
105 {
106  if (pll > (PLLCTL_SOC_PLL_MAX_COUNT - 1)) {
108  }
109 
110  ptr->PLL[pll].CFG1 = (ptr->PLL[pll].CFG1 &
113  return status_success;
114 }
115 
124 static inline hpm_stat_t pllctl_pll_poweron(PLLCTL_Type *ptr, uint8_t pll)
125 {
126  uint32_t cfg;
127  if (pll > (PLLCTL_SOC_PLL_MAX_COUNT - 1)) {
129  }
130 
131  cfg = ptr->PLL[pll].CFG1;
132  if (!(cfg & PLLCTL_PLL_CFG1_PLLPD_SW_MASK)) {
133  return status_success;
134  }
135 
138  }
139 
140  ptr->PLL[pll].CFG1 &= ~PLLCTL_PLL_CFG1_PLLPD_SW_MASK;
141 
142  /*
143  * put back to hardware mode
144  */
146  return status_success;
147 }
148 
160 static inline hpm_stat_t pllctl_pll_ss_enable(PLLCTL_Type *ptr, uint8_t pll,
161  uint8_t spread, uint8_t div,
162  bool down_spread)
163 {
164  if ((pll > (PLLCTL_SOC_PLL_MAX_COUNT - 1))
168  }
169  if (!(ptr->PLL[pll].CFG1 & PLLCTL_PLL_CFG1_PLLPD_SW_MASK)) {
170  pllctl_pll_powerdown(ptr, pll);
171  }
172 
176  ptr->PLL[pll].CFG0 = (ptr->PLL[pll].CFG0
180  | PLLCTL_PLL_CFG0_SS_DOWNSPREAD_SET(down_spread);
181 
182  pllctl_pll_poweron(ptr, pll);
183  return status_success;
184 }
185 
195 static inline hpm_stat_t pllctl_set_postdiv1(PLLCTL_Type *ptr, uint8_t pll, uint8_t div)
196 {
197  if ((pll > (PLLCTL_SOC_PLL_MAX_COUNT - 1))
198  || (!div)
201  }
202 
203  ptr->PLL[pll].CFG0 = ((ptr->PLL[pll].CFG0 & ~(PLLCTL_PLL_CFG0_POSTDIV1_MASK))) | PLLCTL_PLL_CFG0_POSTDIV1_SET(div);
204  return status_success;
205 }
206 
219 static inline hpm_stat_t pllctl_set_fbdiv_int(PLLCTL_Type *ptr, uint8_t pll, uint16_t fbdiv)
220 {
221  if ((pll > (PLLCTL_SOC_PLL_MAX_COUNT - 1))
222  || ((fbdiv - 1) > (uint16_t)(PLLCTL_PLL_CFG2_FBDIV_INT_MASK >> PLLCTL_PLL_CFG2_FBDIV_INT_SHIFT))) {
224  }
225 
226  ptr->PLL[pll].CFG2 = ((ptr->PLL[pll].CFG2 & ~(PLLCTL_PLL_CFG2_FBDIV_INT_MASK))) | PLLCTL_PLL_CFG2_FBDIV_INT_SET(fbdiv - 1);
227  return status_success;
228 }
229 
242 static inline hpm_stat_t pllctl_set_fbdiv_frac(PLLCTL_Type *ptr, uint8_t pll, uint16_t fbdiv)
243 {
244  if ((pll > (PLLCTL_SOC_PLL_MAX_COUNT - 1))
245  || ((fbdiv - 1) > (uint16_t) (PLLCTL_PLL_FREQ_FBDIV_FRAC_MASK >> PLLCTL_PLL_FREQ_FBDIV_FRAC_SHIFT))) {
247  }
248 
249  ptr->PLL[pll].FREQ = (ptr->PLL[pll].FREQ & ~(PLLCTL_PLL_FREQ_FBDIV_FRAC_MASK))
250  | PLLCTL_PLL_FREQ_FBDIV_FRAC_SET(fbdiv - 1);
251  return status_success;
252 }
253 
263 static inline hpm_stat_t pllctl_set_frac(PLLCTL_Type *ptr, uint8_t pll, uint32_t frac)
264 {
265  if ((pll > (PLLCTL_SOC_PLL_MAX_COUNT - 1))
268  }
269  ptr->PLL[pll].FREQ = (ptr->PLL[pll].FREQ & ~(PLLCTL_PLL_FREQ_FRAC_MASK))
270  | PLLCTL_PLL_FREQ_FRAC_SET(frac);
271  return status_success;
272 }
273 
283 static inline hpm_stat_t pllctl_get_div(PLLCTL_Type *ptr, uint8_t pll, uint8_t div_index)
284 {
285  if ((pll > (PLLCTL_SOC_PLL_MAX_COUNT - 1))
286  || !(PLLCTL_SOC_PLL_HAS_DIV0(pll))) {
288  }
289  if (div_index) {
290  return PLLCTL_PLL_DIV0_DIV_GET(ptr->PLL[pll].DIV1) + 1;
291  } else {
292  return PLLCTL_PLL_DIV0_DIV_GET(ptr->PLL[pll].DIV0) + 1;
293  }
294 }
295 
306 static inline hpm_stat_t pllctl_set_div(PLLCTL_Type *ptr, uint8_t pll, uint8_t div_index, uint16_t div)
307 {
308  if ((pll > (PLLCTL_SOC_PLL_MAX_COUNT - 1))
309  || !(PLLCTL_SOC_PLL_HAS_DIV0(pll))
310  || ((div - 1) > (uint16_t) (PLLCTL_PLL_DIV0_DIV_MASK >> PLLCTL_PLL_DIV0_DIV_SHIFT))) {
312  }
313 
314  if (div_index) {
315  ptr->PLL[pll].DIV1 = (ptr->PLL[pll].DIV1 & ~(PLLCTL_PLL_DIV1_DIV_MASK))
316  | PLLCTL_PLL_DIV1_DIV_SET(div - 1);
317  } else {
318  ptr->PLL[pll].DIV0 = (ptr->PLL[pll].DIV0 & ~(PLLCTL_PLL_DIV0_DIV_MASK))
319  | PLLCTL_PLL_DIV0_DIV_SET(div - 1);
320  }
321  return status_success;
322 }
323 
333 static inline bool pllctl_div_is_stable(PLLCTL_Type *ptr, uint8_t pll, uint8_t div_index)
334 {
335  if ((pll > (PLLCTL_SOC_PLL_MAX_COUNT - 1)) || !(PLLCTL_SOC_PLL_HAS_DIV0(pll))) {
336  return false;
337  }
338  if (div_index) {
339  return ptr->PLL[pll].DIV1 & PLLCTL_PLL_DIV0_RESPONSE_MASK;
340  } else {
341  return ptr->PLL[pll].DIV0 & PLLCTL_PLL_DIV0_RESPONSE_MASK;
342  }
343 }
344 
353 static inline bool pllctl_pll_is_enabled(PLLCTL_Type *ptr, uint8_t pll)
354 {
355  return (ptr->PLL[pll].STATUS & PLLCTL_PLL_STATUS_ENABLE_MASK);
356 }
357 
365 static inline bool pllctl_xtal_is_stable(PLLCTL_Type *ptr)
366 {
367  return ptr->XTAL & PLLCTL_XTAL_RESPONSE_MASK;
368 }
369 
377 static inline bool pllctl_xtal_is_enabled(PLLCTL_Type *ptr)
378 {
379  return ptr->XTAL & PLLCTL_XTAL_ENABLE_MASK;
380 }
381 
382 /*
383  * @brief set XTAL rampup time in cycles of IRC24M
384  *
385  * @param[in] ptr PLLCTL base address
386  */
387 static inline void pllctl_xtal_set_rampup_time(PLLCTL_Type *ptr, uint32_t cycles)
388 {
390 }
391 
401 hpm_stat_t pllctl_set_pll_work_mode(PLLCTL_Type *ptr, uint8_t pll, bool int_mode);
402 
412 hpm_stat_t pllctl_set_refdiv(PLLCTL_Type *ptr, uint8_t pll, uint8_t div);
413 
426  uint32_t freq_in_hz);
427 
439  uint32_t freq_in_hz);
440 
449 uint32_t pllctl_get_pll_freq_in_hz(PLLCTL_Type *ptr, uint8_t pll);
450 
451 #ifdef __cplusplus
452 }
453 #endif
457 #endif /* HPM_PLLCTL_DRV_H */
458 
#define PLLCTL_SOC_PLL_HAS_DIV0(x)
Definition: hpm_soc_feature.h:47
#define PLLCTL_SOC_PLL_MAX_COUNT
Definition: hpm_soc_feature.h:43
uint32_t hpm_stat_t
Definition: hpm_common.h:123
#define MAKE_STATUS(group, code)
Definition: hpm_common.h:132
@ status_invalid_argument
Definition: hpm_common.h:179
@ status_success
Definition: hpm_common.h:177
@ status_group_pllctl
Definition: hpm_common.h:158
hpm_stat_t pllctl_init_frac_pll_with_freq(PLLCTL_Type *ptr, uint8_t pll, uint32_t freq_in_hz)
Initialize PLL working at franction mode with specific frequency.
Definition: hpm_pllctl_drv.c:148
static hpm_stat_t pllctl_pll_powerdown(PLLCTL_Type *ptr, uint8_t pll)
Power down target PLL.
Definition: hpm_pllctl_drv.h:104
static void pllctl_pll_lock(PLLCTL_Type *ptr, uint8_t pll, uint32_t lock_mask)
Lock pll.
Definition: hpm_pllctl_drv.h:71
static hpm_stat_t pllctl_pll_poweron(PLLCTL_Type *ptr, uint8_t pll)
Power on target PLL.
Definition: hpm_pllctl_drv.h:124
hpm_stat_t pllctl_set_pll_work_mode(PLLCTL_Type *ptr, uint8_t pll, bool int_mode)
Set pll work mode.
Definition: hpm_pllctl_drv.c:26
static hpm_stat_t pllctl_set_postdiv1(PLLCTL_Type *ptr, uint8_t pll, uint8_t div)
Set postdiv1 for PLL.
Definition: hpm_pllctl_drv.h:195
static hpm_stat_t pllctl_set_div(PLLCTL_Type *ptr, uint8_t pll, uint8_t div_index, uint16_t div)
Set divider.
Definition: hpm_pllctl_drv.h:306
static void pllctl_xtal_set_rampup_time(PLLCTL_Type *ptr, uint32_t cycles)
Definition: hpm_pllctl_drv.h:387
static bool pllctl_xtal_is_enabled(PLLCTL_Type *ptr)
Check if XTAL is enabled.
Definition: hpm_pllctl_drv.h:377
uint32_t pllctl_get_pll_freq_in_hz(PLLCTL_Type *ptr, uint8_t pll)
Get frequency of target PLL.
Definition: hpm_pllctl_drv.c:220
static hpm_stat_t pllctl_set_fbdiv_int(PLLCTL_Type *ptr, uint8_t pll, uint16_t fbdiv)
Set fbdiv for PLL integer mode.
Definition: hpm_pllctl_drv.h:219
static bool pllctl_pll_is_enabled(PLLCTL_Type *ptr, uint8_t pll)
Check if target PLL is enabled.
Definition: hpm_pllctl_drv.h:353
static hpm_stat_t pllctl_get_div(PLLCTL_Type *ptr, uint8_t pll, uint8_t div_index)
Get PLL divx value.
Definition: hpm_pllctl_drv.h:283
static hpm_stat_t pllctl_pll_ss_enable(PLLCTL_Type *ptr, uint8_t pll, uint8_t spread, uint8_t div, bool down_spread)
Enable spread spectrum mode.
Definition: hpm_pllctl_drv.h:160
static hpm_stat_t pllctl_set_fbdiv_frac(PLLCTL_Type *ptr, uint8_t pll, uint16_t fbdiv)
Set fbdiv for PLL fraction mode.
Definition: hpm_pllctl_drv.h:242
static void pllctl_pll_unlock(PLLCTL_Type *ptr, uint8_t pll, uint32_t lock_mask)
Unlock pll.
Definition: hpm_pllctl_drv.h:58
hpm_stat_t pllctl_set_refdiv(PLLCTL_Type *ptr, uint8_t pll, uint8_t div)
Set refdiv.
Definition: hpm_pllctl_drv.c:50
static hpm_stat_t pllctl_pll_ss_disable(PLLCTL_Type *ptr, uint8_t pll)
Disable spread spectrum.
Definition: hpm_pllctl_drv.h:84
static bool pllctl_xtal_is_stable(PLLCTL_Type *ptr)
Check if XTAL is stable.
Definition: hpm_pllctl_drv.h:365
static hpm_stat_t pllctl_set_frac(PLLCTL_Type *ptr, uint8_t pll, uint32_t frac)
Set fraction for PLL fraction mode.
Definition: hpm_pllctl_drv.h:263
static bool pllctl_div_is_stable(PLLCTL_Type *ptr, uint8_t pll, uint8_t div_index)
Check if specific PLL DIV is stable.
Definition: hpm_pllctl_drv.h:333
hpm_stat_t pllctl_init_int_pll_with_freq(PLLCTL_Type *ptr, uint8_t pll, uint32_t freq_in_hz)
Initialize PLL working at integer mode with specific frequency.
Definition: hpm_pllctl_drv.c:81
@ 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_CFG0_SS_DIVVAL_MASK
Definition: hpm_pllctl_regs.h:114
#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_DIV0_DIV_SET(x)
Definition: hpm_pllctl_regs.h:385
#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_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_CFG0_SS_DIVVAL_SET(x)
Definition: hpm_pllctl_regs.h:116
#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_CFG0_SS_SPREAD_MASK
Definition: hpm_pllctl_regs.h:104
#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_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_CFG0_SS_SPREAD_SHIFT
Definition: hpm_pllctl_regs.h:105
#define PLLCTL_PLL_CFG2_FBDIV_INT_SHIFT
Definition: hpm_pllctl_regs.h:213
#define PLLCTL_PLL_CFG0_SS_DOWNSPREAD_SET(x)
Definition: hpm_pllctl_regs.h:128
#define PLLCTL_PLL_CFG0_SS_DIVVAL_SHIFT
Definition: hpm_pllctl_regs.h:115
#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_CFG0_SS_SPREAD_SET(x)
Definition: hpm_pllctl_regs.h:106
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
struct PLLCTL_Type::@523 PLL[5]
__RW uint32_t CFG1
Definition: hpm_pllctl_regs.h:17
__R uint32_t STATUS
Definition: hpm_pllctl_regs.h:22
__RW uint32_t LOCK
Definition: hpm_pllctl_regs.h:20
__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
__RW uint32_t DIV0
Definition: hpm_pllctl_regs.h:24