519 lines
18 KiB
C
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; }
|