1 /*
2 * Copyright (c) 2021 HPMicro
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8 #include "hpm_pcfg_drv.h"
9 #include "hpm_soc_feature.h"
10
11 #define PCFG_CURRENT_MEASUREMENT_STEP (50U)
12 #define HPM_PMU_DRV_RETRY_COUNT (5000U)
13
pcfg_ldo1p1_set_voltage(PCFG_Type * ptr,uint16_t mv)14 hpm_stat_t pcfg_ldo1p1_set_voltage(PCFG_Type *ptr, uint16_t mv)
15 {
16 if ((mv < PCFG_SOC_LDO1P1_MIN_VOLTAGE_IN_MV)
17 || (mv > PCFG_SOC_LDO1P1_MAX_VOLTAGE_IN_MV)) {
18 return status_pcfg_ldo_out_of_range;
19 }
20 ptr->LDO1P1 = (ptr->LDO1P1 & ~PCFG_LDO1P1_VOLT_MASK) | PCFG_LDO1P1_VOLT_SET(mv);
21 return status_success;
22 }
23
pcfg_ldo2p5_set_voltage(PCFG_Type * ptr,uint16_t mv)24 hpm_stat_t pcfg_ldo2p5_set_voltage(PCFG_Type *ptr, uint16_t mv)
25 {
26 uint32_t retry = 0;
27 if ((mv < PCFG_SOC_LDO2P5_MIN_VOLTAGE_IN_MV)
28 || (mv > PCFG_SOC_LDO2P5_MAX_VOLTAGE_IN_MV)) {
29 return status_pcfg_ldo_out_of_range;
30 }
31 ptr->LDO2P5 &= ~PCFG_LDO2P5_ENABLE_MASK;
32 ptr->LDO2P5 = PCFG_LDO2P5_ENABLE_MASK | PCFG_LDO2P5_VOLT_SET(mv);
33
34 while (!PCFG_LDO2P5_READY_GET(ptr->LDO2P5)) {
35 if (retry > HPM_PMU_DRV_RETRY_COUNT) {
36 break;
37 }
38 retry++;
39 }
40 if (retry > HPM_PMU_DRV_RETRY_COUNT) {
41 return status_timeout;
42 }
43
44 return status_success;
45 }
46
pcfg_dcdc_get_current_level(PCFG_Type * ptr)47 uint16_t pcfg_dcdc_get_current_level(PCFG_Type *ptr)
48 {
49 uint32_t retry = 0;
50 while (!pcfg_dcdc_is_measure_current_valid(ptr)) {
51 if (retry > HPM_PMU_DRV_RETRY_COUNT) {
52 break;
53 }
54 retry++;
55 }
56 if (retry > HPM_PMU_DRV_RETRY_COUNT) {
57 return 0;
58 }
59
60 return PCFG_DCDC_CURRENT_LEVEL_GET(ptr->DCDC_CURRENT) * PCFG_CURRENT_MEASUREMENT_STEP;
61 }
62
pcfg_dcdc_set_voltage(PCFG_Type * ptr,uint16_t mv)63 hpm_stat_t pcfg_dcdc_set_voltage(PCFG_Type *ptr, uint16_t mv)
64 {
65 hpm_stat_t stat = status_success;
66 if ((mv < PCFG_SOC_DCDC_MIN_VOLTAGE_IN_MV) || (mv > PCFG_SOC_DCDC_MAX_VOLTAGE_IN_MV)) {
67 return status_invalid_argument;
68 }
69 ptr->DCDC_MODE = (ptr->DCDC_MODE & ~PCFG_DCDC_MODE_VOLT_MASK) | PCFG_DCDC_MODE_VOLT_SET(mv);
70 return stat;
71 }
72
73 #define PCFG_RC24M_FREQ (24000000UL)
pcfg_irc24m_config_track(PCFG_Type * ptr,pcfg_irc24m_config_t * config)74 void pcfg_irc24m_config_track(PCFG_Type *ptr, pcfg_irc24m_config_t *config)
75 {
76 uint32_t calculated_freq;
77 uint16_t mul = 1;
78 uint16_t div = 1;
79
80 if (!(config->freq_in_hz < PCFG_RC24M_FREQ)) {
81 /* calculate div */
82 div = PCFG_RC24M_FREQ / config->freq_in_hz;
83 }
84 calculated_freq = PCFG_RC24M_FREQ / div;
85 while (calculated_freq < config->freq_in_hz) {
86 calculated_freq *= (mul++);
87 }
88 ptr->TRACK_TARGET = PCFG_TRACK_TARGET_PRE_DIV_SET(div - 1)
89 | PCFG_TRACK_TARGET_TARGET_SET(mul - 1);
90 ptr->RC24M_TRACK = PCFG_RC24M_TRACK_SEL24M_SET(config->reference)
91 | PCFG_RC24M_TRACK_RETURN_SET(config->return_to_default_on_xtal_loss)
92 | PCFG_RC24M_TRACK_TRACK_SET(config->free_run);
93 }
94
pcfg_dcdc_set_lpmode_voltage(PCFG_Type * ptr,uint16_t mv)95 hpm_stat_t pcfg_dcdc_set_lpmode_voltage(PCFG_Type *ptr, uint16_t mv)
96 {
97 hpm_stat_t stat = status_success;
98 if ((mv < PCFG_SOC_DCDC_MIN_VOLTAGE_IN_MV) || (mv > PCFG_SOC_DCDC_MAX_VOLTAGE_IN_MV)) {
99 return status_invalid_argument;
100 }
101 ptr->DCDC_LPMODE = (ptr->DCDC_LPMODE & ~PCFG_DCDC_LPMODE_STBY_VOLT_MASK) | PCFG_DCDC_LPMODE_STBY_VOLT_SET(mv);
102 return stat;
103 }
104