/*! * \file xc_drv_pwr.c * * \brief Target xc6xxx hal power implementation * * \copyright Revised BSD License, see section \ref LICENSE. * * \code * * _ __ _ ________ _ * | |/ /(_)___ / ____/ /_ (_)___ * | // / __ \/ / / __ \/ / __ \ * / |/ / / / / /___/ / / / / /_/ / * /_/|_/_/_/ /_/\____/_/ /_/_/ .___/ * /_/ * (C) 2022-2025 XinChip * * \endcode * * \author ( XinChip ) Alex-J * * \author ( XinChip ) */ /*----------------------------------------------------------------------------------- INCLUDE HEADE FILES ------------------------------------------------------------------------------------*/ #include "xc_drv_pwr.h" #if (USE_ROM_FLASH) #include "xc6xxx_fmc_spi.h" #endif // (USE_ROM_FLASH) #if XC_CHECK(XC_PWR_ENABLED) /*------------------------------------------------------------------------------------ Functions -------------------------------------------------------------------------------------*/ /** ************************************************************************************** * @brief xc_pwr_vol_set * @details Set the voltages of bbldo and lpldo * @param void * @retval void *************************************************************************************** */ void xc_pwr_vol_set(void) { uint32_t hf_clk = xc_clock_hfclk_in_get(); switch (hf_clk) { case CLOCK_HFCLK_IN_16M: case CLOCK_HFCLK_IN_24M: case CLOCK_HFCLK_IN_32M: { // if use usb driver, bbldo is at least 0x4E. cprao_aon_bbldo_adj_set(0x2c); } break; case CLOCK_HFCLK_IN_48M: case CLOCK_HFCLK_IN_64M: { cprao_aon_bbldo_adj_set(0x2d); } break; #if !defined(NO_SUPPORT_HFCLK_BBPLL_96M) case CLOCK_HFCLK_IN_96M: { cprao_aon_bbldo_adj_set(0x4f); } break; #endif default: { cprao_aon_bbldo_adj_set(0x2f); } break; } cprao_aon_lpoldo_adj_set(7); } /** ************************************************************************************** * @brief xc_adc_powerdown * @details adc power down * @param void * @retval void *************************************************************************************** */ __RAM_CODE void xc_adc_powerdown(void) { adc_rf_ctl__pd_adc__setf(ADC_RF_CTL_PD_GADC_POWERDOWN); } /** ************************************************************************************** * @brief xc_adc_wakeup * @details adc wakeup * @param void * @retval void *************************************************************************************** */ __RAM_CODE void xc_adc_wakeup(void) { adc_rf_ctl__pd_adc__setf(ADC_RF_CTL_PD_GADC_WAKWUP); } __RAM_CODE void xc_pwr_ao_timer_pclk32k_set(void) { uint32_t val; cprao_aon_reg1__timer_ao_sleep_clksw__setf(1); val = cprao_aon_reg1__timer_ao_sleep_clksw__getf(); while ((val & 0x01) != 1) { __NOP(); __NOP(); val = cprao_aon_reg1__timer_ao_sleep_clksw__getf(); } } __RAM_CODE void xc_pwr_ao_timer_pclk32m_Set() { cprao_aon_reg1__timer_ao_sleep_clksw__setf(0); } void xc_pwr_sleep_init(PWR_InitCfg_t *pwr_cfg) { cprao_aon_sys_time_set((RST_READY_TIME << 12) | (OSC32_STABLE_TIME)); if (pwr_cfg->pwr_sleep_mode == LIGHT_SLEEP_MODE) { xc_pwr_pd_lightsleep_set(); xc_pwr_sleepsrc_mask_set(0x1e001e); } else if (pwr_cfg->pwr_sleep_mode == DEEP_SLEEP_MODE) { xc_pwr_pd_deepsleep_set(); delay_us(100); xc_pwr_sleepsrc_mask_set(0x1e001e); } xc_pwr_osc_off(); xc_pwr_wake_it_set(pwr_cfg->pwr_wake_it_src); } // __RAM_CODE void xc_sleep_init() // { // xc_adc_powerdown(); // xc_pwr_usb_off(); // xc_pwr_rc16m_off(); // xc_pwr_rc32k_calib_off(); // // xc_pwr_rom_off(); // xc_pwr_opa_tempsensor_off(); // xc_pwr_opa_volr_off(); // xc_pwr_revddldo_off(); // xc_pwr_dcdc_close(); // xc_pwr_rfdigital_off(); // xc_pwr_modem_off(); // xc_pwr_pd_lightsleep_set(); // } __RAM_CODE void xc_pwr_ble_sleep_enter(void) { #if (USE_XIP == 1) #if (USE_ROM_FLASH) FMC_SPI_Flash_PowerDown(); #else // (USE_ROM_FLASH) xc_fmc_spi_flash_power_down(); #endif // USE_ROM_FLASH __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); cpr_fmc_ctl_set(0x3000 | (1 << 9)); // close fmc for (int i = 0; i < 10; i++) { __NOP(); __NOP(); __NOP(); } #endif // USE_XIP __disable_irq(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __WFI(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); #if (USE_XIP == 1) cpr_fmc_ctl_set(0x3503); // open FMC __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); xc_pwr_rom_on(); #if (USE_ROM_FLASH) FMC_SPI_Flash_WakeUp(); #else // (USE_ROM_FLASH) xc_fmc_spi_flash_wake_up(); #endif // (USE_ROM_FLASH) __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); #endif xc_pwr_ao_timer_pclk32m_Set(); // xc_pwr_rom_on(); __enable_irq(); #ifdef USED_DCDC xc_pwr_dcdc_open(); #endif xc_pwr_modem_on(); xc_pwr_rfdigital_on(); xc_adc_wakeup(); } __RAM_CODE void xc_sleep(void) { xc_adc_powerdown(); xc_pwr_usb_off(); xc_pwr_rc16m_off(); // xc_pwr_rom_off(); xc_pwr_modem_off(); xc_pwr_opa_tempsensor_off(); xc_pwr_opa_volr_off(); xc_pwr_revddldo_off(); cprao_aon_reg4__bb_coreldo_normal_sw_mux__setf(0); // xc_pwr_bor_off(); xc_pwr_dcdc_close(); xc_pwr_rfdigital_off(); xc_pwr_rc32k_calib_off(); rtc_rccal_en_set(0x00); xc_pwr_pd_lightsleep_set(); #if (USE_XIP == 1) #if (USE_ROM_FLASH) FMC_SPI_Flash_PowerDown(); #else // (USE_ROM_FLASH) xc_fmc_spi_flash_power_down(); #endif // (USE_ROM_FLASH) xc_pwr_rom_off(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); cpr_fmc_ctl_set(0x3000 | (1 << 9)); // close fmc for (int i = 0; i < 10; i++) { __NOP(); __NOP(); __NOP(); } #endif __disable_irq(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __WFI(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); #if (USE_XIP == 1) cpr_fmc_ctl_set(0x3503); // open FMC __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); xc_pwr_rom_on(); #if (USE_ROM_FLASH) FMC_SPI_Flash_WakeUp(); #else // (USE_ROM_FLASH) xc_fmc_spi_flash_wake_up(); #endif // (USE_ROM_FLASH) __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); #endif xc_pwr_ao_timer_pclk32m_Set(); // xc_pwr_rom_on(); __enable_irq(); #ifdef USED_DCDC xc_pwr_dcdc_open(); #endif xc_pwr_modem_on(); xc_pwr_rfdigital_on(); xc_adc_wakeup(); } __RAM_CODE void xc_deep_sleep() { xc_pwr_ao_timer_pclk32k_set(); adc_rf_ctl__pd_adc__setf(ADC_RF_CTL_PD_GADC_POWERDOWN); xc_pwr_usb_off(); xc_pwr_rc16m_off(); xc_pwr_rfdigital_off(); xc_pwr_modem_off(); xc_pwr_pd_deepsleep_set(); xc_pwr_rom_on(); xc_pwr_dcdc_close(); #if (USE_XIP == 1) #if (USE_ROM_FLASH) FMC_SPI_Flash_PowerDown(); #else // (USE_ROM_FLASH) xc_fmc_spi_flash_power_down(); #endif // (USE_ROM_FLASH) __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); cpr_fmc_ctl_set(0x3000 | (1 << 9)); // close FMC for (int i = 0; i < 10; i++) { __NOP(); __NOP(); __NOP(); } #endif __disable_irq(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __WFI(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); #if (USE_XIP == 1) cpr_fmc_ctl_set(0x3503); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); xc_pwr_rom_on(); #if (USE_ROM_FLASH) FMC_SPI_Flash_WakeUp(); #else // (USE_ROM_FLASH) xc_fmc_spi_flash_wake_up(); #endif // (USE_ROM_FLASH) __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); #endif xc_pwr_ao_timer_pclk32m_Set(); // xc_pwr_rom_on(); __enable_irq(); #ifdef USED_DCDC xc_pwr_dcdc_open(); #endif xc_pwr_modem_on(); xc_pwr_rfdigital_on(); xc_adc_wakeup(); } __RAM_CODE void xc_pwr_cpu_sleep_enter(void) { xc_pwr_ao_timer_pclk32k_set(); xc_adc_powerdown(); xc_pwr_usb_off(); xc_pwr_rc16m_off(); xc_pwr_rfdigital_off(); xc_pwr_modem_off(); xc_pwr_pd_lightsleep_set(); // auto switch core ldo voltage 1.17v to 0.89v xc_pwr_opa_tempsensor_off(); xc_pwr_opa_volr_off(); xc_pwr_dcdc_close(); #if (USE_XIP == 1) #if (USE_ROM_FLASH) FMC_SPI_Flash_PowerDown(); #else // (USE_ROM_FLASH) xc_fmc_spi_flash_power_down(); #endif // (USE_ROM_FLASH) cpr_fmc_ctl_set(0x3000 | (1 << 11) | (1 << 9)); // close FMC #endif // USE_XIP xc_pwr_rom_off(); __disable_irq(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __WFI(); // waiting to wake up __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); #if (USE_XIP == 1) cpr_fmc_ctl_set(0x3503); // open FMC __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); xc_pwr_rom_on(); #if (USE_ROM_FLASH) FMC_SPI_Flash_WakeUp(); #else // (USE_ROM_FLASH) xc_fmc_spi_flash_wake_up(); #endif // (USE_ROM_FLASH) #endif // USE_XIP xc_pwr_ao_timer_pclk32m_Set(); // xc_pwr_rom_on(); __enable_irq(); #ifdef USED_DCDC xc_pwr_dcdc_open(); #endif xc_pwr_modem_on(); xc_pwr_rfdigital_on(); xc_adc_wakeup(); } void xc_pwr_gpio_sleep_config(void) { #if (USE_XIP == 1) /* puctrl1= 0xf ,clk,cs,d0,d1 must pulldown */ // cprao_aon_puctrl1_set(0xf); cprao_aon_puctrl1_set(0x5555F); #else // if (sleep_mode == LIGHT_SLEEP_MODE) { // XC_CPR_AO->PU_CTRLx[0] = 0x4; // } else if (sleep_mode == DEEP_SLEEP_MODE) { // XC_CPR_AO->PU_CTRLx[0] = 0xf; // } #endif NVIC_DisableIRQ(GPIO_IRQn); GPIO_InitCfg_t gpio_cfg = {0}; gpio_cfg.Mux = GPIO_Mux0; gpio_cfg.Dir = GPIO_DIR_INPUT; gpio_cfg.FunSel = GPIO_Dx; gpio_cfg.Int = NOT_INT; gpio_cfg.Pull = GPIO_PULLDOWN; // The gpio scripts used cannot be configured. gpio36-39 cannot be // configured. for (int i = 0; i < GPIO_36; i++) { gpio_cfg.Pin = i; if (i == GPIO_18 || i == GPIO_19) { } else if (i == GPIO_33 || i == GPIO_34) { gpio_cfg.Pull = GPIO_PULLDOWN; xc_gpio_init(&gpio_cfg); } else if (i == GPIO_35) { gpio_cfg.Pull = GPIO_PULLDOWN; xc_gpio_init(&gpio_cfg); } else if (i == GPIO_20 || i == GPIO_21) { #if !defined(NO_SUPPORT_LFCLK_XTAL_32768) // Pins required when using an external 32k crystal if (xc_clock_lfclk_src_get() != CLOCK_LFCLK_SRC_XTAL) { xc_gpio_init(&gpio_cfg); } #else xc_gpio_init(&gpio_cfg); #endif } else { xc_gpio_init(&gpio_cfg); } } } // void xc_gpio_sleep_config(void) // { // #if (USE_XIP == 1) // cprao_aon_puctrl1_set(0xf); // // XC_CPR_AO->PU_CTRLx[0] = 0xf; /* puctrl1= 0xf ,clk,cs,d0,d1 must pulldown */ // #endif // NVIC_DisableIRQ(GPIO_IRQn); // GPIO_InitCfg_t gpio_cfg = {0}; // gpio_cfg.Mux = GPIO_Mux0; // gpio_cfg.Dir = GPIO_DIR_INPUT; // gpio_cfg.FunSel = GPIO_Dx; // gpio_cfg.Int = NOT_INT; // gpio_cfg.Pull = GPIO_PULLDOWN; // for (int i = 0; i < GPIO_MAX; i++) { // gpio_cfg.Pin = i; // if (i == 18 || i == 19) // Default for uart0 // { // } else if (i == 33 || i == 34) { // xc_gpio_pull_config(i, GPIO_PULLDOWN); // } else if (i == 35) { // gpio_cfg.Pull = GPIO_PULLDOWN; // xc_gpio_init(&gpio_cfg); // } else if (i == 20 || i == 21) { // // Pins required when using an external 32k crystal // if (xc_clock_lfclk_src_get() != CLOCK_LFCLK_SRC_XTAL) { // xc_gpio_init(&gpio_cfg); // } // } else { // xc_gpio_init(&gpio_cfg); // } // } // } void xc_pwr_gpio_lightsleep_wake_config(uint8_t pin, uint8_t edge_it) { GPIO_InitCfg_t gpio_cfg = {0}; gpio_cfg.Mux = GPIO_Mux0; gpio_cfg.Dir = GPIO_DIR_INPUT; gpio_cfg.FunSel = GPIO_Dx; if (edge_it == RIS_EDGE_INT) { gpio_cfg.Int = RIS_EDGE_INT; gpio_cfg.Pull = GPIO_PULLDOWN; } else if (edge_it == FAIL_EDGE_INT) { gpio_cfg.Int = FAIL_EDGE_INT; gpio_cfg.Pull = GPIO_PULLUP; } gpio_cfg.Pin = pin; xc_gpio_init(&gpio_cfg); NVIC_EnableIRQ(GPIO_IRQn); } void xc_pwr_pwrkey_init(void) { cpr_ctlapbclken_grctl__rtc_pclk_en__setf(ENABLE); cprao_aon_clken_grctl__rtc_clk_en__setf(ENABLE); rtc_pwrkey_ctrl0_set(0); rtc_pwrkey_ctrl1_set(0); rtc_pwrkey_ctrl2_set(0); rtc_pwrkey_ctrl3_set(0); } void xc_pwr_pwrkey_deepsleep_wake_config(uint8_t pin, uint8_t level) { GPIO_InitCfg_t gpio_cfg = {0}; uint32_t val; uint32_t val_ctl; gpio_cfg.Mux = GPIO_Mux0; gpio_cfg.Dir = GPIO_DIR_INPUT; gpio_cfg.FunSel = GPIO_Dx; gpio_cfg.Int = NOT_INT; if(pin <= GPIO_31) { if (level == DEEP_SLEEP_GPIO_WAKE_HIGH_LEVEL) { gpio_cfg.Pull = GPIO_PULLDOWN; val = rtc_pwrkey_ctrl0__powkey_edge__getf(); val &= ~(1 << pin); rtc_pwrkey_ctrl0__powkey_edge__setf(val); } else if (level == DEEP_SLEEP_GPIO_WAKE_LOW_LEVEL) { gpio_cfg.Pull = GPIO_PULLUP; val = rtc_pwrkey_ctrl0__powkey_edge__getf(); val |= (1 << pin); rtc_pwrkey_ctrl0__powkey_edge__setf(val); } gpio_cfg.Pin = pin; xc_gpio_init(&gpio_cfg); val_ctl =rtc_pwrkey_ctrl1_get(); rtc_pwrkey_ctrl1__powkey_en__setf((1 << pin)|val_ctl); rtc_pwrkey_ctrl2__powkey_inten__setf(ENABLE); NVIC_EnableIRQ(RTC_IRQn); } else { gpio_cfg.Pin = pin; pin = pin-32; if (level == DEEP_SLEEP_GPIO_WAKE_HIGH_LEVEL) { gpio_cfg.Pull = GPIO_PULLDOWN; val = rtc_pwrkey_ctrl3__powkey_edge_h__getf(); val &= ~(1 << pin); rtc_pwrkey_ctrl3__powkey_edge_h__setf(val); } else if (level == DEEP_SLEEP_GPIO_WAKE_LOW_LEVEL) { gpio_cfg.Pull = GPIO_PULLUP; val = rtc_pwrkey_ctrl3__powkey_edge_h__getf(); val |= (1 << pin); rtc_pwrkey_ctrl3__powkey_edge_h__setf(val); } val_ctl =rtc_pwrkey_ctrl3__powkey_en_h__getf(); xc_gpio_init(&gpio_cfg); rtc_pwrkey_ctrl2__powkey_inten__setf(ENABLE); rtc_pwrkey_ctrl3__powkey_en_h__setf((1 << pin)|val_ctl); NVIC_EnableIRQ(RTC_IRQn); } } void xc_pwr_pwrkey_write_pin(uint8_t pin, uint8_t level) { uint32_t val; if(cpr_ctlapbclken_grctl__rtc_pclk_en__getf()==DISABLE){ cpr_ctlapbclken_grctl__rtc_pclk_en__setf(ENABLE); } if(cprao_aon_clken_grctl__rtc_clk_en__getf()==DISABLE){ cprao_aon_clken_grctl__rtc_clk_en__setf(ENABLE); } if(pin < 32){ val = rtc_pwrkey_soft_ctrl0_get(); val = val | (1 << pin); rtc_pwrkey_soft_ctrl0_set(val); val = rtc_pwrkey_soft_ctrl1_get(); if(level == 0){ val &= ~(1< 7) { vol_level = 7; } cprao_aon_dcdc_ctr_reg1__dcdc_ctrl__setf(vol_level); } __RAM_CODE void xc_pwr_dcdc_close() { // 0b100, 3.3v supply power cprao_aon_reg1__bb_coreldo_dcdc_sw_soft__setf(0); for (int i = 0; i < 10; i++) { __NOP(); } cprao_aon_reg1__bb_coreldo_dcdc_sw_softsel__setf(0); for (int i = 0; i < 10; i++) { __NOP(); } cprao_aon_reg1__bb_coreldo_dcdc_sw_mux__setf(1); for (int i = 0; i < 10; i++) { __NOP(); } cprao_aon_dcdc_ctr_reg0_set(1<<6); } void xc_pwr_dcdc_open() { cprao_aon_dcdc_ctr_reg0__dcdc_en_soft__setf(1); cprao_aon_dcdc_ctr_reg0__dcdc_bg_en_soft__setf(1); // 0b011, dcdc supply power cprao_aon_reg1__bb_coreldo_dcdc_sw_softsel__setf(1); cprao_aon_reg1__bb_coreldo_dcdc_sw_soft__setf(1); for (volatile uint16_t dly = 0; dly < 600; dly++) ; cprao_aon_reg1__bb_coreldo_dcdc_sw_mux__setf(0); } #endif // XC_CHECK(XC_PWR_ENABLED)