soc: arm: smartbond: Add support for extended sleep

This enabled extended sleep for Renesas SmartBond(tm).

Extended sleep is low power mode where ARM core is powered off and can
be woken up by PDC. This is default sleep mode when CONFIG_PM is
enabled.

Signed-off-by: Andrzej Kaczmarek <andrzej.kaczmarek@codecoup.pl>
Signed-off-by: Jerzy Kasenberg <jerzy.kasenberg@codecoup.pl>
This commit is contained in:
Andrzej Kaczmarek 2023-03-22 14:30:11 +01:00 committed by Carles Cufí
parent 8ccc345c6e
commit fbc7a9e209
6 changed files with 110 additions and 1 deletions

View file

@ -75,6 +75,29 @@ void sys_clock_set_timeout(int32_t ticks, bool idle)
/* FIXME we could disable timer here */
}
/*
* When Watchdog is NOT enabled but power management is, system
* starts watchdog before PD_SYS is powered off.
* Watchdog default reload value is 0x1FFF (~82s for RC32K and 172s for RCX).
* After this time watchdog will reset system if not woken up before.
* When Watchdog is not configured power management freezes watchdog
* as soon as system is awaken. Following code makes sure that
* system never goes to sleep for longer time that watchdog reload value.
*/
if (!IS_ENABLED(CONFIG_WDT_SMARTBOND) && IS_ENABLED(CONFIG_PM)) {
uint32_t watchdog_expire_ticks;
if (CRG_TOP->CLK_RCX_REG & CRG_TOP_CLK_RCX_REG_RCX_ENABLE_Msk) {
watchdog_expire_ticks = SYS_WDOG->WATCHDOG_REG * 21 *
CONFIG_SYS_CLOCK_TICKS_PER_SEC / 1000;
} else {
watchdog_expire_ticks = SYS_WDOG->WATCHDOG_REG *
CONFIG_SYS_CLOCK_TICKS_PER_SEC / 100;
}
if (watchdog_expire_ticks - 2 < ticks) {
ticks = watchdog_expire_ticks - 2;
}
}
ticks = (ticks == K_TICKS_FOREVER) ? MAX_TICKS : ticks;
ticks = CLAMP(ticks - 1, 0, (int32_t)MAX_TICKS);

View file

@ -28,6 +28,16 @@
compatible = "arm,cortex-m33f";
reg = <0>;
clock-frequency = <32000000>;
cpu-power-states = <&standby>;
};
power-states {
standby: standby {
compatible = "zephyr,power-state";
power-state-name = "standby";
min-residency-us = <500>;
exit-latency-us = <100>;
};
};
};

View file

@ -8,5 +8,6 @@ zephyr_linker_sources(
zephyr_library()
zephyr_library_sources(soc.c)
zephyr_include_directories(.)
zephyr_library_sources_ifdef(CONFIG_PM power.c)
set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "")

View file

@ -9,6 +9,7 @@ config SOC_SERIES_DA1469X
select CPU_CORTEX_M_HAS_SYSTICK
select ARMV8_M_DSP
select HAS_SEGGER_RTT if ZEPHYR_SEGGER_MODULE
select HAS_PM
select CLOCK_CONTROL
select CLOCK_CONTROL_SMARTBOND
select PLATFORM_SPECIFIC_INIT

View file

@ -0,0 +1,55 @@
/*
* Copyright (c) 2023 Renesas Electronics Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/init.h>
#include <zephyr/pm/pm.h>
#include <zephyr/logging/log.h>
#include <DA1469xAB.h>
#include <da1469x_clock.h>
#include <da1469x_sleep.h>
LOG_MODULE_DECLARE(soc, CONFIG_SOC_LOG_LEVEL);
void pm_state_set(enum pm_state state, uint8_t substate_id)
{
ARG_UNUSED(substate_id);
switch (state) {
case PM_STATE_STANDBY:
/* We enter here with interrupts disabled by BASEPRI which prevents wfi from
* waking up on interrupts. Need to disable interrupts by PRIMASK instead and
* reset BASEPRI to 0.
*/
__disable_irq();
arch_irq_unlock(0);
da1469x_sleep();
break;
default:
LOG_DBG("Unsupported power state %u", state);
break;
}
}
void pm_state_exit_post_ops(enum pm_state state, uint8_t substate_id)
{
ARG_UNUSED(state);
ARG_UNUSED(substate_id);
}
static int renesas_da1469x_pm_init(void)
{
static const struct da1469x_sleep_config sleep_cfg = {
.enable_xtal_on_wakeup = DT_NODE_HAS_STATUS(DT_NODELABEL(xtal32m), okay),
};
da1469x_sleep_config(&sleep_cfg);
return 0;
}
SYS_INIT(renesas_da1469x_pm_init, PRE_KERNEL_2, 2);

View file

@ -6,6 +6,7 @@
#include <zephyr/init.h>
#include <zephyr/linker/linker-defs.h>
#include <zephyr/logging/log.h>
#include <string.h>
#include <DA1469xAB.h>
#include <da1469x_clock.h>
@ -13,7 +14,9 @@
#include <da1469x_pd.h>
#include <da1469x_pdc.h>
#include <da1469x_trimv.h>
#include <cmsis_core.h>
#include <da1469x_sleep.h>
LOG_MODULE_REGISTER(soc, CONFIG_SOC_LOG_LEVEL);
#define REMAP_ADR0_QSPI 0x2
@ -108,15 +111,31 @@ static void z_renesas_configure_cache(void)
void z_arm_platform_init(void)
{
#if defined(CONFIG_PM)
uint32_t *ivt;
#endif
#if defined(CONFIG_BOOTLOADER_MCUBOOT)
z_renesas_configure_cache();
#endif
#if defined(CONFIG_PM)
/* IVT is always placed in reserved space at the start of RAM which
* is then remapped to 0x0 and retained. Generic reset handler is
* changed to custom routine since next time ARM core is reset we
* need to determine whether it was a regular reset or a wakeup from
* extended sleep and ARM core state needs to be restored.
*/
ivt = (uint32_t *)_image_ram_start;
ivt[1] = (uint32_t)da1469x_wakeup_handler;
#endif
}
static int renesas_da1469x_init(void)
{
/* Freeze watchdog until configured */
GPREG->SET_FREEZE_REG = GPREG_SET_FREEZE_REG_FRZ_SYS_WDOG_Msk;
SYS_WDOG->WATCHDOG_REG = SYS_WDOG_WATCHDOG_REG_WDOG_VAL_Msk;
/* Reset clock dividers to 0 */
CRG_TOP->CLK_AMBA_REG &= ~(CRG_TOP_CLK_AMBA_REG_HCLK_DIV_Msk |