From 2d11df7c382713a69428cfd6e3ab0ca28d4b5ad4 Mon Sep 17 00:00:00 2001 From: zhji Date: Sun, 11 May 2025 22:30:39 +0800 Subject: [PATCH] [feat] update clock driver --- .../RaspberryPi/RP2040/Source/system_RP2040.c | 9 +- driver/inc/clock.h | 91 +--- driver/inc/common.h | 23 + driver/inc/reg/clock_reg.h | 138 ++++-- driver/inc/system.h | 25 + driver/src/clock.c | 433 +++++------------- driver/src/system.c | 111 ++++- 7 files changed, 415 insertions(+), 415 deletions(-) diff --git a/CMSIS/Device/RaspberryPi/RP2040/Source/system_RP2040.c b/CMSIS/Device/RaspberryPi/RP2040/Source/system_RP2040.c index 6177b5d..69fae3a 100644 --- a/CMSIS/Device/RaspberryPi/RP2040/Source/system_RP2040.c +++ b/CMSIS/Device/RaspberryPi/RP2040/Source/system_RP2040.c @@ -52,12 +52,11 @@ void SystemCoreClockUpdate (void) void __attribute__((constructor)) SystemInit (void) { system_regulator_set(SYSTEM_REGULATOR_VOLTAGE_1P30V); - clock_ref_set_src(CLOCK_REF_SRC_XOSC_GLITCHLESS); - clock_sys_set_src(CLOCK_SYS_SRC_REF_GLITCHLESS); + clock_ref_set(CLOCK_REF_SRC_XOSC_GLITCHLESS, 1); + clock_sys_set(CLOCK_SYS_SRC_REF_GLITCHLESS, 1); /* 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_sys_set_div(1 << 8); /* 200MHz / 1 = 200MHz */ - clock_sys_set_src(CLOCK_SYS_SRC_SYSPLL); + clock_syspll_init(1, 100, 3, 2); /* 12MHz / 1 * 100 / 3 / 2 = 200MHz */ + clock_sys_set(CLOCK_SYS_SRC_SYSPLL, 1); /* 200MHz / 1 = 200MHz */ clock_peri_set(ENABLE, CLOCK_PERI_SRC_SYSPLL); SystemCoreClockUpdate(); diff --git a/driver/inc/clock.h b/driver/inc/clock.h index f33ffe8..018f6ec 100644 --- a/driver/inc/clock.h +++ b/driver/inc/clock.h @@ -19,10 +19,6 @@ #define CLOCK_XOSC_STATUS_BADWRITE (24) #define CLOCK_XOSC_STATUS_STABLE (31) -/* PLL type */ -#define CLOCK_PLL_SYSPLL (0) -#define CLOCK_PLL_USBPLL (1) - /* clock instance */ #define CLOCK_GPOUT0 (0) #define CLOCK_GPOUT1 (1) @@ -36,53 +32,17 @@ #define CLOCK_RTC (9) /* clock source */ -#define CLOCK_GPOUT0_SRC_SYSPLL (0) -#define CLOCK_GPOUT0_SRC_GPIN0 (1) -#define CLOCK_GPOUT0_SRC_GPIN1 (2) -#define CLOCK_GPOUT0_SRC_USBPLL (3) -#define CLOCK_GPOUT0_SRC_ROSC (4) -#define CLOCK_GPOUT0_SRC_XOSC (5) -#define CLOCK_GPOUT0_SRC_SYS (6) -#define CLOCK_GPOUT0_SRC_USB (7) -#define CLOCK_GPOUT0_SRC_ADC (8) -#define CLOCK_GPOUT0_SRC_RTC (9) -#define CLOCK_GPOUT0_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_GPOUT_SRC_SYSPLL (0) +#define CLOCK_GPOUT_SRC_GPIN0 (1) +#define CLOCK_GPOUT_SRC_GPIN1 (2) +#define CLOCK_GPOUT_SRC_USBPLL (3) +#define CLOCK_GPOUT_SRC_ROSC (4) +#define CLOCK_GPOUT_SRC_XOSC (5) +#define CLOCK_GPOUT_SRC_SYS (6) +#define CLOCK_GPOUT_SRC_USB (7) +#define CLOCK_GPOUT_SRC_ADC (8) +#define CLOCK_GPOUT_SRC_RTC (9) +#define CLOCK_GPOUT_SRC_REF (10) #define CLOCK_REF_SRC_USBPLL (0) #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); uint8_t clock_xosc_get_count(void); -/* PLL function */ -void clock_pll_init(uint8_t pll, uint8_t refdiv, uint8_t fbdiv, uint8_t postdiv1, uint8_t postdiv2); -void clock_pll_deinit(uint8_t pll); +/* pll function */ +void clock_syspll_init(uint8_t refdiv, uint16_t feedback, uint8_t postdiv1, uint8_t postdiv2); +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 */ -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); -uint32_t clock_ref_get_selected(void); -void clock_ref_set_src(uint8_t src); -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); +/* clock function */ +void clock_gpout_set(uint8_t id, uint8_t enable, uint8_t src, uint32_t div); /* div is 1~16777215 */ +void clock_ref_set(uint8_t src, uint32_t div); /* div is 1~3 */ +void clock_sys_set(uint8_t src, uint32_t div); /* div is 1~16777215 */ 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_adc_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, uint8_t phase, uint8_t nudge); -void clock_enable(uint8_t clock); -void clock_disable(uint8_t clock); -void clock_kill(uint8_t clock); +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); /* div is 1~3 */ +void clock_rtc_set(uint8_t enable, uint8_t src, uint32_t div); /* div is 1~16777215 */ #ifdef __cplusplus } diff --git a/driver/inc/common.h b/driver/inc/common.h index 41d7d4e..acdc096 100644 --- a/driver/inc/common.h +++ b/driver/inc/common.h @@ -3,6 +3,29 @@ #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 extern "C" { #endif diff --git a/driver/inc/reg/clock_reg.h b/driver/inc/reg/clock_reg.h index 393d29e..578b419 100644 --- a/driver/inc/reg/clock_reg.h +++ b/driver/inc/reg/clock_reg.h @@ -81,38 +81,116 @@ #define CLOCK_XOSC_STARTUP_DELAY_MASK (0x3FFF) #define CLOCK_XOSC_STARTUP_X4_POS (20) -/* CLOCK_PLL_CS_OFFSET */ -#define CLOCK_PLL_REFDIV_POS (0) -#define CLOCK_PLL_REFDIV_MASK (0x3F) -#define CLOCK_PLL_BYPASS_POS (8) -#define CLOCK_PLL_LOCK_POS (31) +/* CLOCK_PLL_CS_OFFSET @ 0x000 */ +#define CLOCK_PLL_CS_REFDIV_POS (0) +#define CLOCK_PLL_CS_REFDIV_MASK (0x3F << CLOCK_PLL_CS_REFDIV_POS) +#define CLOCK_PLL_CS_BYPASS (1 << 8U) +#define CLOCK_PLL_CS_LOCK (1 << 31U) -/* CLOCK_PLL_PWR_OFFSET */ -#define CLOCK_PLL_PD_POS (0) -#define CLOCK_PLL_DSMPD_POS (2) -#define CLOCK_PLL_POSTDIVPD_POS (3) -#define CLOCK_PLL_VCOPD_POS (5) -#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_PLL_PWR_OFFSET @ 0x004 */ +#define CLOCK_PLL_PWR_PD (1 << 0U) +#define CLOCK_PLL_PWR_DSMPD (1 << 2U) +#define CLOCK_PLL_PWR_POSTDIVPD (1 << 3U) +#define CLOCK_PLL_PWR_VCOPD (1 << 5U) -/* CLOCK_CTRL_OFFSET */ -#define CLOCK_SRC_POS (0) -#define CLOCK_SRC_MASK (0x3) -#define CLOCK_AUXSRC_POS (5) -#define CLOCK_AUXSRC_MASK (0xF) -#define CLOCK_KILL_POS (10) -#define CLOCK_ENABLE_POS (11) -#define CLOCK_DC50_POS (12) -#define CLOCK_PHASE_POS (16) -#define CLOCK_PHASE_MASK (0x3) -#define CLOCK_NUDGE_POS (20) +/* CLOCK_PLL_PRIM_OFFSET @ 0x00C */ +#define CLOCK_PLL_PRIM_POSTDIV2_POS (12U) +#define CLOCK_PLL_PRIM_POSTDIV2_MASK (0x7 << CLOCK_PLL_PRIM_POSTDIV2_POS) +#define CLOCK_PLL_PRIM_POSTDIV1_POS (16U) +#define CLOCK_PLL_PRIM_POSTDIV1_MASK (0x7 << CLOCK_PLL_PRIM_POSTDIV1_POS) + +/* CLOCK_CTRL_OFFSET @ 0x000 */ +#define CLOCK_CTRL_SRC_POS (0U) +#define CLOCK_CTRL_AUXSRC_POS (5U) +#define CLOCK_CTRL_KILL (1 << 10U) +#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 extern "C" { diff --git a/driver/inc/system.h b/driver/inc/system.h index bc36d0a..0a54462 100644 --- a/driver/inc/system.h +++ b/driver/inc/system.h @@ -36,6 +36,30 @@ #define SYSTEM_BLOCK_PROC0 (1 << 15) #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 extern "C" { #endif @@ -50,6 +74,7 @@ void system_wdg_unbound(uint32_t block); uint8_t system_block_is_available(uint32_t block); void system_init(void); +void system_clock_config(uint8_t ref_xosc, uint8_t sys_freq); #ifdef __cplusplus } diff --git a/driver/src/clock.c b/driver/src/clock.c index f6670fd..b88359e 100644 --- a/driver/src/clock.c +++ b/driver/src/clock.c @@ -273,371 +273,190 @@ uint8_t clock_xosc_get_count(void) 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; - uint32_t val; - - if (pll == CLOCK_PLL_SYSPLL) { - reset_unreset_blocks_wait(RESETS_BLOCK_SYSPLL); - 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 */ + if (refdiv == 0) { + refdiv = 1; + } else if (refdiv > 63) { + refdiv = 63; } - /* Load VCO-related dividers before starting VCO */ - putreg32((uint32_t)refdiv, addr + CLOCK_PLL_CS_OFFSET); - putreg32((uint32_t)fbdiv, addr + CLOCK_PLL_FBDIV_INT_OFFSET); - /* Turn on PLL */ - val = (1 << CLOCK_PLL_PD_POS) | (1 << CLOCK_PLL_VCOPD_POS); - 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; - } + pll->cs = refdiv; + if (feedback == 0) { + feedback = 1; + } else if (feedback > 4095) { + feedback = 4095; } - /* Set up post dividers */ - val = (postdiv1 << CLOCK_PLL_POSTDIV1_POS) | (postdiv2 << CLOCK_PLL_POSTDIV2_POS); - putreg32(val, addr + CLOCK_PLL_PRIM_OFFSET); - /* Turn on post divider */ - putreg32(1 << CLOCK_PLL_POSTDIVPD_POS, addr + CLOCK_PLL_PWR_OFFSET + REG_ALIAS_CLR_BITS); + pll->fbdiv_int = feedback; + /* turn on PLL, write 0 for release power down */ + pll->pwr = CLOCK_PLL_PWR_POSTDIVPD | CLOCK_PLL_PWR_DSMPD; + /* wait for PLL to lock */ + 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); - 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); - } + reset_unreset_blocks_wait(RESETS_BLOCK_SYSPLL); + pll_init(pll_sys_hw, refdiv, feedback, postdiv1, postdiv2); } -/* id: 0 ~ 3 */ -/* div[31:8]: Integer component of the divisor, 0 is for 2^24 */ -/* div[ 7:0]: Fractional component of the divisor */ -/* phase: 0 ~ 3 */ -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_usbpll_init(uint8_t refdiv, uint16_t feedback, uint8_t postdiv1, uint8_t postdiv2) +{ + reset_unreset_blocks_wait(RESETS_BLOCK_USBPLL); + pll_init(pll_usb_hw, refdiv, feedback, postdiv1, postdiv2); +} + +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; - /* step1: disable clock */ - addr = CLOCKS_BASE + CLOCK_GPOUT0_CTRL_OFFSET + id * 0xC; - 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); - /* 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 */ + div = (div > 0xFFFFFF) ? 0xFFFFFF : div; + div = div << CLOCK_DIV_INT_POS; + val = ((uint32_t)src << CLOCK_CTRL_AUXSRC_POS) | CLOCK_CTRL_DC50; + clocks_hw->clk[CLOCK_GPOUT0 + id].ctrl = val; + clocks_hw->clk[CLOCK_GPOUT0 + id].div = div; 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; - 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) { - /* switch to the glitchless mux */ clock_rosc_enable(); - /* step1: switch the glitchless mux to an alternate source */ - putreg32(0, addr); - /* step2: poll the SELECTED register until the switch is completed */ - while (1) { - if (clock_ref_get_selected() & (1 << 0)) { - break; - } - } + clocks_hw->clk[CLOCK_REF].ctrl = 0; + while (!(clocks_hw->clk[CLOCK_REF].selected & (1u << 0))); } else if (src == CLOCK_REF_SRC_XOSC_GLITCHLESS) { - /* switch to the glitchless mux */ clock_xosc_enable(); - /* step1: switch the glitchless mux to an alternate source */ - putreg32(2, addr); - /* step2: poll the SELECTED register until the switch is completed */ - while (1) { - if (clock_ref_get_selected() & (1 << 2)) { - break; - } - } + clocks_hw->clk[CLOCK_REF].ctrl = 2; + while (!(clocks_hw->clk[CLOCK_REF].selected & (1u << 2))); } else { - /* switch to the auxiliary mux when the generator has a glitchless mux */ clock_rosc_enable(); - /* step1: switch the glitchless mux to a source that isn’t the aux mux */ - putreg32(0, addr); - /* step2: poll the SELECTED register until the switch is completed */ - while (1) { - if (clock_ref_get_selected() & (1 << 0)) { - break; - } - } - /* 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_ref_get_selected() & (1 << 1)) { - break; - } - } + clocks_hw->clk[CLOCK_REF].ctrl = 0; + while (!(clocks_hw->clk[CLOCK_REF].selected & (1u << 0))); + val = (uint32_t)src << CLOCK_CTRL_AUXSRC_POS; + clocks_hw->clk[CLOCK_REF].ctrl = val; + val |= (1u << CLOCK_CTRL_SRC_POS); + clocks_hw->clk[CLOCK_REF].ctrl = val; + while (!(clocks_hw->clk[CLOCK_REF].selected & (1u << 1))); + } + if (div < clocks_hw->clk[CLOCK_REF].div) { + clocks_hw->clk[CLOCK_REF].div = div; } } -/* div[9:8]: Integer component of the divisor, 0 is for 2^2 */ -/* div[7:0]: reserved */ -void clock_ref_set_div(uint32_t div) +void clock_sys_set(uint8_t src, 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; - addr = CLOCKS_BASE + CLOCK_SYS_CTRL_OFFSET; - if (src == CLOCK_SYS_SRC_REF_GLITCHLESS) { - /* switch to the glitchless mux */ - /* step1: switch the glitchless mux to an alternate source */ - putreg32(0, addr); - /* step2: poll the SELECTED register until the switch is completed */ - while (1) { - if (clock_sys_get_selected() & (1 << 0)) { - break; - } - } - } else { - /* switch to the auxiliary mux when the generator has a glitchless mux */ - /* step1: switch the glitchless mux to a source that isn’t the aux mux */ - putreg32(0, addr); - /* step2: poll the SELECTED register until the switch is completed */ - while (1) { - if (clock_sys_get_selected() & (1 << 0)) { - break; - } - } - /* 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 = (div > 0xFFFFFF) ? 0xFFFFFF : div; + div = div << CLOCK_DIV_INT_POS; + if (div > clocks_hw->clk[CLOCK_SYS].div) { + clocks_hw->clk[CLOCK_SYS].div = div; + } + if (src == CLOCK_SYS_SRC_REF_GLITCHLESS) { + clocks_hw->clk[CLOCK_SYS].ctrl = 0; + while (!(clocks_hw->clk[CLOCK_SYS].selected & (1u << 0))); + } else { + clocks_hw->clk[CLOCK_SYS].ctrl = 0; + while (!(clocks_hw->clk[CLOCK_SYS].selected & (1u << 0))); + val = (uint32_t)src << CLOCK_CTRL_AUXSRC_POS; + clocks_hw->clk[CLOCK_SYS].ctrl = val; + val |= (1u << CLOCK_CTRL_SRC_POS); + clocks_hw->clk[CLOCK_SYS].ctrl = val; + while (!(clocks_hw->clk[CLOCK_SYS].selected & (1u << 1))); + } + if (div < clocks_hw->clk[CLOCK_SYS].div) { + clocks_hw->clk[CLOCK_SYS].div = div; } -} - -/* 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) { - uint32_t addr; uint32_t val; - /* step1: disable clock */ - addr = CLOCKS_BASE + CLOCK_PERI_CTRL_OFFSET; - 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 */ + val = (uint32_t)src << CLOCK_CTRL_AUXSRC_POS; + clocks_hw->clk[CLOCK_PERI].ctrl = val; 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 */ -/* 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) +void clock_usb_set(uint8_t enable, uint8_t src, uint32_t div) { - uint32_t addr; uint32_t val; - /* step1: disable clock */ - addr = CLOCKS_BASE + CLOCK_USB_CTRL_OFFSET; - 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); - /* 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 */ + div = (div > 3) ? 3 : div; + div = div << CLOCK_DIV_INT_POS; + val = (uint32_t)src << CLOCK_CTRL_AUXSRC_POS; + clocks_hw->clk[CLOCK_USB].ctrl = val; + clocks_hw->clk[CLOCK_USB].div = div; 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 */ -/* 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) +void clock_adc_set(uint8_t enable, uint8_t src, uint32_t div) { - uint32_t addr; uint32_t val; - /* step1: disable clock */ - addr = CLOCKS_BASE + CLOCK_ADC_CTRL_OFFSET; - 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); - /* 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 */ + div = (div > 3) ? 3 : div; + div = div << CLOCK_DIV_INT_POS; + val = (uint32_t)src << CLOCK_CTRL_AUXSRC_POS; + clocks_hw->clk[CLOCK_ADC].ctrl = val; + clocks_hw->clk[CLOCK_ADC].div = div; 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 */ -/* 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) +void clock_rtc_set(uint8_t enable, uint8_t src, uint32_t div) { - uint32_t addr; uint32_t val; - /* step1: disable clock */ - addr = CLOCKS_BASE + CLOCK_RTC_CTRL_OFFSET; - 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); - /* 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 */ + div = (div > 0xFFFFFF) ? 0xFFFFFF : div; + div = div << CLOCK_DIV_INT_POS; + val = (uint32_t)src << CLOCK_CTRL_AUXSRC_POS; + clocks_hw->clk[CLOCK_RTC].ctrl = val; + clocks_hw->clk[CLOCK_RTC].div = div; 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); -} diff --git a/driver/src/system.c b/driver/src/system.c index 0713208..8aae13d 100644 --- a/driver/src/system.c +++ b/driver/src/system.c @@ -5,6 +5,7 @@ #include "gpio.h" #include "timer.h" #include "uart.h" +#include "RP2040.h" #include "stdio.h" /* voltage: SYSTEM_REGULATOR_VOLTAGE_XXX */ @@ -106,17 +107,117 @@ void system_init(void) }; system_regulator_set(SYSTEM_REGULATOR_VOLTAGE_1P30V); - clock_ref_set_src(CLOCK_REF_SRC_XOSC_GLITCHLESS); - clock_sys_set_src(CLOCK_SYS_SRC_REF_GLITCHLESS); + clock_ref_set(CLOCK_REF_SRC_XOSC_GLITCHLESS, 1); + clock_sys_set(CLOCK_SYS_SRC_REF_GLITCHLESS, 1); /* 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_sys_set_div(1 << 8); /* 200MHz / 1 = 200MHz */ - clock_sys_set_src(CLOCK_SYS_SRC_SYSPLL); + clock_syspll_init(1, 100, 3, 2); /* 12MHz / 1 * 100 / 3 / 2 = 200MHz */ + clock_sys_set(CLOCK_SYS_SRC_SYSPLL, 1); /* 200MHz / 1 = 200MHz */ 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); uart_init(UART_ID_0, &uart_cfg); gpio_init_simple(0, GPIO_FUNC_UART, DISABLE, ENABLE); timer_start(); irq_init(); + SysTick->CTRL = 0; 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); +}