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:
parent
937361856d
commit
f2afcd171b
@ -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);
|
||||
|
||||
|
@ -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 */
|
||||
};
|
||||
/** @} */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user