1 /*
2  * Copyright (c) 2015, Freescale Semiconductor, Inc.
3  * Copyright (c) 2016, NXP
4  * All rights reserved.
5  *
6  *
7  * SPDX-License-Identifier: BSD-3-Clause
8  */
9 
10 #include "fsl_spm.h"
11 #include "math.h" /* Using floor() function to convert float variable to int. */
12 
SPM_GetRegulatorStatus(SPM_Type * base,spm_regulator_status_t * info)13 void SPM_GetRegulatorStatus(SPM_Type *base, spm_regulator_status_t *info)
14 {
15     assert(info);
16 
17     volatile uint32_t tmp32 = base->RSR; /* volatile here is to make sure this value is actually from the hardware. */
18 
19     info->isRadioRunForcePowerModeOn = (SPM_RSR_RFRUNFORCE_MASK == (tmp32 & SPM_RSR_RFRUNFORCE_MASK));
20     info->radioLowPowerModeStatus =
21         (spm_radio_low_power_mode_status_t)((tmp32 & SPM_RSR_RFPMSTAT_MASK) >> SPM_RSR_RFPMSTAT_SHIFT);
22     info->mcuLowPowerModeStatus =
23         (spm_mcu_low_power_mode_status_t)((tmp32 & SPM_RSR_MCUPMSTAT_MASK) >> SPM_RSR_MCUPMSTAT_SHIFT);
24     info->isDcdcLdoOn =
25         (0x4 == (0x4 & ((tmp32 & SPM_RSR_REGSEL_MASK) >> SPM_RSR_REGSEL_SHIFT))); /* 1<<2 responses DCDC LDO. */
26     info->isRfLdoOn =
27         (0x2 == (0x2 & ((tmp32 & SPM_RSR_REGSEL_MASK) >> SPM_RSR_REGSEL_SHIFT))); /* 1<<1 responses RF LDO. */
28     info->isCoreLdoOn =
29         (0x1 == (0x1 & ((tmp32 & SPM_RSR_REGSEL_MASK) >> SPM_RSR_REGSEL_SHIFT))); /* 1<<0 responses CORE LDO. */
30 }
31 
SPM_SetLowVoltDetectConfig(SPM_Type * base,const spm_low_volt_detect_config_t * config)32 void SPM_SetLowVoltDetectConfig(SPM_Type *base, const spm_low_volt_detect_config_t *config)
33 {
34     uint32_t tmp32 = base->LVDSC1 &
35                      ~(SPM_LVDSC1_VDD_LVDIE_MASK | SPM_LVDSC1_VDD_LVDRE_MASK | SPM_LVDSC1_VDD_LVDV_MASK |
36                        SPM_LVDSC1_COREVDD_LVDIE_MASK | SPM_LVDSC1_COREVDD_LVDRE_MASK);
37 
38     /* VDD voltage detection. */
39     tmp32 |= SPM_LVDSC1_VDD_LVDV(config->vddLowVoltDetectSelect);
40     if (config->enableIntOnVddLowVolt)
41     {
42         tmp32 |= SPM_LVDSC1_VDD_LVDIE_MASK;
43     }
44     if (config->enableResetOnVddLowVolt)
45     {
46         tmp32 |= SPM_LVDSC1_VDD_LVDRE_MASK;
47     }
48     /* Clear the Low Voltage Detect Flag with previouse power detect setting. */
49     tmp32 |= SPM_LVDSC1_VDD_LVDACK_MASK;
50 
51     /* COREVDD voltage detection. */
52     if (config->enableIntOnCoreLowVolt)
53     {
54         tmp32 |= SPM_LVDSC1_COREVDD_LVDIE_MASK;
55     }
56     if (config->enableResetOnCoreLowVolt)
57     {
58         tmp32 |= SPM_LVDSC1_COREVDD_LVDRE_MASK;
59     }
60     tmp32 |= SPM_LVDSC1_COREVDD_LVDACK_MASK; /* Clear previous error flag. */
61 
62     base->LVDSC1 = tmp32;
63 }
64 
SPM_SetLowVoltWarningConfig(SPM_Type * base,const spm_low_volt_warning_config_t * config)65 void SPM_SetLowVoltWarningConfig(SPM_Type *base, const spm_low_volt_warning_config_t *config)
66 {
67     uint32_t tmp32 = base->LVDSC2 & ~(SPM_LVDSC2_VDD_LVWV_MASK | SPM_LVDSC2_VDD_LVWIE_MASK);
68 
69     tmp32 |= SPM_LVDSC2_VDD_LVWV(config->vddLowVoltDetectSelect);
70     if (config->enableIntOnVddLowVolt)
71     {
72         tmp32 |= SPM_LVDSC2_VDD_LVWIE_MASK;
73     }
74     tmp32 |= SPM_LVDSC2_VDD_LVWACK_MASK; /* Clear previous error flag. */
75 
76     base->LVDSC2 = tmp32;
77 }
78 
SPM_SetHighVoltDetectConfig(SPM_Type * base,const spm_high_volt_detect_config_t * config)79 void SPM_SetHighVoltDetectConfig(SPM_Type *base, const spm_high_volt_detect_config_t *config)
80 {
81     uint32_t tmp32;
82 
83     tmp32 = base->HVDSC1 & ~(SPM_HVDSC1_VDD_HVDIE_MASK | SPM_HVDSC1_VDD_HVDRE_MASK |\
84                              SPM_HVDSC1_VDD_HVDV_MASK);
85     tmp32 |= SPM_HVDSC1_VDD_HVDV(config->vddHighVoltDetectSelect);
86     if(config->enableIntOnVddHighVolt)
87     {
88         tmp32 |= SPM_HVDSC1_VDD_HVDIE_MASK;
89     }
90     if(config->enableResetOnVddHighVolt)
91     {
92         tmp32 |= SPM_HVDSC1_VDD_HVDRE_MASK;
93     }
94     tmp32 |= SPM_HVDSC1_VDD_HVDACK_MASK; /* Clear previous error flag. */
95 
96     base->HVDSC1 = tmp32;
97 }
98 
SPM_SetRfLdoConfig(SPM_Type * base,const spm_rf_ldo_config_t * config)99 void SPM_SetRfLdoConfig(SPM_Type *base, const spm_rf_ldo_config_t *config)
100 {
101     uint32_t tmp32 = 0U;
102 
103     switch (config->lowPowerMode)
104     {
105         case kSPM_RfLdoRemainInHighPowerInLowPowerModes:
106             tmp32 |= SPM_RFLDOLPCNFG_LPSEL_MASK;
107             break;
108         default: /* kSPM_RfLdoEnterLowPowerInLowPowerModes. */
109             break;
110     }
111     base->RFLDOLPCNFG = tmp32;
112 
113     tmp32 = SPM_RFLDOSC_IOSSSEL(config->softStartDuration) | SPM_RFLDOSC_IOREGVSEL(config->rfIoRegulatorVolt);
114     if (config->enableCurSink)
115     {
116         tmp32 |= SPM_RFLDOSC_ISINKEN_MASK;
117     }
118     base->RFLDOSC = tmp32;
119 }
120 
SPM_SetDcdcBattMonitor(SPM_Type * base,uint32_t batAdcVal)121 void SPM_SetDcdcBattMonitor(SPM_Type *base, uint32_t batAdcVal)
122 {
123     /* Clear the value and disable it at first. */
124     base->DCDCC2 &= ~(SPM_DCDCC2_DCDC_BATTMONITOR_BATT_VAL_MASK | SPM_DCDCC2_DCDC_BATTMONITOR_EN_BATADJ_MASK);
125     if (0U != batAdcVal)
126     {
127         /* When setting the value to BATT_VAL field, it should be zero before. */
128         base->DCDCC2 |= SPM_DCDCC2_DCDC_BATTMONITOR_BATT_VAL(batAdcVal);
129         base->DCDCC2 |= SPM_DCDCC2_DCDC_BATTMONITOR_EN_BATADJ_MASK;
130     }
131 }
132 
SPM_EnableVddxStepLock(SPM_Type * base,bool enable)133 void SPM_EnableVddxStepLock(SPM_Type *base, bool enable)
134 {
135     if (enable)
136     {
137         base->DCDCC3 |= (SPM_DCDCC3_DCDC_VDD1P8CTRL_DISABLE_STEP_MASK | SPM_DCDCC3_DCDC_VDD1P2CTRL_DISABLE_STEP_MASK);
138     }
139     else
140     {
141         base->DCDCC3 &= ~(SPM_DCDCC3_DCDC_VDD1P8CTRL_DISABLE_STEP_MASK | SPM_DCDCC3_DCDC_VDD1P2CTRL_DISABLE_STEP_MASK);
142     }
143 }
144 
SPM_BypassDcdcBattMonitor(SPM_Type * base,bool enable,uint32_t value)145 void SPM_BypassDcdcBattMonitor(SPM_Type *base, bool enable, uint32_t value)
146 {
147     if (enable)
148     {
149         /* Set the user-defined value before enable the bypass. */
150         base->DCDCC3 = (base->DCDCC3 & ~SPM_DCDCC3_DCDC_VBAT_VALUE_MASK) | SPM_DCDCC3_DCDC_VBAT_VALUE(value);
151         /* Enable the bypass and load the user-defined value. */
152         base->DCDCC3 |= SPM_DCDCC3_DCDC_BYPASS_ADC_MEAS_MASK;
153     }
154     else
155     {
156         base->DCDCC3 &= ~SPM_DCDCC3_DCDC_BYPASS_ADC_MEAS_MASK;
157     }
158 }
159 
SPM_SetDcdcIntegratorConfig(SPM_Type * base,const spm_dcdc_integrator_config_t * config)160 void SPM_SetDcdcIntegratorConfig(SPM_Type *base, const spm_dcdc_integrator_config_t *config)
161 {
162     int32_t tmp32u;
163     double dutyCycle;
164 
165     if (NULL == config)
166     {
167         base->DCDCC4 = 0U;
168     }
169     else
170     {
171         dutyCycle = ((config->vdd1p2Value / config->vBatValue)*32 - 16)*8192;
172         tmp32u = (int32_t)(dutyCycle);
173         base->DCDCC4 = SPM_DCDCC4_PULSE_RUN_SPEEDUP_MASK | SPM_DCDCC4_INTEGRATOR_VALUE_SELECT_MASK |
174                        SPM_DCDCC4_INTEGRATOR_VALUE(tmp32u);
175     }
176 }
177 
178 
179 
SPM_SetLowPowerReqOutPinConfig(SPM_Type * base,const spm_low_power_req_out_pin_config_t * config)180 void SPM_SetLowPowerReqOutPinConfig(SPM_Type *base, const spm_low_power_req_out_pin_config_t *config)
181 {
182     if ((NULL == config) || (config->pinOutEnable))
183     {
184         base->LPREQPINCNTRL = 0U;
185     }
186     else
187     {
188         base->LPREQPINCNTRL =
189             SPM_LPREQPINCNTRL_POLARITY(config->pinOutPol) | SPM_LPREQPINCNTRL_LPREQOE_MASK; /* Enable the output. */
190     }
191 }
192