Files
2026-06-06 16:49:48 +08:00

519 lines
18 KiB
C

/*!
* \file xc_drv_clock.c
*
* \brief Target xinchip clock driver 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_clock.h"
/*------------------------------------------------------------------------------------
Local Variables
-------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------
Global Variables
-------------------------------------------------------------------------------------*/
CLOCK_InitCfg_t clock_cb;
/*------------------------------------------------------------------------------------
Func Prototype
-------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------
Functions
-------------------------------------------------------------------------------------*/
/**
****************************************************************************************
* @brief xc_clock_bbpll_common_cfg
* @details Common Settings for frequency doubling
* @param[in] void
* @param[in] void
* @param[out] void
* @retval void
****************************************************************************************
*/
void xc_clock_bbpll_common_cfg(void)
{
cpr_bt_clk_ctl__bt_clk_en__setf(ENABLE);
cpr_ctlapbclken_grctl__bt_pclk_en__setf(ENABLE);
bt_rf_pm_reg__bt_en_pm__setf(ENABLE);
cprao_aon_coreldo_en_set(ENABLE);
}
/**
****************************************************************************************
* @brief xc_clock_bbpll_freq_cfg
* @details Initializes the frequency doubling clock
* @param[in] hfclk_src :Source clock
* @param[in] loopdiv :clock multiplier factor
* @param[in] clk_div :Frequency division coefficient
* @param[out] void
* @retval void
****************************************************************************************
*/
void xc_clock_bbpll_freq_cfg(CLOCK_HFCLK_Src_Typedef hfclk_src, uint16_t loopdiv,
uint8_t clk_div)
{
if (CLOCK_HFCLK_SRC_RC == hfclk_src)
rf_ana27__bbpll_16m_sel__setf(ENABLE);
else
rf_ana27__bbpll_16m_sel__setf(DISABLE);
if(loopdiv != 0x03)
rf_ana27__bbpll_core_96m_en__setf(ENABLE);
else
rf_ana27__bbpll_core_96m_en__setf(DISABLE);
rf_ana26__bbpll_loopdiv__setf(loopdiv);
rf_ana26__clk_bbpll_en__setf(ENABLE);
rf_ana26__clk_bbpll_rstn__setf(ENABLE);
rf_ana26__bbpll_en__setf(ENABLE);
rf_ana26__bbpll_core_64m_en__setf(ENABLE);
cpr_rf_reg4__bbpll_clk_div__setf(clk_div);
cpr_rf_reg4__bbpll_clk_en__setf(ENABLE);
}
/**
****************************************************************************************
* @brief xc_clock_set_rc16m
* @details The clock is set to RC16M
* @param[in] CLOCK_InitCfg_t *cb
* @param[in]
* @param[out] void
* @retval void
****************************************************************************************
*/
void xc_clock_set_rc16m(CLOCK_InitCfg_t *cb)
{
cpr_rf_reg3__mclk_src_sel__setf(CLOCK_SRC_RC16M);
cb->hfclk_in = CLOCK_HFCLK_IN_16M;
cb->systick_unit = SYSTICK_UNIT_IN_16M;
}
/**
****************************************************************************************
* @brief xc_clock_set_rc16m_bbpll_32m
* @details RC16M clock overclocked to 32M
* @param[in] CLOCK_InitCfg_t *cb
* @param[in]
* @param[out] void
* @retval void
****************************************************************************************
*/
void xc_clock_set_rc16m_bbpll_32m(CLOCK_InitCfg_t *cb)
{
xc_clock_bbpll_common_cfg();
xc_clock_bbpll_freq_cfg(cb->hfclk_src, 0x08, 0x01);
cpr_rf_reg3__mclk_src_sel__setf(CLOCK_SRC_BBPLL_DIV);
cb->hfclk_in = CLOCK_HFCLK_IN_32M;
cb->systick_unit = SYSTICK_UNIT_IN_32M;
}
/**
****************************************************************************************
* @brief xc_clock_set_rc16m_bbpll_48m
* @details RC16M clock overclocked to 48M
* @param[in] CLOCK_InitCfg_t *cb
* @param[in]
* @param[out] void
* @retval void
****************************************************************************************
*/
void xc_clock_set_rc16m_bbpll_48m(CLOCK_InitCfg_t *cb)
{
xc_clock_bbpll_common_cfg();
xc_clock_bbpll_freq_cfg(cb->hfclk_src, 0x0C, 0x01);
cpr_rf_reg3__mclk_src_sel__setf(CLOCK_SRC_BBPLL_DIV);
cb->hfclk_in = CLOCK_HFCLK_IN_48M;
cb->systick_unit = SYSTICK_UNIT_IN_48M;
}
/**
****************************************************************************************
* @brief xc_clock_set_rc16m_bbpll_64m
* @details RC16M clock overclocked to 64M
* @param[in] CLOCK_InitCfg_t *cb
* @param[in]
* @param[out] void
* @retval void
****************************************************************************************
*/
void xc_clock_set_rc16m_bbpll_64m(CLOCK_InitCfg_t *cb)
{
xc_clock_bbpll_common_cfg();
xc_clock_bbpll_freq_cfg(cb->hfclk_src, 0x08, 0x01);
cpr_rf_reg3__mclk_src_sel__setf(CLOCK_SRC_BBPLL);
cb->hfclk_in = CLOCK_HFCLK_IN_64M;
cb->systick_unit = SYSTICK_UNIT_IN_64M;
}
/**
****************************************************************************************
* @brief xc_clock_set_rc16m_bbpll_96m
* @details RC16M clock overclocked to 96M
* @param[in] CLOCK_InitCfg_t *cb
* @param[in]
* @param[out] void
* @retval void
****************************************************************************************
*/
void xc_clock_set_rc16m_bbpll_96m(CLOCK_InitCfg_t *cb)
{
xc_clock_bbpll_common_cfg();
xc_clock_bbpll_freq_cfg(cb->hfclk_src, 0x0C, 0x01);
cpr_rf_reg3__mclk_src_sel__setf(CLOCK_SRC_BBPLL);
cb->hfclk_in = CLOCK_HFCLK_IN_96M;
cb->systick_unit = SYSTICK_UNIT_IN_96M;
}
/**
****************************************************************************************
* @brief xc_clock_set_osc32m_bbpll_16m
* @details osc32M Clock overclocked to 16M
* @param[in] CLOCK_InitCfg_t *cb
* @param[in]
* @param[out] void
* @retval void
****************************************************************************************
*/
void xc_clock_set_osc32m_bbpll_16m(CLOCK_InitCfg_t *cb)
{
xc_clock_bbpll_common_cfg();
xc_clock_bbpll_freq_cfg(cb->hfclk_src, 0x06, 0x05);
cpr_rf_reg3__mclk_src_sel__setf(CLOCK_SRC_BBPLL_DIV);
cb->hfclk_in = CLOCK_HFCLK_IN_16M;
cb->systick_unit = SYSTICK_UNIT_IN_16M;
}
/**
****************************************************************************************
* @brief xc_clock_set_osc32m_div_16m
* @details osc32M Clock divided into 16M
* @param[in] CLOCK_InitCfg_t *cb
* @param[in]
* @param[out] void
* @retval void
****************************************************************************************
*/
void xc_clock_set_osc32m_div_16m(CLOCK_InitCfg_t *cb)
{
//M0_FCLK
cpr_m0_fclk_ctl__m0_fclk_div_p__setf(0x1);
cpr_m0_fclk_ctl__m0_fclk_direct_sw__setf(0x1);
//CTL_PCLK
cpr_ctl_pclk_grctl__ctl_pclk_gr__setf(0x8);
cpr_ctl_pclk_grctl__ctl_pclk_gr_upd__setf(0x1);
cprao_aon_bbldo_adj_set(0x3c);
/* The value needs to be configured to 7,
otherwise the current drop will be slower during sleep
and the clock accuracy of the rc32k will be affected.
*/
cprao_aon_lpoldo_adj_set(0x7);
cb->hfclk_in = CLOCK_HFCLK_IN_16M;
cb->systick_unit = SYSTICK_UNIT_IN_16M;
}
/**
****************************************************************************************
* @brief xc_clock_set_osc32m
* @details The clock is set to osc32M
* @param[in] CLOCK_InitCfg_t *cb
* @param[in]
* @param[out] void
* @retval void
****************************************************************************************
*/
void xc_clock_set_osc32m(CLOCK_InitCfg_t *cb)
{
cpr_rf_reg3__mclk_src_sel__setf(CLOCK_SRC_OSC32M);
cb->hfclk_in = CLOCK_HFCLK_IN_32M;
cb->systick_unit = SYSTICK_UNIT_IN_32M;
}
#if (CONFIG_HFCLK_IS_OSC32M_PLL_32M)
/**
****************************************************************************************
* @brief xc_clock_set_osc32m_bbpll_32m
* @details osc32M Clock overclocked to 64M and hflck is 32M
* @param[in] CLOCK_InitCfg_t *cb
* @param[in]
* @param[out] void
* @retval void
****************************************************************************************
*/
void xc_clock_set_osc32m_bbpll_32m(CLOCK_InitCfg_t *cb)
{
xc_clock_bbpll_common_cfg();
xc_clock_bbpll_freq_cfg(cb->hfclk_src, 0x04, 0x01);
cpr_rf_reg3__mclk_src_sel__setf(CLOCK_SRC_BBPLL_DIV);
cb->hfclk_in = CLOCK_HFCLK_IN_32M;
cb->systick_unit = SYSTICK_UNIT_IN_32M;
}
#endif
/**
****************************************************************************************
* @brief xc_clock_set_osc32m_bbpll_48m
* @details osc32M Clock overclocked to 48M
* @param[in] CLOCK_InitCfg_t *cb
* @param[in]
* @param[out] void
* @retval void
****************************************************************************************
*/
void xc_clock_set_osc32m_bbpll_48m(CLOCK_InitCfg_t *cb)
{
xc_clock_bbpll_common_cfg();
xc_clock_bbpll_freq_cfg(cb->hfclk_src, 0x03, 0x01);
cpr_rf_reg3__mclk_src_sel__setf(CLOCK_SRC_BBPLL_DIV);
cb->hfclk_in = CLOCK_HFCLK_IN_48M;
cb->systick_unit = SYSTICK_UNIT_IN_48M;
}
/**
****************************************************************************************
* @brief xc_clock_set_osc32m_bbpll_64m
* @details osc32M Clock overclocked to 64M
* @param[in] CLOCK_InitCfg_t *cb
* @param[in]
* @param[out] void
* @retval void
****************************************************************************************
*/
void xc_clock_set_osc32m_bbpll_64m(CLOCK_InitCfg_t *cb)
{
xc_clock_bbpll_common_cfg();
xc_clock_bbpll_freq_cfg(cb->hfclk_src, 0x04, 0x01);
cpr_rf_reg3__mclk_src_sel__setf(CLOCK_SRC_BBPLL);
cb->hfclk_in = CLOCK_HFCLK_IN_64M;
cb->systick_unit = SYSTICK_UNIT_IN_64M;
}
/**
****************************************************************************************
* @brief xc_clock_set_osc32m_bbpll_96m
* @details osc32M Clock overclocked to 96M
* @param[in] CLOCK_InitCfg_t *cb
* @param[in]
* @param[out] void
* @retval void
****************************************************************************************
*/
void xc_clock_set_osc32m_bbpll_96m(CLOCK_InitCfg_t *cb)
{
xc_clock_bbpll_common_cfg();
xc_clock_bbpll_freq_cfg(cb->hfclk_src, 0x03, 0x01);
cpr_rf_reg3__mclk_src_sel__setf(CLOCK_SRC_BBPLL);
cb->hfclk_in = CLOCK_HFCLK_IN_96M;
cb->systick_unit = SYSTICK_UNIT_IN_96M;
}
/**
****************************************************************************************
* @brief xc_clock_hfclk_set
* @details High speed clock setting
* @param[in] CLOCK_HFCLK_Src_Typedef hfclk_src
* @param[in] CLOCK_HFCLK_In_Typedef hfclk_in
* @param[out] void
* @retval void
****************************************************************************************
*/
void xc_clock_hfclk_set(CLOCK_HFCLK_Src_Typedef hfclk_src,
CLOCK_HFCLK_In_Typedef hfclk_in)
{
uint32_t baudrate, uart_clk, div, mul, clk_ctl, adj_div, m0_fclk_div;
CLOCK_InitCfg_t *pclock_cb = &clock_cb;
pclock_cb->hfclk_src = hfclk_src;
switch (hfclk_src) {
case CLOCK_HFCLK_SRC_RC: {
if (CLOCK_HFCLK_IN_16M == hfclk_in) {
xc_clock_set_rc16m(pclock_cb);
} else if (CLOCK_HFCLK_IN_32M == hfclk_in) {
xc_clock_set_rc16m_bbpll_32m(pclock_cb);
} else if (CLOCK_HFCLK_IN_48M == hfclk_in) {
xc_clock_set_rc16m_bbpll_48m(pclock_cb);
} else if (CLOCK_HFCLK_IN_64M == hfclk_in) {
xc_clock_set_rc16m_bbpll_64m(pclock_cb);
} else if (CLOCK_HFCLK_IN_96M == hfclk_in) {
xc_clock_set_rc16m_bbpll_96m(pclock_cb);
}
} break;
case CLOCK_HFCLK_SRC_XTAL: {
// if(cpr_m0_fclk_ctl__m0_fclk_div__getf( )) {
// cpr_m0_fclk_ctl__m0_fclk_div_p__setf(0);
// cpr_m0_fclk_ctl__m0_fclk_direct_sw__setf(0x1);
// }
if (CLOCK_HFCLK_IN_16M == hfclk_in) {
xc_clock_set_osc32m_div_16m(pclock_cb);
} else if (CLOCK_HFCLK_IN_32M == hfclk_in) {
#if (CONFIG_HFCLK_IS_OSC32M_PLL_32M)
xc_clock_set_osc32m_bbpll_32m(pclock_cb);
#else
xc_clock_set_osc32m(pclock_cb);
#endif
} else if (CLOCK_HFCLK_IN_48M == hfclk_in) {
xc_clock_set_osc32m_bbpll_48m(pclock_cb);
} else if (CLOCK_HFCLK_IN_64M == hfclk_in) {
xc_clock_set_osc32m_bbpll_64m(pclock_cb);
} else if (CLOCK_HFCLK_IN_96M == hfclk_in) {
xc_clock_set_osc32m_bbpll_96m(pclock_cb);
}
} break;
}
m0_fclk_div = cpr_m0_fclk_ctl__m0_fclk_div__getf( );
uart_clk = xc_clock_hfclk_in_get() * (m0_fclk_div+1);
baudrate = cpr_uart0_clk_ctl_get();
mul = (baudrate >> 16) & 0xFFFF;
div = (baudrate & 0xFFFF);
adj_div = uart_clk / 1000000;
clk_ctl = (mul << 16) | (div * adj_div / 32);
cpr_uart0_clk_ctl_set(clk_ctl);
}
/**
****************************************************************************************
* @brief xc_clock_lfclk_set
* @details Low speed clock setting
* @param[in] CLOCK_LFCLK_Src_Typedef lfclk_src
* @param[in] CLOCK_LFCLK_In_Typedef lfclk_in
* @param[out] void
* @retval void
****************************************************************************************
*/
void xc_clock_lfclk_set(CLOCK_LFCLK_Src_Typedef lfclk_src,
CLOCK_LFCLK_In_Typedef lfclk_in)
{
clock_cb.lfclk_src = lfclk_src;
clock_cb.lfclk_in = lfclk_in;
if(lfclk_src == CLOCK_LFCLK_SRC_XTAL)
{
GPIO_InitCfg_t gpio_cfg = {0};
gpio_cfg.Mux = GPIO_Mux0;
gpio_cfg.FunSel = GPIO_Dx;
gpio_cfg.Dir = GPIO_DIR_INPUT;
gpio_cfg.Pull = GPIO_NOPULL;
gpio_cfg.Int = NOT_INT;
gpio_cfg.Pin = 20;
xc_gpio_init(&gpio_cfg);
gpio_cfg.Pin = 21;
xc_gpio_init(&gpio_cfg);
cprao_aon_xtl32k_val__xtl32k_v__setf(0x01);
cprao_aon_xtl32k_val__xtl32k_en__setf(ENABLE);
cprao_aon_ctl_clk32k__osc32k_sel__setf(2);
}
else if(lfclk_src == CLOCK_LFCLK_SRC_RC)
{
}
}
/**
****************************************************************************************
* @brief xc_clock_init_cfg
* @details Configure the clock initially
* @param[in] CLOCK_InitCfg_t *clock_cfg
* @param[out] void
* @retval void
****************************************************************************************
*/
void xc_clock_init_cfg(CLOCK_InitCfg_t *clock_cfg)
{
xc_clock_hfclk_set(clock_cfg->hfclk_src, clock_cfg->hfclk_in);
xc_clock_lfclk_set(clock_cfg->lfclk_src, clock_cfg->lfclk_in);
xc_pwr_vol_set();
}
/**
****************************************************************************************
* @brief xc_clock_hfclk_in_get
* @details Gets the current high speed clock ( system clock )
* @param[in]
* @param[out] void
* @retval clock_cb.hfclk_in
****************************************************************************************
*/
CLOCK_HFCLK_In_Typedef xc_clock_hfclk_in_get(void) { return clock_cb.hfclk_in; }
/**
****************************************************************************************
* @brief xc_clock_lfclk_in_get
* @details Gets the current low speed clock ( Low power clock )
* @param[in]
* @param[out] void
* @retval clock_cb.lfclk_in
****************************************************************************************
*/
CLOCK_LFCLK_In_Typedef xc_clock_lfclk_in_get(void) { return clock_cb.lfclk_in; }
/**
****************************************************************************************
* @brief xc_clock_hfclk_src_get
* @details Obtain the current high-speed source clock
* @param[in]
* @param[out] void
* @retval clock_cb.hfclk_src
****************************************************************************************
*/
CLOCK_HFCLK_Src_Typedef xc_clock_hfclk_src_get(void) { return clock_cb.hfclk_src; }
/**
****************************************************************************************
* @brief xc_clock_lfclk_src_get
* @details Obtain the current low-speed source clock
* @param[in]
* @param[out] void
* @retval clock_cb.lfclk_src
****************************************************************************************
*/
CLOCK_LFCLK_Src_Typedef xc_clock_lfclk_src_get(void) { return clock_cb.lfclk_src; }
/**
****************************************************************************************
* @brief xc_systick_unit_get
* @details Obtain the current systick unit
* @param[in]
* @param[out] void
* @retval clock_cb.lfclk_src
****************************************************************************************
*/
Systick_Unit_Typedef xc_systick_unit_get(void) { return clock_cb.systick_unit; }