• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2023 HPMicro
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  *
6  */
7 
8 #include "hpm_pllctlv2_drv.h"
9 
10 
11 #define PLLCTLV2_PLL_MFN_FACTOR (10U)                       /*!< PLLCTLV2 PLL MFN Factor */
12 #define PLLCTLV2_PLL_MFD_DEFAULT (240UL * 1000000UL)        /*!< PLLCTLV2 PLL Default MFD value */
13 
14 #define PLLCTLV2_PLL_MFI_MIN (16U)
15 #define PLLCTLV2_PLL_MFI_MAX (42U)
16 #define PLLCTLV2_PLL_XTAL_FREQ (24000000UL)
17 
18 #define PLLCTLV2_PLL_FREQ_MIN (PLLCTLV2_PLL_MFI_MIN * PLLCTLV2_PLL_XTAL_FREQ)
19 #define PLLCTLV2_PLL_FREQ_MAX ((PLLCTLV2_PLL_MFI_MAX + 1U) * PLLCTLV2_PLL_XTAL_FREQ)
20 
pllctlv2_init_pll_with_freq(PLLCTLV2_Type * ptr,uint8_t pll,uint32_t freq_in_hz)21 hpm_stat_t pllctlv2_init_pll_with_freq(PLLCTLV2_Type *ptr, uint8_t pll, uint32_t freq_in_hz)
22 {
23     hpm_stat_t status;
24     if ((ptr == NULL) || (freq_in_hz < PLLCTLV2_PLL_FREQ_MIN) || (freq_in_hz > PLLCTLV2_PLL_FREQ_MAX) ||
25         (pll >= PLLCTL_SOC_PLL_MAX_COUNT)) {
26         status = status_invalid_argument;
27     } else {
28         uint32_t mfn = freq_in_hz % PLLCTLV2_PLL_XTAL_FREQ;
29         uint32_t mfi = freq_in_hz / PLLCTLV2_PLL_XTAL_FREQ;
30 
31         if (PLLCTLV2_PLL_MFI_MFI_GET(ptr->PLL[pll].MFI) == mfi) {
32             ptr->PLL[pll].MFI = mfi - 1U;
33         }
34 
35         ptr->PLL[pll].MFI = mfi;
36         /*
37          * NOTE: Default MFD value is 240M
38          */
39         ptr->PLL[pll].MFN = mfn * PLLCTLV2_PLL_MFN_FACTOR;
40 
41         status = status_success;
42     }
43     return status;
44 }
45 
pllctlv2_enable_spread_spectrum(PLLCTLV2_Type * ptr,uint8_t pll,uint32_t step,uint32_t stop)46 void pllctlv2_enable_spread_spectrum(PLLCTLV2_Type *ptr, uint8_t pll, uint32_t step, uint32_t stop)
47 {
48     /*
49      * NOTE: The spread spectrum related registers cannot be configured under below conditions:
50      *       1. PLL is enabled
51      *       2. spread spectrum is enabled
52      */
53     if ((ptr != NULL) && (pll < PLLCTL_SOC_PLL_MAX_COUNT)) {
54 
55         ptr->PLL[pll].CONFIG &= ~PLLCTLV2_PLL_CONFIG_SPREAD_MASK;
56 
57         ptr->PLL[pll].SS_STEP = step;
58         ptr->PLL[pll].SS_STOP = stop;
59 
60         ptr->PLL[pll].CONFIG |= PLLCTLV2_PLL_CONFIG_SPREAD_MASK;
61     }
62 }
63 
pllctlv2_set_postdiv(PLLCTLV2_Type * ptr,uint8_t pll,uint8_t div_index,uint8_t div_value)64 void pllctlv2_set_postdiv(PLLCTLV2_Type *ptr, uint8_t pll, uint8_t div_index, uint8_t div_value)
65 {
66     if ((ptr != NULL) && (pll < PLLCTL_SOC_PLL_MAX_COUNT)) {
67         ptr->PLL[pll].DIV[div_index] =
68             (ptr->PLL[pll].DIV[div_index] & ~PLLCTLV2_PLL_DIV_DIV_MASK) | PLLCTLV2_PLL_DIV_DIV_SET(div_value) |
69                 PLLCTLV2_PLL_DIV_ENABLE_MASK;
70     }
71 }
72 
pllctlv2_get_pll_freq_in_hz(PLLCTLV2_Type * ptr,uint8_t pll)73 uint32_t pllctlv2_get_pll_freq_in_hz(PLLCTLV2_Type *ptr, uint8_t pll)
74 {
75     uint32_t freq = 0;
76     if ((ptr != NULL) && (pll < PLLCTL_SOC_PLL_MAX_COUNT)) {
77         uint32_t mfi = PLLCTLV2_PLL_MFI_MFI_GET(ptr->PLL[pll].MFI);
78         uint32_t mfn = PLLCTLV2_PLL_MFN_MFN_GET(ptr->PLL[pll].MFN);
79         uint32_t mfd = PLLCTLV2_PLL_MFD_MFD_GET(ptr->PLL[pll].MFD);
80         freq = (uint32_t) (PLLCTLV2_PLL_XTAL_FREQ * (mfi + 1.0 * mfn / mfd));
81     }
82     return freq;
83 }
84 
pllctlv2_get_pll_postdiv_freq_in_hz(PLLCTLV2_Type * ptr,uint8_t pll,uint8_t div_index)85 uint32_t pllctlv2_get_pll_postdiv_freq_in_hz(PLLCTLV2_Type *ptr, uint8_t pll, uint8_t div_index)
86 {
87     uint32_t postdiv_freq = 0;
88     if ((ptr != NULL) && (pll < PLLCTL_SOC_PLL_MAX_COUNT)) {
89         uint32_t postdiv = PLLCTLV2_PLL_DIV_DIV_GET(ptr->PLL[pll].DIV[div_index]);
90         uint32_t pll_freq = pllctlv2_get_pll_freq_in_hz(ptr, pll);
91         postdiv_freq = (uint32_t) (pll_freq / (1U + postdiv * 1.0 / 5U));
92     }
93 
94     return postdiv_freq;
95 }
96