Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
da1469x/clock: Eliminate magic numbers
This commit replaces the magic numbers with meaningfully named constants.
  • Loading branch information
apc067 committed Oct 29, 2024
commit e818ba1b30da2ee2a0defafff19fa2f40227f8ad
4 changes: 2 additions & 2 deletions hw/mcu/dialog/da1469x/include/mcu/da1469x_clock.h
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ void da1469x_clock_lp_xtal32k_calibrate(void);
/**
* Calibrate RC32M
*/
void da1469x_clock_lp_rc32m_calibrate(void);
void da1469x_clock_sys_rc32m_calibrate(void);

/**
* Get calibrated (measured) RCX frequency
Expand All @@ -153,7 +153,7 @@ uint32_t da1469x_clock_lp_xtal32k_freq_get(void);
/**
* Get calibrated (measured) RC32M frequency
*/
uint32_t da1469x_clock_lp_rc32m_freq_get(void);
uint32_t da1469x_clock_sys_rc32m_freq_get(void);

/**
* Disable RCX
Expand Down
113 changes: 81 additions & 32 deletions hw/mcu/dialog/da1469x/src/da1469x_clock.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,53 @@

#define XTAL32M_FREQ 32000000
#define RC32M_FREQ 32000000
#define RC32M_FREQ_MIN 30600000
#define RC32M_FREQ_MAX 32600000
#define DIVN_FREQ 32000000 /* For CLK_CTRL_REG::SYS_CLK_SEL != 2 (LP clock) */
#define CAL_REF_FREQ DIVN_FREQ /* For CLK_REF_SEL_REG::CAL_CLK_SEL = 0 (DivN) */
#define PLL_FREQ 96000000
#define XTAL32K_FREQ 32768
#define XTALRDY_IRQ_FREQ 256000 /* For XTALRDY_CTRL_REG::XTALRDY_CLK_SEL = 1 (256 kHz) */

#define XTALRDY_IRQ_DIV (RC32M_FREQ / XTALRDY_IRQ_FREQ)
#define XTALRDY_IRQ_FREQ_MAX (RC32M_FREQ_MAX / XTALRDY_IRQ_DIV)

enum da1469x_sys_clk_sel {
DA1469X_SYS_XTAL32M = 0,
DA1469X_SYS_RC32M,
DA1469X_SYS_LP_CLK,
DA1469X_SYS_PLL96M,
};

enum da1469x_xtalrdy_clk_sel {
DA1469X_XTALRDY_CLK_32K = 0,
DA1469X_XTALRDY_CLK_256K,
};
#define DA1469X_XTALRDY_CLK_SEL DA1469X_XTALRDY_CLK_256K

enum da1469x_lp_clk_sel {
DA1469X_LP_RC32K = 0,
DA1469X_LP_RCX,
DA1469X_LP_XTAL32K,
DA1469X_LP_EXT,
};

enum da1469x_ref_sel {
DA1469X_REF_DIVN = 0,
DA1469X_REF_RC32M,
DA1469X_REF_RC32K,
DA1469X_REF_XTAL32K,
DA1469X_REF_RCOSC,
};
#define DA1469X_REF_SEL DA1469X_REF_DIVN

enum da1469x_calib_sel {
DA1469X_CALIB_RC32K = 0,
DA1469X_CALIB_RC32M,
DA1469X_CALIB_XTAL32K,
DA1469X_CALIB_RCX,
DA1469X_CALIB_RCOSC,
};

static uint32_t g_mcu_clock_rcx_freq;
static uint32_t g_mcu_clock_rc32k_freq;
Expand All @@ -42,27 +87,23 @@ uint32_t SystemCoreClock = RC32M_FREQ;
static inline bool
da1469x_clock_is_xtal32m_settled(void)
{
return ((*(uint32_t *)0x5001001c & 0xff00) == 0) &&
((*(uint32_t *)0x50010054 & 0x000f) != 0xb);
return ((CRG_XTAL->XTALRDY_STAT_REG & CRG_XTAL_XTALRDY_STAT_REG_XTALRDY_COUNT_Msk) == 0) &&
((CRG_XTAL->XTAL32M_STAT1_REG & CRG_XTAL_XTAL32M_STAT1_REG_XTAL32M_STATE_Msk) != 0xb);
}

void
da1469x_clock_sys_xtal32m_init(void)
{
uint32_t reg;
int xtalrdy_cnt;

/*
* Number of 256kHz clock cycles (~4.085us) assuming worst case when actual frequency is 244800.
* RC32M is in range <30.6, 32.6> so 256Khz can ba as low as 30.6MHz / 125 = 244.8kHz.
* Number of XTALRDY IRQ timer clock cycles making up the desired xtal settling time,
* sufficient even at maximum RC32M frequency.
*/
xtalrdy_cnt = MYNEWT_VAL(MCU_CLOCK_XTAL32M_SETTLE_TIME_US) * 1000 / 4085;
xtalrdy_cnt = MYNEWT_VAL(MCU_CLOCK_XTAL32M_SETTLE_TIME_US) * XTALRDY_IRQ_FREQ_MAX / 1000000;

reg = CRG_XTAL->XTALRDY_CTRL_REG;
reg &= ~(CRG_XTAL_XTALRDY_CTRL_REG_XTALRDY_CNT_Msk);
reg |= CRG_XTAL_XTALRDY_CTRL_REG_XTALRDY_CLK_SEL_Msk;
reg |= xtalrdy_cnt;
CRG_XTAL->XTALRDY_CTRL_REG = reg;
CRG_XTAL->XTALRDY_CTRL_REG = (xtalrdy_cnt << CRG_XTAL_XTALRDY_CTRL_REG_XTALRDY_CNT_Pos) |
(DA1469X_XTALRDY_CLK_SEL << CRG_XTAL_XTALRDY_CTRL_REG_XTALRDY_CLK_SEL_Pos);
}

void
Expand All @@ -88,7 +129,9 @@ da1469x_clock_sys_xtal32m_switch(void)
if (CRG_TOP->CLK_CTRL_REG & CRG_TOP_CLK_CTRL_REG_RUNNING_AT_RC32M_Msk) {
CRG_TOP->CLK_SWITCH2XTAL_REG = CRG_TOP_CLK_SWITCH2XTAL_REG_SWITCH2XTAL_Msk;
} else {
CRG_TOP->CLK_CTRL_REG &= ~CRG_TOP_CLK_CTRL_REG_SYS_CLK_SEL_Msk;
CRG_TOP->CLK_CTRL_REG = (CRG_TOP->CLK_CTRL_REG &
~CRG_TOP_CLK_CTRL_REG_SYS_CLK_SEL_Msk) |
(DA1469X_SYS_XTAL32M << CRG_TOP_CLK_CTRL_REG_SYS_CLK_SEL_Pos);
}

while (!(CRG_TOP->CLK_CTRL_REG & CRG_TOP_CLK_CTRL_REG_RUNNING_AT_XTAL32M_Msk));
Expand Down Expand Up @@ -141,7 +184,7 @@ da1469x_clock_sys_rc32m_switch(void)
{
CRG_TOP->CLK_CTRL_REG = (CRG_TOP->CLK_CTRL_REG &
~CRG_TOP_CLK_CTRL_REG_SYS_CLK_SEL_Msk) |
(1 << CRG_TOP_CLK_CTRL_REG_SYS_CLK_SEL_Pos);
(DA1469X_SYS_RC32M << CRG_TOP_CLK_CTRL_REG_SYS_CLK_SEL_Pos);

while (!(CRG_TOP->CLK_CTRL_REG & CRG_TOP_CLK_CTRL_REG_RUNNING_AT_RC32M_Msk));

Expand All @@ -165,7 +208,7 @@ da1469x_clock_lp_xtal32k_switch(void)
{
CRG_TOP->CLK_CTRL_REG = (CRG_TOP->CLK_CTRL_REG &
~CRG_TOP_CLK_CTRL_REG_LP_CLK_SEL_Msk) |
(2 << CRG_TOP_CLK_CTRL_REG_LP_CLK_SEL_Pos);
(DA1469X_LP_XTAL32K << CRG_TOP_CLK_CTRL_REG_LP_CLK_SEL_Pos);
/* If system is running on LP clock update SystemCoreClock */
if (CRG_TOP->CLK_CTRL_REG & CRG_TOP_CLK_CTRL_REG_RUNNING_AT_LP_CLK_Msk) {
SystemCoreClock = XTAL32K_FREQ;
Expand All @@ -189,7 +232,7 @@ da1469x_clock_lp_rc32k_switch(void)
{
CRG_TOP->CLK_CTRL_REG = (CRG_TOP->CLK_CTRL_REG &
~CRG_TOP_CLK_CTRL_REG_LP_CLK_SEL_Msk) |
(0 << CRG_TOP_CLK_CTRL_REG_LP_CLK_SEL_Pos);
(DA1469X_LP_RC32K << CRG_TOP_CLK_CTRL_REG_LP_CLK_SEL_Pos);

/* If system is running on LP clock update SystemCoreClock */
if (CRG_TOP->CLK_CTRL_REG & CRG_TOP_CLK_CTRL_REG_RUNNING_AT_LP_CLK_Msk) {
Expand All @@ -208,7 +251,7 @@ da1469x_clock_lp_rcx_switch(void)
{
CRG_TOP->CLK_CTRL_REG = (CRG_TOP->CLK_CTRL_REG &
~CRG_TOP_CLK_CTRL_REG_LP_CLK_SEL_Msk) |
(1 << CRG_TOP_CLK_CTRL_REG_LP_CLK_SEL_Pos);
(DA1469X_LP_RCX << CRG_TOP_CLK_CTRL_REG_LP_CLK_SEL_Pos);

/* If system is running on LP clock update SystemCoreClock */
if (CRG_TOP->CLK_CTRL_REG & CRG_TOP_CLK_CTRL_REG_RUNNING_AT_LP_CLK_Msk) {
Expand Down Expand Up @@ -238,23 +281,30 @@ da1469x_clock_calibrate(uint8_t clock_sel, uint16_t ref_cnt)
assert(!(ANAMISC_BIF->CLK_REF_SEL_REG & ANAMISC_BIF_CLK_REF_SEL_REG_REF_CAL_START_Msk));

ANAMISC_BIF->CLK_REF_CNT_REG = ref_cnt;
ANAMISC_BIF->CLK_REF_SEL_REG = (clock_sel << ANAMISC_BIF_CLK_REF_SEL_REG_REF_CLK_SEL_Pos) |
ANAMISC_BIF_CLK_REF_SEL_REG_REF_CAL_START_Msk;

/* Select reference clock & calibrated clock */
ANAMISC_BIF->CLK_REF_SEL_REG =
(DA1469X_REF_SEL << ANAMISC_BIF_CLK_REF_SEL_REG_CAL_CLK_SEL_Pos) |
(clock_sel << ANAMISC_BIF_CLK_REF_SEL_REG_REF_CLK_SEL_Pos);

/* Start measurement */
ANAMISC_BIF->CLK_REF_SEL_REG |= ANAMISC_BIF_CLK_REF_SEL_REG_REF_CAL_START_Msk;

/* Wait for meaurement to complete */
while (ANAMISC_BIF->CLK_REF_SEL_REG & ANAMISC_BIF_CLK_REF_SEL_REG_REF_CAL_START_Msk);

ref_val = ANAMISC_BIF->CLK_REF_VAL_REG;

da1469x_pd_release(MCU_PD_DOMAIN_PER);

return 32000000 * ref_cnt / ref_val;
return CAL_REF_FREQ * ref_cnt / ref_val;
}

void
da1469x_clock_lp_rcx_calibrate(void)
{
g_mcu_clock_rcx_freq =
da1469x_clock_calibrate(3, MYNEWT_VAL(MCU_CLOCK_RCX_CAL_REF_CNT));
da1469x_clock_calibrate(DA1469X_CALIB_RCX, MYNEWT_VAL(MCU_CLOCK_RCX_CAL_REF_CNT));
}

#define RC32K_TARGET_FREQ 32000
Expand Down Expand Up @@ -302,7 +352,7 @@ da1469x_clock_lp_rc32k_calibrate(void)
freq_prev = freq;
freq_delta_prev = freq_delta;

freq = da1469x_clock_calibrate(0, MYNEWT_VAL(MCU_CLOCK_RC32K_CAL_REF_CNT));
freq = da1469x_clock_calibrate(DA1469X_CALIB_RC32K, MYNEWT_VAL(MCU_CLOCK_RC32K_CAL_REF_CNT));

freq_delta = freq - RC32K_TARGET_FREQ;
freq_delta = (int32_t)freq_delta < 0 ? -freq_delta : freq_delta;
Expand Down Expand Up @@ -341,16 +391,17 @@ da1469x_clock_lp_xtal32k_calibrate(void)
{
#if MYNEWT_VAL(MCU_CLOCK_XTAL32K_ALLOW_CALIB)
g_mcu_clock_xtal32k_freq =
da1469x_clock_calibrate(2, MYNEWT_VAL(MCU_CLOCK_RCX_CAL_REF_CNT));
da1469x_clock_calibrate(DA1469X_CALIB_XTAL32K, MYNEWT_VAL(MCU_CLOCK_XTAL32K_CAL_REF_CNT));
#else
g_mcu_clock_xtal32k_freq = XTAL32K_FREQ;
#endif
}

void
da1469x_clock_lp_rc32m_calibrate(void)
da1469x_clock_sys_rc32m_calibrate(void)
{
g_mcu_clock_rc32m_freq = da1469x_clock_calibrate(1, 100);
g_mcu_clock_rc32m_freq = da1469x_clock_calibrate(DA1469X_CALIB_RC32M,
MYNEWT_VAL(MCU_CLOCK_RC32M_CAL_REF_CNT));
}

uint32_t
Expand Down Expand Up @@ -378,7 +429,7 @@ da1469x_clock_lp_xtal32k_freq_get(void)
}

uint32_t
da1469x_clock_lp_rc32m_freq_get(void)
da1469x_clock_sys_rc32m_freq_get(void)
{
assert(g_mcu_clock_rc32m_freq);

Expand All @@ -394,11 +445,8 @@ da1469x_clock_lp_rcx_disable(void)
static void
da1469x_delay_us(uint32_t delay_us)
{
/*
* SysTick runs on ~32 MHz clock while PLL is not started.
* so multiplying by 32 to convert from us to SysTicks.
*/
SysTick->LOAD = delay_us * 32;
/* Convert from us to SysTicks (PLL is not started yet) */
SysTick->LOAD = delay_us * XTAL32M_FREQ / 1000000;
SysTick->VAL = 0UL;
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_ENABLE_Msk;
while (0 == (SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk));
Expand Down Expand Up @@ -483,8 +531,9 @@ da1469x_clock_pll_wait_to_lock(void)
void
da1469x_clock_sys_pll_switch(void)
{
/* CLK_SEL_Msk == 3 means PLL */
CRG_TOP->CLK_CTRL_REG |= CRG_TOP_CLK_CTRL_REG_SYS_CLK_SEL_Msk;
CRG_TOP->CLK_CTRL_REG = (CRG_TOP->CLK_CTRL_REG &
~CRG_TOP_CLK_CTRL_REG_SYS_CLK_SEL_Msk) |
(DA1469X_SYS_PLL96M << CRG_TOP_CLK_CTRL_REG_SYS_CLK_SEL_Pos);

while (!(CRG_TOP->CLK_CTRL_REG & CRG_TOP_CLK_CTRL_REG_RUNNING_AT_PLL96M_Msk));

Expand Down
12 changes: 12 additions & 0 deletions hw/mcu/dialog/da1469x/syscfg.yml
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,18 @@ syscfg.defs:
value: 1
restrictions: '!0'

MCU_CLOCK_XTAL32K_CAL_REF_CNT:
description: >
Reference count value for calibration of XTAL32K clock.
value: 100
restrictions: '!0'

MCU_CLOCK_RC32M_CAL_REF_CNT:
description: >
Reference count value for calibration of RC32M clock.
value: 100
restrictions: '!0'

MCU_SYSCLK_SOURCE:
description: >
Specifies system clock source
Expand Down