From 951a99dba381ec6b5ce77b7f449287a84be8762a Mon Sep 17 00:00:00 2001 From: Jean Pierre Dudey Date: Wed, 29 Apr 2020 18:11:27 -0500 Subject: [PATCH] cc26x2_cc13x2: add setup_trim_device function This function trims the necessary registers for the device to operate normally. Signed-off-by: Jean Pierre Dudey --- cpu/cc26x2_cc13x2/cpu.c | 3 + .../include/cc26x2_cc13x2_setup.h | 121 +++++++++++ cpu/cc26x2_cc13x2/include/cpu_conf.h | 1 + cpu/cc26x2_cc13x2/setup.c | 198 ++++++++++++++++++ cpu/cc26xx_cc13xx/include/cc26xx_cc13xx.h | 2 + 5 files changed, 325 insertions(+) create mode 100644 cpu/cc26x2_cc13x2/include/cc26x2_cc13x2_setup.h create mode 100644 cpu/cc26x2_cc13x2/setup.c diff --git a/cpu/cc26x2_cc13x2/cpu.c b/cpu/cc26x2_cc13x2/cpu.c index 50fa72cc3b..f68513981c 100644 --- a/cpu/cc26x2_cc13x2/cpu.c +++ b/cpu/cc26x2_cc13x2/cpu.c @@ -33,6 +33,9 @@ void cpu_init(void) /* initialize the Cortex-M core */ cortexm_init(); + /* trim device */ + setup_trim_device(); + /* initialize stdio prior to periph_init() to allow use of DEBUG() there */ stdio_init(); diff --git a/cpu/cc26x2_cc13x2/include/cc26x2_cc13x2_setup.h b/cpu/cc26x2_cc13x2/include/cc26x2_cc13x2_setup.h new file mode 100644 index 0000000000..2411f1a4d4 --- /dev/null +++ b/cpu/cc26x2_cc13x2/include/cc26x2_cc13x2_setup.h @@ -0,0 +1,121 @@ +/* + * Copyright (C) 2020 Locha Inc + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup cpu_cc26x2_cc13x2 + * @{ + * + * @file + * @brief CC26x2/CC13x2 Device setup functions + */ + +#ifndef CC26X2_CC13X2_SETUP_H +#define CC26X2_CC13X2_SETUP_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Setup API address + */ +#define ROM_API_SETUP ((uint32_t *) (ROM_API_TABLE[28])) + +/** + * @brief Setup API ROM functions + * @{ + */ +#define rom_setup_after_cold_reset_wakeup_from_shutdown_cfg1 \ + ((void (*)(uint32_t mode_conf))ROM_API_SETUP[0]) + +#define rom_setup_after_cold_reset_wakeup_from_shutdown_cfg2 \ + ((void (*)(uint32_t rev, uint32_t mode_conf))ROM_API_SETUP[1]) + +#define rom_setup_after_cold_reset_wakeup_from_shutdown_cfg3 \ + ((void (*)(uint32_t mode_conf))ROM_API_SETUP[2]) + +#define rom_setup_get_trim_for_adc_sh_mode_en \ + ((uint32_t (*)(uint32_t rev))ROM_API_SETUP[3]) + +#define rom_setup_get_trim_for_adc_sh_vbuf_en \ + ((uint32_t (*)(uint32_t rev))ROM_API_SETUP[4]) + +#define rom_setup_get_trim_for_ampcomp_ctrl \ + ((uint32_t (*)(uint32_t rev))ROM_API_SETUP[5]) + +#define rom_setup_get_trim_for_ampcomp_th1 \ + ((uint32_t (*)(void))ROM_API_SETUP[6]) + +#define rom_setup_get_trim_for_ampcomp_th2 \ + ((uint32_t (*)(void))ROM_API_SETUP[7]) + +#define rom_setup_get_trim_for_anabypass_value1 \ + ((uint32_t (*)(uint32_t mode_conf))ROM_API_SETUP[8]) + +#define rom_setup_get_trim_for_dblr_loop_filter_reset_voltage \ + ((uint32_t (*)(uint32_t rev))ROM_API_SETUP[9]) + +#define rom_setup_get_trim_for_radc_ext_cfg \ + ((uint32_t (*)(uint32_t rev))ROM_API_SETUP[10]) + +#define rom_setup_get_trim_for_rc_osc_lf_ibias_trim \ + ((uint32_t (*)(uint32_t rev))ROM_API_SETUP[11]) + +#define rom_setup_get_trim_for_rc_osc_lf_rtune_ctune_trim \ + ((uint32_t (*)(void))ROM_API_SETUP[12]) + +#define rom_setup_get_trim_for_xosc_hf_ctl \ + ((uint32_t (*)(uint32_t rev))ROM_API_SETUP[13]) + +#define rom_setup_get_trim_for_xosc_hf_fast_start \ + ((uint32_t (*)(void))ROM_API_SETUP[14]) + +#define rom_setup_get_trim_for_xosc_hf_ibiastherm \ + ((uint32_t (*)(void))ROM_API_SETUP[15]) + +#define rom_setup_get_trim_for_xosc_lf_regulator_and_cmirrwr_ratio \ + ((uint32_t (*)(uint32_t rev))ROM_API_SETUP[16]) + +#define rom_setup_set_aon_rtc_sub_sec_inc \ + ((void (*)(uint32_t subsecinc))ROM_API_SETUP[17]) + +#define rom_setup_set_cache_mode_according_to_ccfg_setting \ + ((void (*)(void))ROM_API_SETUP[18]) + +#define rom_setup_step_vddr_trim_to \ + ((void (*)(uint32_t tocode))ROM_API_SETUP[19]) +/** @} */ + +/** + * @brief Performs the necessary trim of the device which is not done in ROM + * boot code. + * + * The following is handled by this function: + * + * - Checks if the driverlib variant used by the application is supported by the + * device. Execution is halted in case of unsupported driverlib variant. + * - Configures VIMS cache mode based on setting in CCFG. + * - Configures functionalities like DCDC and XOSC dependent on startup modes + * like cold reset, wakeup from shutdown and wakeup from from powerdown. + * - Configures VIMS power domain control. + * - Configures optimal wait time for flash FSM in cases where flash pump wakes + * up from sleep. + * + * @note It does no damage to execute this function again. It only consumes + * time. + */ +void setup_trim_device(void); + +#ifdef __cplusplus +} /* end extern "C" */ +#endif + +#endif /* CC26X2_CC13X2_SETUP_H */ +/** @} */ diff --git a/cpu/cc26x2_cc13x2/include/cpu_conf.h b/cpu/cc26x2_cc13x2/include/cpu_conf.h index fec3f880c0..40bf1e6125 100644 --- a/cpu/cc26x2_cc13x2/include/cpu_conf.h +++ b/cpu/cc26x2_cc13x2/include/cpu_conf.h @@ -27,6 +27,7 @@ #include "cc26x2_cc13x2_aux.h" #include "cc26x2_cc13x2_fcfg.h" #include "cc26x2_cc13x2_prcm.h" +#include "cc26x2_cc13x2_setup.h" #ifdef __cplusplus extern "C" { diff --git a/cpu/cc26x2_cc13x2/setup.c b/cpu/cc26x2_cc13x2/setup.c new file mode 100644 index 0000000000..9fe1278c01 --- /dev/null +++ b/cpu/cc26x2_cc13x2/setup.c @@ -0,0 +1,198 @@ + +/* + * Copyright (C) 2020 Locha Inc + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License v2.1. See the file LICENSE in the top level directory for more + * details. + */ +/** + * @ingroup cpu_cc26x2_cc13x2 + * @{ + * + * @file + * @brief CC26x2, CC13x2 Functions to setup the device + * + * @author Jean Pierre Dudey + * @} + */ + +#include "cpu.h" + +/** + * @brief Optimal wait time in cases where flash pump wakes up from sleep. + */ +#define FPAC1_OPTIMAL_PSLEEPTDIS (0x139) + +/** + * @brief Trims to be applied when coming from PIN_RESET. + */ +__attribute__ ((weak)) void trim_after_cold_reset(void) +{ + /* Currently no specific trim for Cold Reset */ +} + +/** + * @brief Trims to be applied when coming from POWER_DOWN (also called when + * coming from SHUTDOWN and PIN_RESET). + */ +__attribute__ ((weak)) void trim_after_cold_reset_wakeup_from_shutdown_wakeup_from_powerdown(void) +{ + /* Currently no specific trim for Powerdown */ +} + +/** + * @brief Trims to be applied when coming from SHUTDOWN (also called when + * coming from PIN_RESET). + * + * @param[in] fcfg_rev FCFG1 revision + */ +void trim_after_cold_reset_wakeup_from_shutdown(uint32_t fcfg_rev) +{ + uint32_t ccfg_mode_conf_reg; + + /* Check in CCFG for alternative DCDC setting */ + if ((CCFG->SIZE_AND_DIS_FLAGS & CCFG_SIZE_AND_DIS_FLAGS_DIS_ALT_DCDC_SETTING) == 0) { + /* ADI_3_REFSYS:DCDCCTL5[3] (=DITHER_EN) = CCFG_MODE_CONF_1[19] (=ALT_DCDC_DITHER_EN) + * ADI_3_REFSYS:DCDCCTL5[2:0](=IPEAK ) = CCFG_MODE_CONF_1[18:16](=ALT_DCDC_IPEAK ) + * + * Using a single 4-bit masked write since layout is equal for both + * source and destination + */ + ADI3_M4->DCDCCTL5.LOW = 0xF0 | (CCFG->MODE_CONF_1 >> + CCFG_MODE_CONF_1_ALT_DCDC_IPEAK_s); + } + + /* Force DCDC to use RCOSC before starting up XOSC. + * Clock loss detector does not use XOSC until SCLK_HF actually switches + * and thus DCDC is not protected from clock loss on XOSC in that time frame. + * The force must be released when the switch to XOSC has happened. */ + DDI_0_OSC_M16->CTL0.HIGH = DDI_0_OSC_CTL0_CLK_DCDC_SRC_SEL_m | + (DDI_0_OSC_CTL0_CLK_DCDC_SRC_SEL_m >> 16); + /* Dummy read to ensure that the write has propagated */ + DDI_0_OSC->CTL0; + + /* Read the MODE_CONF register in CCFG */ + ccfg_mode_conf_reg = CCFG->MODE_CONF; + + /* First part of trim done after cold reset and wakeup from shutdown: + * + * - Adjust the VDDR_TRIM_SLEEP value. + * - Configure DCDC. + */ + rom_setup_after_cold_reset_wakeup_from_shutdown_cfg1(ccfg_mode_conf_reg); + + /* Addition to the CC1352 boost mode for HWREV >= 2.0 + * The combination VDDR_EXT_LOAD=0 and VDDS_BOD_LEVEL=1 is defined to select + * boost mode */ + if (((ccfg_mode_conf_reg & CCFG_MODE_CONF_VDDR_EXT_LOAD) == 0) && + ((ccfg_mode_conf_reg & CCFG_MODE_CONF_VDDS_BOD_LEVEL) != 0)) { + ADI3->DCDCCTL3 = ADI_3_REFSYS_DCDCCTL3_VDDR_BOOST_COMP_BOOST; + } + + /* Second part of trim done after cold reset and wakeup from shutdown: + * + * - Configure XOSC. + */ + rom_setup_after_cold_reset_wakeup_from_shutdown_cfg2(fcfg_rev, ccfg_mode_conf_reg); + + { + uint32_t trim_reg; + uint32_t trim_value; + + /* Propagate the LPM_BIAS trim */ + trim_reg = FCFG->DAC_BIAS_CNF; + trim_value = (trim_reg & FCFG1_DAC_BIAS_CNF_LPM_TRIM_IOUT_m) >> + FCFG1_DAC_BIAS_CNF_LPM_TRIM_IOUT_s; + ADI_4_AUX->LPMBIAS = (trim_value << ADI_4_AUX_LPMBIAS_LPM_TRIM_IOUT_s) & + ADI_4_AUX_LPMBIAS_LPM_TRIM_IOUT_m; + + /* Set LPM_BIAS_BACKUP_EN according to FCFG1 configuration */ + if (trim_reg & FCFG1_DAC_BIAS_CNF_LPM_BIAS_BACKUP_EN) { + ADI3_SET->AUX_DEBUG = ADI_3_REFSYS_AUX_DEBUG_LPM_BIAS_BACKUP_EN; + } + else { + ADI3_CLR->AUX_DEBUG = ADI_3_REFSYS_AUX_DEBUG_LPM_BIAS_BACKUP_EN; + } + + /* Set LPM_BIAS_WIDTH_TRIM according to FCFG1 configuration */ + { + uint32_t width_trim = (trim_reg & FCFG1_DAC_BIAS_CNF_LPM_BIAS_WIDTH_TRIM_m) >> + FCFG1_DAC_BIAS_CNF_LPM_BIAS_WIDTH_TRIM_s; + /* Set LPM_BIAS_WIDTH_TRIM = 3 + * Set mask (bits to be written) in [15:8] + * Set value (in correct bit pos) in [7:0] + */ + ADI_4_AUX_M8->COMP = (ADI_4_AUX_COMP_LPM_BIAS_WIDTH_TRIM_m << 8) | + (width_trim << ADI_4_AUX_COMP_LPM_BIAS_WIDTH_TRIM_s); + } + } + + /* Third part of trim done after cold reset and wakeup from shutdown: + * + * - Configure HPOSC. + * - Setup the LF clock. + */ + rom_setup_after_cold_reset_wakeup_from_shutdown_cfg3(ccfg_mode_conf_reg); + + /* Set AUX into power down active mode */ + aux_sysif_opmode_change(AUX_SYSIF_OPMODEREQ_REQ_PDA); + + /* Disable EFUSE clock */ + FLASH->CFG |= FLASH_CFG_DIS_EFUSECLK; +} + +void setup_trim_device(void) +{ + /* Get factory configuration revision, treat undefined revision as 0 */ + uint32_t fcfg_rev = FCFG->FCFG1_REVISION; + if (fcfg_rev == 0xFFFFFFFF) { + fcfg_rev = 0; + } + + /* Enable standby in flash bank */ + FLASH->CFG &= ~FLASH_CFG_DIS_STANDBY; + + if (!(AON_IOC->IOCLATCH & AON_IOC_IOCLATCH_EN)) { + trim_after_cold_reset_wakeup_from_shutdown_wakeup_from_powerdown(); + } + else if (!(AON_PMCTL->SLEEPCTL & AON_PMCTL_SLEEPCTL_IO_PAD_SLEEP_DIS)) { + trim_after_cold_reset_wakeup_from_shutdown(fcfg_rev); + trim_after_cold_reset_wakeup_from_shutdown_wakeup_from_powerdown(); + } + else { + trim_after_cold_reset(); + trim_after_cold_reset_wakeup_from_shutdown(fcfg_rev); + trim_after_cold_reset_wakeup_from_shutdown_wakeup_from_powerdown(); + } + + /* Set VIMS power domain */ + PRCM->PDCTL1VIMS = 0; + + /* Configure optimal wait time for flash FSM in cases where flash pump + * wakes up from sleep */ + FLASH->FPAC1 = (FLASH->FPAC1 & ~FLASH_FPAC1_PSLEEPTDIS_m) | + (FPAC1_OPTIMAL_PSLEEPTDIS << FLASH_FPAC1_PSLEEPTDIS_s); + + /* Set BOOT_DET bits in AON_PMCTL to 3 if already found to be 1. + * Note: The BOOT_DET_x_CLR/SET bits must be manually cleared */ + uint32_t boot_det_m = AON_PMCTL_RESETCTL_BOOT_DET_1_m | + AON_PMCTL_RESETCTL_BOOT_DET_0_m; + uint32_t boot_det = (AON_PMCTL->RESETCTL & boot_det_m) >> + AON_PMCTL_RESETCTL_BOOT_DET_0_s; + if (boot_det == 1) { + uint32_t aon_sys_resetctl = AON_PMCTL->RESETCTL & + ~(AON_PMCTL_RESETCTL_BOOT_DET_1_CLR_m | + AON_PMCTL_RESETCTL_BOOT_DET_0_CLR_m | + AON_PMCTL_RESETCTL_BOOT_DET_1_SET_m | + AON_PMCTL_RESETCTL_BOOT_DET_0_SET_m | + AON_PMCTL_RESETCTL_MCU_WARM_RESET_m); + AON_PMCTL->RESETCTL = aon_sys_resetctl | + AON_PMCTL_RESETCTL_BOOT_DET_1_SET_m; + AON_PMCTL->RESETCTL = aon_sys_resetctl; + } + + /* Make sure there are no ongoing VIMS mode change when leaving (There + * should typically be no wait time here, but need to be sure) */ + while (VIMS->STAT & VIMS_STAT_MODE_CHANGING) {} +} diff --git a/cpu/cc26xx_cc13xx/include/cc26xx_cc13xx.h b/cpu/cc26xx_cc13xx/include/cc26xx_cc13xx.h index 0d5f0e5b48..4214adf4cb 100644 --- a/cpu/cc26xx_cc13xx/include/cc26xx_cc13xx.h +++ b/cpu/cc26xx_cc13xx/include/cc26xx_cc13xx.h @@ -144,6 +144,8 @@ typedef enum IRQn #define FLASH_BASE 0x00000000 /**< FLASH base address */ #define PERIPH_BASE 0x40000000 /**< Peripheral base address */ #define PERIPH_BASE_NONBUF 0x60000000 /**< Peripheral base address (nonbuf) */ +#define ROM_API_TABLE ((uint32_t *) 0x10000180) /**< ROM API table */ + /*@}*/ /**