1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2025-01-17 05:12:57 +01:00

cpu/saml21: add DFLL48M support

This commit is contained in:
dylad 2020-03-25 22:18:51 +01:00 committed by Dylan Laduranty
parent 937361856d
commit f2afcd171b
2 changed files with 79 additions and 4 deletions

View File

@ -75,6 +75,8 @@ uint32_t sam0_gclk_freq(uint8_t id)
switch (id) {
case SAM0_GCLK_MAIN:
return CLOCK_CORECLOCK;
case SAM0_GCLK_8MHZ:
return 8000000;
case SAM0_GCLK_32KHZ:
return 32768;
default:
@ -82,6 +84,48 @@ uint32_t sam0_gclk_freq(uint8_t id)
}
}
static void _dfll_setup(void)
{
#if (CLOCK_CORECLOCK == 48000000U) || defined (MODULE_PERIPH_USBDEV)
GCLK->PCHCTRL[OSCCTRL_GCLK_ID_DFLL48].reg = GCLK_PCHCTRL_CHEN |
GCLK_PCHCTRL_GEN_GCLK2;
/* wait for sync */
while (!(GCLK->PCHCTRL[OSCCTRL_GCLK_ID_DFLL48].reg & GCLK_PCHCTRL_CHEN)) {}
OSCCTRL->DFLLCTRL.reg = OSCCTRL_DFLLCTRL_ENABLE;
/* Wait for write synchronization */
while (!(OSCCTRL->STATUS.reg & OSCCTRL_STATUS_DFLLRDY)) {}
OSCCTRL->DFLLVAL.reg = OSCCTRL_DFLLVAL_COARSE((*(uint32_t*)NVMCTRL_OTP5)
>> 26) | OSCCTRL_DFLLVAL_FINE(512);
/* Wait for write synchronization */
while (!(OSCCTRL->STATUS.reg & OSCCTRL_STATUS_DFLLRDY)) {}
/* Generate a 48 Mhz clock from the 32KHz */
OSCCTRL->DFLLMUL.reg = OSCCTRL_DFLLMUL_CSTEP(0x08) |
OSCCTRL_DFLLMUL_FSTEP(0x08) |
OSCCTRL_DFLLMUL_MUL((48000000U/32768));
/* Disable DFLL before setting its configuration */
OSCCTRL->DFLLCTRL.reg = 0;
while (!(OSCCTRL->STATUS.reg & OSCCTRL_STATUS_DFLLRDY)) {}
/* Write full configuration to DFLL control register */
OSCCTRL->DFLLCTRL.reg = OSCCTRL_DFLLCTRL_WAITLOCK |
OSCCTRL_DFLLCTRL_MODE |
OSCCTRL_DFLLCTRL_CCDIS |
OSCCTRL_DFLLCTRL_BPLCKC |
OSCCTRL_DFLLCTRL_ENABLE;
/* Ensure COARSE and FINE are locked */
while ((!(OSCCTRL->STATUS.bit.DFLLLCKC)) && (!(OSCCTRL->STATUS.bit.DFLLLCKF))) {}
while (!(OSCCTRL->STATUS.bit.DFLLRDY)) {}
/* Enable NVMCTRL */
MCLK->APBBMASK.reg |= MCLK_APBBMASK_NVMCTRL;
/* Set Wait State to meet requirements */
NVMCTRL->CTRLB.reg |= NVMCTRL_CTRLB_RWS(3);
#endif
}
/**
* @brief Initialize the CPU, set IRQ priorities, clocks
*/
@ -90,6 +134,14 @@ void cpu_init(void)
/* disable the watchdog timer */
WDT->CTRLA.bit.ENABLE = 0;
/* Disable the RTC module to prevent synchronization issues during CPU init
if the RTC was running from a previous boot (e.g wakeup from backup) */
if (RTC->MODE2.CTRLA.bit.ENABLE) {
while (RTC->MODE2.SYNCBUSY.reg) {}
RTC->MODE2.CTRLA.bit.ENABLE = 0;
while (RTC->MODE2.SYNCBUSY.reg) {}
}
/* initialize the Cortex-M core */
cortexm_init();
@ -125,14 +177,36 @@ void cpu_init(void)
_osc32k_setup();
_xosc32k_setup();
/* Setup GCLK generators */
_gclk_setup(SAM0_GCLK_MAIN, GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_OSC16M);
#if EXTERNAL_OSC32_SOURCE
_gclk_setup(SAM0_GCLK_32KHZ, GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_XOSC32K);
#else
_gclk_setup(SAM0_GCLK_32KHZ, GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_OSCULP32K);
#endif
_dfll_setup();
/* Setup GCLK generators */
#if (CLOCK_CORECLOCK == 16000000U)
_gclk_setup(SAM0_GCLK_MAIN, GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_OSC16M);
#elif (CLOCK_CORECLOCK == 48000000U)
_gclk_setup(SAM0_GCLK_MAIN, GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_DFLL48M);
#else
#error "Please select a valid CPU frequency"
#endif
/* Ensure APB Backup domain clock is within the 6MHZ limit, BUPDIV value
must be a power of 2 and between 1(2^0) and 128(2^7) */
for (unsigned i = 0; i < 8; i++) {
if (CLOCK_CORECLOCK / (1 << i) <= 6000000) {
MCLK->BUPDIV.reg = (1 << i);
while (!MCLK->INTFLAG.bit.CKRDY) {}
break;
}
}
/* clock used by timers */
_gclk_setup(SAM0_GCLK_8MHZ, GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_OSC16M
| GCLK_GENCTRL_DIV(2));
#ifdef MODULE_PERIPH_PM
PM->CTRLA.reg = PM_CTRLA_MASK & (~PM_CTRLA_IORET);

View File

@ -36,8 +36,9 @@ extern "C" {
* @{
*/
enum {
SAM0_GCLK_MAIN = 0, /**< 16 MHz main clock */
SAM0_GCLK_32KHZ, /**< 32 kHz clock */
SAM0_GCLK_MAIN = 0, /**< Main clock */
SAM0_GCLK_8MHZ = 1, /**< 8MHz clock */
SAM0_GCLK_32KHZ = 2, /**< 32 kHz clock */
};
/** @} */