1 /******************************************************************************
2 *  Filename:       sys_ctrl.c
3 *  Revised:        2015-09-25 11:16:31 +0200 (Fri, 25 Sep 2015)
4 *  Revision:       44664
5 *
6 *  Description:    Driver for the System Control.
7 *
8 *  Copyright (c) 2015, Texas Instruments Incorporated
9 *  All rights reserved.
10 *
11 *  Redistribution and use in source and binary forms, with or without
12 *  modification, are permitted provided that the following conditions are met:
13 *
14 *  1) Redistributions of source code must retain the above copyright notice,
15 *     this list of conditions and the following disclaimer.
16 *
17 *  2) Redistributions in binary form must reproduce the above copyright notice,
18 *     this list of conditions and the following disclaimer in the documentation
19 *     and/or other materials provided with the distribution.
20 *
21 *  3) Neither the name of the ORGANIZATION nor the names of its contributors may
22 *     be used to endorse or promote products derived from this software without
23 *     specific prior written permission.
24 *
25 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26 *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
29 *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 *  POSSIBILITY OF SUCH DAMAGE.
36 *
37 ******************************************************************************/
38 
39 // Hardware headers
40 #include <inc/hw_types.h>
41 #include <inc/hw_ccfg.h>
42 // Driverlib headers
43 #include <driverlib/aon_batmon.h>
44 #include <driverlib/sys_ctrl.h>
45 
46 // Prototype from setup.c
47 int32_t SignExtendVddrTrimValue( uint32_t ui32VddrTrimVal );
48 
49 //*****************************************************************************
50 //
51 // Handle support for DriverLib in ROM:
52 // This section will undo prototype renaming made in the header file
53 //
54 //*****************************************************************************
55 #if !defined(DOXYGEN)
56     #undef  SysCtrlPowerEverything
57     #define SysCtrlPowerEverything          NOROM_SysCtrlPowerEverything
58     #undef  SysCtrlStandby
59     #define SysCtrlStandby                  NOROM_SysCtrlStandby
60     #undef  SysCtrlPowerdown
61     #define SysCtrlPowerdown                NOROM_SysCtrlPowerdown
62     #undef  SysCtrlShutdown
63     #define SysCtrlShutdown                 NOROM_SysCtrlShutdown
64     #undef  SysCtrlResetSourceGet
65     #define SysCtrlResetSourceGet           NOROM_SysCtrlResetSourceGet
66 #endif
67 
68 //*****************************************************************************
69 //
70 // Recharge calculator defines and globals
71 //
72 //*****************************************************************************
73 
74 #define  PD_STATE_CACHE_RET      1
75 #define  PD_STATE_RFMEM_RET      2
76 #define  PD_STATE_XOSC_LPM       4
77 #define  PD_STATE_EXT_REG_MODE   8
78 
79 typedef struct {
80    uint32_t    pdTime               ;
81    uint16_t    pdRechargePeriod     ;
82    uint8_t     pdState              ;
83    int8_t      pdTemp               ;
84 } PowerQualGlobals_t;
85 
86 static PowerQualGlobals_t powerQualGlobals;
87 
88 
89 //*****************************************************************************
90 //
91 // Arrays that maps the "peripheral set" number (which is stored in the
92 // third nibble of the PRCM_PERIPH_* defines) to the PRCM register that
93 // contains the relevant bit for that peripheral.
94 //
95 //*****************************************************************************
96 
97 // Run mode registers
98 static const uint32_t g_pui32ModuleCG[] =
99 {
100     PRCM_PERIPH_TIMER0,
101     PRCM_PERIPH_TIMER1,
102     PRCM_PERIPH_TIMER2,
103     PRCM_PERIPH_TIMER3,
104     PRCM_PERIPH_SSI0,
105     PRCM_PERIPH_SSI1,
106     PRCM_PERIPH_UART0,
107     PRCM_PERIPH_I2C0,
108     PRCM_PERIPH_UDMA,
109     PRCM_PERIPH_TRNG,
110     PRCM_PERIPH_CRYPTO,
111     PRCM_PERIPH_GPIO,
112     PRCM_PERIPH_I2S
113 };
114 
115 //*****************************************************************************
116 //
117 // Power up everything
118 //
119 //*****************************************************************************
120 void
SysCtrlPowerEverything(void)121 SysCtrlPowerEverything(void)
122 {
123     uint32_t ui32Idx;
124     uint32_t ui32AuxClocks;
125 
126     //
127     // Force power on AUX
128     //
129     AONWUCAuxWakeupEvent(AONWUC_AUX_WAKEUP);
130     while(!(AONWUCPowerStatusGet() & AONWUC_AUX_POWER_ON))
131     { }
132 
133     //
134     // Enable all the AUX domain clocks and wait for them to be ready
135     //
136     ui32AuxClocks = AUX_WUC_ADI_CLOCK | AUX_WUC_OSCCTRL_CLOCK |
137                     AUX_WUC_TDCIF_CLOCK | AUX_WUC_ANAIF_CLOCK |
138                     AUX_WUC_TIMER_CLOCK | AUX_WUC_AIODIO0_CLOCK |
139                     AUX_WUC_AIODIO1_CLOCK | AUX_WUC_SMPH_CLOCK |
140                     AUX_WUC_TDC_CLOCK | AUX_WUC_ADC_CLOCK |
141                     AUX_WUC_REF_CLOCK;
142     AUXWUCClockEnable(ui32AuxClocks);
143     while(AUXWUCClockStatus(ui32AuxClocks) != AUX_WUC_CLOCK_READY)
144     { }
145 
146     //
147     // Request to switch to the crystal to enable radio operation.
148     // It takes a while for the XTAL to be ready so it is possible to
149     // perform other tasks while waiting.
150     OSCClockSourceSet(OSC_SRC_CLK_MF | OSC_SRC_CLK_HF, OSC_XOSC_HF);
151     OSCClockSourceSet(OSC_SRC_CLK_LF, OSC_XOSC_LF);
152 
153     //
154     // Switch the HF source to XTAL - must be performed safely out of ROM to
155     // avoid flash issues when switching the clock.
156     //
157     // NB. If already running XTAL on HF clock source the ROM will wait forever
158     // on a flag that will never be set - need to check.
159     //
160     if(OSCClockSourceGet(OSC_SRC_CLK_HF) != OSC_XOSC_HF) {
161         OSCHfSourceSwitch();
162     }
163 
164     //
165     // Turn on all the MCU power domains
166     // If the CPU is running and executing code the SYSBUS, VIMS and CPU are
167     // automatically on as well.
168     //
169     PRCMPowerDomainOn(PRCM_DOMAIN_RFCORE | PRCM_DOMAIN_SERIAL |
170                       PRCM_DOMAIN_PERIPH);
171     //
172     // Wait for power to be on
173     //
174     while(PRCMPowerDomainStatus(PRCM_DOMAIN_RFCORE | PRCM_DOMAIN_SERIAL |
175                                 PRCM_DOMAIN_PERIPH) != PRCM_DOMAIN_POWER_ON);
176 
177     PRCMLoadSet();
178     while(!PRCMLoadGet());
179 
180     //
181     // Ensure the domain clocks are running and wait for the clock settings to
182     // take effect
183     //
184     PRCMDomainEnable(PRCM_DOMAIN_RFCORE | PRCM_DOMAIN_VIMS);
185     PRCMLoadSet();
186     while(!PRCMLoadGet())
187     { }
188 
189     //
190     // Enable all the RF Core clocks
191     //
192     // Do not read back to check, for two reasons:
193     // 1. CPE will update the PWMCLKENABLE register right after boot
194     // 2. The PWMCLKENABLE register always reads back what is written
195     HWREG(RFC_PWR_NONBUF_BASE + RFC_PWR_O_PWMCLKEN) = 0x7FF;
196 
197     //
198     // Enable all peripheral clocks in System CPU run/sleep/deep-sleep mode.
199     //
200     for(ui32Idx = 0; ui32Idx < sizeof(g_pui32ModuleCG) / sizeof(uint32_t);
201         ui32Idx++)
202     {
203         PRCMPeripheralRunEnable(g_pui32ModuleCG[ui32Idx]);
204         PRCMPeripheralSleepEnable(g_pui32ModuleCG[ui32Idx]);
205         PRCMPeripheralDeepSleepEnable(g_pui32ModuleCG[ui32Idx]);
206     }
207     PRCMLoadSet();
208     while(!PRCMLoadGet())
209     { }
210 }
211 
212 //*****************************************************************************
213 //
214 //! Force the system in to standby mode
215 //
216 //*****************************************************************************
SysCtrlStandby(void)217 void SysCtrlStandby(void)
218 {
219     //
220     // Enable the oscillator configuration interface
221     //
222     OSCInterfaceEnable();
223 
224     //
225     // Ensure the low frequency clock source is sourced from a low frequency
226     // oscillator. The XTAL will provide the most accurate real time clock.
227     //
228     OSCClockSourceSet(OSC_SRC_CLK_LF,OSC_XOSC_LF);
229 
230     //
231     // Enable the oscillator configuration interface
232     //
233     OSCInterfaceDisable();
234 
235     //
236     // Execute the transition to standby
237     //
238     PowerCtrlStateSet(PWRCTRL_STANDBY);
239 }
240 
241 //*****************************************************************************
242 //
243 //! Force the system in to power down.
244 //
245 //*****************************************************************************
246 void
SysCtrlPowerdown(void)247 SysCtrlPowerdown(void)
248 {
249     //
250     // Make sure the oscillator interface is enabled
251     //
252     OSCInterfaceEnable();
253 
254     //
255     // Source the LF clock from the low frequency XTAL_OSC.
256     // HF and MF are sourced from the high frequency RC_OSC.
257     //
258     OSCClockSourceSet(OSC_SRC_CLK_LF, OSC_XOSC_LF);
259     OSCClockSourceSet(OSC_SRC_CLK_MF | OSC_SRC_CLK_HF, OSC_RCOSC_HF);
260 
261     //
262     // Check if already sourcing the HF clock from RC_OSC.
263     // If a switch of the clock source is not required, then the call to ROM
264     // will loop forever.
265     //
266     if(OSCClockSourceGet(OSC_SRC_CLK_HF) != OSC_RCOSC_HF)
267     {
268         OSCHfSourceSwitch();
269     }
270 
271     //
272     // Disable the oscillator interface
273     //
274     OSCInterfaceDisable();
275 
276     //
277     // Execute the transition to power down.
278     //
279     PowerCtrlStateSet(PWRCTRL_POWER_DOWN);
280 }
281 
282 //*****************************************************************************
283 //
284 //! Force the system in to shutdown.
285 //
286 //*****************************************************************************
287 void
SysCtrlShutdown(void)288 SysCtrlShutdown(void)
289 {
290     //
291     // Make sure the oscillator interface is enabled
292     //
293     OSCInterfaceEnable();
294 
295     //
296     // Source the LF clock from the low frequency RC_OSC.
297     // HF and MF are sourced from the high frequency RC_OSC.
298     //
299     OSCClockSourceSet(OSC_SRC_CLK_LF, OSC_RCOSC_LF);
300     OSCClockSourceSet(OSC_SRC_CLK_MF | OSC_SRC_CLK_HF, OSC_RCOSC_HF);
301 
302     //
303     // Check if already sourcing the HF clock from RC_OSC.
304     // If a switch of the clock source is not required, then the call to ROM
305     // will loop forever.
306     //
307     if(OSCClockSourceGet(OSC_SRC_CLK_HF) != OSC_RCOSC_HF)
308     {
309         OSCHfSourceSwitch();
310     }
311 
312     //
313     // Disable the oscillator interface
314     //
315     OSCInterfaceDisable();
316 
317     //
318     // Execute transition to shutdown.
319     //
320     PowerCtrlStateSet(PWRCTRL_SHUTDOWN);
321 }
322 
323 
324 //*****************************************************************************
325 // Need to know the CCFG:MODE_CONF.VDDR_TRIM_SLEEP_DELTA fild width in order
326 // to sign extend correctly but this is however not defined in the hardware
327 // description fields and are therefore defined separately here.
328 //*****************************************************************************
329 #define CCFG_MODE_CONF_VDDR_TRIM_SLEEP_DELTA_WIDTH    4
330 
331 //*****************************************************************************
332 //
333 // SysCtrlSetRechargeBeforePowerDown( xoscPowerMode )
334 //
335 //*****************************************************************************
336 void
SysCtrlSetRechargeBeforePowerDown(uint32_t xoscPowerMode)337 SysCtrlSetRechargeBeforePowerDown( uint32_t xoscPowerMode )
338 {
339    int32_t           curTemp                 ;
340    int32_t           shiftedTemp             ;
341    int32_t           deltaVddrSleepTrim      ;
342    int32_t           vddrTrimSleep           ;
343    int32_t           vddrTrimActve           ;
344    int32_t           diffVddrActiveSleep     ;
345    uint32_t          ccfg_ModeConfReg        ;
346    uint32_t          curState                ;
347    uint32_t          prcmRamRetention        ;
348    uint32_t          di                      ;
349    uint32_t          dii                     ;
350    uint32_t          ti                      ;
351    uint32_t          cd                      ;
352    uint32_t          cl                      ;
353    uint32_t          load                    ;
354    uint32_t          k                       ;
355    uint32_t          vddrCap                 ;
356    uint32_t          newRechargePeriod       ;
357    uint32_t          perE                    ;
358    uint32_t          perM                    ;
359    const uint32_t  * pLookupTable            ;
360 
361    //
362    // If external regulator mode we shall:
363    // - Disable adaptive recharge (bit[31]=0) in AON_WUC_O_RECHARGECFG
364    // - Set recharge period to approximately 500 mS (perM=31, perE=5 => 0xFD)
365    // - Make sure you get a recalculation if leaving external regulator mode by setting powerQualGlobals.pdState accordingly
366    //
367    if ( HWREG( AON_SYSCTL_BASE + AON_SYSCTL_O_PWRCTL ) & AON_SYSCTL_PWRCTL_EXT_REG_MODE ) {
368       powerQualGlobals.pdState = PD_STATE_EXT_REG_MODE;
369       HWREG( AON_WUC_BASE + AON_WUC_O_RECHARGECFG  ) = 0x00A4FDFD;
370       return;
371    }
372 
373    //--- Spec. point 1 ---
374    curTemp  = AONBatMonTemperatureGetDegC();
375    curState = 0;
376 
377    // read the MODE_CONF register in CCFG
378    ccfg_ModeConfReg = HWREG( CCFG_BASE + CCFG_O_MODE_CONF );
379    // Get VDDR_TRIM_SLEEP_DELTA + 1 (sign extended)
380    deltaVddrSleepTrim = ((((int32_t) ccfg_ModeConfReg )
381       << ( 32 - CCFG_MODE_CONF_VDDR_TRIM_SLEEP_DELTA_WIDTH - CCFG_MODE_CONF_VDDR_TRIM_SLEEP_DELTA_S ))
382       >> ( 32 - CCFG_MODE_CONF_VDDR_TRIM_SLEEP_DELTA_WIDTH )) + 1;
383    // Do temperature compensation if enabled
384    if (( ccfg_ModeConfReg & CCFG_MODE_CONF_VDDR_TRIM_SLEEP_TC ) == 0 ) {
385       int32_t tcDelta = ( 62 - curTemp ) >> 3;
386       if ( tcDelta > 8 ) tcDelta = 8;
387       if ( tcDelta > deltaVddrSleepTrim ) deltaVddrSleepTrim = tcDelta;
388    }
389    if ((( ccfg_ModeConfReg & CCFG_MODE_CONF_VDDR_EXT_LOAD  ) == 0 ) &&
390        (( ccfg_ModeConfReg & CCFG_MODE_CONF_VDDS_BOD_LEVEL ) != 0 )    )
391    {
392       vddrTrimSleep = SignExtendVddrTrimValue((
393          HWREG( FCFG1_BASE + FCFG1_O_VOLT_TRIM ) &
394          FCFG1_VOLT_TRIM_VDDR_TRIM_SLEEP_H_M ) >>
395          FCFG1_VOLT_TRIM_VDDR_TRIM_SLEEP_H_S ) ;
396       vddrTrimActve = SignExtendVddrTrimValue((
397          HWREG( FCFG1_BASE + FCFG1_O_VOLT_TRIM ) &
398          FCFG1_VOLT_TRIM_VDDR_TRIM_HH_M ) >>
399          FCFG1_VOLT_TRIM_VDDR_TRIM_HH_S ) ;
400    } else
401    {
402       vddrTrimSleep = SignExtendVddrTrimValue((
403          HWREG( FCFG1_BASE + FCFG1_O_LDO_TRIM ) &
404          FCFG1_LDO_TRIM_VDDR_TRIM_SLEEP_M ) >>
405          FCFG1_LDO_TRIM_VDDR_TRIM_SLEEP_S ) ;
406       vddrTrimActve = SignExtendVddrTrimValue((
407          HWREG( FCFG1_BASE + FCFG1_O_SHDW_ANA_TRIM ) &
408          FCFG1_SHDW_ANA_TRIM_VDDR_TRIM_M ) >>
409          FCFG1_SHDW_ANA_TRIM_VDDR_TRIM_S ) ;
410    }
411    vddrTrimSleep += deltaVddrSleepTrim;
412    if ( vddrTrimSleep >  21 ) vddrTrimSleep =  21;
413    if ( vddrTrimSleep < -10 ) vddrTrimSleep = -10;
414    // Write adjusted value using MASKED write (MASK8)
415    HWREGH( ADI3_BASE + ADI_O_MASK8B + ( ADI_3_REFSYS_O_DCDCCTL1 * 2 )) = (( ADI_3_REFSYS_DCDCCTL1_VDDR_TRIM_SLEEP_M << 8 ) |
416       (( vddrTrimSleep << ADI_3_REFSYS_DCDCCTL1_VDDR_TRIM_SLEEP_S ) & ADI_3_REFSYS_DCDCCTL1_VDDR_TRIM_SLEEP_M ));
417 
418    prcmRamRetention = HWREG( PRCM_BASE + PRCM_O_RAMRETEN );
419    if ( prcmRamRetention & PRCM_RAMRETEN_VIMS_M ) {
420       curState |= PD_STATE_CACHE_RET;
421    }
422    if ( prcmRamRetention & PRCM_RAMRETEN_RFC ) {
423       curState |= PD_STATE_RFMEM_RET;
424    }
425    if ( xoscPowerMode != XOSC_IN_HIGH_POWER_MODE ) {
426       curState |= PD_STATE_XOSC_LPM;
427    }
428 
429    //--- Spec. point 2 ---
430    if ((( curTemp - powerQualGlobals.pdTemp ) >= 5 ) || ( curState != powerQualGlobals.pdState )) {
431       //--- Spec. point 3 ---
432       shiftedTemp = curTemp - 15;
433 
434       //--- Spec point 4 ---
435       //4. Check for external VDDR load option (may not be supported): ext_load = (VDDR_EXT_LOAD=0 in CCFG)
436       // Currently not implementing external load handling
437       // if ( __ccfg.ulModeConfig & MODE_CONF_VDDR_EXT_LOAD ) {
438       // }
439 
440       pLookupTable = (uint32_t *)( FCFG1_BASE + FCFG1_O_PWD_CURR_20C );
441 
442       //--- Spec point 5 ---
443       di    = 0;
444       ti    = 0;
445       if ( shiftedTemp >= 0 ) {
446          //--- Spec point 5.a ---
447          shiftedTemp += ( shiftedTemp << 4 );
448 
449          //--- Spec point 5.b ---
450          ti = ( shiftedTemp >> 8 );
451          if ( ti > 7 ) {
452             ti = 7;
453          }
454          dii = ti;
455          if ( dii > 6 ) {
456             dii = 6;
457          }
458 
459          //--- Spec point 5.c ---
460          cd = pLookupTable[ dii + 1 ] - pLookupTable[ dii ];
461 
462          //--- Spec point 5.d ---
463          di = cd & 0xFF;
464 
465          //--- Spec point 5.e ---
466          if ( curState & PD_STATE_XOSC_LPM ) {
467             di += (( cd >> 8 ) & 0xFF );
468          }
469          if ( curState & PD_STATE_RFMEM_RET ) {
470             di += (( cd >> 16 ) & 0xFF );
471          }
472          if ( curState & PD_STATE_CACHE_RET ) {
473             di += (( cd >> 24 ) & 0xFF );
474          }
475 
476          //--- Spec point 5.f ---
477          // Currently not implementing external load handling
478       }
479 
480       //--- Spec. point 6 ---
481       cl = pLookupTable[ ti ];
482 
483       //--- Spec. point 7 ---
484       load = cl & 0xFF;
485 
486       //--- Spec. point 8 ---
487       if ( curState & PD_STATE_XOSC_LPM ) {
488          load += (( cl >> 8 ) & 0xFF );
489       }
490       if ( curState & PD_STATE_RFMEM_RET ) {
491          load += (( cl >> 16 ) & 0xFF );
492       }
493       if ( curState & PD_STATE_CACHE_RET ) {
494          load += (( cl >> 24 ) & 0xFF );
495       }
496 
497       //--- Spec. point 9 ---
498       load += ((( di * ( shiftedTemp - ( ti << 8 ))) + 128 ) >> 8 );
499 
500       // Currently not implementing external load handling
501       // if ( __ccfg.ulModeConfig & MODE_CONF_VDDR_EXT_LOAD ) {
502          //--- Spec. point 10 ---
503       // } else {
504          //--- Spec. point 11 ---
505          diffVddrActiveSleep = ( vddrTrimActve - vddrTrimSleep );
506          if ( diffVddrActiveSleep < 1 ) diffVddrActiveSleep = 1;
507          k = ( diffVddrActiveSleep * 52 );
508       // }
509 
510       //--- Spec. point 12 ---
511 
512       vddrCap = ( ccfg_ModeConfReg & CCFG_MODE_CONF_VDDR_CAP_M ) >> CCFG_MODE_CONF_VDDR_CAP_S;
513       newRechargePeriod = ( vddrCap * k ) / load;
514       if ( newRechargePeriod > 0xFFFF ) {
515          newRechargePeriod = 0xFFFF;
516       }
517       powerQualGlobals.pdRechargePeriod = newRechargePeriod;
518 
519       //--- Spec. point 13 ---
520       if ( curTemp >  127 ) curTemp =  127;
521       if ( curTemp < -128 ) curTemp = -128;
522       powerQualGlobals.pdTemp    = curTemp;
523       powerQualGlobals.pdState   = curState;
524    }
525 
526    powerQualGlobals.pdTime    = HWREG( AON_RTC_BASE + AON_RTC_O_SEC );
527 
528    // Calculate PER_E and PER_M (based on powerQualGlobals.pdRechargePeriod)
529    // Round downwards but make sure PER_E=0 and PER_M=1 is the minimum possible setting.
530    // (assuming that powerQualGlobals.pdRechargePeriod always are <= 0xFFFF)
531    perE = 0;
532    perM = powerQualGlobals.pdRechargePeriod;
533    if ( perM < 31 ) {
534       perM = 31;
535       powerQualGlobals.pdRechargePeriod = 31;
536    }
537    while ( perM > 511 ) {
538       perM >>= 1;
539       perE  += 1;
540    }
541    perM = ( perM - 15 ) >> 4;
542 
543    HWREG( AON_WUC_BASE + AON_WUC_O_RECHARGECFG ) =
544       ( 0x80A4E700                          ) |
545       ( perM << AON_WUC_RECHARGECFG_PER_M_S ) |
546       ( perE << AON_WUC_RECHARGECFG_PER_E_S ) ;
547    HWREG( AON_WUC_BASE + AON_WUC_O_RECHARGESTAT ) = 0;
548 }
549 
550 
551 //*****************************************************************************
552 //
553 // SysCtrlAdjustRechargeAfterPowerDown()
554 //
555 //*****************************************************************************
556 void
SysCtrlAdjustRechargeAfterPowerDown(void)557 SysCtrlAdjustRechargeAfterPowerDown( void )
558 {
559    int32_t     curTemp                 ;
560    uint32_t    longestRechargePeriod   ;
561    uint32_t    deltaTime               ;
562    uint32_t    newRechargePeriod       ;
563 
564    //--- Spec. point 2 ---
565    longestRechargePeriod = ( HWREG( AON_WUC_BASE + AON_WUC_O_RECHARGESTAT ) &
566       AON_WUC_RECHARGESTAT_MAX_USED_PER_M ) >>
567       AON_WUC_RECHARGESTAT_MAX_USED_PER_S ;
568 
569    if ( longestRechargePeriod != 0 ) {
570       //--- Spec. changed (originaly point 1) ---
571       curTemp = AONBatMonTemperatureGetDegC();
572       if ( curTemp < powerQualGlobals.pdTemp ) {
573          if ( curTemp < -128 ) {
574             curTemp = -128;
575          }
576          powerQualGlobals.pdTemp = curTemp;
577       }
578 
579       //--- Spec. point 4 ---
580       if ( longestRechargePeriod < powerQualGlobals.pdRechargePeriod ) {
581          powerQualGlobals.pdRechargePeriod = longestRechargePeriod;
582       } else {
583          //--- Spec. point 5 ---
584          deltaTime = HWREG( AON_RTC_BASE + AON_RTC_O_SEC ) - powerQualGlobals.pdTime + 2;
585          if ( deltaTime > 31 ) {
586             deltaTime = 31;
587          }
588          newRechargePeriod = powerQualGlobals.pdRechargePeriod + (( longestRechargePeriod - powerQualGlobals.pdRechargePeriod ) >> (deltaTime>>1));
589          if ( newRechargePeriod > 0xFFFF ) {
590             newRechargePeriod = 0xFFFF;
591          }
592          powerQualGlobals.pdRechargePeriod = newRechargePeriod;
593       }
594    }
595 }
596 
597 
598 //*****************************************************************************
599 //
600 // SysCtrl_DCDC_VoltageConditionalControl()
601 //
602 //*****************************************************************************
603 void
SysCtrl_DCDC_VoltageConditionalControl(void)604 SysCtrl_DCDC_VoltageConditionalControl( void )
605 {
606    uint32_t batThreshold     ;  // Fractional format with 8 fractional bits.
607    uint32_t aonBatmonBat     ;  // Fractional format with 8 fractional bits.
608    uint32_t ccfg_ModeConfReg ;  // Holds a copy of the CCFG_O_MODE_CONF register.
609    uint32_t aonSysctlPwrctl  ;  // Reflect whats read/written to the AON_SYSCTL_O_PWRCTL register.
610 
611    //
612    // We could potentially call this function before any battery voltage measurement
613    // is made/available. In that case we must make sure that we do not turn off the DCDC.
614    // This can be done by doing nothing as long as the battery voltage is 0 (Since the
615    // reset value of the battery voltage register is 0).
616    //
617    aonBatmonBat = HWREG( AON_BATMON_BASE + AON_BATMON_O_BAT );
618    if ( aonBatmonBat != 0 ) {
619       //
620       // Check if Voltage Conditional Control is enabled
621       // It is enabled if both:
622       // - DCDC in use (either in active or recharge mode), (in use if one of the corresponding CCFG bits are zero).
623       // - Alternative DCDC settings are enabled ( DIS_ALT_DCDC_SETTING == 0 )
624       //
625       ccfg_ModeConfReg = HWREG( CCFG_BASE + CCFG_O_MODE_CONF );
626 
627       if (((( ccfg_ModeConfReg & CCFG_MODE_CONF_DCDC_RECHARGE_M ) == 0                                            ) ||
628            (( ccfg_ModeConfReg & CCFG_MODE_CONF_DCDC_ACTIVE_M   ) == 0                                            )    ) &&
629           (( HWREG( CCFG_BASE + CCFG_O_SIZE_AND_DIS_FLAGS ) & CCFG_SIZE_AND_DIS_FLAGS_DIS_ALT_DCDC_SETTING ) == 0      )    )
630       {
631          aonSysctlPwrctl = HWREG( AON_SYSCTL_BASE + AON_SYSCTL_O_PWRCTL );
632          batThreshold    = (((( HWREG( CCFG_BASE + CCFG_O_MODE_CONF_1 ) &
633             CCFG_MODE_CONF_1_ALT_DCDC_VMIN_M ) >>
634             CCFG_MODE_CONF_1_ALT_DCDC_VMIN_S ) + 28 ) << 4 );
635 
636          if ( aonSysctlPwrctl & ( AON_SYSCTL_PWRCTL_DCDC_EN_M | AON_SYSCTL_PWRCTL_DCDC_ACTIVE_M )) {
637             //
638             // DCDC is ON, check if it should be switched off
639             //
640             if ( aonBatmonBat < batThreshold ) {
641                aonSysctlPwrctl &= ~( AON_SYSCTL_PWRCTL_DCDC_EN_M | AON_SYSCTL_PWRCTL_DCDC_ACTIVE_M );
642 
643                HWREG( AON_SYSCTL_BASE + AON_SYSCTL_O_PWRCTL ) = aonSysctlPwrctl;
644             }
645          } else {
646             //
647             // DCDC is OFF, check if it should be switched on
648             //
649             if ( aonBatmonBat > batThreshold ) {
650                if (( ccfg_ModeConfReg & CCFG_MODE_CONF_DCDC_RECHARGE_M ) == 0 ) aonSysctlPwrctl |= AON_SYSCTL_PWRCTL_DCDC_EN_M     ;
651                if (( ccfg_ModeConfReg & CCFG_MODE_CONF_DCDC_ACTIVE_M   ) == 0 ) aonSysctlPwrctl |= AON_SYSCTL_PWRCTL_DCDC_ACTIVE_M ;
652 
653                HWREG( AON_SYSCTL_BASE + AON_SYSCTL_O_PWRCTL ) = aonSysctlPwrctl;
654             }
655          }
656       }
657    }
658 }
659 
660 
661 //*****************************************************************************
662 //
663 // SysCtrlResetSourceGet()
664 //
665 //*****************************************************************************
666 uint32_t
SysCtrlResetSourceGet(void)667 SysCtrlResetSourceGet( void )
668 {
669    if ( HWREG( AON_SYSCTL_BASE + AON_SYSCTL_O_RESETCTL ) & AON_SYSCTL_RESETCTL_WU_FROM_SD_M ) {
670       return ( RSTSRC_WAKEUP_FROM_SHUTDOWN );
671    } else {
672       return (( HWREG( AON_SYSCTL_BASE + AON_SYSCTL_O_RESETCTL ) &
673                 AON_SYSCTL_RESETCTL_RESET_SRC_M ) >>
674                 AON_SYSCTL_RESETCTL_RESET_SRC_S ) ;
675    }
676 }
677