rt-thread-official/bsp/renesas/ra2l1-cpk/board/drv_pm.c

762 lines
21 KiB
C

/*
* Copyright (c) 2006-2022, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2022-03-22 Sherman first version
*/
// #define DRV_DEBUG
#define DBG_TAG "drv.pm"
#ifdef DRV_DEBUG
#define DBG_LVL DBG_LOG
#else
#define DBG_LVL DBG_INFO
#endif /* DRV_DEBUG */
#include <rtdbg.h>
#include <rtthread.h>
#include <rtdevice.h>
#include <hal_data.h>
#include <drivers/pm.h>
#define RESET_VALUE (0x00)
#define CLOCK_START (0U)
#define CLOCK_STOP (1U)
/* Control block configuration in LPM mode */
#ifdef BSP_LPM_SLEEP
#define LPM_SLEEP_CTRL (lpm_instance_ctrl_t *)&g_lpm_sleep_ctrl
#define LPM_SLEEP_CFG (lpm_cfg_t *)&g_lpm_sleep_cfg
#else
#define LPM_SLEEP_CTRL RT_NULL
#define LPM_SLEEP_CFG RT_NULL
#endif
#ifdef BSP_LPM_STANDBY
#define LPM_SW_STANDBY_CTRL (lpm_instance_ctrl_t *)&g_lpm_sw_standby_ctrl
#define LPM_SW_STANDBY_CFG (lpm_cfg_t *)&g_lpm_sw_standby_cfg
#else
#define LPM_SW_STANDBY_CTRL RT_NULL
#define LPM_SW_STANDBY_CFG RT_NULL
#endif
#ifdef BSP_LPM_SNOOZE
#define LPM_SW_SNOOZE_CTRL (lpm_instance_ctrl_t *)&g_lpm_sw_standby_with_snooze_ctrl
#define LPM_SW_SNOOZE_CFG (lpm_cfg_t *)&g_lpm_sw_standby_with_snooze_cfg
#else
#define LPM_SW_SNOOZE_CFG RT_NULL
#define LPM_SW_SNOOZE_CTRL RT_NULL
#endif
/**
* These are LPM Mode instances for Sleep, Software Standby, Snooze and Deep
* Software Standby Modes.These instances are created by the FSP. We need these
* at the Application level to take the MCU to different LPM modes with configured
* trigger/cancel sources
*/
lpm_instance_ctrl_t *g_lpm_ctrl_instance_ctrls[] =
{
LPM_SLEEP_CTRL,
LPM_SW_STANDBY_CTRL,
LPM_SW_SNOOZE_CTRL,
};
lpm_cfg_t *g_lpm_ctrl_instance_cfgs[] =
{
LPM_SLEEP_CFG,
LPM_SW_STANDBY_CFG,
LPM_SW_SNOOZE_CFG,
};
/**
* Low Power Mode Definitions for LPM app
* Since there are no Normal mode definition in LPM driver, use this enum to keep LPM app state including:
* Sleep, SW Standby, SW Standby with Snooze enabled, Deep SW Standby, Normal.
* Power consumption: NORMAL_STATE > SLEEP_STATE > SW_STANDBY_SNOOZE_STATE > SW_STANDBY_STATE > DEEP_SW_STANDBY_STATE
*/
enum
{
SLEEP_STATE = 0, /* Sleep mode */
SW_STANDBY_STATE, /* SW Standby mode */
SW_STANDBY_SNOOZE_STATE, /* SW Standby mode with Snooze enabled */
DEEP_SW_STANDBY_STATE, /* Deep SW Standby mode */
NORMAL_STATE /* Normal mode */
};
#ifdef DRV_DEBUG
static char *lpmstate_to_string(rt_uint8_t state)
{
switch (state)
{
case SLEEP_STATE:
return "SLEEP";
case SW_STANDBY_STATE:
return "SW STANDBY";
case SW_STANDBY_SNOOZE_STATE:
return "SW STANDBY SNOOZE";
case DEEP_SW_STANDBY_STATE:
return "DEEP SW STANDBY";
case NORMAL_STATE:
return "NORMAL";
default:
return "UNKNOWN";
}
return "UNKNOWN";
}
static char *clk_to_string(cgc_clock_t cstate)
{
switch (cstate)
{
case CGC_CLOCK_HOCO:
return "HOCO CLOCK";
case CGC_CLOCK_MOCO:
return "MOCO CLOCK";
case CGC_CLOCK_LOCO:
return "LOCO CLOCK";
case CGC_CLOCK_MAIN_OSC:
return "MAIN OSC CLOCK";
case CGC_CLOCK_SUBCLOCK:
return "SUB OSC CLOCK";
case CGC_CLOCK_PLL:
return "PLL OSC CLOCK";
default:
return "UNKNOWN";
}
return "UNKNOWN";
}
#endif
/**
* @brief This function enables and puts the MCU in sleep mode.
* @param[IN] Requested LPM Mode and the pointer to it's instance
* @retval FSP_SUCCESS: Upon successful entering sleep mode
* @retval Any Other Error code apart from FSP_SUCCESS
*/
static fsp_err_t lpm_mode_enter(uint8_t lpm_mode, lpm_instance_ctrl_t *const p_current_ctrl)
{
fsp_err_t err = FSP_SUCCESS;
switch (lpm_mode)
{
case SW_STANDBY_STATE:
/* Enter SW Standby mode */
err = R_LPM_LowPowerModeEnter(p_current_ctrl);
break;
case SLEEP_STATE:
/* Enter Sleep mode */
err = R_LPM_LowPowerModeEnter(p_current_ctrl);
break;
case SW_STANDBY_SNOOZE_STATE:
/* Enter SW Standby with Snooze enabled mode */
err = R_LPM_LowPowerModeEnter(p_current_ctrl);
break;
default:
/* return error */
err = FSP_ERR_INVALID_MODE;
break;
}
return err;
}
/**
* @brief Start the LPM mode based on the incoming state
* @param[IN] state: This is requested LPM state
* @retval None.
*/
static void entry_lpm(uint8_t state)
{
if (RT_NULL == g_lpm_ctrl_instance_ctrls[state])
{
return;
}
fsp_err_t err = FSP_SUCCESS;
/* Disable IO port if it's not in Deep SW Standby mode */
if (DEEP_SW_STANDBY_STATE != state)
{
/* Disable IO port before going to LPM mode*/
err = R_IOPORT_PinsCfg(&g_ioport_ctrl, &g_bsp_pin_cfg);
/* Handle error */
if (FSP_SUCCESS != err)
{
LOG_E("Returned Error Code: 0x%x", err);
}
}
/* Open LPM instance*/
err = R_LPM_Open(g_lpm_ctrl_instance_ctrls[state], g_lpm_ctrl_instance_cfgs[state]);
/* Handle error */
if (FSP_SUCCESS != err)
{
LOG_E("Returned Error Code: 0x%x", err);
}
/* Enter LPM mode. Function will return after waking from low power mode. */
err = lpm_mode_enter(state, g_lpm_ctrl_instance_ctrls[state]);
/* Handle error */
if (FSP_SUCCESS == err)
{
/* Close LPM instance.*/
err = R_LPM_Close(g_lpm_ctrl_instance_ctrls[state]);
/* Handle error */
if (FSP_SUCCESS != err)
{
LOG_E("Returned Error Code: 0x%x", err);
}
/* Put IO port configuration back to user's selections */
err = R_IOPORT_PinsCfg(&g_ioport_ctrl, &g_bsp_pin_cfg);
/* Handle error */
if (FSP_SUCCESS != err)
{
LOG_E("Returned Error Code: 0x%x", err);
}
}
else
{
LOG_E("Returned Error Code: 0x%x", err);
}
}
/**********************************************************************************************************************
* @brief This function does necessary setups before entering SW Standby with Snooze enabled.
* @retval FSP_SUCCESS Upon successful checking and starting LOCO clock, AGT1 timer
* @retval Any Other Error code apart from FSP_SUCCESS
**********************************************************************************************************************/
static fsp_err_t standby_snooze_set(void)
{
fsp_err_t err = FSP_SUCCESS;
agt_extended_cfg_t const *p_agt0_extend = agt1_timer_cascade_trigger_cfg.p_extend;
/* Turn off part of the clock before entering Snooze */
err = R_CGC_ClockStop(&g_cgc0_ctrl, CGC_CLOCK_MOCO);
if (FSP_SUCCESS != err)
{
LOG_E("Returned Error Code: 0x%x", err);
}
err = R_CGC_ClockStop(&g_cgc0_ctrl, CGC_CLOCK_MAIN_OSC);
if (FSP_SUCCESS != err)
{
LOG_E("Returned Error Code: 0x%x", err);
}
err = R_CGC_ClockStop(&g_cgc0_ctrl, CGC_CLOCK_SUBCLOCK);
if (FSP_SUCCESS != err)
{
LOG_E("Returned Error Code: 0x%x", err);
}
/*
* Check and start LOCO clock. LOCO is needed since it is selected as AGT1 timer counter source
* CGC module is opened in user_clocks_set function
*/
if (AGT_CLOCK_LOCO == p_agt0_extend->count_source)
{
if (CLOCK_STOP == R_SYSTEM->LOCOCR_b.LCSTP)
{
/* Start LOCO clock */
err = R_CGC_ClockStart(&g_cgc0_ctrl, CGC_CLOCK_LOCO, NULL);
/* Handle error */
if (FSP_SUCCESS != err)
{
return err;
}
/* LOCO does not have Oscillation Stabilization Flag, wait for its stabilization by adding delay */
R_BSP_SoftwareDelay(BSP_FEATURE_CGC_LOCO_STABILIZATION_MAX_US, BSP_DELAY_UNITS_MICROSECONDS);
}
}
return err;
}
static void ra_sleep(struct rt_pm *pm, rt_uint8_t mode)
{
switch (mode)
{
case PM_SLEEP_MODE_NONE:
break;
case PM_SLEEP_MODE_IDLE:
#ifdef BSP_LPM_SLEEP
/* enrty sleep mode */
entry_lpm(SLEEP_STATE);
#else
LOG_W("Disable mode:%s", lpmstate_to_string(SLEEP_STATE));
#endif
break;
case PM_SLEEP_MODE_LIGHT:
LOG_W("PM_SLEEP_MODE_LIGHT:This mode is not supported!");
break;
case PM_SLEEP_MODE_DEEP:
#ifdef BSP_LPM_SNOOZE
/* enrty standby snooze mode */
standby_snooze_set();
entry_lpm(SW_STANDBY_SNOOZE_STATE);
#else
LOG_W("Disable mode:%s", lpmstate_to_string(SW_STANDBY_SNOOZE_STATE));
#endif
break;
case PM_SLEEP_MODE_STANDBY:
#ifdef BSP_LPM_STANDBY
/* enrty standby mode */
entry_lpm(SW_STANDBY_STATE);
#else
LOG_W("Disable mode:%s", lpmstate_to_string(SW_STANDBY_STATE));
#endif
break;
case PM_SLEEP_MODE_SHUTDOWN:
LOG_W("PM_SLEEP_MODE_SHUTDOWN:This mode is not supported!");
break;
default:
RT_ASSERT(0);
break;
}
}
/**
* @brief This function changes the System Clock. Currently MOSC and SOSC are not connected on RA2L1 board.
* So these needs to be turned OFF
*/
static void preffered_ra_clock_setting(void)
{
fsp_err_t err = FSP_SUCCESS;
/* Stop the Main Oscillator as it is not available on RA2L1-EK Board */
err = R_CGC_ClockStop(&g_cgc0_ctrl, CGC_CLOCK_MAIN_OSC);
if (FSP_SUCCESS != err)
{
LOG_E("Returned Error Code: 0x%x", err);
}
/* Stop the Sub Oscillator as it is not available on RA2L1-EK Board */
err = R_CGC_ClockStop(&g_cgc0_ctrl, CGC_CLOCK_SUBCLOCK);
if (FSP_SUCCESS != err)
{
LOG_E("Returned Error Code: 0x%x", err);
}
}
#ifdef R_CGC_H
void uart_update(rt_uint8_t clockmode)
{
baud_setting_t baud_setting;
uint32_t baud_rate = BAUD_RATE_115200;
bool enable_bitrate_modulation = false;
uint32_t error_rate_x_1000 = 5000;
switch (clockmode)
{
case CGC_CLOCK_HOCO:
baud_rate = BAUD_RATE_115200;
break;
case CGC_CLOCK_MOCO:
baud_rate = BAUD_RATE_38400;
break;
case CGC_CLOCK_LOCO:
case CGC_CLOCK_SUBCLOCK:
baud_rate = 600;
break;
default:
baud_rate = BAUD_RATE_115200;
break;
}
fsp_err_t err = R_SCI_UART_BaudCalculate(baud_rate,
enable_bitrate_modulation,
error_rate_x_1000,
&baud_setting);
err = R_SCI_UART_BaudSet(&g_uart9_ctrl, (void *) &baud_setting);
assert(FSP_SUCCESS == err);
}
/**
* @brief This function is used to changes the System Clock.
*/
static void change_system_clock(rt_uint8_t clockmode)
{
fsp_err_t err = FSP_SUCCESS;
cgc_divider_cfg_t sys_divider_cf = { RESET_VALUE };
cgc_clock_t sys_clock_source = { RESET_VALUE };
cgc_clocks_cfg_t sys_clk_cfg = { RESET_VALUE };
cgc_pll_cfg_t new_clk = { RESET_VALUE };
#if defined (CPK_R7FA2L1AB)
preffered_ra_clock_setting();
sys_clk_cfg.mainosc_state = CGC_CLOCK_CHANGE_STOP;
#endif
err = R_CGC_SystemClockGet(&g_cgc0_ctrl, &sys_clock_source, &sys_divider_cf);
if (FSP_SUCCESS != err)
{
LOG_E("Returned Error Code: 0x%x", err);
}
LOG_D("MCU Running with Clock Source = %s.", clk_to_string(sys_clock_source));
switch (clockmode)
{
case CGC_CLOCK_HOCO:
case CGC_CLOCK_MOCO:
{
sys_clock_source = clockmode;
sys_clk_cfg.hoco_state = CGC_CLOCK_CHANGE_START;
sys_clk_cfg.pll_cfg.source_clock = sys_clock_source;
sys_clk_cfg.pll_cfg.divider = CGC_PLL_DIV_1;
sys_clk_cfg.pll_cfg.multiplier = 0;
sys_clk_cfg.pll2_cfg.source_clock = sys_clock_source;
sys_clk_cfg.pll2_cfg.divider = CGC_PLL_DIV_1;
sys_clk_cfg.pll2_cfg.multiplier = 0;
sys_clk_cfg.divider_cfg.pclka_div = CGC_SYS_CLOCK_DIV_1;
sys_clk_cfg.divider_cfg.pclkb_div = CGC_SYS_CLOCK_DIV_2;
sys_clk_cfg.divider_cfg.pclkc_div = CGC_SYS_CLOCK_DIV_1;
sys_clk_cfg.divider_cfg.pclkd_div = CGC_SYS_CLOCK_DIV_1;
sys_clk_cfg.divider_cfg.iclk_div = CGC_SYS_CLOCK_DIV_1;
sys_clk_cfg.divider_cfg.bclk_div = CGC_SYS_CLOCK_DIV_1;
sys_clk_cfg.divider_cfg.fclk_div = CGC_SYS_CLOCK_DIV_1;
break;
}
case CGC_CLOCK_LOCO:
case CGC_CLOCK_SUBCLOCK:
{
sys_clock_source = clockmode;
sys_clk_cfg.hoco_state = CGC_CLOCK_CHANGE_START;
sys_clk_cfg.pll_cfg.source_clock = sys_clock_source;
sys_clk_cfg.pll_cfg.divider = CGC_PLL_DIV_1;
sys_clk_cfg.pll_cfg.multiplier = 0;
sys_clk_cfg.pll2_cfg.source_clock = sys_clock_source;
sys_clk_cfg.pll2_cfg.divider = CGC_PLL_DIV_1;
sys_clk_cfg.pll2_cfg.multiplier = 0;
sys_clk_cfg.divider_cfg.pclka_div = CGC_SYS_CLOCK_DIV_1;
sys_clk_cfg.divider_cfg.pclkb_div = CGC_SYS_CLOCK_DIV_1;
sys_clk_cfg.divider_cfg.pclkc_div = CGC_SYS_CLOCK_DIV_1;
sys_clk_cfg.divider_cfg.pclkd_div = CGC_SYS_CLOCK_DIV_1;
sys_clk_cfg.divider_cfg.iclk_div = CGC_SYS_CLOCK_DIV_1;
sys_clk_cfg.divider_cfg.bclk_div = CGC_SYS_CLOCK_DIV_1;
sys_clk_cfg.divider_cfg.fclk_div = CGC_SYS_CLOCK_DIV_1;
break;
}
default:
{
sys_clock_source = CGC_CLOCK_PLL;
sys_clk_cfg.pll_state = CGC_CLOCK_CHANGE_NONE;
break;
}
}
sys_clk_cfg.system_clock = sys_clock_source;
err = R_CGC_ClocksCfg(&g_cgc0_ctrl, &sys_clk_cfg);
if (FSP_SUCCESS != err)
{
LOG_E("Returned Error Code: 0x%x", err);
}
err = R_CGC_SystemClockSet(&g_cgc0_ctrl, sys_clock_source, &sys_clk_cfg.divider_cfg);
if (FSP_SUCCESS != err)
{
LOG_E("Returned Error Code: 0x%x", err);
}
LOG_D("Requested Clock Source for MCU = %s.", clk_to_string(sys_clock_source));
if (CGC_CLOCK_SUBCLOCK == sys_clock_source)
{
new_clk.source_clock = CGC_CLOCK_SUBCLOCK;
err = R_CGC_ClockStart(&g_cgc0_ctrl, CGC_CLOCK_SUBCLOCK, &new_clk);
if (FSP_SUCCESS != err)
{
LOG_E("Returned Error Code: 0x%x", err);
}
err = R_CGC_ClockStop(&g_cgc0_ctrl, CGC_CLOCK_HOCO);
if (FSP_SUCCESS != err)
{
LOG_E("Returned Error Code: 0x%x", err);
}
err = R_CGC_ClockStop(&g_cgc0_ctrl, CGC_CLOCK_MOCO);
if (FSP_SUCCESS != err)
{
LOG_E("Returned Error Code: 0x%x", err);
}
err = R_CGC_ClockStop(&g_cgc0_ctrl, CGC_CLOCK_LOCO);
if (FSP_SUCCESS != err)
{
LOG_E("Returned Error Code: 0x%x", err);
}
}
else if (CGC_CLOCK_LOCO == sys_clock_source)
{
new_clk.source_clock = CGC_CLOCK_LOCO;
err = R_CGC_ClockStart(&g_cgc0_ctrl, CGC_CLOCK_LOCO, &new_clk);
if (FSP_SUCCESS != err)
{
LOG_E("Returned Error Code: 0x%x", err);
}
err = R_CGC_ClockStop(&g_cgc0_ctrl, CGC_CLOCK_HOCO);
if (FSP_SUCCESS != err)
{
LOG_E("Returned Error Code: 0x%x", err);
}
err = R_CGC_ClockStop(&g_cgc0_ctrl, CGC_CLOCK_MOCO);
if (FSP_SUCCESS != err)
{
LOG_E("Returned Error Code: 0x%x", err);
}
}
else if (CGC_CLOCK_MOCO == sys_clock_source)
{
new_clk.source_clock = CGC_CLOCK_MOCO;
err = R_CGC_ClockStart(&g_cgc0_ctrl, CGC_CLOCK_MOCO, &new_clk);
if (FSP_SUCCESS != err)
{
LOG_E("Returned Error Code: 0x%x", err);
}
err = R_CGC_ClockStop(&g_cgc0_ctrl, CGC_CLOCK_HOCO);
if (FSP_SUCCESS != err)
{
LOG_E("Returned Error Code: 0x%x", err);
}
}
else if (CGC_CLOCK_HOCO == sys_clock_source)
{
new_clk.source_clock = CGC_CLOCK_HOCO;
err = R_CGC_ClockStart(&g_cgc0_ctrl, CGC_CLOCK_HOCO, &new_clk);
if (FSP_SUCCESS != err)
{
LOG_E("Returned Error Code: 0x%x", err);
}
err = R_CGC_ClockStop(&g_cgc0_ctrl, CGC_CLOCK_MOCO);
if (FSP_SUCCESS != err)
{
LOG_E("Returned Error Code: 0x%x", err);
}
}
/* Clock Oscillation Stabilization, wait for its stabilization by adding delay */
R_BSP_SoftwareDelay(BSP_FEATURE_CGC_LOCO_STABILIZATION_MAX_US, BSP_DELAY_UNITS_MICROSECONDS);
extern void rt_hw_systick_init(void);
rt_hw_systick_init();
uart_update(clockmode);
}
static void ra_run(struct rt_pm *pm, rt_uint8_t mode)
{
switch (mode)
{
case PM_RUN_MODE_HIGH_SPEED:
case PM_RUN_MODE_NORMAL_SPEED:
change_system_clock(CGC_CLOCK_HOCO);
break;
case PM_RUN_MODE_MEDIUM_SPEED:
change_system_clock(CGC_CLOCK_MOCO);
break;
case PM_RUN_MODE_LOW_SPEED:
change_system_clock(CGC_CLOCK_LOCO);
break;
default:
break;
}
}
#endif
/* Agt1 serves as a low-power timer */
/**
* @brief This function opens AGT modules
*/
static fsp_err_t agt_timer_init(void)
{
fsp_err_t err = FSP_SUCCESS;
/* Open AGT1 Timer in Periodic mode */
err = R_AGT_Open(&agt1_timer_cascade_trigger_ctrl, &agt1_timer_cascade_trigger_cfg);
return err;
}
/**
* @brief This function starts AGT modules
*/
#define AGT_SECOND_COUNT 512 /* clock_frequency / clock_divider */
#define PERIOD_MAX 0xFFFF
static fsp_err_t agt_timer_start(rt_uint32_t timeout)
{
fsp_err_t err = FSP_SUCCESS;
rt_uint32_t tick = timeout * AGT_SECOND_COUNT / RT_TICK_PER_SECOND;
rt_uint32_t period1 = tick > PERIOD_MAX ? PERIOD_MAX : tick;
if (period1)
{
/* PeriodSet AGT1 timer */
err = R_AGT_PeriodSet(&agt1_timer_cascade_trigger_ctrl, period1);
if (FSP_SUCCESS == err)
{
/* Start AGT1 timer */
err = R_AGT_Start(&agt1_timer_cascade_trigger_ctrl);
}
}
return err;
}
/**
* @brief This function stops AGT modules
*/
static fsp_err_t agt_timer_stop(void)
{
fsp_err_t err = FSP_SUCCESS;
timer_status_t agt_status = {0};
err = R_AGT_StatusGet(&agt1_timer_cascade_trigger_ctrl, &agt_status);
if (FSP_SUCCESS == err)
{
if (agt_status.state)
{
/* Stop Timer */
err = R_AGT_Stop(&agt1_timer_cascade_trigger_ctrl);
if (FSP_SUCCESS == err)
{
/* Reset counter */
err = R_AGT_PeriodSet(&agt1_timer_cascade_trigger_ctrl, 0);
err = R_AGT_Reset(&agt1_timer_cascade_trigger_ctrl);
}
}
}
return err;
}
static rt_uint32_t agt_timer_get(void)
{
rt_uint32_t tick = 0;
rt_uint32_t counter = 0;
timer_status_t agt1_status = {0};
timer_info_t agt1_info = {RESET_VALUE};
/* Stop AGT timers if they are counting */
R_AGT_InfoGet(&agt1_timer_cascade_trigger_ctrl, &agt1_info);
R_AGT_StatusGet(&agt1_timer_cascade_trigger_ctrl, &agt1_status);
counter = agt1_status.counter < agt1_info.period_counts ?
agt1_info.period_counts : (agt1_info.period_counts - agt1_status.counter);
tick = counter * RT_TICK_PER_SECOND / AGT_SECOND_COUNT;
LOG_D("get tick %u counter %u", tick, counter);
return tick;
}
static void ra_timer_start(struct rt_pm *pm, rt_uint32_t timeout)
{
agt_timer_start(timeout);
}
static void ra_timer_stop(struct rt_pm *pm)
{
agt_timer_stop();
}
static rt_tick_t ra_timer_get_tick(struct rt_pm *pm)
{
return agt_timer_get();
}
static const struct rt_pm_ops _ops =
{
ra_sleep,
#ifdef R_CGC_H
ra_run,
#else
RT_NULL,
#endif
ra_timer_start,
ra_timer_stop,
ra_timer_get_tick
};
/**
* @brief This function initializes clock module by opening the CGC Module and Changes the System Clock to MOSC
* @param[IN] None
* @retval FSP_SUCCESS: Upon successful initialization.
* @retval Any Other Error code apart from FSP_SUCCESS
*/
static fsp_err_t init_cgc(void)
{
fsp_err_t err = FSP_SUCCESS;
cgc_clock_t lsys_clock_source = {RESET_VALUE};
cgc_divider_cfg_t sys_divider_cf = {RESET_VALUE};
/* Open CGC module */
err = R_CGC_Open(&g_cgc0_ctrl, &g_cgc0_cfg);
/* Handle error */
if (FSP_SUCCESS == err)
{
/* Get system clock source */
err = R_CGC_SystemClockGet(&g_cgc0_ctrl, &lsys_clock_source, &sys_divider_cf);
/* Handle error */
if (FSP_SUCCESS == err)
{
LOG_D("MCU Running with Clock Source = %s.", clk_to_string(lsys_clock_source));
}
}
return err;
}
/**
* @brief This function initialize the power manager
*/
int drv_pm_hw_init(void)
{
rt_uint8_t timer_mask = 0;
fsp_err_t err = FSP_SUCCESS;
/* Initialize the CGC(Clock Generation Circuit) module.
* The CGC module API is used to dynamically change the required clock source */
err = init_cgc();
if (FSP_SUCCESS != err)
{
LOG_D("CGC Initialization Failed \r\n");
LOG_E("Returned Error Code: 0x%x", err);
return -1;
}
err = agt_timer_init();
if (FSP_SUCCESS != err)
{
LOG_D("AGT Initialization Failed \r\n");
LOG_E("Returned Error Code: 0x%x", err);
return -1;
}
/* initialize timer mask */
timer_mask = (1UL << PM_SLEEP_MODE_DEEP) | (1UL << PM_SLEEP_MODE_STANDBY);
/* initialize system pm module */
rt_system_pm_init(&_ops, timer_mask, RT_NULL);
return 0;
}
INIT_BOARD_EXPORT(drv_pm_hw_init);