[feat] update clock driver
This commit is contained in:
parent
d5f776d614
commit
2d11df7c38
@ -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();
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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" {
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user