1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

cpu/saml21: enable buck voltage regulator when possible

Switch from the on-chip LDO to the on-chip buck voltage regulator
when not fast internal oscillators are used.

On `saml21-xpro` with `examples/default` this gives

**before:** 750 µA
** after:** 385 µA
This commit is contained in:
Benjamin Valentin 2020-02-21 17:03:12 +01:00 committed by Benjamin Valentin
parent 3f95d3d2e3
commit f037e06b13

View File

@ -23,6 +23,22 @@
#include "periph_conf.h"
#include "stdio_base.h"
/* As long as DFLL & DPLL are not used, we can default to
* always use the buck converter when available.
*
* 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 == 48000000U) || defined (MODULE_PERIPH_USBDEV)
#define USE_DFLL (1)
#else
#define USE_DFLL (0)
#endif
static void _gclk_setup(int gclk, uint32_t reg)
{
GCLK->GENCTRL[gclk].reg = reg;
@ -86,7 +102,10 @@ uint32_t sam0_gclk_freq(uint8_t id)
static void _dfll_setup(void)
{
#if (CLOCK_CORECLOCK == 48000000U) || defined (MODULE_PERIPH_USBDEV)
if (!USE_DFLL) {
return;
}
GCLK->PCHCTRL[OSCCTRL_GCLK_ID_DFLL48].reg = GCLK_PCHCTRL_CHEN |
GCLK_PCHCTRL_GEN_GCLK2;
@ -124,19 +143,52 @@ static void _dfll_setup(void)
MCLK->APBBMASK.reg |= MCLK_APBBMASK_NVMCTRL;
/* Set Wait State to meet requirements */
NVMCTRL->CTRLB.reg |= NVMCTRL_CTRLB_RWS(3);
#endif
}
static void _set_active_mode_vreg(void)
{
if (!USE_VREG_BUCK) {
return;
}
/* not compatible with 48 MHz DFLL & 96 MHz FDPLL */
if (USE_DFLL) {
sam0_set_voltage_regulator(SAM0_VREG_LDO);
} else {
sam0_set_voltage_regulator(SAM0_VREG_BUCK);
}
}
void cpu_pm_cb_enter(int deep)
{
(void) deep;
/* will be called before entering sleep */
if (!deep) {
return;
}
/* If you are using saml21 rev. B, switch Main Clock to OSCULP32 during standby
to work around errata 1.2.1.
See discussion in #13441 */
assert((DSU->DID.bit.REVISION > 1) || ((PM->STDBYCFG.reg & 0x80) == 0));
/* errata 51.1.5 When VDDCORE is supplied by the BUCK converter in performance
level 0, the chip cannot wake-up from standby mode because the
VCORERDY status is stuck at 0. */
if (USE_VREG_BUCK && !PM->PLCFG.bit.PLSEL) {
sam0_set_voltage_regulator(SAM0_VREG_LDO);
}
/* TODO: If we source Main Clock from OSCULP32 during standby and are not in
performance level 0, we should always be able to use the BUCK converter
during standby */
}
void cpu_pm_cb_leave(int deep)
{
(void) deep;
/* will be called after wake-up */
if (!deep) {
return;
}
_set_active_mode_vreg();
}
/**
@ -158,6 +210,9 @@ void cpu_init(void)
/* initialize the Cortex-M core */
cortexm_init();
/* select the right voltage regulator config for active mode */
_set_active_mode_vreg();
/* turn on only needed APB peripherals */
MCLK->APBAMASK.reg =
MCLK_APBAMASK_PM