Files
hpw421/component/xc6xx_drivers/Drivers/xc_driver/xc_drv_pwr.c
T
2026-06-06 16:49:48 +08:00

906 lines
19 KiB
C

/*!
* \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)
/*------------------------------------------------------------------------------------
Functions
-------------------------------------------------------------------------------------*/
void xc_pwr_vol_set(void)
{
uint32_t hf_clk = xc_clock_hfclk_in_get();
switch (hf_clk) {
case CLOCK_HFCLK_IN_16M: {
cprao_aon_bbldo_adj_set(0x3C);
cprao_aon_lpoldo_adj_set(4);
// XC_CPR_AO->BBLDO_ADJ = 0x3C; // 0x4a;
// XC_CPR_AO->LPOLDO_ADJ = 4; // 1;
} break;
case CLOCK_HFCLK_IN_32M: {
// if use usb driver, bbldo is at least 0x4E.
// cprao_aon_bbldo_adj_set(0x4E);
cprao_aon_bbldo_adj_set(0x2c);
cprao_aon_lpoldo_adj_set(7);
// XC_CPR_AO->BBLDO_ADJ = 0x9E; // 0x2C;
// XC_CPR_AO->LPOLDO_ADJ = 7;
} break;
case CLOCK_HFCLK_IN_48M: {
cprao_aon_bbldo_adj_set(0x3C);
cprao_aon_lpoldo_adj_set(4);
// XC_CPR_AO->BBLDO_ADJ = 0x9C;
// XC_CPR_AO->LPOLDO_ADJ = 4;
} break;
case CLOCK_HFCLK_IN_64M: {
cprao_aon_bbldo_adj_set(0x9C);
cprao_aon_lpoldo_adj_set(4);
// XC_CPR_AO->BBLDO_ADJ = 0x9C;
// XC_CPR_AO->LPOLDO_ADJ = 4;
} break;
case CLOCK_HFCLK_IN_96M: {
cprao_aon_bbldo_adj_set(0x9C);
cprao_aon_lpoldo_adj_set(7);
// XC_CPR_AO->BBLDO_ADJ = 0x9e;
// XC_CPR_AO->LPOLDO_ADJ = 7;
} break;
default: {
cprao_aon_bbldo_adj_set(0x9C);
cprao_aon_lpoldo_adj_set(4);
// XC_CPR_AO->BBLDO_ADJ = 0x9C;
// XC_CPR_AO->LPOLDO_ADJ = 4;
} break;
}
}
/**
**************************************************************************************
* @brief xc_adc_powerdown
* @details adc power down
* @param void
* @retval void
***************************************************************************************
*/
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
***************************************************************************************
*/
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();
}
}
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(1);
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 == 18 || i == 19 ) // Default for uart0
{
} else if (i == 33 || i == 34) {
gpio_cfg.Pull = GPIO_PULLDOWN;
xc_gpio_init(&gpio_cfg);
}
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_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);
}
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 (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);
}
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<<pin);
}else{
val |= (1<<pin);
}
rtc_pwrkey_soft_ctrl1_set(val);
}else{
val = rtc_pwrkey_ctrl3__aogpio_soft_out_en_h__getf();
val = val | (1 << (pin-32));
rtc_pwrkey_ctrl3__aogpio_soft_out_en_h__setf(val);
val = rtc_pwrkey_ctrl3__aogpio_soft_out_value_h__getf();
if(level == 0){
val &= ~(1<<(pin-32));
}else{
val |= (1<<(pin-32));
}
rtc_pwrkey_ctrl3__aogpio_soft_out_value_h__setf(val);
}
}
void xc_pwr_pwrkey_toggle_pin(uint8_t pin)
{
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(val == 0){
val |= (1<<pin);
}else{
val &= ~(1<<pin);
}
rtc_pwrkey_soft_ctrl1_set(val);
}else{
val = rtc_pwrkey_ctrl3__aogpio_soft_out_en_h__getf();
val = val | (1 << (pin-32));
rtc_pwrkey_ctrl3__aogpio_soft_out_en_h__setf(val);
val = rtc_pwrkey_ctrl3__aogpio_soft_out_value_h__getf();
if(( val & 1<<(pin-32)) == 0){
val |= (1<<(pin-32));
}else{
val &= ~(1<<(pin-32));
}
rtc_pwrkey_ctrl3__aogpio_soft_out_value_h__setf(val);
}
}
void xc_pwr_dcdc_init(uint8_t vol_level)
{
if (vol_level > 7) {
vol_level = 7;
}
cprao_aon_dcdc_ctr_reg1__dcdc_ctrl__setf(vol_level);
}
void xc_pwr_dcdc_close()
{
// 0b100, 3.3v supply power
cprao_aon_reg1__bb_coreldo_dcdc_sw_soft__setf(0);
cprao_aon_reg1__bb_coreldo_dcdc_sw_softsel__setf(0);
cprao_aon_reg1__bb_coreldo_dcdc_sw_mux__setf(1);
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);
}