/**
* \file
*
* \brief SAM L21/L22/R30/R34/R35 Power functionality
*
* Copyright (c) 2014-2018 Microchip Technology Inc. and its subsidiaries.
*
* \asf_license_start
*
* \page License
*
* Subject to your compliance with these terms, you may use Microchip
* software and any derivatives exclusively with Microchip products.
* It is your responsibility to comply with third party license terms applicable
* to your use of third party software (including open source software) that
* may accompany Microchip software.
*
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
* WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
* INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
* AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
* LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
* LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
* SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
* POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT
* ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
* RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
* THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
*
* \asf_license_stop
*
*/
/*
* Support and FAQ: visit Microchip Support
*/
#ifndef POWER_H_INCLUDED
#define POWER_H_INCLUDED
#include
#include
#ifdef __cplusplus
extern "C" {
#endif
/**
* \addtogroup asfdoc_sam0_system_group
* @{
*/
/**
* \brief Device sleep modes.
*
* List of available sleep modes in the device. A table of clocks available in
* different sleep modes can be found in \ref asfdoc_sam0_system_module_overview_sleep_mode.
*/
enum system_sleepmode {
/** IDLE sleep mode */
SYSTEM_SLEEPMODE_IDLE = PM_SLEEPCFG_SLEEPMODE(0x2),
/** STANDBY sleep mode */
SYSTEM_SLEEPMODE_STANDBY = PM_SLEEPCFG_SLEEPMODE_STANDBY,
/** BACKUP sleep mode */
SYSTEM_SLEEPMODE_BACKUP = PM_SLEEPCFG_SLEEPMODE_BACKUP,
/** OFF sleep mode */
SYSTEM_SLEEPMODE_OFF = PM_SLEEPCFG_SLEEPMODE_OFF,
};
/**
* \brief Performance level.
*
* List of performance levels. Performance level technique consists of
* adjusting the regulator output voltage to reduce power consumption.
*/
enum system_performance_level {
/** Performance level 0 */
SYSTEM_PERFORMANCE_LEVEL_0 = PM_PLCFG_PLSEL_PL0,
/** Performance level 2 */
SYSTEM_PERFORMANCE_LEVEL_2 = PM_PLCFG_PLSEL_PL2,
};
/**
* \brief RAM Back-biasing mode.
*
* List of RAM back bias modes. By default, in standby sleep mode,
* RAM is in low power mode (back biased) if its power domain is in
* retention state. This behavior can be changed by configuring the Back Bias
* bit groups in STDBYCFG(STDBYCFG.BBIASxx).
*/
enum system_ram_back_bias_mode {
/** Retention Back biasing mode */
SYSTEM_RAM_BACK_BIAS_RETENTION = 0,
/** Standby Back Biasing mode */
SYSTEM_RAM_BACK_BIAS_STANDBY,
/** Standby OFF mode */
SYSTEM_RAM_BACK_BIAS_STANDBY_OFF,
/** Always OFF mode */
SYSTEM_RAM_BACK_BIAS_OFF,
};
#if SAML21 || SAMR30 || (SAMR34) || (SAMR35)
/**
* \brief Linked power domain.
*
* List of linked power domains. Power domains can be linked to each other.
* It allows a power domain (PDn) to be kept in active state if the inferior
* power domain (PDn-1) is in active state too.
*/
enum system_linked_power_domain {
/** Power domains PD0/PD1/PD2 are not linked */
SYSTEM_LINKED_POWER_DOMAIN_DEFAULT = PM_STDBYCFG_LINKPD_DEFAULT_Val,
/** Power domains PD0 and PD1 are linked */
SYSTEM_LINKED_POWER_DOMAIN_PD01 = PM_STDBYCFG_LINKPD_PD01_Val,
/** Power domains PD1 and PD2 are linked */
SYSTEM_LINKED_POWER_DOMAIN_PD12 = PM_STDBYCFG_LINKPD_PD12_Val,
/** All Power domains are linked */
SYSTEM_LINKED_POWER_DOMAIN_PD012 = PM_STDBYCFG_LINKPD_PD012_Val,
};
#if (SAML21XXXB) || (SAMR30) || (SAMR34) || (SAMR35)
/**
* \brief VREG switching mode.
*
* List of VREG switching modes.
*/
enum system_vreg_switch_mode {
/** Automatic mode. */
SYSTEM_SYSTEM_VREG_SWITCH_AUTO = 0,
/** Performance oriented. */
SYSTEM_SYSTEM_VREG_SWITCH_PERFORMANCE,
/** Low Power consumption oriented. */
SYSTEM_SYSTEM_VREG_SWITCH_LP,
};
#endif
/**
* \brief Power domain.
*
* List of power domains. Power domain gating technique consists of turning
* on or off power domain voltage to save power while keeping other domains
* powered up.
*/
enum system_power_domain {
/** All power domains switching are handled by hardware */
SYSTEM_POWER_DOMAIN_DEFAULT = PM_STDBYCFG_PDCFG_DEFAULT_Val,
/** Power domain 0 (PD0) is forced ACTIVE */
SYSTEM_POWER_DOMAIN_PD0 = PM_STDBYCFG_PDCFG_PD0_Val,
/** Power domain 0 and 1 (PD0 and PD1) are forced ACTIVE */
SYSTEM_POWER_DOMAIN_PD01 = PM_STDBYCFG_PDCFG_PD01_Val,
/** All power domains are forced ACTIVE */
SYSTEM_POWER_DOMAIN_PD012 = PM_STDBYCFG_PDCFG_PD012_Val,
};
#endif
#if SAML22
/**
* \brief Voltage Regulator switch in Standby mode.
*
*/
enum system_vreg_switch_mode {
/** Automatic mode. */
SYSTEM_VREG_SWITCH_AUTO = PM_STDBYCFG_VREGSMOD_AUTO_Val,
/** Performance oriented. */
SYSTEM_VREG_SWITCH_PERFORMANCE = PM_STDBYCFG_VREGSMOD_PERFORMANCE_Val,
/** Low Power consumption oriented. */
SYSTEM_VREG_SWITCH_LP = PM_STDBYCFG_VREGSMOD_LP_Val,
};
#endif
/**
* \brief Voltage regulator.
*
* Voltage regulators selection. In active mode, the voltage regulator
* can be chosen on the fly between a LDO or a Buck converter.
*/
enum system_voltage_regulator_sel {
/** The voltage regulator in active mode is a LDO voltage regulator */
SYSTEM_VOLTAGE_REGULATOR_LDO = SUPC_VREG_SEL_LDO_Val,
/** The voltage regulator in active mode is a buck converter */
SYSTEM_VOLTAGE_REGULATOR_BUCK = SUPC_VREG_SEL_BUCK_Val,
};
/**
* \brief Low power efficiency.
*
* Low power mode efficiency.
*/
enum system_voltage_regulator_low_power_efficiency {
/** The voltage regulator in Low power mode has the default efficiency and
support the whole VDD range (1.62V to 3.6V) */
SYSTEM_VOLTAGE_REGULATOR_LOW_POWER_EFFICIENCY_DEFAULT,
/** The voltage regulator in Low power mode has the highest efficiency and
support the limited VDD range (2.5V to 3.6V) */
SYSTEM_VOLTAGE_REGULATOR_LOW_POWER_EFFICIENCY_HIGHTEST,
};
/**
* \brief Voltage reference value.
*
* Voltage references selection.
*/
enum system_voltage_references_sel {
/** 1.0V voltage reference typical value */
SYSTEM_VOLTAGE_REFERENCE_1V0 = SUPC_VREF_SEL_1V0_Val,
/** 1.1V voltage reference typical value */
SYSTEM_VOLTAGE_REFERENCE_1V1 = SUPC_VREF_SEL_1V1_Val,
/** 1.2V voltage reference typical value */
SYSTEM_VOLTAGE_REFERENCE_1V2 = SUPC_VREF_SEL_1V2_Val,
/** 1.25V voltage reference typical value */
SYSTEM_VOLTAGE_REFERENCE_1V25 = SUPC_VREF_SEL_1V25_Val,
/** 2.0V voltage reference typical value */
SYSTEM_VOLTAGE_REFERENCE_2V0 = SUPC_VREF_SEL_2V0_Val,
/** 2.2V voltage reference typical value */
SYSTEM_VOLTAGE_REFERENCE_2V2 = SUPC_VREF_SEL_2V2_Val,
/** 2.4V voltage reference typical value */
SYSTEM_VOLTAGE_REFERENCE_2V4 = SUPC_VREF_SEL_2V4_Val,
/** 2.5V voltage reference typical value */
SYSTEM_VOLTAGE_REFERENCE_2V5 = SUPC_VREF_SEL_2V5_Val,
};
/**
* \brief Battery power switch configuration enum.
*
* Enum for Battery power switch modes.
*/
enum system_battery_power_switch {
/** The backup domain is always supplied by main power */
SYSTEM_BATTERY_POWER_SWITCH_NONE = SUPC_BBPS_CONF_NONE_Val,
/** The power switch is handled by the automatic power switch */
SYSTEM_BATTERY_POWER_SWITCH_AUTOMATIC = SUPC_BBPS_CONF_APWS_Val,
/** The backup domain is always supplied by battery backup power */
SYSTEM_BATTERY_POWER_SWITCH_FORCED = SUPC_BBPS_CONF_FORCED_Val,
/** The power switch is handled by the BOD33 */
SYSTEM_BATTERY_POWER_SWITCH_BOD33 = SUPC_BBPS_CONF_BOD33_Val,
};
/**
* \brief Voltage reference.
*
* List of available voltage references (VREF) that may be used within the
* device.
*/
enum system_voltage_reference {
/** Temperature sensor voltage reference */
SYSTEM_VOLTAGE_REFERENCE_TEMPSENSE,
/** Voltage reference output */
SYSTEM_VOLTAGE_REFERENCE_OUTPUT,
};
/**
* \brief Backup IO enum.
*
* List of Backup input and output pins.
* If enabled (\ref system_backup_pin_output_enable), the pins can be driven
* by the SUPC.
*/
enum system_backup_pin {
/** Power Supply OK status pin */
SYSTEM_BACKUP_PIN_PSOK = (0x1 << 0),
/** Backup output pin 0 */
SYSTEM_BACKUP_PIN_OUT_0 = (0x1 << 1),
/** Backup output pin 1 */
SYSTEM_BACKUP_PIN_OUT_1 = (0x1 << 2)
};
/**
* \brief Standby configuration.
*
* Configuration structure for standby mode.
*/
struct system_standby_config {
#if SAML21 || SAMR30 || (SAMR34) || (SAMR35)
/** Power domain. */
enum system_power_domain power_domain;
/** Enable dynamic power gating for power domain 0 */
bool enable_dpgpd0;
/** Enable dynamic power gating for power domain 1 */
bool enable_dpgpd1;
#if (SAML21XXXA)
/** Automatic VREG switching disable. */
bool disable_avregsd;
#else
/** VREG switching mode */
enum system_vreg_switch_mode vregs_mode;
#endif
/** Linked power domain */
enum system_linked_power_domain linked_power_domain;
#elif SAML22
/** Regulator switch mode in standby. */
enum system_vreg_switch_mode vreg_switch_mode;
#endif
/** Back bias for HMCRAMCHS. */
enum system_ram_back_bias_mode hmcramchs_back_bias;
/** Back bias for HMCRAMCLP */
enum system_ram_back_bias_mode hmcramclp_back_bias;
};
/**
* \brief Voltage Regulator System (VREG) Control configuration.
*
* Configuration structure for VREG.
*/
struct system_voltage_regulator_config {
/** Voltage scaling period */
uint8_t voltage_scale_period;
/** Voltage scaling voltage step */
uint8_t voltage_scale_step;
/** Run in standby in standby sleep mode */
bool run_in_standby;
/** Voltage Regulator Selection */
enum system_voltage_regulator_sel regulator_sel;
/** Low power efficiency */
enum system_voltage_regulator_low_power_efficiency low_power_efficiency;
#if SAML22 || SAML21XXXB || (SAMR34J) || (SAMR35J)
/** Run in standby in performance level 0. */
bool run_in_standby_pl0;
#endif
};
/**
* \brief Voltage References System (VREF) Control configuration.
*
* Configuration structure for VREF.
*/
struct system_voltage_references_config {
/** Voltage References Selection */
enum system_voltage_references_sel sel;
/** On Demand Control */
bool on_demand;
/** Run in standby */
bool run_in_standby;
#if SAML22
/** Temperature Sensor Selection. */
bool temperature_sensor_sel;
#endif
};
/**
* \brief Battery Backup Power Switch (BBPS) Control configuration.
*
* Configuration structure for Battery Backup Power Switch (BBPS).
*/
struct system_battery_backup_power_switch_config {
/** Enable device wake up when BBPS switches from
battery backup power to main power */
bool wake_enabled;
/** Battery backup power switch configuration */
enum system_battery_power_switch battery_power_switch;
};
/**
* \name Voltage Regulator
* @{
*/
/**
* \brief Retrieve the default configuration for voltage regulator.
*
* Fills a configuration structure with the default configuration:
* - Voltage scaling period is 1μs
* - Voltage scaling voltage step is 2*min_step
* - The voltage regulator is in low power mode in Standby sleep mode
* - The voltage regulator in active mode is an LDO voltage regulator
* - The voltage regulator in Low power mode has the default efficiency
*
* \param[out] config Configuration structure to fill with default values
*/
static inline void system_voltage_regulator_get_config_defaults(
struct system_voltage_regulator_config *const config)
{
Assert(config);
config->voltage_scale_period = 0;
config->voltage_scale_step = 0;
config->run_in_standby = false;
config->regulator_sel = SYSTEM_VOLTAGE_REGULATOR_LDO;
config->low_power_efficiency = SYSTEM_VOLTAGE_REGULATOR_LOW_POWER_EFFICIENCY_DEFAULT;
#if SAML22 || SAML21XXXB || SAMR34J || SAMR35J
config->run_in_standby_pl0 = false;
#endif
}
/**
* \brief Configure voltage regulator.
*
* Configures voltage regulator with the given configuration.
*
* \param[in] config Voltage regulator configuration structure containing
* the new config
*/
static inline void system_voltage_regulator_set_config(
struct system_voltage_regulator_config *const config)
{
Assert(config);
SUPC->VREG.bit.VSPER = config->voltage_scale_period;
SUPC->VREG.bit.VSVSTEP = config->voltage_scale_step;
SUPC->VREG.bit.RUNSTDBY = config->run_in_standby;
SUPC->VREG.bit.SEL = config->regulator_sel;
#if (SAML21XXXB) || (SAMR30) || (SAMR34) || (SAMR35)
SUPC->VREG.bit.LPEFF = config->low_power_efficiency;
#endif
#if SAML22 || SAML21XXXB || SAMR34J || SAMR35J
SUPC->VREG.bit.STDBYPL0 = config->run_in_standby_pl0;
#endif
while(!(SUPC->STATUS.reg & SUPC_STATUS_VREGRDY)) {
;
}
}
/**
* \brief Enable the selected voltage regulator.
*
* Enables the selected voltage regulator source.
*/
static inline void system_voltage_regulator_enable(void)
{
SUPC->VREG.reg |= SUPC_VREG_ENABLE;
}
/**
* \brief Disable the selected voltage regulator.
*
* Disables the selected voltage regulator.
*/
static inline void system_voltage_regulator_disable(void)
{
SUPC->VREG.reg &= ~SUPC_VREG_ENABLE;
}
/**
* @}
*/
/**
* \name Voltage References
* @{
*/
/**
* \brief Retrieve the default configuration for voltage reference.
*
* Fill a configuration structure with the default configuration:
* - 1.0V voltage reference typical value
* - On demand control disabled
* - The voltage reference and the temperature sensor are halted during standby sleep mode
*
* \param[out] config Configuration structure to fill with default values
*/
static inline void system_voltage_reference_get_config_defaults(
struct system_voltage_references_config *const config)
{
Assert(config);
config->sel = SYSTEM_VOLTAGE_REFERENCE_1V0;
config->on_demand = false;
config->run_in_standby = false;
#if SAML22
config->temperature_sensor_sel = false;
#endif
}
/**
* \brief Configure voltage reference.
*
* Configures voltage reference with the given configuration.
*
* \param[in] config Voltage reference configuration structure containing
* the new config
*/
static inline void system_voltage_reference_set_config(
struct system_voltage_references_config *const config)
{
Assert(config);
SUPC->VREF.bit.SEL = config->sel;
SUPC->VREF.bit.ONDEMAND = config->on_demand;
SUPC->VREF.bit.RUNSTDBY = config->run_in_standby;
#if SAML22
SUPC->VREF.bit.TSSEL = config->temperature_sensor_sel;
#endif
}
/**
* \brief Enable the selected voltage reference.
*
* Enables the selected voltage reference source, making the voltage reference
* available on a pin as well as an input source to the analog peripherals.
*
* \param[in] vref Voltage reference to enable
*/
static inline void system_voltage_reference_enable(
const enum system_voltage_reference vref)
{
switch (vref) {
case SYSTEM_VOLTAGE_REFERENCE_TEMPSENSE:
SUPC->VREF.reg |= SUPC_VREF_TSEN;
break;
case SYSTEM_VOLTAGE_REFERENCE_OUTPUT:
SUPC->VREF.reg |= SUPC_VREF_VREFOE;
break;
default:
Assert(false);
return;
}
}
/**
* \brief Disable the selected voltage reference.
*
* Disables the selected voltage reference source.
*
* \param[in] vref Voltage reference to disable
*/
static inline void system_voltage_reference_disable(
const enum system_voltage_reference vref)
{
switch (vref) {
case SYSTEM_VOLTAGE_REFERENCE_TEMPSENSE:
SUPC->VREF.reg &= ~SUPC_VREF_TSEN;
break;
case SYSTEM_VOLTAGE_REFERENCE_OUTPUT:
SUPC->VREF.reg &= ~SUPC_VREF_VREFOE;
break;
default:
Assert(false);
return;
}
}
/**
* @}
*/
/**
* \name Battery Backup Power Switch
* @{
*/
/**
* \brief Retrieve the default configuration for battery backup power switch control.
*
* Fills a configuration structure with the default configuration:
* - The main Power Supply OK status is not available on the PSOK pin
* - The device is not woken up when switched from battery backup power to main power
* - The backup domain is always supplied by main power
*
* \param[out] config Configuration structure to fill with default values
*/
static inline void system_battery_backup_power_switch_get_config_defaults(
struct system_battery_backup_power_switch_config *const config)
{
Assert(config);
config->wake_enabled = false;
config->battery_power_switch = SYSTEM_BATTERY_POWER_SWITCH_NONE;
}
/**
* \brief Configure battery backup power switch.
*
* Configures battery backup power switch with the given configuration.
*
* \param[in] config Battery backup power switch configuration structure containing
* the new config
*/
static inline void system_battery_backup_power_switch_set_config(
struct system_battery_backup_power_switch_config *const config)
{
Assert(config);
uint32_t new_config = SUPC->BBPS.reg & SUPC_BBPS_PSOKEN;
if(config->wake_enabled) {
new_config |= SUPC_BBPS_WAKEEN;
}
new_config |= SUPC_BBPS_CONF(config->battery_power_switch);
SUPC->BBPS.reg = new_config;
if (config->battery_power_switch == SYSTEM_BATTERY_POWER_SWITCH_AUTOMATIC) {
while (!(SUPC->STATUS.reg & SUPC_STATUS_APWSRDY)) {
;
}
}
}
/**
* @}
*/
/**
* \name Output Pins in Backup Mode
* @{
*/
/**
* \brief Enable the backup pin output.
*
* The output is enabled and driven by the SUPC.
*
* \param[in] pin Backup pin index
*/
static inline void system_backup_pin_output_enable(
enum system_backup_pin pin)
{
if (pin == SYSTEM_BACKUP_PIN_PSOK) {
SUPC->BBPS.reg |= SUPC_BBPS_PSOKEN;
} else {
SUPC->BKOUT.reg |= SUPC_BKOUT_EN(pin >> 1);
}
}
/**
* \brief Disable the backup pin output.
*
* The output is not enabled.
*
* \param[in] pin Backup pin index
*/
static inline void system_backup_pin_output_disable(
enum system_backup_pin pin)
{
if (pin == SYSTEM_BACKUP_PIN_PSOK) {
SUPC->BBPS.reg &= ~SUPC_BBPS_PSOKEN;
} else {
SUPC->BKOUT.reg &= ~SUPC_BKOUT_EN(pin >> 1);
}
}
/**
* \brief Check if backup pin output is enabled.
*
* \param[in] pin Backup pin index
*
* \return The enabled status.
* \retval true The output is enabled
* \retval false The output is not enabled
*/
static inline bool system_backup_pin_output_is_enabled(
enum system_backup_pin pin)
{
bool enabled = false;
if (pin == SYSTEM_BACKUP_PIN_PSOK) {
if (SUPC->BBPS.reg & SUPC_BBPS_PSOKEN) {
enabled = true;
}
} else {
if (SUPC->BKOUT.reg & SUPC_BKOUT_EN(pin >> 1)) {
enabled = true;
}
}
return enabled;
}
/**
* \brief Enable the backup pin toggle on RTC event.
*
* Toggle output on RTC event is enabled.
*
* \param[in] pin Backup pin index
*/
static inline void system_backup_pin_output_enable_rtc_toggle(
enum system_backup_pin pin)
{
Assert(pin != SYSTEM_BACKUP_PIN_PSOK);
SUPC->BKOUT.reg |= SUPC_BKOUT_RTCTGL(pin >> 1);
}
/**
* \brief Disable the backup pin toggle on RTC event.
*
* Toggle output on RTC event is disabled.
*
* \param[in] pin Backup pin index
*/
static inline void system_backup_pin_output_disable_rtc_toggle(
enum system_backup_pin pin)
{
Assert(pin != SYSTEM_BACKUP_PIN_PSOK);
SUPC->BKOUT.reg &= ~SUPC_BKOUT_RTCTGL(pin >> 1);
}
/**
* \brief Set the backup pin.
*
* Set the corresponding output pin.
*
* \param[in] pin Backup pin index
*/
static inline void system_backup_pin_output_set(
enum system_backup_pin pin)
{
Assert(pin != SYSTEM_BACKUP_PIN_PSOK);
SUPC->BKOUT.reg |= SUPC_BKOUT_SET(pin >> 1);
}
/**
* \brief Clear the backup pin.
*
* Clear the corresponding output.
*
* \param[in] pin Backup pin index
*/
static inline void system_backup_pin_output_clear(
enum system_backup_pin pin)
{
Assert(pin != SYSTEM_BACKUP_PIN_PSOK);
SUPC->BKOUT.reg |= SUPC_BKOUT_CLR(pin >> 1);
}
/**
* \brief Get the backup I/O input values.
*
* Get the backup I/O data input values. If the corresponding pin is enabled,
* the I/O input value is given on the pin.
*
* \param[in] pin Backup pin index
*
* \return The backup I/O input level value.
*/
static inline bool system_backup_pin_output_get(enum system_backup_pin pin)
{
Assert(pin != SYSTEM_BACKUP_PIN_PSOK);
return (SUPC->BKIN.reg & SUPC_BKIN_BKIN(pin >> 1));
}
/**
* @}
*/
/**
* \name Device Sleep Control
* @{
*/
/**
* \brief Set the sleep mode of the device.
*
* Sets the sleep mode of the device; the configured sleep mode will be entered
* upon the next call of the \ref system_sleep() function.
*
* For an overview of which systems are disabled in sleep for the different
* sleep modes, see \ref asfdoc_sam0_system_module_overview_sleep_mode.
*
* \param[in] sleep_mode Sleep mode to configure for the next sleep operation
*/
static inline void system_set_sleepmode(
const enum system_sleepmode sleep_mode)
{
PM->SLEEPCFG.reg = sleep_mode;
while(PM->SLEEPCFG.reg != sleep_mode) ;
}
/**
* \brief Put the system to sleep waiting for interrupt.
*
* Executes a device DSB (Data Synchronization Barrier) instruction to ensure
* all ongoing memory accesses have completed. Further, a WFI (Wait For Interrupt)
* instruction is executed to place the device into the sleep mode specified by
* \ref system_set_sleepmode.
*/
static inline void system_sleep(void)
{
__DSB();
__WFI();
}
/**
* @}
*/
/**
* \name Performance Level Control
* @{
*/
/**
* \brief Switch performance level.
*
* The bus frequency must be reduced prior to scaling down the performance level,
* in order to not exceed the maximum frequency allowed for the performance level.
*
* When scaling up the performance level (for example from PL0 to PL2), the bus
* frequency can be increased first when the performance level transition is
* completed. Check the performance level status before increasing the frequency.
*
* \param[in] performance_level Performance level to switch
*
* \retval STATUS_ERR_INVALID_ARG Invalid parameter
* \retval STATUS_OK Successfully
*/
static inline enum status_code system_switch_performance_level(
const enum system_performance_level performance_level)
{
if (performance_level == (enum system_performance_level)PM->PLCFG.reg) {
return STATUS_OK;
}
#if SAML22 || SAML21XXXB || SAMR34J || SAMR35J
if (PM->PLCFG.reg & PM_PLCFG_PLDIS) {
return STATUS_ERR_INVALID_ARG;
}
#endif
/* Clear performance level status */
PM->INTFLAG.reg = PM_INTFLAG_PLRDY;
/* Switch performance level */
PM->PLCFG.reg = performance_level;
/* Waiting performance level ready */
while (!PM->INTFLAG.reg) {
;
}
return STATUS_OK;
}
#if SAML22 || SAML21XXXB || SAMR34J || SAMR35J
/**
* \brief Enable performance level switch.
*
* Enable performance level switch.
*/
static inline void system_performance_level_enable(void)
{
PM->PLCFG.reg &= ~PM_PLCFG_PLDIS;
}
/**
* \brief Disable performance level switch.
*
* Disable performance level switch.
*/
static inline void system_performance_level_disable(void)
{
PM->PLCFG.reg |= PM_PLCFG_PLDIS;
}
#endif
/**
* \brief Get performance level.
*
* Get performance level.
*
* \return Current performance level.
*/
static inline enum system_performance_level system_get_performance_level(void)
{
return (enum system_performance_level)PM->PLCFG.reg;
}
/**
* \brief Get performance level status.
*
* Get performance level status.
* \return Performance level status: Written to one when the performance level is ready.
*/
static inline uint8_t system_get_performance_level_status(void)
{
return PM->INTFLAG.reg;
}
/**
* \brief Clear performance level status.
*
* Clear performance level status.
*/
static inline void system_clear_performance_level_status(void)
{
PM->INTFLAG.reg = PM_INTFLAG_PLRDY;
}
/**
* @}
*/
/**
* \name Standby Configuration
* @{
*/
/**
* \brief Retrieve the default configuration for standby.
*
* Fills a configuration structure with the default configuration for standby:
* - Retention back biasing mode for HMCRAMCLP
* - Retention back biasing mode for HMCRAMCHS
* - Power domains PD0/PD1/PD2 are not linked
* - Automatic VREG switching is used
* - Dynamic power gating for power domain 1 is disabled
* - Dynamic power gating for power domain 0 is disabled
* - All power domains switching are handled by hardware
*
* \param[out] config Configuration structure to fill with default values
*/
static inline void system_standby_get_config_defaults(
struct system_standby_config *const config)
{
Assert(config);
#if SAML21 || SAMR30 || (SAMR34) || (SAMR35)
config->power_domain = SYSTEM_POWER_DOMAIN_DEFAULT;
config->enable_dpgpd0 = false;
config->enable_dpgpd1 = false;
#if (SAML21XXXB) || (SAMR30) || (SAMR34) || (SAMR35)
config->vregs_mode = SYSTEM_SYSTEM_VREG_SWITCH_AUTO;
#else
config->disable_avregsd = false;
#endif
config->linked_power_domain = SYSTEM_LINKED_POWER_DOMAIN_DEFAULT;
#elif SAML22
config->vreg_switch_mode = SYSTEM_VREG_SWITCH_AUTO;
#endif
config->hmcramchs_back_bias = SYSTEM_RAM_BACK_BIAS_RETENTION;
config->hmcramclp_back_bias = SYSTEM_RAM_BACK_BIAS_RETENTION;
}
/**
* \brief Configure standby mode.
*
* Configures standby with the given configuration.
*
* \param[in] config Standby configuration structure containing
* the new config
*/
static inline void system_standby_set_config(
struct system_standby_config *const config)
{
Assert(config);
#if SAML21 || SAMR30 || (SAMR34) || (SAMR35)
PM->STDBYCFG.reg = PM_STDBYCFG_PDCFG(config->power_domain)
| (config->enable_dpgpd0 << PM_STDBYCFG_DPGPD0_Pos)
| (config->enable_dpgpd1 << PM_STDBYCFG_DPGPD1_Pos)
#if (SAML21XXXB) || (SAMR30) || (SAMR34) || (SAMR35)
| PM_STDBYCFG_VREGSMOD(config->vregs_mode)
#else
| (config->disable_avregsd << PM_STDBYCFG_AVREGSD_Pos)
#endif
| PM_STDBYCFG_LINKPD(config->linked_power_domain)
| PM_STDBYCFG_BBIASHS(config->hmcramchs_back_bias)
| PM_STDBYCFG_BBIASLP(config->hmcramclp_back_bias);
#elif SAML22
PM->STDBYCFG.reg = PM_STDBYCFG_VREGSMOD(config->vreg_switch_mode) |
PM_STDBYCFG_BBIASHS(config->hmcramchs_back_bias);
#endif
}
/**
* @}
*/
/**
* \name I/O Retention
* @{
*/
/**
* \brief Enable I/O retention.
*
* Enable I/O retention. After waking up from Backup mode, I/O lines are held
* until the bit is written to 0.
*/
static inline void system_io_retension_enable(void)
{
PM->CTRLA.reg = PM_CTRLA_IORET;
}
/**
* \brief Disable I/O retention.
*
* Disable IO retention. After waking up from Backup mode, I/O lines are not held.
*/
static inline void system_io_retension_disable(void)
{
PM->CTRLA.reg = PM_CTRLA_MASK & (~PM_CTRLA_IORET);
}
/**
* @}
*/
/** @} */
#ifdef __cplusplus
}
#endif
#endif /* POWER_H_INCLUDED */