1 /******************************************************************************
2 *  Filename:       setup.c
3 *
4 *  Description:    Setup file for CC13xx/CC26xx devices.
5 *
6 *  Copyright (c) 2015 - 2022, Texas Instruments Incorporated
7 *  All rights reserved.
8 *
9 *  Redistribution and use in source and binary forms, with or without
10 *  modification, are permitted provided that the following conditions are met:
11 *
12 *  1) Redistributions of source code must retain the above copyright notice,
13 *     this list of conditions and the following disclaimer.
14 *
15 *  2) Redistributions in binary form must reproduce the above copyright notice,
16 *     this list of conditions and the following disclaimer in the documentation
17 *     and/or other materials provided with the distribution.
18 *
19 *  3) Neither the name of the ORGANIZATION nor the names of its contributors may
20 *     be used to endorse or promote products derived from this software without
21 *     specific prior written permission.
22 *
23 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24 *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
27 *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28 *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29 *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30 *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31 *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 *  POSSIBILITY OF SUCH DAMAGE.
34 *
35 ******************************************************************************/
36 
37 
38 // Hardware headers
39 #include "../inc/hw_types.h"
40 #include "../inc/hw_memmap.h"
41 #include "../inc/hw_adi.h"
42 #include "../inc/hw_adi_2_refsys.h"
43 #include "../inc/hw_adi_3_refsys.h"
44 #include "../inc/hw_adi_4_aux.h"
45 // Temporarily adding these defines as they are missing in hw_adi_4_aux.h
46 #define ADI_4_AUX_O_LPMBIAS                                         0x0000000E
47 #define ADI_4_AUX_LPMBIAS_LPM_TRIM_IOUT_M                           0x0000003F
48 #define ADI_4_AUX_LPMBIAS_LPM_TRIM_IOUT_S                                    0
49 #define ADI_4_AUX_COMP_LPM_BIAS_WIDTH_TRIM_M                        0x00000038
50 #define ADI_4_AUX_COMP_LPM_BIAS_WIDTH_TRIM_S                                 3
51 #include "../inc/hw_aon_ioc.h"
52 #include "../inc/hw_aon_pmctl.h"
53 #include "../inc/hw_aon_rtc.h"
54 #include "../inc/hw_ddi_0_osc.h"
55 #include "../inc/hw_ddi.h"
56 #include "../inc/hw_ccfg.h"
57 #include "../inc/hw_fcfg1.h"
58 #include "../inc/hw_flash.h"
59 #include "../inc/hw_prcm.h"
60 #include "../inc/hw_vims.h"
61 // Driverlib headers
62 #include "aon_rtc.h"
63 #include "interrupt.h"
64 #include "aux_sysif.h"
65 #include "chipinfo.h"
66 #include "osc.h"
67 #include "setup.h"
68 #include "setup_rom.h"
69 
70 //*****************************************************************************
71 //
72 // Handle support for DriverLib in ROM:
73 // This section will undo prototype renaming made in the header file
74 //
75 //*****************************************************************************
76 #if !defined(DOXYGEN)
77     #undef  SetupTrimDevice
78     #define SetupTrimDevice                 NOROM_SetupTrimDevice
79 #endif
80 
81 
82 
83 //*****************************************************************************
84 //
85 // Defined CPU delay macro with microseconds as input
86 // Quick check shows: (To be further investigated)
87 // At 48 MHz RCOSC and VIMS.CONTROL.PREFETCH = 0, there is 5 cycles
88 // At 48 MHz RCOSC and VIMS.CONTROL.PREFETCH = 1, there is 4 cycles
89 // At 24 MHz RCOSC and VIMS.CONTROL.PREFETCH = 0, there is 3 cycles
90 //
91 //*****************************************************************************
92 #define CPU_DELAY_MICRO_SECONDS( x ) \
93    CPUdelay(((uint32_t)((( x ) * 48.0 ) / 5.0 )) - 1 )
94 
95 
96 //*****************************************************************************
97 //
98 // Function declarations
99 //
100 //*****************************************************************************
101 static void     TrimAfterColdReset( void );
102 static void     TrimAfterColdResetWakeupFromShutDown( uint32_t ui32Fcfg1Revision );
103 static void     TrimAfterColdResetWakeupFromShutDownWakeupFromPowerDown( void );
104 
105 //*****************************************************************************
106 //
107 // Perform the necessary trim of the device which is not done in boot code
108 //
109 // This function should only execute coming from ROM boot. The current
110 // implementation does not take soft reset into account. However, it does no
111 // damage to execute it again. It only consumes time.
112 //
113 //*****************************************************************************
114 void
SetupTrimDevice(void)115 SetupTrimDevice(void)
116 {
117     uint32_t ui32Fcfg1Revision;
118     uint32_t ui32AonSysResetctl;
119 
120     // Get layout revision of the factory configuration area
121     // (Handle undefined revision as revision = 0)
122     ui32Fcfg1Revision = HWREG(FCFG1_BASE + FCFG1_O_FCFG1_REVISION);
123     if ( ui32Fcfg1Revision == 0xFFFFFFFF ) {
124         ui32Fcfg1Revision = 0;
125     }
126 
127     // This driverlib version and setup file is for the CC13x2x7, CC26x2x7 chips.
128     // Halt if violated
129     ThisLibraryIsFor_CC13x2x7_CC26x2x7_HaltIfViolated();
130 
131     // Enable standby in flash bank
132     HWREGBITW( FLASH_BASE + FLASH_O_CFG, FLASH_CFG_DIS_STANDBY_BITN ) = 0;
133 
134     // Select correct CACHE mode and set correct CACHE configuration
135 #if ( CCFG_BASE == CCFG_BASE_DEFAULT )
136     SetupSetCacheModeAccordingToCcfgSetting();
137 #else
138     NOROM_SetupSetCacheModeAccordingToCcfgSetting();
139 #endif
140 
141     // 1. Check for powerdown
142     // 2. Check for shutdown
143     // 3. Assume cold reset if none of the above.
144     //
145     // It is always assumed that the application will freeze the latches in
146     // AON_IOC when going to powerdown in order to retain the values on the IOs.
147     //
148     // NB. If this bit is not cleared before proceeding to powerdown, the IOs
149     //     will all default to the reset configuration when restarting.
150     if( ! ( HWREGBITW( AON_IOC_BASE + AON_IOC_O_IOCLATCH, AON_IOC_IOCLATCH_EN_BITN )))
151     {
152         // NB. This should be calling a ROM implementation of required trim and
153         // compensation
154         // e.g. TrimAfterColdResetWakeupFromShutDownWakeupFromPowerDown()
155         TrimAfterColdResetWakeupFromShutDownWakeupFromPowerDown();
156     }
157     // Check for shutdown
158     //
159     // When device is going to shutdown the hardware will automatically clear
160     // the SLEEPDIS bit in the SLEEP register in the AON_PMCTL module.
161     // It is left for the application to assert this bit when waking back up,
162     // but not before the desired IO configuration has been re-established.
163     else if( ! ( HWREGBITW( AON_PMCTL_BASE + AON_PMCTL_O_SLEEPCTL, AON_PMCTL_SLEEPCTL_IO_PAD_SLEEP_DIS_BITN )))
164     {
165         // NB. This should be calling a ROM implementation of required trim and
166         // compensation
167         // e.g. TrimAfterColdResetWakeupFromShutDown()    -->
168         //      TrimAfterColdResetWakeupFromShutDownWakeupFromPowerDown();
169         TrimAfterColdResetWakeupFromShutDown(ui32Fcfg1Revision);
170         TrimAfterColdResetWakeupFromShutDownWakeupFromPowerDown();
171     }
172     else
173     {
174         // Consider adding a check for soft reset to allow debugging to skip
175         // this section!!!
176         //
177         // NB. This should be calling a ROM implementation of required trim and
178         // compensation
179         // e.g. TrimAfterColdReset()   -->
180         //      TrimAfterColdResetWakeupFromShutDown()    -->
181         //      TrimAfterColdResetWakeupFromShutDownWakeupFromPowerDown()
182         TrimAfterColdReset();
183         TrimAfterColdResetWakeupFromShutDown(ui32Fcfg1Revision);
184         TrimAfterColdResetWakeupFromShutDownWakeupFromPowerDown();
185 
186     }
187 
188     // Set VIMS power domain control.
189     // PDCTL1VIMS = 0 ==> VIMS power domain is only powered when CPU power domain is powered
190     HWREG( PRCM_BASE + PRCM_O_PDCTL1VIMS ) = 0;
191 
192     // Configure optimal wait time for flash FSM in cases where flash pump
193     // wakes up from sleep
194     HWREG(FLASH_BASE + FLASH_O_FPAC1) = (HWREG(FLASH_BASE + FLASH_O_FPAC1) &
195                                          ~FLASH_FPAC1_PSLEEPTDIS_M) |
196                                         (0x139<<FLASH_FPAC1_PSLEEPTDIS_S);
197 
198     // And finally at the end of the flash boot process:
199     // SET BOOT_DET bits in AON_PMCTL to 3 if already found to be 1
200     // Note: The BOOT_DET_x_CLR/SET bits must be manually cleared
201     if ((( HWREG( AON_PMCTL_BASE + AON_PMCTL_O_RESETCTL ) &
202         ( AON_PMCTL_RESETCTL_BOOT_DET_1_M | AON_PMCTL_RESETCTL_BOOT_DET_0_M )) >>
203         AON_PMCTL_RESETCTL_BOOT_DET_0_S ) == 1 )
204     {
205         ui32AonSysResetctl = ( HWREG( AON_PMCTL_BASE + AON_PMCTL_O_RESETCTL ) &
206         ~( AON_PMCTL_RESETCTL_BOOT_DET_1_CLR_M | AON_PMCTL_RESETCTL_BOOT_DET_0_CLR_M |
207            AON_PMCTL_RESETCTL_BOOT_DET_1_SET_M | AON_PMCTL_RESETCTL_BOOT_DET_0_SET_M | AON_PMCTL_RESETCTL_MCU_WARM_RESET_M ));
208         HWREG( AON_PMCTL_BASE + AON_PMCTL_O_RESETCTL ) = ui32AonSysResetctl | AON_PMCTL_RESETCTL_BOOT_DET_1_SET_M;
209         HWREG( AON_PMCTL_BASE + AON_PMCTL_O_RESETCTL ) = ui32AonSysResetctl;
210     }
211 
212     // Reset the RTC
213     AONRTCReset();
214     // Configure the combined event
215     IntPendClear(INT_AON_RTC_COMB);
216     AONRTCCombinedEventConfig(AON_RTC_CH0 | AON_RTC_CH1 | AON_RTC_CH2);
217     // Start the RTC
218     AONRTCEnable();
219 
220     // Make sure there are no ongoing VIMS mode change when leaving SetupTrimDevice()
221     // (There should typically be no wait time here, but need to be sure)
222     while ( HWREGBITW( VIMS_BASE + VIMS_O_STAT, VIMS_STAT_MODE_CHANGING_BITN )) {
223         // Do nothing - wait for an eventual ongoing mode change to complete.
224     }
225 
226 }
227 
228 //*****************************************************************************
229 //
230 //! \brief Trims to be applied when coming from POWER_DOWN (also called when
231 //! coming from SHUTDOWN and PIN_RESET).
232 //!
233 //! \return None
234 //
235 //*****************************************************************************
236 static void
TrimAfterColdResetWakeupFromShutDownWakeupFromPowerDown(void)237 TrimAfterColdResetWakeupFromShutDownWakeupFromPowerDown( void )
238 {
239     // Currently no specific trim for Powerdown
240 }
241 
242 //*****************************************************************************
243 //
244 //! \brief Trims to be applied when coming from SHUTDOWN (also called when
245 //! coming from PIN_RESET).
246 //!
247 //! \param ui32Fcfg1Revision
248 //!
249 //! \return None
250 //
251 //*****************************************************************************
252 static void
TrimAfterColdResetWakeupFromShutDown(uint32_t ui32Fcfg1Revision)253 TrimAfterColdResetWakeupFromShutDown(uint32_t ui32Fcfg1Revision)
254 {
255     uint32_t   ccfg_ModeConfReg  ;
256 
257     // Check in CCFG for alternative DCDC setting
258     if (( HWREG( CCFG_BASE + CCFG_O_SIZE_AND_DIS_FLAGS ) & CCFG_SIZE_AND_DIS_FLAGS_DIS_ALT_DCDC_SETTING ) == 0 ) {
259         // ADI_3_REFSYS:DCDCCTL5[3]  (=DITHER_EN) = CCFG_MODE_CONF_1[19]   (=ALT_DCDC_DITHER_EN)
260         // ADI_3_REFSYS:DCDCCTL5[2:0](=IPEAK    ) = CCFG_MODE_CONF_1[18:16](=ALT_DCDC_IPEAK    )
261         // Using a single 4-bit masked write since layout is equal for both source and destination
262         HWREGB( ADI3_BASE + ADI_O_MASK4B + ( ADI_3_REFSYS_O_DCDCCTL5 * 2 )) = ( 0xF0 |
263             ( HWREG( CCFG_BASE + CCFG_O_MODE_CONF_1 ) >> CCFG_MODE_CONF_1_ALT_DCDC_IPEAK_S ));
264     }
265 
266     // Force DCDC to use RCOSC before starting up XOSC.
267     // Clock loss detector does not use XOSC until SCLK_HF actually switches
268     // and thus DCDC is not protected from clock loss on XOSC in that time frame.
269     // The force must be released when the switch to XOSC has happened. This is done
270     // in OSCHfSourceSwitch().
271     HWREG(AUX_DDI0_OSC_BASE + DDI_O_MASK16B + (DDI_0_OSC_O_CTL0 << 1) + 4) = DDI_0_OSC_CTL0_CLK_DCDC_SRC_SEL_M | (DDI_0_OSC_CTL0_CLK_DCDC_SRC_SEL_M >> 16);
272     // Dummy read to ensure that the write has propagated
273     HWREGH(AUX_DDI0_OSC_BASE + DDI_0_OSC_O_CTL0);
274 
275     // read the MODE_CONF register in CCFG
276     ccfg_ModeConfReg = HWREG( CCFG_BASE + CCFG_O_MODE_CONF );
277 
278     // First part of trim done after cold reset and wakeup from shutdown:
279     // -Adjust the VDDR_TRIM_SLEEP value.
280     // -Configure DCDC.
281     SetupAfterColdResetWakeupFromShutDownCfg1( ccfg_ModeConfReg );
282 
283     // Addition to the CC1352 boost mode for HWREV >= 2.0
284     // The combination VDDR_EXT_LOAD=0 and VDDS_BOD_LEVEL=1 is defined to select boost mode
285     if ((( ccfg_ModeConfReg & CCFG_MODE_CONF_VDDR_EXT_LOAD  ) == 0 ) &&
286         (( ccfg_ModeConfReg & CCFG_MODE_CONF_VDDS_BOD_LEVEL ) != 0 )    )
287     {
288         // OR in VDDR_BOOST_COMP_BOOST and maintain the other register fields.
289         // On CC13X2, CC26X2, CC13X1 and CC26X1 devices, there are no other
290         // fields in this register. But on CC26X4 and CC13X4 devices, there is
291         // an additional trim field that must not be overwritten.
292         HWREGB( ADI3_BASE + ADI_3_REFSYS_O_DCDCCTL3 ) |= ADI_3_REFSYS_DCDCCTL3_VDDR_BOOST_COMP_BOOST ;
293     }
294 
295     // Second part of trim done after cold reset and wakeup from shutdown:
296     // -Configure XOSC.
297 #if ( CCFG_BASE == CCFG_BASE_DEFAULT )
298     SetupAfterColdResetWakeupFromShutDownCfg2( ui32Fcfg1Revision, ccfg_ModeConfReg );
299 #else
300     NOROM_SetupAfterColdResetWakeupFromShutDownCfg2( ui32Fcfg1Revision, ccfg_ModeConfReg );
301 #endif
302 
303     {
304         uint32_t  trimReg        ;
305         uint32_t  ui32TrimValue  ;
306 
307         //--- Propagate the LPM_BIAS trim ---
308         trimReg = HWREG( FCFG1_BASE + FCFG1_O_DAC_BIAS_CNF );
309         ui32TrimValue = (( trimReg & FCFG1_DAC_BIAS_CNF_LPM_TRIM_IOUT_M ) >>
310                                      FCFG1_DAC_BIAS_CNF_LPM_TRIM_IOUT_S ) ;
311         HWREGB( AUX_ADI4_BASE + ADI_4_AUX_O_LPMBIAS ) = (( ui32TrimValue << ADI_4_AUX_LPMBIAS_LPM_TRIM_IOUT_S ) &
312                                                                             ADI_4_AUX_LPMBIAS_LPM_TRIM_IOUT_M ) ;
313         // Set LPM_BIAS_BACKUP_EN according to FCFG1 configuration
314         if ( trimReg & FCFG1_DAC_BIAS_CNF_LPM_BIAS_BACKUP_EN ) {
315             HWREGB( ADI3_BASE + ADI_O_SET + ADI_3_REFSYS_O_AUX_DEBUG ) = ADI_3_REFSYS_AUX_DEBUG_LPM_BIAS_BACKUP_EN;
316         } else {
317             HWREGB( ADI3_BASE + ADI_O_CLR + ADI_3_REFSYS_O_AUX_DEBUG ) = ADI_3_REFSYS_AUX_DEBUG_LPM_BIAS_BACKUP_EN;
318         }
319         // Set LPM_BIAS_WIDTH_TRIM according to FCFG1 configuration
320         {
321             uint32_t widthTrim = (( trimReg & FCFG1_DAC_BIAS_CNF_LPM_BIAS_WIDTH_TRIM_M ) >> FCFG1_DAC_BIAS_CNF_LPM_BIAS_WIDTH_TRIM_S );
322             HWREGH( AUX_ADI4_BASE + ADI_O_MASK8B + ( ADI_4_AUX_O_COMP * 2 )) = // Set LPM_BIAS_WIDTH_TRIM = 3
323                 (( ADI_4_AUX_COMP_LPM_BIAS_WIDTH_TRIM_M << 8         ) |       // Set mask (bits to be written) in [15:8]
324                  ( widthTrim << ADI_4_AUX_COMP_LPM_BIAS_WIDTH_TRIM_S )   );    // Set value (in correct bit pos) in [7:0]
325         }
326     }
327 
328     // Third part of trim done after cold reset and wakeup from shutdown:
329     // -Configure HPOSC.
330     // -Setup the LF clock.
331 #if ( CCFG_BASE == CCFG_BASE_DEFAULT )
332     SetupAfterColdResetWakeupFromShutDownCfg3( ccfg_ModeConfReg );
333 #else
334     NOROM_SetupAfterColdResetWakeupFromShutDownCfg3( ccfg_ModeConfReg );
335 #endif
336 
337     // Set AUX into power down active mode
338     AUXSYSIFOpModeChange( AUX_SYSIF_OPMODE_TARGET_PDA );
339 
340     // Disable EFUSE clock
341     HWREGBITW( FLASH_BASE + FLASH_O_CFG, FLASH_CFG_DIS_EFUSECLK_BITN ) = 1;
342 }
343 
344 
345 //*****************************************************************************
346 //
347 //! \brief Trims to be applied when coming from PIN_RESET.
348 //!
349 //! \return None
350 //
351 //*****************************************************************************
352 static void
TrimAfterColdReset(void)353 TrimAfterColdReset( void )
354 {
355     // Currently no specific trim for Cold Reset
356 }
357