Merge pull request #13786 from benpicco/cpu/saml21/buck_converter
cpu/saml21: enable buck voltage regulator when possible
This commit is contained in:
commit
b87be4bd6e
@ -34,6 +34,12 @@ extern "C" {
|
|||||||
*/
|
*/
|
||||||
#define CLOCK_CORECLOCK (48000000U)
|
#define CLOCK_CORECLOCK (48000000U)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Enable the internal DC/DC converter
|
||||||
|
* The board is equipped with the necessary inductor.
|
||||||
|
*/
|
||||||
|
#define USE_VREG_BUCK (1)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @name Timer peripheral configuration
|
* @name Timer peripheral configuration
|
||||||
* @{
|
* @{
|
||||||
|
|||||||
@ -31,6 +31,12 @@ extern "C" {
|
|||||||
*/
|
*/
|
||||||
#define CLOCK_CORECLOCK (48000000U)
|
#define CLOCK_CORECLOCK (48000000U)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Enable the internal DC/DC converter
|
||||||
|
* The board is equipped with the necessary inductor.
|
||||||
|
*/
|
||||||
|
#define USE_VREG_BUCK (1)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @name Timer peripheral configuration
|
* @name Timer peripheral configuration
|
||||||
* @{
|
* @{
|
||||||
|
|||||||
@ -23,6 +23,22 @@
|
|||||||
#include "periph_conf.h"
|
#include "periph_conf.h"
|
||||||
#include "stdio_base.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)
|
static void _gclk_setup(int gclk, uint32_t reg)
|
||||||
{
|
{
|
||||||
GCLK->GENCTRL[gclk].reg = reg;
|
GCLK->GENCTRL[gclk].reg = reg;
|
||||||
@ -86,7 +102,10 @@ uint32_t sam0_gclk_freq(uint8_t id)
|
|||||||
|
|
||||||
static void _dfll_setup(void)
|
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[OSCCTRL_GCLK_ID_DFLL48].reg = GCLK_PCHCTRL_CHEN |
|
||||||
GCLK_PCHCTRL_GEN_GCLK2;
|
GCLK_PCHCTRL_GEN_GCLK2;
|
||||||
|
|
||||||
@ -124,19 +143,52 @@ static void _dfll_setup(void)
|
|||||||
MCLK->APBBMASK.reg |= MCLK_APBBMASK_NVMCTRL;
|
MCLK->APBBMASK.reg |= MCLK_APBBMASK_NVMCTRL;
|
||||||
/* Set Wait State to meet requirements */
|
/* Set Wait State to meet requirements */
|
||||||
NVMCTRL->CTRLB.reg |= NVMCTRL_CTRLB_RWS(3);
|
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 cpu_pm_cb_enter(int deep)
|
||||||
{
|
{
|
||||||
(void) deep;
|
if (!deep) {
|
||||||
/* will be called before entering sleep */
|
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 cpu_pm_cb_leave(int deep)
|
||||||
{
|
{
|
||||||
(void) deep;
|
if (!deep) {
|
||||||
/* will be called after wake-up */
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_set_active_mode_vreg();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -158,6 +210,9 @@ void cpu_init(void)
|
|||||||
/* initialize the Cortex-M core */
|
/* initialize the Cortex-M core */
|
||||||
cortexm_init();
|
cortexm_init();
|
||||||
|
|
||||||
|
/* select the right voltage regulator config for active mode */
|
||||||
|
_set_active_mode_vreg();
|
||||||
|
|
||||||
/* turn on only needed APB peripherals */
|
/* turn on only needed APB peripherals */
|
||||||
MCLK->APBAMASK.reg =
|
MCLK->APBAMASK.reg =
|
||||||
MCLK_APBAMASK_PM
|
MCLK_APBAMASK_PM
|
||||||
|
|||||||
@ -26,16 +26,19 @@
|
|||||||
|
|
||||||
void pm_set(unsigned mode)
|
void pm_set(unsigned mode)
|
||||||
{
|
{
|
||||||
|
int deep = 0;
|
||||||
uint32_t _mode;
|
uint32_t _mode;
|
||||||
|
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case 0:
|
case 0:
|
||||||
DEBUG_PUTS("pm_set(): setting BACKUP mode.");
|
DEBUG_PUTS("pm_set(): setting BACKUP mode.");
|
||||||
_mode = PM_SLEEPCFG_SLEEPMODE_BACKUP;
|
_mode = PM_SLEEPCFG_SLEEPMODE_BACKUP;
|
||||||
|
deep = 1;
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
DEBUG_PUTS("pm_set(): setting STANDBY mode.");
|
DEBUG_PUTS("pm_set(): setting STANDBY mode.");
|
||||||
_mode = PM_SLEEPCFG_SLEEPMODE_STANDBY;
|
_mode = PM_SLEEPCFG_SLEEPMODE_STANDBY;
|
||||||
|
deep = 1;
|
||||||
break;
|
break;
|
||||||
default: /* Falls through */
|
default: /* Falls through */
|
||||||
case 2:
|
case 2:
|
||||||
@ -53,5 +56,5 @@ void pm_set(unsigned mode)
|
|||||||
/* make sure value has been set */
|
/* make sure value has been set */
|
||||||
while (PM->SLEEPCFG.bit.SLEEPMODE != _mode) {}
|
while (PM->SLEEPCFG.bit.SLEEPMODE != _mode) {}
|
||||||
|
|
||||||
sam0_cortexm_sleep(0);
|
sam0_cortexm_sleep(deep);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user