diff --git a/cpu/samd5x/cpu.c b/cpu/samd5x/cpu.c index e4769c94009f..0daf4665a398 100644 --- a/cpu/samd5x/cpu.c +++ b/cpu/samd5x/cpu.c @@ -34,14 +34,6 @@ #define USE_VREG_BUCK (0) #endif -/* - * An external inductor needs to be present on the board, - * so the feature can only be enabled by the board configuration. - */ -#ifndef USE_VREG_BUCK -#define USE_VREG_BUCK (0) -#endif - #if CLOCK_CORECLOCK == 0 #error Please select CLOCK_CORECLOCK #endif @@ -191,37 +183,43 @@ static void dfll_init(void) while (!OSCCTRL->STATUS.bit.DFLLRDY) {} } -static void fdpll0_init(uint32_t f_cpu) +static void fdpll_init_nolock(uint8_t idx, uint32_t f_cpu, uint8_t flags) { + /* Trigger assertion if not using FDPLL0 or FDPLL1 */ + assert(idx == 0 || idx == 1); + if (!USE_DPLL) { - OSCCTRL->Dpll[0].DPLLCTRLA.reg = 0; + OSCCTRL->Dpll[idx].DPLLCTRLA.reg = 0; return; } - /* We source the DPLL from 32kHz GCLK1 */ - const uint32_t LDR = ((f_cpu << 5) / 32768); + /* Source the DPLL from 32kHz GCLK1 ( equivalent to ((f_cpu << 5) / 32768) ) */ + const uint32_t LDR = (f_cpu >> 10); /* disable the DPLL before changing the configuration */ - OSCCTRL->Dpll[0].DPLLCTRLA.bit.ENABLE = 0; - while (OSCCTRL->Dpll[0].DPLLSYNCBUSY.reg) {} + OSCCTRL->Dpll[idx].DPLLCTRLA.bit.ENABLE = 0; + while (OSCCTRL->Dpll[idx].DPLLSYNCBUSY.reg) {} /* set DPLL clock source */ - GCLK->PCHCTRL[OSCCTRL_GCLK_ID_FDPLL0].reg = GCLK_PCHCTRL_GEN(1) | GCLK_PCHCTRL_CHEN; - while (!(GCLK->PCHCTRL[OSCCTRL_GCLK_ID_FDPLL0].reg & GCLK_PCHCTRL_CHEN)) {} + GCLK->PCHCTRL[OSCCTRL_GCLK_ID_FDPLL0 + idx].reg = GCLK_PCHCTRL_GEN(1) | GCLK_PCHCTRL_CHEN; + while (!(GCLK->PCHCTRL[OSCCTRL_GCLK_ID_FDPLL0 + idx].reg & GCLK_PCHCTRL_CHEN)) {} - OSCCTRL->Dpll[0].DPLLRATIO.reg = OSCCTRL_DPLLRATIO_LDRFRAC(LDR & 0x1F) - | OSCCTRL_DPLLRATIO_LDR((LDR >> 5) - 1); + OSCCTRL->Dpll[idx].DPLLRATIO.reg = OSCCTRL_DPLLRATIO_LDRFRAC(LDR & 0x1F) + | OSCCTRL_DPLLRATIO_LDR((LDR >> 5) - 1); /* Without LBYPASS, startup takes very long, see errata section 2.13. */ - OSCCTRL->Dpll[0].DPLLCTRLB.reg = OSCCTRL_DPLLCTRLB_REFCLK_GCLK - | OSCCTRL_DPLLCTRLB_WUF - | OSCCTRL_DPLLCTRLB_LBYPASS; + OSCCTRL->Dpll[idx].DPLLCTRLB.reg = OSCCTRL_DPLLCTRLB_REFCLK_GCLK + | OSCCTRL_DPLLCTRLB_WUF + | OSCCTRL_DPLLCTRLB_LBYPASS; - OSCCTRL->Dpll[0].DPLLCTRLA.reg = OSCCTRL_DPLLCTRLA_ENABLE; + OSCCTRL->Dpll[idx].DPLLCTRLA.reg = OSCCTRL_DPLLCTRLA_ENABLE | flags; - while (OSCCTRL->Dpll[0].DPLLSYNCBUSY.reg) {} - while (!(OSCCTRL->Dpll[0].DPLLSTATUS.bit.CLKRDY && - OSCCTRL->Dpll[0].DPLLSTATUS.bit.LOCK)) {} + while (OSCCTRL->Dpll[idx].DPLLSYNCBUSY.reg) {} +} + +static void fdpll_lock(uint8_t idx) { + while (!(OSCCTRL->Dpll[idx].DPLLSTATUS.bit.CLKRDY && + OSCCTRL->Dpll[idx].DPLLSTATUS.bit.LOCK)) {} } static void gclk_connect(uint8_t id, uint8_t src, uint32_t flags) { @@ -256,7 +254,11 @@ void sam0_gclk_enable(uint8_t id) } else if (USE_XOSC) { gclk_connect(SAM0_GCLK_PERIPH, GCLK_SOURCE_ACTIVE_XOSC, 0); } - + break; + case SAM0_GCLK_200MHZ: + fdpll_init_nolock(1, MHZ(200), OSCCTRL_DPLLCTRLA_ONDEMAND); + gclk_connect(SAM0_GCLK_200MHZ, GCLK_SOURCE_DPLL1, 0); + fdpll_lock(1); break; } } @@ -279,6 +281,8 @@ uint32_t sam0_gclk_freq(uint8_t id) assert(0); return 0; } + case SAM0_GCLK_200MHZ: + return MHZ(200); default: return 0; } @@ -354,12 +358,13 @@ void cpu_init(void) xosc_init(0); xosc_init(1); - fdpll0_init(CLOCK_CORECLOCK * DPLL_DIV); /* select the source of the main clock */ if (USE_DPLL) { + fdpll_init_nolock(0, CLOCK_CORECLOCK * DPLL_DIV, OSCCTRL_DPLLCTRLA_ONDEMAND); gclk_connect(SAM0_GCLK_MAIN, GCLK_SOURCE_DPLL0, GCLK_GENCTRL_DIV(DPLL_DIV)); + fdpll_lock(0); } else if (USE_DFLL) { gclk_connect(SAM0_GCLK_MAIN, GCLK_SOURCE_DFLL, GCLK_GENCTRL_DIV(SAM0_DFLL_FREQ_HZ / CLOCK_CORECLOCK)); diff --git a/cpu/samd5x/include/periph_cpu.h b/cpu/samd5x/include/periph_cpu.h index e6ff957d00c9..09d0493de9c3 100644 --- a/cpu/samd5x/include/periph_cpu.h +++ b/cpu/samd5x/include/periph_cpu.h @@ -47,7 +47,7 @@ extern "C" { /** * @brief DPLL frequency must not exceed 200 MHz */ -#define SAM0_DPLL_FREQ_MAX_HZ MHZ(20) +#define SAM0_DPLL_FREQ_MAX_HZ MHZ(200) /** * @name Power mode configuration @@ -65,6 +65,7 @@ enum { SAM0_GCLK_32KHZ, /**< 32 kHz clock */ SAM0_GCLK_TIMER, /**< 4-8 MHz clock for xTimer */ SAM0_GCLK_PERIPH, /**< 12-48 MHz (DFLL) clock */ + SAM0_GCLK_200MHZ, /**< 200MHz FDPLL clock */ }; /** @} */