1 /*
2 * Copyright (c) 2022-2024 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_set_pll_with_mfi_mfn(PLLCTLV2_Type * ptr,uint8_t pll,uint32_t mfi,uint32_t mfn)21 hpm_stat_t pllctlv2_set_pll_with_mfi_mfn(PLLCTLV2_Type *ptr, uint8_t pll, uint32_t mfi, uint32_t mfn)
22 {
23 hpm_stat_t status;
24 if ((ptr == NULL) || (mfi < PLLCTLV2_PLL_MFI_MIN) || (mfi > PLLCTLV2_PLL_MFI_MAX) ||
25 (pll >= PLLCTL_SOC_PLL_MAX_COUNT)) {
26 status = status_invalid_argument;
27 } else {
28 if (PLLCTLV2_PLL_MFI_MFI_GET(ptr->PLL[pll].MFI) == mfi) {
29 ptr->PLL[pll].MFI = mfi - 1U;
30 }
31 ptr->PLL[pll].MFI = mfi;
32 ptr->PLL[pll].MFN = mfn;
33
34 status = status_success;
35 }
36 return status;
37 }
38
pllctlv2_init_pll_with_freq(PLLCTLV2_Type * ptr,uint8_t pll,uint32_t freq_in_hz)39 hpm_stat_t pllctlv2_init_pll_with_freq(PLLCTLV2_Type *ptr, uint8_t pll, uint32_t freq_in_hz)
40 {
41 hpm_stat_t status;
42 if ((ptr == NULL) || (freq_in_hz < PLLCTLV2_PLL_FREQ_MIN) || (freq_in_hz > PLLCTLV2_PLL_FREQ_MAX) ||
43 (pll >= PLLCTL_SOC_PLL_MAX_COUNT)) {
44 status = status_invalid_argument;
45 } else {
46 uint32_t mfn = freq_in_hz % PLLCTLV2_PLL_XTAL_FREQ;
47 uint32_t mfi = freq_in_hz / PLLCTLV2_PLL_XTAL_FREQ;
48
49 if (PLLCTLV2_PLL_MFI_MFI_GET(ptr->PLL[pll].MFI) == mfi) {
50 ptr->PLL[pll].MFI = mfi - 1U;
51 }
52
53 ptr->PLL[pll].MFI = mfi;
54 /*
55 * NOTE: Default MFD value is 240M
56 */
57 ptr->PLL[pll].MFN = mfn * PLLCTLV2_PLL_MFN_FACTOR;
58
59 status = status_success;
60 }
61 return status;
62 }
63
pllctlv2_enable_spread_spectrum(PLLCTLV2_Type * ptr,uint8_t pll,uint32_t step,uint32_t stop)64 void pllctlv2_enable_spread_spectrum(PLLCTLV2_Type *ptr, uint8_t pll, uint32_t step, uint32_t stop)
65 {
66 /*
67 * NOTE: The spread spectrum related registers cannot be configured under below conditions:
68 * 1. PLL is enabled
69 * 2. spread spectrum is enabled
70 */
71 if ((ptr != NULL) && (pll < PLLCTL_SOC_PLL_MAX_COUNT)) {
72
73 ptr->PLL[pll].CONFIG &= ~PLLCTLV2_PLL_CONFIG_SPREAD_MASK;
74
75 ptr->PLL[pll].SS_STEP = step;
76 ptr->PLL[pll].SS_STOP = stop;
77
78 ptr->PLL[pll].CONFIG |= PLLCTLV2_PLL_CONFIG_SPREAD_MASK;
79 }
80 }
81
pllctlv2_set_postdiv(PLLCTLV2_Type * ptr,uint8_t pll,uint8_t div_index,uint8_t div_value)82 void pllctlv2_set_postdiv(PLLCTLV2_Type *ptr, uint8_t pll, uint8_t div_index, uint8_t div_value)
83 {
84 if ((ptr != NULL) && (pll < PLLCTL_SOC_PLL_MAX_COUNT)) {
85 ptr->PLL[pll].DIV[div_index] =
86 (ptr->PLL[pll].DIV[div_index] & ~PLLCTLV2_PLL_DIV_DIV_MASK) | PLLCTLV2_PLL_DIV_DIV_SET(div_value) |
87 PLLCTLV2_PLL_DIV_ENABLE_MASK;
88 }
89 }
90
pllctlv2_get_pll_freq_in_hz(PLLCTLV2_Type * ptr,uint8_t pll)91 uint32_t pllctlv2_get_pll_freq_in_hz(PLLCTLV2_Type *ptr, uint8_t pll)
92 {
93 uint32_t freq = 0;
94 if ((ptr != NULL) && (pll < PLLCTL_SOC_PLL_MAX_COUNT)) {
95 uint32_t mfi = PLLCTLV2_PLL_MFI_MFI_GET(ptr->PLL[pll].MFI);
96 uint32_t mfn = PLLCTLV2_PLL_MFN_MFN_GET(ptr->PLL[pll].MFN);
97 uint32_t mfd = PLLCTLV2_PLL_MFD_MFD_GET(ptr->PLL[pll].MFD);
98 freq = (uint32_t) (PLLCTLV2_PLL_XTAL_FREQ * (mfi + 1.0 * mfn / mfd));
99 }
100 return freq;
101 }
102
pllctlv2_get_pll_postdiv_freq_in_hz(PLLCTLV2_Type * ptr,uint8_t pll,uint8_t div_index)103 uint32_t pllctlv2_get_pll_postdiv_freq_in_hz(PLLCTLV2_Type *ptr, uint8_t pll, uint8_t div_index)
104 {
105 uint32_t postdiv_freq = 0;
106 if ((ptr != NULL) && (pll < PLLCTL_SOC_PLL_MAX_COUNT)) {
107 uint32_t postdiv = PLLCTLV2_PLL_DIV_DIV_GET(ptr->PLL[pll].DIV[div_index]);
108 uint32_t pll_freq = pllctlv2_get_pll_freq_in_hz(ptr, pll);
109 postdiv_freq = (uint32_t) (pll_freq / (1U + postdiv * 1.0 / 5U));
110 }
111
112 return postdiv_freq;
113 }
114