1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00
RIOT/cpu/cc26x0_cc13x0/vendor/driverlib/sys_ctrl.c
Jean Pierre Dudey 7db791476e cpu/cc26x0: rename to cc26x0_cc13x0
Signed-off-by: Jean Pierre Dudey <me@jeandudey.tech>
2021-02-08 17:25:42 +01:00

424 lines
17 KiB
C

/******************************************************************************
* Filename: sys_ctrl.c
* Revised: 2018-06-26 15:19:11 +0200 (Tue, 26 Jun 2018)
* Revision: 52220
*
* Description: Driver for the System Control.
*
* Copyright (c) 2015 - 2017, Texas Instruments Incorporated
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3) Neither the name of the ORGANIZATION nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************/
// Hardware headers
#include "../inc/hw_types.h"
#include "../inc/hw_ccfg.h"
#include "../inc/hw_adi.h"
// Driverlib headers
#include "aon_batmon.h"
#include "setup_rom.h"
#include "sys_ctrl.h"
//*****************************************************************************
//
// Handle support for DriverLib in ROM:
// This section will undo prototype renaming made in the header file
//
//*****************************************************************************
#if !defined(DOXYGEN)
#undef SysCtrlSetRechargeBeforePowerDown
#define SysCtrlSetRechargeBeforePowerDown NOROM_SysCtrlSetRechargeBeforePowerDown
#undef SysCtrlAdjustRechargeAfterPowerDown
#define SysCtrlAdjustRechargeAfterPowerDown NOROM_SysCtrlAdjustRechargeAfterPowerDown
#undef SysCtrl_DCDC_VoltageConditionalControl
#define SysCtrl_DCDC_VoltageConditionalControl NOROM_SysCtrl_DCDC_VoltageConditionalControl
#undef SysCtrlResetSourceGet
#define SysCtrlResetSourceGet NOROM_SysCtrlResetSourceGet
#endif
//*****************************************************************************
//
// Recharge calculator defines and globals
//
//*****************************************************************************
#define PD_STATE_CACHE_RET 1
#define PD_STATE_RFMEM_RET 2
#define PD_STATE_XOSC_LPM 4
#define PD_STATE_EXT_REG_MODE 8
typedef struct {
uint32_t pdTime ;
uint16_t pdRechargePeriod ;
uint8_t pdState ;
int8_t pdTemp ;
} PowerQualGlobals_t;
static PowerQualGlobals_t powerQualGlobals;
//*****************************************************************************
//
// SysCtrlSetRechargeBeforePowerDown( xoscPowerMode )
//
//*****************************************************************************
void
SysCtrlSetRechargeBeforePowerDown( uint32_t xoscPowerMode )
{
int32_t curTemp ;
int32_t shiftedTemp ;
int32_t deltaVddrSleepTrim ;
int32_t vddrTrimSleep ;
int32_t vddrTrimActve ;
int32_t diffVddrActiveSleep ;
uint32_t ccfg_ModeConfReg ;
uint32_t curState ;
uint32_t prcmRamRetention ;
uint32_t di ;
uint32_t dii ;
uint32_t ti ;
uint32_t cd ;
uint32_t cl ;
uint32_t load ;
uint32_t k ;
uint32_t vddrCap ;
uint32_t newRechargePeriod ;
uint32_t perE ;
uint32_t perM ;
const uint32_t * pLookupTable ;
// If external regulator mode we shall:
// - Disable adaptive recharge (bit[31]=0) in AON_WUC_O_RECHARGECFG
// - Set recharge period to approximately 500 mS (perM=31, perE=5 => 0xFD)
// - Make sure you get a recalculation if leaving external regulator mode by setting powerQualGlobals.pdState accordingly
if ( HWREG( AON_SYSCTL_BASE + AON_SYSCTL_O_PWRCTL ) & AON_SYSCTL_PWRCTL_EXT_REG_MODE ) {
powerQualGlobals.pdState = PD_STATE_EXT_REG_MODE;
HWREG( AON_WUC_BASE + AON_WUC_O_RECHARGECFG ) = 0x00A4FDFD;
return;
}
//--- Spec. point 1 ---
curTemp = AONBatMonTemperatureGetDegC();
curState = 0;
// read the MODE_CONF register in CCFG
ccfg_ModeConfReg = HWREG( CCFG_BASE + CCFG_O_MODE_CONF );
// Get VDDR_TRIM_SLEEP_DELTA + 1 (sign extended)
deltaVddrSleepTrim = ((((int32_t) ccfg_ModeConfReg )
<< ( 32 - CCFG_MODE_CONF_VDDR_TRIM_SLEEP_DELTA_W - CCFG_MODE_CONF_VDDR_TRIM_SLEEP_DELTA_S ))
>> ( 32 - CCFG_MODE_CONF_VDDR_TRIM_SLEEP_DELTA_W )) + 1;
// Do temperature compensation if enabled
if (( ccfg_ModeConfReg & CCFG_MODE_CONF_VDDR_TRIM_SLEEP_TC ) == 0 ) {
int32_t tcDelta = ( 62 - curTemp ) >> 3;
if ( tcDelta > 8 ) tcDelta = 8;
if ( tcDelta > deltaVddrSleepTrim ) deltaVddrSleepTrim = tcDelta;
}
{
vddrTrimSleep = SetupSignExtendVddrTrimValue((
HWREG( FCFG1_BASE + FCFG1_O_LDO_TRIM ) &
FCFG1_LDO_TRIM_VDDR_TRIM_SLEEP_M ) >>
FCFG1_LDO_TRIM_VDDR_TRIM_SLEEP_S ) ;
vddrTrimActve = SetupSignExtendVddrTrimValue((
HWREG( FCFG1_BASE + FCFG1_O_SHDW_ANA_TRIM ) &
FCFG1_SHDW_ANA_TRIM_VDDR_TRIM_M ) >>
FCFG1_SHDW_ANA_TRIM_VDDR_TRIM_S ) ;
}
vddrTrimSleep += deltaVddrSleepTrim;
if ( vddrTrimSleep > 21 ) vddrTrimSleep = 21;
if ( vddrTrimSleep < -10 ) vddrTrimSleep = -10;
// Write adjusted value using MASKED write (MASK8)
HWREGH( ADI3_BASE + ADI_O_MASK8B + ( ADI_3_REFSYS_O_DCDCCTL1 * 2 )) = (( ADI_3_REFSYS_DCDCCTL1_VDDR_TRIM_SLEEP_M << 8 ) |
(( vddrTrimSleep << ADI_3_REFSYS_DCDCCTL1_VDDR_TRIM_SLEEP_S ) & ADI_3_REFSYS_DCDCCTL1_VDDR_TRIM_SLEEP_M ));
prcmRamRetention = HWREG( PRCM_BASE + PRCM_O_RAMRETEN );
if ( prcmRamRetention & PRCM_RAMRETEN_VIMS_M ) {
curState |= PD_STATE_CACHE_RET;
}
if ( prcmRamRetention & PRCM_RAMRETEN_RFC ) {
curState |= PD_STATE_RFMEM_RET;
}
if ( xoscPowerMode != XOSC_IN_HIGH_POWER_MODE ) {
curState |= PD_STATE_XOSC_LPM;
}
//--- Spec. point 2 ---
if ((( curTemp - powerQualGlobals.pdTemp ) >= 5 ) || ( curState != powerQualGlobals.pdState )) {
//--- Spec. point 3 ---
shiftedTemp = curTemp - 15;
//--- Spec point 4 ---
//4. Check for external VDDR load option (may not be supported): ext_load = (VDDR_EXT_LOAD=0 in CCFG)
// Currently not implementing external load handling
// if ( __ccfg.ulModeConfig & MODE_CONF_VDDR_EXT_LOAD ) {
// }
pLookupTable = (uint32_t *)( FCFG1_BASE + FCFG1_O_PWD_CURR_20C );
//--- Spec point 5 ---
di = 0;
ti = 0;
if ( shiftedTemp >= 0 ) {
//--- Spec point 5.a ---
shiftedTemp += ( shiftedTemp << 4 );
//--- Spec point 5.b ---
ti = ( shiftedTemp >> 8 );
if ( ti > 7 ) {
ti = 7;
}
dii = ti;
if ( dii > 6 ) {
dii = 6;
}
//--- Spec point 5.c ---
cd = pLookupTable[ dii + 1 ] - pLookupTable[ dii ];
//--- Spec point 5.d ---
di = cd & 0xFF;
//--- Spec point 5.e ---
if ( curState & PD_STATE_XOSC_LPM ) {
di += (( cd >> 8 ) & 0xFF );
}
if ( curState & PD_STATE_RFMEM_RET ) {
di += (( cd >> 16 ) & 0xFF );
}
if ( curState & PD_STATE_CACHE_RET ) {
di += (( cd >> 24 ) & 0xFF );
}
//--- Spec point 5.f ---
// Currently not implementing external load handling
}
//--- Spec. point 6 ---
cl = pLookupTable[ ti ];
//--- Spec. point 7 ---
load = cl & 0xFF;
//--- Spec. point 8 ---
if ( curState & PD_STATE_XOSC_LPM ) {
load += (( cl >> 8 ) & 0xFF );
}
if ( curState & PD_STATE_RFMEM_RET ) {
load += (( cl >> 16 ) & 0xFF );
}
if ( curState & PD_STATE_CACHE_RET ) {
load += (( cl >> 24 ) & 0xFF );
}
//--- Spec. point 9 ---
load += ((( di * ( shiftedTemp - ( ti << 8 ))) + 128 ) >> 8 );
// Currently not implementing external load handling
// if ( __ccfg.ulModeConfig & MODE_CONF_VDDR_EXT_LOAD ) {
//--- Spec. point 10 ---
// } else {
//--- Spec. point 11 ---
diffVddrActiveSleep = ( vddrTrimActve - vddrTrimSleep );
if ( diffVddrActiveSleep < 1 ) diffVddrActiveSleep = 1;
k = ( diffVddrActiveSleep * 52 );
// }
//--- Spec. point 12 ---
vddrCap = ( ccfg_ModeConfReg & CCFG_MODE_CONF_VDDR_CAP_M ) >> CCFG_MODE_CONF_VDDR_CAP_S;
newRechargePeriod = ( vddrCap * k ) / load;
if ( newRechargePeriod > 0xFFFF ) {
newRechargePeriod = 0xFFFF;
}
powerQualGlobals.pdRechargePeriod = newRechargePeriod;
//--- Spec. point 13 ---
if ( curTemp > 127 ) curTemp = 127;
if ( curTemp < -128 ) curTemp = -128;
powerQualGlobals.pdTemp = curTemp;
powerQualGlobals.pdState = curState;
}
powerQualGlobals.pdTime = HWREG( AON_RTC_BASE + AON_RTC_O_SEC );
// Calculate PER_E and PER_M (based on powerQualGlobals.pdRechargePeriod)
// Round downwards but make sure PER_E=0 and PER_M=1 is the minimum possible setting.
// (assuming that powerQualGlobals.pdRechargePeriod always are <= 0xFFFF)
perE = 0;
perM = powerQualGlobals.pdRechargePeriod;
if ( perM < 31 ) {
perM = 31;
powerQualGlobals.pdRechargePeriod = 31;
}
while ( perM > 511 ) {
perM >>= 1;
perE += 1;
}
perM = ( perM - 15 ) >> 4;
HWREG( AON_WUC_BASE + AON_WUC_O_RECHARGECFG ) =
( 0x80A4E700 ) |
( perM << AON_WUC_RECHARGECFG_PER_M_S ) |
( perE << AON_WUC_RECHARGECFG_PER_E_S ) ;
HWREG( AON_WUC_BASE + AON_WUC_O_RECHARGESTAT ) = 0;
}
//*****************************************************************************
//
// SysCtrlAdjustRechargeAfterPowerDown()
//
//*****************************************************************************
void
SysCtrlAdjustRechargeAfterPowerDown( uint32_t vddrRechargeMargin )
{
int32_t curTemp ;
uint32_t longestRechargePeriod ;
uint32_t deltaTime ;
uint32_t newRechargePeriod ;
//--- Spec. point 2 ---
longestRechargePeriod = ( HWREG( AON_WUC_BASE + AON_WUC_O_RECHARGESTAT ) &
AON_WUC_RECHARGESTAT_MAX_USED_PER_M ) >>
AON_WUC_RECHARGESTAT_MAX_USED_PER_S ;
if ( longestRechargePeriod != 0 ) {
//--- Spec. changed (originally point 1) ---
curTemp = AONBatMonTemperatureGetDegC();
if ( curTemp < powerQualGlobals.pdTemp ) {
if ( curTemp < -128 ) {
curTemp = -128;
}
powerQualGlobals.pdTemp = curTemp;
}
// Add some margin between the longest previous recharge period and the
// next initial recharge period. Since it is a fixed margin, it will have a
// higher impact as a fraction of the converged recharge period at higher temperatures
// where it is needed more due to higher leakage.
if (longestRechargePeriod > vddrRechargeMargin) {
longestRechargePeriod -= vddrRechargeMargin;
}
else {
longestRechargePeriod = 1;
}
//--- Spec. point 4 ---
if ( longestRechargePeriod < powerQualGlobals.pdRechargePeriod ) {
powerQualGlobals.pdRechargePeriod = longestRechargePeriod;
} else {
//--- Spec. point 5 ---
deltaTime = HWREG( AON_RTC_BASE + AON_RTC_O_SEC ) - powerQualGlobals.pdTime + 2;
if ( deltaTime > 31 ) {
deltaTime = 31;
}
newRechargePeriod = powerQualGlobals.pdRechargePeriod + (( longestRechargePeriod - powerQualGlobals.pdRechargePeriod ) >> (deltaTime>>1));
if ( newRechargePeriod > 0xFFFF ) {
newRechargePeriod = 0xFFFF;
}
powerQualGlobals.pdRechargePeriod = newRechargePeriod;
}
}
}
//*****************************************************************************
//
// SysCtrl_DCDC_VoltageConditionalControl()
//
//*****************************************************************************
void
SysCtrl_DCDC_VoltageConditionalControl( void )
{
uint32_t batThreshold ; // Fractional format with 8 fractional bits.
uint32_t aonBatmonBat ; // Fractional format with 8 fractional bits.
uint32_t ccfg_ModeConfReg ; // Holds a copy of the CCFG_O_MODE_CONF register.
uint32_t aonSysctlPwrctl ; // Reflect whats read/written to the AON_SYSCTL_O_PWRCTL register.
// We could potentially call this function before any battery voltage measurement
// is made/available. In that case we must make sure that we do not turn off the DCDC.
// This can be done by doing nothing as long as the battery voltage is 0 (Since the
// reset value of the battery voltage register is 0).
aonBatmonBat = HWREG( AON_BATMON_BASE + AON_BATMON_O_BAT );
if ( aonBatmonBat != 0 ) {
// Check if Voltage Conditional Control is enabled
// It is enabled if all the following are true:
// - DCDC in use (either in active or recharge mode), (in use if one of the corresponding CCFG bits are zero).
// - Alternative DCDC settings are enabled ( DIS_ALT_DCDC_SETTING == 0 )
// - Not in external regulator mode ( EXT_REG_MODE == 0 )
ccfg_ModeConfReg = HWREG( CCFG_BASE + CCFG_O_MODE_CONF );
if (((( ccfg_ModeConfReg & CCFG_MODE_CONF_DCDC_RECHARGE_M ) == 0 ) ||
(( ccfg_ModeConfReg & CCFG_MODE_CONF_DCDC_ACTIVE_M ) == 0 ) ) &&
(( HWREG( AON_SYSCTL_BASE + AON_SYSCTL_O_PWRCTL ) & AON_SYSCTL_PWRCTL_EXT_REG_MODE ) == 0 ) &&
(( HWREG( CCFG_BASE + CCFG_O_SIZE_AND_DIS_FLAGS ) & CCFG_SIZE_AND_DIS_FLAGS_DIS_ALT_DCDC_SETTING ) == 0 ) )
{
aonSysctlPwrctl = HWREG( AON_SYSCTL_BASE + AON_SYSCTL_O_PWRCTL );
batThreshold = (((( HWREG( CCFG_BASE + CCFG_O_MODE_CONF_1 ) &
CCFG_MODE_CONF_1_ALT_DCDC_VMIN_M ) >>
CCFG_MODE_CONF_1_ALT_DCDC_VMIN_S ) + 28 ) << 4 );
if ( aonSysctlPwrctl & ( AON_SYSCTL_PWRCTL_DCDC_EN_M | AON_SYSCTL_PWRCTL_DCDC_ACTIVE_M )) {
// DCDC is ON, check if it should be switched off
if ( aonBatmonBat < batThreshold ) {
aonSysctlPwrctl &= ~( AON_SYSCTL_PWRCTL_DCDC_EN_M | AON_SYSCTL_PWRCTL_DCDC_ACTIVE_M );
HWREG( AON_SYSCTL_BASE + AON_SYSCTL_O_PWRCTL ) = aonSysctlPwrctl;
}
} else {
// DCDC is OFF, check if it should be switched on
if ( aonBatmonBat > batThreshold ) {
if (( ccfg_ModeConfReg & CCFG_MODE_CONF_DCDC_RECHARGE_M ) == 0 ) aonSysctlPwrctl |= AON_SYSCTL_PWRCTL_DCDC_EN_M ;
if (( ccfg_ModeConfReg & CCFG_MODE_CONF_DCDC_ACTIVE_M ) == 0 ) aonSysctlPwrctl |= AON_SYSCTL_PWRCTL_DCDC_ACTIVE_M ;
HWREG( AON_SYSCTL_BASE + AON_SYSCTL_O_PWRCTL ) = aonSysctlPwrctl;
}
}
}
}
}
//*****************************************************************************
//
// SysCtrlResetSourceGet()
//
//*****************************************************************************
uint32_t
SysCtrlResetSourceGet( void )
{
uint32_t aonSysctlResetCtl = HWREG( AON_SYSCTL_BASE + AON_SYSCTL_O_RESETCTL );
if ( aonSysctlResetCtl & AON_SYSCTL_RESETCTL_WU_FROM_SD_M ) {
return ( RSTSRC_WAKEUP_FROM_SHUTDOWN );
} else {
return (( aonSysctlResetCtl & AON_SYSCTL_RESETCTL_RESET_SRC_M ) >> AON_SYSCTL_RESETCTL_RESET_SRC_S ) ;
}
}