From ab50a402d8879daee4fda5b91bb87c4a03339cc2 Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Thu, 28 May 2020 17:05:54 +0200 Subject: [PATCH] hw/mcu/dialog: Add callbacks on enter/exit sleep This patch adds callbacks to be called before and after deep sleep. Those are intended to be registered by BSP which can then decide to save/restore state of certain peripherals and release/acquire power domains in order to save some power while M33 goes into deep sleep. Note that similar power saving can usually be achieved if application uses os_dev_open/close consistently, i.e. opens device only when needed, which should properly acquire and release power domains (although the actual behavior depends on a driver implementation). However, there may still be some cases where quick save/restore is possible and this can be handled in new callbacks. --- .../da1469x/include/mcu/da1469x_sleep.h | 41 +++++++++++++++++++ hw/mcu/dialog/da1469x/src/da1469x_sleep.c | 29 +++++++++++-- 2 files changed, 67 insertions(+), 3 deletions(-) create mode 100755 hw/mcu/dialog/da1469x/include/mcu/da1469x_sleep.h diff --git a/hw/mcu/dialog/da1469x/include/mcu/da1469x_sleep.h b/hw/mcu/dialog/da1469x/include/mcu/da1469x_sleep.h new file mode 100755 index 0000000000..75e72a4d36 --- /dev/null +++ b/hw/mcu/dialog/da1469x/include/mcu/da1469x_sleep.h @@ -0,0 +1,41 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef __MCU_DA1469X_SLEEP_H_ +#define __MCU_DA1469X_SLEEP_H_ + +#include +#include "os/os_time.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct da1469x_sleep_cb { + void (* enter_sleep)(os_time_t ticks); + void (* exit_sleep)(bool slept); +}; + +void da1469x_sleep_cb_register(struct da1469x_sleep_cb *cb); + +#ifdef __cplusplus +} +#endif + +#endif /* __MCU_DA1469X_SLEEP_H_ */ diff --git a/hw/mcu/dialog/da1469x/src/da1469x_sleep.c b/hw/mcu/dialog/da1469x/src/da1469x_sleep.c index a476e83139..691097b0f1 100644 --- a/hw/mcu/dialog/da1469x/src/da1469x_sleep.c +++ b/hw/mcu/dialog/da1469x/src/da1469x_sleep.c @@ -22,6 +22,7 @@ #include "mcu/da1469x_pd.h" #include "mcu/da1469x_pdc.h" #include "mcu/da1469x_prail.h" +#include "mcu/da1469x_sleep.h" #include "mcu/mcu.h" #include "hal/hal_system.h" #include "da1469x_priv.h" @@ -35,6 +36,8 @@ uint8_t g_mcu_pdc_combo_idx; static bool g_mcu_wait_for_jtag; static os_time_t g_mcu_wait_for_jtag_until; +static struct da1469x_sleep_cb g_da1469x_sleep_cb; + static inline bool da1469x_sleep_any_irq_pending(void) { @@ -56,7 +59,7 @@ da1469x_sleep_is_blocked(void) void da1469x_sleep(os_time_t ticks) { - int ret; + int slept; da1469x_pdc_ack_all_m33(); @@ -69,10 +72,19 @@ da1469x_sleep(os_time_t ticks) /* PD_SYS will not be disabled here until we enter deep sleep, so don't wait */ da1469x_pd_release_nowait(MCU_PD_DOMAIN_SYS); + if (g_da1469x_sleep_cb.enter_sleep) { + g_da1469x_sleep_cb.enter_sleep(ticks); + } + mcu_gpio_enter_sleep(); - ret = da1469x_m33_sleep(); + slept = da1469x_m33_sleep(); mcu_gpio_exit_sleep(); - if (!ret) { + + if (g_da1469x_sleep_cb.exit_sleep) { + g_da1469x_sleep_cb.exit_sleep(slept); + } + + if (!slept) { /* We were not sleeping, no need to apply PD_SYS settings again */ da1469x_pd_acquire_noconf(MCU_PD_DOMAIN_SYS); return; @@ -101,6 +113,12 @@ da1469x_sleep(os_time_t ticks) da1469x_clock_sys_xtal32m_switch_safe(); } +void +da1469x_sleep_cb_register(struct da1469x_sleep_cb *cb) +{ + g_da1469x_sleep_cb = *cb; +} + #else void @@ -110,4 +128,9 @@ da1469x_sleep(os_time_t ticks) __WFI(); } +void +da1469x_sleep_cb_register(struct da1469x_sleep_cb *cb) +{ +} + #endif