[feat] update clock driver

This commit is contained in:
zhji 2025-05-11 22:30:39 +08:00
parent d5f776d614
commit 2d11df7c38
7 changed files with 415 additions and 415 deletions

View File

@ -52,12 +52,11 @@ void SystemCoreClockUpdate (void)
void __attribute__((constructor)) SystemInit (void) void __attribute__((constructor)) SystemInit (void)
{ {
system_regulator_set(SYSTEM_REGULATOR_VOLTAGE_1P30V); system_regulator_set(SYSTEM_REGULATOR_VOLTAGE_1P30V);
clock_ref_set_src(CLOCK_REF_SRC_XOSC_GLITCHLESS); clock_ref_set(CLOCK_REF_SRC_XOSC_GLITCHLESS, 1);
clock_sys_set_src(CLOCK_SYS_SRC_REF_GLITCHLESS); clock_sys_set(CLOCK_SYS_SRC_REF_GLITCHLESS, 1);
/* refdiv >= 5MHz, VCO=[750:1600]MHz, fbdiv=[16:320], postdiv=[1:7] */ /* refdiv >= 5MHz, VCO=[750:1600]MHz, fbdiv=[16:320], postdiv=[1:7] */
clock_pll_init(CLOCK_PLL_SYSPLL, 1, 100, 3, 2); /* 12MHz / 1 * 100 / 3 / 2 = 200MHz */ clock_syspll_init(1, 100, 3, 2); /* 12MHz / 1 * 100 / 3 / 2 = 200MHz */
clock_sys_set_div(1 << 8); /* 200MHz / 1 = 200MHz */ clock_sys_set(CLOCK_SYS_SRC_SYSPLL, 1); /* 200MHz / 1 = 200MHz */
clock_sys_set_src(CLOCK_SYS_SRC_SYSPLL);
clock_peri_set(ENABLE, CLOCK_PERI_SRC_SYSPLL); clock_peri_set(ENABLE, CLOCK_PERI_SRC_SYSPLL);
SystemCoreClockUpdate(); SystemCoreClockUpdate();

View File

@ -19,10 +19,6 @@
#define CLOCK_XOSC_STATUS_BADWRITE (24) #define CLOCK_XOSC_STATUS_BADWRITE (24)
#define CLOCK_XOSC_STATUS_STABLE (31) #define CLOCK_XOSC_STATUS_STABLE (31)
/* PLL type */
#define CLOCK_PLL_SYSPLL (0)
#define CLOCK_PLL_USBPLL (1)
/* clock instance */ /* clock instance */
#define CLOCK_GPOUT0 (0) #define CLOCK_GPOUT0 (0)
#define CLOCK_GPOUT1 (1) #define CLOCK_GPOUT1 (1)
@ -36,53 +32,17 @@
#define CLOCK_RTC (9) #define CLOCK_RTC (9)
/* clock source */ /* clock source */
#define CLOCK_GPOUT0_SRC_SYSPLL (0) #define CLOCK_GPOUT_SRC_SYSPLL (0)
#define CLOCK_GPOUT0_SRC_GPIN0 (1) #define CLOCK_GPOUT_SRC_GPIN0 (1)
#define CLOCK_GPOUT0_SRC_GPIN1 (2) #define CLOCK_GPOUT_SRC_GPIN1 (2)
#define CLOCK_GPOUT0_SRC_USBPLL (3) #define CLOCK_GPOUT_SRC_USBPLL (3)
#define CLOCK_GPOUT0_SRC_ROSC (4) #define CLOCK_GPOUT_SRC_ROSC (4)
#define CLOCK_GPOUT0_SRC_XOSC (5) #define CLOCK_GPOUT_SRC_XOSC (5)
#define CLOCK_GPOUT0_SRC_SYS (6) #define CLOCK_GPOUT_SRC_SYS (6)
#define CLOCK_GPOUT0_SRC_USB (7) #define CLOCK_GPOUT_SRC_USB (7)
#define CLOCK_GPOUT0_SRC_ADC (8) #define CLOCK_GPOUT_SRC_ADC (8)
#define CLOCK_GPOUT0_SRC_RTC (9) #define CLOCK_GPOUT_SRC_RTC (9)
#define CLOCK_GPOUT0_SRC_REF (10) #define CLOCK_GPOUT_SRC_REF (10)
#define CLOCK_GPOUT1_SRC_SYSPLL (0)
#define CLOCK_GPOUT1_SRC_GPIN0 (1)
#define CLOCK_GPOUT1_SRC_GPIN1 (2)
#define CLOCK_GPOUT1_SRC_USBPLL (3)
#define CLOCK_GPOUT1_SRC_ROSC (4)
#define CLOCK_GPOUT1_SRC_XOSC (5)
#define CLOCK_GPOUT1_SRC_SYS (6)
#define CLOCK_GPOUT1_SRC_USB (7)
#define CLOCK_GPOUT1_SRC_ADC (8)
#define CLOCK_GPOUT1_SRC_RTC (9)
#define CLOCK_GPOUT1_SRC_REF (10)
#define CLOCK_GPOUT2_SRC_SYSPLL (0)
#define CLOCK_GPOUT2_SRC_GPIN0 (1)
#define CLOCK_GPOUT2_SRC_GPIN1 (2)
#define CLOCK_GPOUT2_SRC_USBPLL (3)
#define CLOCK_GPOUT2_SRC_ROSC_PH (4)
#define CLOCK_GPOUT2_SRC_XOSC (5)
#define CLOCK_GPOUT2_SRC_SYS (6)
#define CLOCK_GPOUT2_SRC_USB (7)
#define CLOCK_GPOUT2_SRC_ADC (8)
#define CLOCK_GPOUT2_SRC_RTC (9)
#define CLOCK_GPOUT2_SRC_REF (10)
#define CLOCK_GPOUT3_SRC_SYSPLL (0)
#define CLOCK_GPOUT3_SRC_GPIN0 (1)
#define CLOCK_GPOUT3_SRC_GPIN1 (2)
#define CLOCK_GPOUT3_SRC_USBPLL (3)
#define CLOCK_GPOUT3_SRC_ROSC_PH (4)
#define CLOCK_GPOUT3_SRC_XOSC (5)
#define CLOCK_GPOUT3_SRC_SYS (6)
#define CLOCK_GPOUT3_SRC_USB (7)
#define CLOCK_GPOUT3_SRC_ADC (8)
#define CLOCK_GPOUT3_SRC_RTC (9)
#define CLOCK_GPOUT3_SRC_REF (10)
#define CLOCK_REF_SRC_USBPLL (0) #define CLOCK_REF_SRC_USBPLL (0)
#define CLOCK_REF_SRC_GPIN0 (1) #define CLOCK_REF_SRC_GPIN0 (1)
@ -159,25 +119,20 @@ void clock_xosc_set_startup_delay(uint32_t cycle);
void clock_xosc_set_count(uint8_t count); void clock_xosc_set_count(uint8_t count);
uint8_t clock_xosc_get_count(void); uint8_t clock_xosc_get_count(void);
/* PLL function */ /* pll function */
void clock_pll_init(uint8_t pll, uint8_t refdiv, uint8_t fbdiv, uint8_t postdiv1, uint8_t postdiv2); void clock_syspll_init(uint8_t refdiv, uint16_t feedback, uint8_t postdiv1, uint8_t postdiv2);
void clock_pll_deinit(uint8_t pll); void clock_usbpll_init(uint8_t refdiv, uint16_t feedback, uint8_t postdiv1, uint8_t postdiv2);
void clock_syspll_deinit(void);
void clock_usbpll_deinit(void);
/* CLOCK function */ /* clock function */
void clock_gpout_set(uint8_t id, uint8_t enable, uint8_t src, uint32_t div, uint8_t dc50, uint8_t phase, uint8_t nudge); void clock_gpout_set(uint8_t id, uint8_t enable, uint8_t src, uint32_t div); /* div is 1~16777215 */
uint32_t clock_ref_get_selected(void); void clock_ref_set(uint8_t src, uint32_t div); /* div is 1~3 */
void clock_ref_set_src(uint8_t src); void clock_sys_set(uint8_t src, uint32_t div); /* div is 1~16777215 */
void clock_ref_set_div(uint32_t div);
uint32_t clock_sys_get_selected(void);
void clock_sys_set_src(uint8_t src);
void clock_sys_set_div(uint32_t div);
void clock_peri_set(uint8_t enable, uint8_t src); void clock_peri_set(uint8_t enable, uint8_t src);
void clock_usb_set(uint8_t enable, uint8_t src, uint32_t div, uint8_t phase, uint8_t nudge); void clock_usb_set(uint8_t enable, uint8_t src, uint32_t div); /* div is 1~3 */
void clock_adc_set(uint8_t enable, uint8_t src, uint32_t div, uint8_t phase, uint8_t nudge); void clock_adc_set(uint8_t enable, uint8_t src, uint32_t div); /* div is 1~3 */
void clock_rtc_set(uint8_t enable, uint8_t src, uint32_t div, uint8_t phase, uint8_t nudge); void clock_rtc_set(uint8_t enable, uint8_t src, uint32_t div); /* div is 1~16777215 */
void clock_enable(uint8_t clock);
void clock_disable(uint8_t clock);
void clock_kill(uint8_t clock);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -3,6 +3,29 @@
#include "reg.h" #include "reg.h"
struct fw_header_s {
uint32_t size;
uint32_t jump_address;
/* syspll config */
uint8_t syspll_refdiv; /* must be in 1~63, fref/refdiv must >= 5MHz */
uint8_t syspll_feedback; /* must be in 16~320, fvco must be in 750MHz~1600MHz */
uint8_t syspll_postdiv1; /* must be in 1~7 */
uint8_t syspll_postdiv2; /* must be in 1~7 */
/* usbpll config */
uint8_t usbpll_refdiv; /* must be in 1~63, fref/refdiv must >= 5MHz */
uint8_t usbpll_feedback; /* must be in 16~320, fvco must be in 750MHz~1600MHz */
uint8_t usbpll_postdiv1; /* must be in 1~7 */
uint8_t usbpll_postdiv2; /* must be in 1~7 */
/* system clock div */
uint32_t sysclk_div; /* 1~2^24-1 is available */
/* flash config */
uint16_t flash_div; /* 0 is for disable, 2~65534 is available, must be even value */
uint16_t flash_resv;
uint32_t resv;
/* checksum */
uint32_t checksum;
};
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif

View File

@ -81,38 +81,116 @@
#define CLOCK_XOSC_STARTUP_DELAY_MASK (0x3FFF) #define CLOCK_XOSC_STARTUP_DELAY_MASK (0x3FFF)
#define CLOCK_XOSC_STARTUP_X4_POS (20) #define CLOCK_XOSC_STARTUP_X4_POS (20)
/* CLOCK_PLL_CS_OFFSET */ /* CLOCK_PLL_CS_OFFSET @ 0x000 */
#define CLOCK_PLL_REFDIV_POS (0) #define CLOCK_PLL_CS_REFDIV_POS (0)
#define CLOCK_PLL_REFDIV_MASK (0x3F) #define CLOCK_PLL_CS_REFDIV_MASK (0x3F << CLOCK_PLL_CS_REFDIV_POS)
#define CLOCK_PLL_BYPASS_POS (8) #define CLOCK_PLL_CS_BYPASS (1 << 8U)
#define CLOCK_PLL_LOCK_POS (31) #define CLOCK_PLL_CS_LOCK (1 << 31U)
/* CLOCK_PLL_PWR_OFFSET */ /* CLOCK_PLL_PWR_OFFSET @ 0x004 */
#define CLOCK_PLL_PD_POS (0) #define CLOCK_PLL_PWR_PD (1 << 0U)
#define CLOCK_PLL_DSMPD_POS (2) #define CLOCK_PLL_PWR_DSMPD (1 << 2U)
#define CLOCK_PLL_POSTDIVPD_POS (3) #define CLOCK_PLL_PWR_POSTDIVPD (1 << 3U)
#define CLOCK_PLL_VCOPD_POS (5) #define CLOCK_PLL_PWR_VCOPD (1 << 5U)
#define CLOCK_PLL_PWR_MASK ((1 << CLOCK_PLL_PD_POS) | \
(1 << CLOCK_PLL_DSMPD_POS) | \
(1 << CLOCK_PLL_POSTDIVPD_POS) | \
(1 << CLOCK_PLL_VCOPD_POS))
/* CLOCK_PLL_PRIM_OFFSET */
#define CLOCK_PLL_POSTDIV2_POS (12)
#define CLOCK_PLL_POSTDIV2_MASK (0x7)
#define CLOCK_PLL_POSTDIV1_POS (16)
#define CLOCK_PLL_POSTDIV1_MASK (0x7)
/* CLOCK_CTRL_OFFSET */ /* CLOCK_PLL_PRIM_OFFSET @ 0x00C */
#define CLOCK_SRC_POS (0) #define CLOCK_PLL_PRIM_POSTDIV2_POS (12U)
#define CLOCK_SRC_MASK (0x3) #define CLOCK_PLL_PRIM_POSTDIV2_MASK (0x7 << CLOCK_PLL_PRIM_POSTDIV2_POS)
#define CLOCK_AUXSRC_POS (5) #define CLOCK_PLL_PRIM_POSTDIV1_POS (16U)
#define CLOCK_AUXSRC_MASK (0xF) #define CLOCK_PLL_PRIM_POSTDIV1_MASK (0x7 << CLOCK_PLL_PRIM_POSTDIV1_POS)
#define CLOCK_KILL_POS (10)
#define CLOCK_ENABLE_POS (11) /* CLOCK_CTRL_OFFSET @ 0x000 */
#define CLOCK_DC50_POS (12) #define CLOCK_CTRL_SRC_POS (0U)
#define CLOCK_PHASE_POS (16) #define CLOCK_CTRL_AUXSRC_POS (5U)
#define CLOCK_PHASE_MASK (0x3) #define CLOCK_CTRL_KILL (1 << 10U)
#define CLOCK_NUDGE_POS (20) #define CLOCK_CTRL_ENABLE (1 << 11U)
#define CLOCK_CTRL_DC50 (1 << 12U)
#define CLOCK_CTRL_PHASE_POS (16U)
#define CLOCK_CTRL_NUDGE (1 << 20U)
/* CLOCK_DIV_OFFSET @0x004 */
#define CLOCK_DIV_FRAC_POS (0U)
#define CLOCK_DIV_INT_POS (8U)
typedef struct {
io_rw_32 ctrl;
io_rw_32 div;
io_rw_32 selected;
} clock_hw_t;
typedef struct {
io_rw_32 ref_khz;
io_rw_32 min_khz;
io_rw_32 max_khz;
io_rw_32 delay;
io_rw_32 interval;
io_rw_32 src;
io_ro_32 status;
io_ro_32 result;
} fc_hw_t;
typedef struct {
clock_hw_t clk[10];
struct {
io_rw_32 ctrl;
io_rw_32 status;
} resus;
fc_hw_t fc0;
io_rw_32 wake_en0;
io_rw_32 wake_en1;
io_rw_32 sleep_en0;
io_rw_32 sleep_en1;
io_rw_32 enabled0;
io_rw_32 enabled1;
io_rw_32 intr;
io_rw_32 inte;
io_rw_32 intf;
io_rw_32 ints;
} clocks_hw_t;
#define clocks_hw ((clocks_hw_t *const)CLOCKS_BASE)
#define clocks_hw_set ((clocks_hw *const)hw_set_alias_untyped(clocks_hw))
#define clocks_hw_clear ((clocks_hw *const)hw_clear_alias_untyped(clocks_hw))
typedef struct {
io_rw_32 cs;
io_rw_32 pwr;
io_rw_32 fbdiv_int;
io_rw_32 prim;
} pll_hw_t;
#define pll_sys_hw ((pll_hw_t *const)PLL_SYS_BASE)
#define pll_sys_hw_set ((pll_sys_hw *const)hw_set_alias_untyped(pll_sys_hw))
#define pll_sys_hw_clear ((pll_sys_hw *const)hw_clear_alias_untyped(pll_sys_hw))
#define pll_usb_hw ((pll_hw_t *const)PLL_USB_BASE)
#define pll_usb_hw_set ((pll_usb_hw *const)hw_set_alias_untyped(pll_usb_hw))
#define pll_usb_hw_clear ((pll_usb_hw *const)hw_clear_alias_untyped(pll_usb_hw))
typedef struct {
io_rw_32 ctrl;
io_rw_32 freqa;
io_rw_32 freqb;
io_rw_32 dormant;
io_rw_32 div;
io_rw_32 phase;
io_rw_32 status;
io_rw_32 randombit;
io_rw_32 count;
io_rw_32 dftx;
} rosc_hw_t;
#define rosc_hw ((rosc_hw_t *const)ROSC_BASE)
typedef struct {
io_rw_32 ctrl;
io_rw_32 status;
io_rw_32 dormant;
io_rw_32 startup;
io_rw_32 _reserved[3];
io_rw_32 count;
} xosc_hw_t;
#define xosc_hw ((xosc_hw_t *const)XOSC_BASE)
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {

View File

@ -36,6 +36,30 @@
#define SYSTEM_BLOCK_PROC0 (1 << 15) #define SYSTEM_BLOCK_PROC0 (1 << 15)
#define SYSTEM_BLOCK_PROC1 (1 << 16) #define SYSTEM_BLOCK_PROC1 (1 << 16)
#define SYSTEM_CLOCK_REF_XOSC_8MHZ (0)
#define SYSTEM_CLOCK_REF_XOSC_12MHZ (1)
#define SYSTEM_CLOCK_REF_XOSC_24MHZ (2)
#define SYSTEM_CLOCK_REF_XOSC_32MHZ (3)
#define SYSTEM_CLOCK_REF_XOSC_40MHZ (4)
#define SYSTEM_CLOCK_REF_XOSC_50MHZ (5)
#define SYSTEM_CLOCK_REF_XOSC_MHZ_COUNT (6)
#define SYSTEM_CLOCK_FREQ_48MHZ (0)
#define SYSTEM_CLOCK_FREQ_96MHZ (1)
#define SYSTEM_CLOCK_FREQ_100MHZ (2)
#define SYSTEM_CLOCK_FREQ_120MHZ (2)
#define SYSTEM_CLOCK_FREQ_125MHZ (3)
#define SYSTEM_CLOCK_FREQ_144MHZ (4)
#define SYSTEM_CLOCK_FREQ_150MHZ (5)
#define SYSTEM_CLOCK_FREQ_192MHZ (6)
#define SYSTEM_CLOCK_FREQ_200MHZ (7)
#define SYSTEM_CLOCK_FREQ_240MHZ (8)
#define SYSTEM_CLOCK_FREQ_250MHZ (9)
#define SYSTEM_CLOCK_FREQ_320MHZ (10)
#define SYSTEM_CLOCK_FREQ_384MHZ (11)
#define SYSTEM_CLOCK_FREQ_400MHZ (12)
#define SYSTEM_CLOCK_FREQ_MHZ_COUNT (13)
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@ -50,6 +74,7 @@ void system_wdg_unbound(uint32_t block);
uint8_t system_block_is_available(uint32_t block); uint8_t system_block_is_available(uint32_t block);
void system_init(void); void system_init(void);
void system_clock_config(uint8_t ref_xosc, uint8_t sys_freq);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -273,371 +273,190 @@ uint8_t clock_xosc_get_count(void)
return (uint8_t)getreg32(XOSC_BASE + CLOCK_XOSC_COUNT_OFFSET); return (uint8_t)getreg32(XOSC_BASE + CLOCK_XOSC_COUNT_OFFSET);
} }
void clock_pll_init(uint8_t pll, uint8_t refdiv, uint8_t fbdiv, uint8_t postdiv1, uint8_t postdiv2) /******************************** PLL *********************************/
static void pll_init(pll_hw_t *pll, uint8_t refdiv, uint16_t feedback, uint8_t postdiv1, uint8_t postdiv2)
{ {
uint32_t addr; /* load VCO-related dividers before starting VCO */
uint32_t val; if (refdiv == 0) {
refdiv = 1;
if (pll == CLOCK_PLL_SYSPLL) { } else if (refdiv > 63) {
reset_unreset_blocks_wait(RESETS_BLOCK_SYSPLL); refdiv = 63;
addr = PLL_SYS_BASE;
} else if (pll == CLOCK_PLL_USBPLL) {
reset_unreset_blocks_wait(RESETS_BLOCK_USBPLL);
addr = PLL_USB_BASE;
} else {
return;
} }
/* Load VCO-related dividers before starting VCO */ pll->cs = refdiv;
putreg32((uint32_t)refdiv, addr + CLOCK_PLL_CS_OFFSET); if (feedback == 0) {
putreg32((uint32_t)fbdiv, addr + CLOCK_PLL_FBDIV_INT_OFFSET); feedback = 1;
/* Turn on PLL */ } else if (feedback > 4095) {
val = (1 << CLOCK_PLL_PD_POS) | (1 << CLOCK_PLL_VCOPD_POS); feedback = 4095;
putreg32(val, addr + CLOCK_PLL_PWR_OFFSET + REG_ALIAS_CLR_BITS);
/* Wait for PLL to lock */
while (1) {
val = getreg32(addr + CLOCK_PLL_CS_OFFSET);
val &= (1 << CLOCK_PLL_LOCK_POS);
if (val) {
break;
}
} }
/* Set up post dividers */ pll->fbdiv_int = feedback;
val = (postdiv1 << CLOCK_PLL_POSTDIV1_POS) | (postdiv2 << CLOCK_PLL_POSTDIV2_POS); /* turn on PLL, write 0 for release power down */
putreg32(val, addr + CLOCK_PLL_PRIM_OFFSET); pll->pwr = CLOCK_PLL_PWR_POSTDIVPD | CLOCK_PLL_PWR_DSMPD;
/* Turn on post divider */ /* wait for PLL to lock */
putreg32(1 << CLOCK_PLL_POSTDIVPD_POS, addr + CLOCK_PLL_PWR_OFFSET + REG_ALIAS_CLR_BITS); while (!(pll->cs & CLOCK_PLL_CS_LOCK));
/* set up post dividers */
if (postdiv1 == 0) {
postdiv1 = 1;
} else if (postdiv1 > 7) {
postdiv1 = 7;
}
if (postdiv2 == 0) {
postdiv2 = 1;
} else if (postdiv2 > 7) {
postdiv2 = 7;
}
pll->prim = (postdiv1 << CLOCK_PLL_PRIM_POSTDIV1_POS) | (postdiv2 << CLOCK_PLL_PRIM_POSTDIV2_POS);
/* turn on post divider */
pll->pwr = 0;
} }
void clock_pll_deinit(uint8_t pll) void clock_syspll_init(uint8_t refdiv, uint16_t feedback, uint8_t postdiv1, uint8_t postdiv2)
{ {
if (pll == CLOCK_PLL_SYSPLL) { reset_unreset_blocks_wait(RESETS_BLOCK_SYSPLL);
reset_unreset_blocks_wait(RESETS_BLOCK_SYSPLL); pll_init(pll_sys_hw, refdiv, feedback, postdiv1, postdiv2);
putreg32(CLOCK_PLL_PWR_MASK, PLL_SYS_BASE + CLOCK_PLL_PWR_OFFSET);
} else if (pll == CLOCK_PLL_USBPLL) {
reset_unreset_blocks_wait(RESETS_BLOCK_USBPLL);
putreg32(CLOCK_PLL_PWR_MASK, PLL_USB_BASE + CLOCK_PLL_PWR_OFFSET);
}
} }
/* id: 0 ~ 3 */ void clock_usbpll_init(uint8_t refdiv, uint16_t feedback, uint8_t postdiv1, uint8_t postdiv2)
/* div[31:8]: Integer component of the divisor, 0 is for 2^24 */ {
/* div[ 7:0]: Fractional component of the divisor */ reset_unreset_blocks_wait(RESETS_BLOCK_USBPLL);
/* phase: 0 ~ 3 */ pll_init(pll_usb_hw, refdiv, feedback, postdiv1, postdiv2);
void clock_gpout_set(uint8_t id, uint8_t enable, uint8_t src, uint32_t div, uint8_t dc50, uint8_t phase, uint8_t nudge) }
void clock_syspll_deinit(void)
{
reset_unreset_blocks_wait(RESETS_BLOCK_SYSPLL);
}
void clock_usbpll_deinit(void)
{
reset_unreset_blocks_wait(RESETS_BLOCK_USBPLL);
}
void clock_gpout_set(uint8_t id, uint8_t enable, uint8_t src, uint32_t div)
{ {
uint32_t addr;
uint32_t val; uint32_t val;
/* step1: disable clock */ div = (div > 0xFFFFFF) ? 0xFFFFFF : div;
addr = CLOCKS_BASE + CLOCK_GPOUT0_CTRL_OFFSET + id * 0xC; div = div << CLOCK_DIV_INT_POS;
putreg32(1 << CLOCK_ENABLE_POS, addr + REG_ALIAS_CLR_BITS); val = ((uint32_t)src << CLOCK_CTRL_AUXSRC_POS) | CLOCK_CTRL_DC50;
clocks_hw->clk[CLOCK_GPOUT0 + id].ctrl = val;
/* step2: config ctrl register */ clocks_hw->clk[CLOCK_GPOUT0 + id].div = div;
val = getreg32(addr);
/* config clock source */
val &= ~(CLOCK_AUXSRC_MASK << CLOCK_AUXSRC_POS);
val |= ((src & CLOCK_AUXSRC_MASK) << CLOCK_AUXSRC_POS);
/* config duty cycle correction for odd divisors */
if (dc50) {
val |= 1 << CLOCK_DC50_POS;
} else {
val &= ~(1 << CLOCK_DC50_POS);
}
/* config delay phase up to 3 cycles of the input clock */
val &= ~(CLOCK_PHASE_MASK << CLOCK_PHASE_POS);
val |= ((phase & CLOCK_PHASE_MASK) << CLOCK_PHASE_POS);
/* config signal shifts the phase of the output by 1 cycle of the input clock */
if (nudge) {
val |= 1 << CLOCK_NUDGE_POS;
} else {
val &= ~(1 << CLOCK_NUDGE_POS);
}
/* disable clock */
val &= ~(1 << CLOCK_ENABLE_POS);
putreg32(val, addr);
/* step3: config div */
putreg32(div, CLOCKS_BASE + CLOCK_GPOUT0_DIV_OFFSET + id * 0xC);
/* step4: config enable */
if (enable) { if (enable) {
putreg32(1 << CLOCK_ENABLE_POS, addr + REG_ALIAS_SET_BITS); val |= CLOCK_CTRL_ENABLE;
clocks_hw->clk[CLOCK_GPOUT0 + id].ctrl = val;
} }
} }
uint32_t clock_ref_get_selected(void) void clock_ref_set(uint8_t src, uint32_t div)
{ {
return getreg32(CLOCKS_BASE + CLOCK_REF_SELECTED_OFFSET);
}
void clock_ref_set_src(uint8_t src)
{
uint32_t addr;
uint32_t val; uint32_t val;
addr = CLOCKS_BASE + CLOCK_REF_CTRL_OFFSET; div = (div > 3) ? 3 : div;
div = div << CLOCK_DIV_INT_POS;
if (div > clocks_hw->clk[CLOCK_REF].div) {
clocks_hw->clk[CLOCK_REF].div = div;
}
if (src == CLOCK_REF_SRC_ROSC_PH_GLITCHLESS) { if (src == CLOCK_REF_SRC_ROSC_PH_GLITCHLESS) {
/* switch to the glitchless mux */
clock_rosc_enable(); clock_rosc_enable();
/* step1: switch the glitchless mux to an alternate source */ clocks_hw->clk[CLOCK_REF].ctrl = 0;
putreg32(0, addr); while (!(clocks_hw->clk[CLOCK_REF].selected & (1u << 0)));
/* step2: poll the SELECTED register until the switch is completed */
while (1) {
if (clock_ref_get_selected() & (1 << 0)) {
break;
}
}
} else if (src == CLOCK_REF_SRC_XOSC_GLITCHLESS) { } else if (src == CLOCK_REF_SRC_XOSC_GLITCHLESS) {
/* switch to the glitchless mux */
clock_xosc_enable(); clock_xosc_enable();
/* step1: switch the glitchless mux to an alternate source */ clocks_hw->clk[CLOCK_REF].ctrl = 2;
putreg32(2, addr); while (!(clocks_hw->clk[CLOCK_REF].selected & (1u << 2)));
/* step2: poll the SELECTED register until the switch is completed */
while (1) {
if (clock_ref_get_selected() & (1 << 2)) {
break;
}
}
} else { } else {
/* switch to the auxiliary mux when the generator has a glitchless mux */
clock_rosc_enable(); clock_rosc_enable();
/* step1: switch the glitchless mux to a source that isnt the aux mux */ clocks_hw->clk[CLOCK_REF].ctrl = 0;
putreg32(0, addr); while (!(clocks_hw->clk[CLOCK_REF].selected & (1u << 0)));
/* step2: poll the SELECTED register until the switch is completed */ val = (uint32_t)src << CLOCK_CTRL_AUXSRC_POS;
while (1) { clocks_hw->clk[CLOCK_REF].ctrl = val;
if (clock_ref_get_selected() & (1 << 0)) { val |= (1u << CLOCK_CTRL_SRC_POS);
break; clocks_hw->clk[CLOCK_REF].ctrl = val;
} while (!(clocks_hw->clk[CLOCK_REF].selected & (1u << 1)));
} }
/* step3: change the auxiliary mux select control */ if (div < clocks_hw->clk[CLOCK_REF].div) {
val = (uint32_t)src << CLOCK_AUXSRC_POS; clocks_hw->clk[CLOCK_REF].div = div;
putreg32(val, addr);
/* step4: switch the glitchless mux back to the aux mux */
val |= 1;
putreg32(val, addr);
/* step5: if required, poll the SELECTED register until the switch is completed */
while (1) {
if (clock_ref_get_selected() & (1 << 1)) {
break;
}
}
} }
} }
/* div[9:8]: Integer component of the divisor, 0 is for 2^2 */ void clock_sys_set(uint8_t src, uint32_t div)
/* div[7:0]: reserved */
void clock_ref_set_div(uint32_t div)
{ {
putreg32(div, CLOCKS_BASE + CLOCK_REF_DIV_OFFSET);
}
uint32_t clock_sys_get_selected(void)
{
return getreg32(CLOCKS_BASE + CLOCK_SYS_SELECTED_OFFSET);
}
/* must: call clock_ref_set_src brfore call clock_sys_set_src */
void clock_sys_set_src(uint8_t src)
{
uint32_t addr;
uint32_t val; uint32_t val;
addr = CLOCKS_BASE + CLOCK_SYS_CTRL_OFFSET; div = (div > 0xFFFFFF) ? 0xFFFFFF : div;
if (src == CLOCK_SYS_SRC_REF_GLITCHLESS) { div = div << CLOCK_DIV_INT_POS;
/* switch to the glitchless mux */ if (div > clocks_hw->clk[CLOCK_SYS].div) {
/* step1: switch the glitchless mux to an alternate source */ clocks_hw->clk[CLOCK_SYS].div = div;
putreg32(0, addr); }
/* step2: poll the SELECTED register until the switch is completed */ if (src == CLOCK_SYS_SRC_REF_GLITCHLESS) {
while (1) { clocks_hw->clk[CLOCK_SYS].ctrl = 0;
if (clock_sys_get_selected() & (1 << 0)) { while (!(clocks_hw->clk[CLOCK_SYS].selected & (1u << 0)));
break; } else {
} clocks_hw->clk[CLOCK_SYS].ctrl = 0;
} while (!(clocks_hw->clk[CLOCK_SYS].selected & (1u << 0)));
} else { val = (uint32_t)src << CLOCK_CTRL_AUXSRC_POS;
/* switch to the auxiliary mux when the generator has a glitchless mux */ clocks_hw->clk[CLOCK_SYS].ctrl = val;
/* step1: switch the glitchless mux to a source that isnt the aux mux */ val |= (1u << CLOCK_CTRL_SRC_POS);
putreg32(0, addr); clocks_hw->clk[CLOCK_SYS].ctrl = val;
/* step2: poll the SELECTED register until the switch is completed */ while (!(clocks_hw->clk[CLOCK_SYS].selected & (1u << 1)));
while (1) { }
if (clock_sys_get_selected() & (1 << 0)) { if (div < clocks_hw->clk[CLOCK_SYS].div) {
break; clocks_hw->clk[CLOCK_SYS].div = div;
}
}
/* step3: change the auxiliary mux select control */
val = (uint32_t)src << CLOCK_AUXSRC_POS;
putreg32(val, addr);
/* step4: switch the glitchless mux back to the aux mux */
val |= 1;
putreg32(val, addr);
/* step5: if required, poll the SELECTED register until the switch is completed */
while (1) {
if (clock_sys_get_selected() & (1 << 1)) {
break;
}
}
} }
}
/* div[31:8]: Integer component of the divisor, 0 is for 2^24 */
/* div[ 7:0]: Fractional component of the divisor */
void clock_sys_set_div(uint32_t div)
{
putreg32(div, CLOCKS_BASE + CLOCK_SYS_DIV_OFFSET);
} }
void clock_peri_set(uint8_t enable, uint8_t src) void clock_peri_set(uint8_t enable, uint8_t src)
{ {
uint32_t addr;
uint32_t val; uint32_t val;
/* step1: disable clock */ val = (uint32_t)src << CLOCK_CTRL_AUXSRC_POS;
addr = CLOCKS_BASE + CLOCK_PERI_CTRL_OFFSET; clocks_hw->clk[CLOCK_PERI].ctrl = val;
putreg32(1 << CLOCK_ENABLE_POS, addr + REG_ALIAS_CLR_BITS);
/* step2: config ctrl register */
val = getreg32(addr);
/* config clock source */
val &= ~(CLOCK_AUXSRC_MASK << CLOCK_AUXSRC_POS);
val |= ((src & CLOCK_AUXSRC_MASK) << CLOCK_AUXSRC_POS);
/* disable clock */
val &= ~(1 << CLOCK_ENABLE_POS);
putreg32(val, addr);
/* step3: config enable */
if (enable) { if (enable) {
putreg32(1 << CLOCK_ENABLE_POS, addr + REG_ALIAS_SET_BITS); val |= CLOCK_CTRL_ENABLE;
clocks_hw->clk[CLOCK_PERI].ctrl = val;
} }
} }
/* div[9:8]: Integer component of the divisor, 0 is for 2^2 */ void clock_usb_set(uint8_t enable, uint8_t src, uint32_t div)
/* div[7:0]: reserved */
/* phase: 0 ~ 3 */
void clock_usb_set(uint8_t enable, uint8_t src, uint32_t div, uint8_t phase, uint8_t nudge)
{ {
uint32_t addr;
uint32_t val; uint32_t val;
/* step1: disable clock */ div = (div > 3) ? 3 : div;
addr = CLOCKS_BASE + CLOCK_USB_CTRL_OFFSET; div = div << CLOCK_DIV_INT_POS;
putreg32(1 << CLOCK_ENABLE_POS, addr + REG_ALIAS_CLR_BITS); val = (uint32_t)src << CLOCK_CTRL_AUXSRC_POS;
clocks_hw->clk[CLOCK_USB].ctrl = val;
/* step2: config ctrl register */ clocks_hw->clk[CLOCK_USB].div = div;
val = getreg32(addr);
/* config clock source */
val &= ~(CLOCK_AUXSRC_MASK << CLOCK_AUXSRC_POS);
val |= ((src & CLOCK_AUXSRC_MASK) << CLOCK_AUXSRC_POS);
/* config delay phase up to 3 cycles of the input clock */
val &= ~(CLOCK_PHASE_MASK << CLOCK_PHASE_POS);
val |= ((phase & CLOCK_PHASE_MASK) << CLOCK_PHASE_POS);
/* config signal shifts the phase of the output by 1 cycle of the input clock */
if (nudge) {
val |= 1 << CLOCK_NUDGE_POS;
} else {
val &= ~(1 << CLOCK_NUDGE_POS);
}
/* disable clock */
val &= ~(1 << CLOCK_ENABLE_POS);
putreg32(val, addr);
/* step3: config div */
putreg32(div, CLOCKS_BASE + CLOCK_USB_DIV_OFFSET);
/* step4: config enable */
if (enable) { if (enable) {
putreg32(1 << CLOCK_ENABLE_POS, addr + REG_ALIAS_SET_BITS); val |= CLOCK_CTRL_ENABLE;
clocks_hw->clk[CLOCK_USB].ctrl = val;
} }
} }
/* div[9:8]: Integer component of the divisor, 0 is for 2^2 */ void clock_adc_set(uint8_t enable, uint8_t src, uint32_t div)
/* div[7:0]: reserved */
/* phase: 0 ~ 3 */
void clock_adc_set(uint8_t enable, uint8_t src, uint32_t div, uint8_t phase, uint8_t nudge)
{ {
uint32_t addr;
uint32_t val; uint32_t val;
/* step1: disable clock */ div = (div > 3) ? 3 : div;
addr = CLOCKS_BASE + CLOCK_ADC_CTRL_OFFSET; div = div << CLOCK_DIV_INT_POS;
putreg32(1 << CLOCK_ENABLE_POS, addr + REG_ALIAS_CLR_BITS); val = (uint32_t)src << CLOCK_CTRL_AUXSRC_POS;
clocks_hw->clk[CLOCK_ADC].ctrl = val;
/* step2: config ctrl register */ clocks_hw->clk[CLOCK_ADC].div = div;
val = getreg32(addr);
/* config clock source */
val &= ~(CLOCK_AUXSRC_MASK << CLOCK_AUXSRC_POS);
val |= ((src & CLOCK_AUXSRC_MASK) << CLOCK_AUXSRC_POS);
/* config delay phase up to 3 cycles of the input clock */
val &= ~(CLOCK_PHASE_MASK << CLOCK_PHASE_POS);
val |= ((phase & CLOCK_PHASE_MASK) << CLOCK_PHASE_POS);
/* config signal shifts the phase of the output by 1 cycle of the input clock */
if (nudge) {
val |= 1 << CLOCK_NUDGE_POS;
} else {
val &= ~(1 << CLOCK_NUDGE_POS);
}
/* disable clock */
val &= ~(1 << CLOCK_ENABLE_POS);
putreg32(val, addr);
/* step3: config div */
putreg32(div, CLOCKS_BASE + CLOCK_ADC_DIV_OFFSET);
/* step4: config enable */
if (enable) { if (enable) {
putreg32(1 << CLOCK_ENABLE_POS, addr + REG_ALIAS_SET_BITS); val |= CLOCK_CTRL_ENABLE;
clocks_hw->clk[CLOCK_ADC].ctrl = val;
} }
} }
/* div[31:8]: Integer component of the divisor, 0 is for 2^2 */ void clock_rtc_set(uint8_t enable, uint8_t src, uint32_t div)
/* div[ 7:0]: Fractional component of the divisor */
/* phase: 0 ~ 3 */
void clock_rtc_set(uint8_t enable, uint8_t src, uint32_t div, uint8_t phase, uint8_t nudge)
{ {
uint32_t addr;
uint32_t val; uint32_t val;
/* step1: disable clock */ div = (div > 0xFFFFFF) ? 0xFFFFFF : div;
addr = CLOCKS_BASE + CLOCK_RTC_CTRL_OFFSET; div = div << CLOCK_DIV_INT_POS;
putreg32(1 << CLOCK_ENABLE_POS, addr + REG_ALIAS_CLR_BITS); val = (uint32_t)src << CLOCK_CTRL_AUXSRC_POS;
clocks_hw->clk[CLOCK_RTC].ctrl = val;
/* step2: config ctrl register */ clocks_hw->clk[CLOCK_RTC].div = div;
val = getreg32(addr);
/* config clock source */
val &= ~(CLOCK_AUXSRC_MASK << CLOCK_AUXSRC_POS);
val |= ((src & CLOCK_AUXSRC_MASK) << CLOCK_AUXSRC_POS);
/* config delay phase up to 3 cycles of the input clock */
val &= ~(CLOCK_PHASE_MASK << CLOCK_PHASE_POS);
val |= ((phase & CLOCK_PHASE_MASK) << CLOCK_PHASE_POS);
/* config signal shifts the phase of the output by 1 cycle of the input clock */
if (nudge) {
val |= 1 << CLOCK_NUDGE_POS;
} else {
val &= ~(1 << CLOCK_NUDGE_POS);
}
/* disable clock */
val &= ~(1 << CLOCK_ENABLE_POS);
putreg32(val, addr);
/* step3: config div */
putreg32(div, CLOCKS_BASE + CLOCK_RTC_DIV_OFFSET);
/* step4: config enable */
if (enable) { if (enable) {
putreg32(1 << CLOCK_ENABLE_POS, addr + REG_ALIAS_SET_BITS); val |= CLOCK_CTRL_ENABLE;
clocks_hw->clk[CLOCK_RTC].ctrl = val;
} }
} }
void clock_enable(uint8_t clock)
{
putreg32(1 << CLOCK_ENABLE_POS, CLOCKS_BASE + CLOCK_CTRL_OFFSET + REG_ALIAS_SET_BITS + (uint32_t)clock * 0xC);
}
void clock_disable(uint8_t clock)
{
putreg32(1 << CLOCK_ENABLE_POS, CLOCKS_BASE + CLOCK_CTRL_OFFSET + REG_ALIAS_CLR_BITS + (uint32_t)clock * 0xC);
}
void clock_kill(uint8_t clock)
{
putreg32(1 << CLOCK_KILL_POS, CLOCKS_BASE + CLOCK_CTRL_OFFSET + REG_ALIAS_SET_BITS + (uint32_t)clock * 0xC);
putreg32(1 << CLOCK_KILL_POS, CLOCKS_BASE + CLOCK_CTRL_OFFSET + REG_ALIAS_CLR_BITS + (uint32_t)clock * 0xC);
}

View File

@ -5,6 +5,7 @@
#include "gpio.h" #include "gpio.h"
#include "timer.h" #include "timer.h"
#include "uart.h" #include "uart.h"
#include "RP2040.h"
#include "stdio.h" #include "stdio.h"
/* voltage: SYSTEM_REGULATOR_VOLTAGE_XXX */ /* voltage: SYSTEM_REGULATOR_VOLTAGE_XXX */
@ -106,17 +107,117 @@ void system_init(void)
}; };
system_regulator_set(SYSTEM_REGULATOR_VOLTAGE_1P30V); system_regulator_set(SYSTEM_REGULATOR_VOLTAGE_1P30V);
clock_ref_set_src(CLOCK_REF_SRC_XOSC_GLITCHLESS); clock_ref_set(CLOCK_REF_SRC_XOSC_GLITCHLESS, 1);
clock_sys_set_src(CLOCK_SYS_SRC_REF_GLITCHLESS); clock_sys_set(CLOCK_SYS_SRC_REF_GLITCHLESS, 1);
/* refdiv >= 5MHz, VCO=[750:1600]MHz, fbdiv=[16:320], postdiv=[1:7] */ /* refdiv >= 5MHz, VCO=[750:1600]MHz, fbdiv=[16:320], postdiv=[1:7] */
clock_pll_init(CLOCK_PLL_SYSPLL, 1, 100, 3, 2); /* 12MHz / 1 * 100 / 3 / 2 = 200MHz */ clock_syspll_init(1, 100, 3, 2); /* 12MHz / 1 * 100 / 3 / 2 = 200MHz */
clock_sys_set_div(1 << 8); /* 200MHz / 1 = 200MHz */ clock_sys_set(CLOCK_SYS_SRC_SYSPLL, 1); /* 200MHz / 1 = 200MHz */
clock_sys_set_src(CLOCK_SYS_SRC_SYSPLL);
clock_peri_set(ENABLE, CLOCK_PERI_SRC_SYSPLL); clock_peri_set(ENABLE, CLOCK_PERI_SRC_SYSPLL);
reset_unreset_blocks_wait(RESETS_BLOCK_IO_BANK0 | RESETS_BLOCK_PADS_BANK0 | RESETS_BLOCK_UART0 | RESETS_BLOCK_TIMER); reset_unreset_blocks_wait(RESETS_BLOCK_IO_BANK0 | RESETS_BLOCK_PADS_BANK0 | RESETS_BLOCK_UART0 | RESETS_BLOCK_TIMER);
uart_init(UART_ID_0, &uart_cfg); uart_init(UART_ID_0, &uart_cfg);
gpio_init_simple(0, GPIO_FUNC_UART, DISABLE, ENABLE); gpio_init_simple(0, GPIO_FUNC_UART, DISABLE, ENABLE);
timer_start(); timer_start();
irq_init(); irq_init();
SysTick->CTRL = 0;
printf("system clock = 200MHz\r\n"); printf("system clock = 200MHz\r\n");
} }
const static uint8_t system_clock_cfg_para[SYSTEM_CLOCK_REF_XOSC_MHZ_COUNT][SYSTEM_CLOCK_FREQ_MHZ_COUNT][5] = {
[SYSTEM_CLOCK_REF_XOSC_8MHZ][SYSTEM_CLOCK_FREQ_48MHZ] = {1, 2, 3, 4, 5},
[SYSTEM_CLOCK_REF_XOSC_8MHZ][SYSTEM_CLOCK_FREQ_96MHZ] = {6, 7, 8, 9, 0},
[SYSTEM_CLOCK_REF_XOSC_8MHZ][SYSTEM_CLOCK_FREQ_100MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_8MHZ][SYSTEM_CLOCK_FREQ_120MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_8MHZ][SYSTEM_CLOCK_FREQ_125MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_8MHZ][SYSTEM_CLOCK_FREQ_144MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_8MHZ][SYSTEM_CLOCK_FREQ_150MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_8MHZ][SYSTEM_CLOCK_FREQ_192MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_8MHZ][SYSTEM_CLOCK_FREQ_200MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_8MHZ][SYSTEM_CLOCK_FREQ_240MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_8MHZ][SYSTEM_CLOCK_FREQ_250MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_8MHZ][SYSTEM_CLOCK_FREQ_320MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_8MHZ][SYSTEM_CLOCK_FREQ_384MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_8MHZ][SYSTEM_CLOCK_FREQ_400MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_12MHZ][SYSTEM_CLOCK_FREQ_48MHZ] = {1, 96, 6, 4, 1}, /* 12MHz / 1 * 96 / 6 / 4 = 48MHz */
[SYSTEM_CLOCK_REF_XOSC_12MHZ][SYSTEM_CLOCK_FREQ_96MHZ] = {1, 96, 6, 2, 1}, /* 12MHz / 1 * 96 / 6 / 2 = 96MHz */
[SYSTEM_CLOCK_REF_XOSC_12MHZ][SYSTEM_CLOCK_FREQ_100MHZ] = {1, 100, 6, 2, 1}, /* 12MHz / 1 * 100 / 6 / 2 = 100MHz */
[SYSTEM_CLOCK_REF_XOSC_12MHZ][SYSTEM_CLOCK_FREQ_120MHZ] = {1, 100, 5, 2, 1}, /* 12MHz / 1 * 100 / 5 / 2 = 120MHz */
[SYSTEM_CLOCK_REF_XOSC_12MHZ][SYSTEM_CLOCK_FREQ_125MHZ] = {1, 125, 6, 2, 1}, /* 12MHz / 1 * 125 / 6 / 2 = 125MHz */
[SYSTEM_CLOCK_REF_XOSC_12MHZ][SYSTEM_CLOCK_FREQ_144MHZ] = {1, 96, 4, 2, 1}, /* 12MHz / 1 * 96 / 4 / 2 = 144MHz */
[SYSTEM_CLOCK_REF_XOSC_12MHZ][SYSTEM_CLOCK_FREQ_150MHZ] = {1, 100, 4, 2, 1}, /* 12MHz / 1 * 100 / 4 / 2 = 150MHz */
[SYSTEM_CLOCK_REF_XOSC_12MHZ][SYSTEM_CLOCK_FREQ_192MHZ] = {1, 96, 6, 1, 1}, /* 12MHz / 1 * 96 / 6 / 1 = 192MHz */
[SYSTEM_CLOCK_REF_XOSC_12MHZ][SYSTEM_CLOCK_FREQ_200MHZ] = {1, 100, 6, 1, 1}, /* 12MHz / 1 * 100 / 6 / 1 = 200MHz */
[SYSTEM_CLOCK_REF_XOSC_12MHZ][SYSTEM_CLOCK_FREQ_240MHZ] = {1, 100, 5, 1, 1}, /* 12MHz / 1 * 100 / 5 / 1 = 240MHz */
[SYSTEM_CLOCK_REF_XOSC_12MHZ][SYSTEM_CLOCK_FREQ_250MHZ] = {1, 125, 6, 1, 1}, /* 12MHz / 1 * 125 / 6 / 1 = 250MHz */
[SYSTEM_CLOCK_REF_XOSC_12MHZ][SYSTEM_CLOCK_FREQ_320MHZ] = {1, 80, 3, 1, 1}, /* 12MHz / 1 * 80 / 3 / 1 = 320MHz */
[SYSTEM_CLOCK_REF_XOSC_12MHZ][SYSTEM_CLOCK_FREQ_384MHZ] = {1, 96, 3, 1, 1}, /* 12MHz / 1 * 96 / 3 / 1 = 384MHz */
[SYSTEM_CLOCK_REF_XOSC_12MHZ][SYSTEM_CLOCK_FREQ_400MHZ] = {1, 100, 3, 1, 1}, /* 12MHz / 1 * 100 / 3 / 1 = 400MHz */
[SYSTEM_CLOCK_REF_XOSC_24MHZ][SYSTEM_CLOCK_FREQ_48MHZ] = {1, 2, 3, 4, 5},
[SYSTEM_CLOCK_REF_XOSC_24MHZ][SYSTEM_CLOCK_FREQ_96MHZ] = {6, 7, 8, 9, 0},
[SYSTEM_CLOCK_REF_XOSC_24MHZ][SYSTEM_CLOCK_FREQ_100MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_24MHZ][SYSTEM_CLOCK_FREQ_120MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_24MHZ][SYSTEM_CLOCK_FREQ_125MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_24MHZ][SYSTEM_CLOCK_FREQ_144MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_24MHZ][SYSTEM_CLOCK_FREQ_150MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_24MHZ][SYSTEM_CLOCK_FREQ_192MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_24MHZ][SYSTEM_CLOCK_FREQ_200MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_24MHZ][SYSTEM_CLOCK_FREQ_240MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_24MHZ][SYSTEM_CLOCK_FREQ_250MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_24MHZ][SYSTEM_CLOCK_FREQ_320MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_24MHZ][SYSTEM_CLOCK_FREQ_384MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_24MHZ][SYSTEM_CLOCK_FREQ_400MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_32MHZ][SYSTEM_CLOCK_FREQ_48MHZ] = {1, 2, 3, 4, 5},
[SYSTEM_CLOCK_REF_XOSC_32MHZ][SYSTEM_CLOCK_FREQ_96MHZ] = {6, 7, 8, 9, 0},
[SYSTEM_CLOCK_REF_XOSC_32MHZ][SYSTEM_CLOCK_FREQ_100MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_32MHZ][SYSTEM_CLOCK_FREQ_120MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_32MHZ][SYSTEM_CLOCK_FREQ_125MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_32MHZ][SYSTEM_CLOCK_FREQ_144MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_32MHZ][SYSTEM_CLOCK_FREQ_150MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_32MHZ][SYSTEM_CLOCK_FREQ_192MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_32MHZ][SYSTEM_CLOCK_FREQ_200MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_32MHZ][SYSTEM_CLOCK_FREQ_240MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_32MHZ][SYSTEM_CLOCK_FREQ_250MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_32MHZ][SYSTEM_CLOCK_FREQ_320MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_32MHZ][SYSTEM_CLOCK_FREQ_384MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_32MHZ][SYSTEM_CLOCK_FREQ_400MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_40MHZ][SYSTEM_CLOCK_FREQ_48MHZ] = {1, 2, 3, 4, 5},
[SYSTEM_CLOCK_REF_XOSC_40MHZ][SYSTEM_CLOCK_FREQ_96MHZ] = {6, 7, 8, 9, 0},
[SYSTEM_CLOCK_REF_XOSC_40MHZ][SYSTEM_CLOCK_FREQ_100MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_40MHZ][SYSTEM_CLOCK_FREQ_120MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_40MHZ][SYSTEM_CLOCK_FREQ_125MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_40MHZ][SYSTEM_CLOCK_FREQ_144MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_40MHZ][SYSTEM_CLOCK_FREQ_150MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_40MHZ][SYSTEM_CLOCK_FREQ_192MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_40MHZ][SYSTEM_CLOCK_FREQ_200MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_40MHZ][SYSTEM_CLOCK_FREQ_240MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_40MHZ][SYSTEM_CLOCK_FREQ_250MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_40MHZ][SYSTEM_CLOCK_FREQ_320MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_40MHZ][SYSTEM_CLOCK_FREQ_384MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_40MHZ][SYSTEM_CLOCK_FREQ_400MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_50MHZ][SYSTEM_CLOCK_FREQ_48MHZ] = {1, 2, 3, 4, 5},
[SYSTEM_CLOCK_REF_XOSC_50MHZ][SYSTEM_CLOCK_FREQ_96MHZ] = {6, 7, 8, 9, 0},
[SYSTEM_CLOCK_REF_XOSC_50MHZ][SYSTEM_CLOCK_FREQ_100MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_50MHZ][SYSTEM_CLOCK_FREQ_120MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_50MHZ][SYSTEM_CLOCK_FREQ_125MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_50MHZ][SYSTEM_CLOCK_FREQ_144MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_50MHZ][SYSTEM_CLOCK_FREQ_150MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_50MHZ][SYSTEM_CLOCK_FREQ_192MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_50MHZ][SYSTEM_CLOCK_FREQ_200MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_50MHZ][SYSTEM_CLOCK_FREQ_240MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_50MHZ][SYSTEM_CLOCK_FREQ_250MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_50MHZ][SYSTEM_CLOCK_FREQ_384MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_50MHZ][SYSTEM_CLOCK_FREQ_320MHZ] = {0, 0, 0, 0, 0},
[SYSTEM_CLOCK_REF_XOSC_50MHZ][SYSTEM_CLOCK_FREQ_400MHZ] = {0, 0, 0, 0, 0},
};
void system_clock_config(uint8_t ref_xosc, uint8_t sys_freq)
{
system_regulator_set(SYSTEM_REGULATOR_VOLTAGE_1P30V);
clock_ref_set(CLOCK_REF_SRC_XOSC_GLITCHLESS, 1);
clock_sys_set(CLOCK_SYS_SRC_REF_GLITCHLESS, 1);
clock_syspll_init(system_clock_cfg_para[ref_xosc][sys_freq][0], \
system_clock_cfg_para[ref_xosc][sys_freq][1], \
system_clock_cfg_para[ref_xosc][sys_freq][2], \
system_clock_cfg_para[ref_xosc][sys_freq][3]);
clock_sys_set(CLOCK_SYS_SRC_SYSPLL, system_clock_cfg_para[ref_xosc][sys_freq][4]);
clock_peri_set(ENABLE, CLOCK_PERI_SRC_SYSPLL);
}