1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one 3 * or more contributor license agreements. See the NOTICE file 4 * distributed with this work for additional information 5 * regarding copyright ownership. The ASF licenses this file 6 * to you under the Apache License, Version 2.0 (the 7 * "License"); you may not use this file except in compliance 8 * with the License. You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, 13 * software distributed under the License is distributed on an 14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 * KIND, either express or implied. See the License for the 16 * specific language governing permissions and limitations 17 * under the License. 18 */ 19 20 #include <stdbool.h> 21 #include <DA1469xAB.h> 22 #include <da1469x_config.h> 23 #include <da1469x_clock.h> 24 #include <da1469x_pd.h> 25 #include <da1469x_pdc.h> 26 #include <da1469x_sleep.h> 27 28 static int pdc_idx_combo; 29 static bool wait_for_jtag; 30 static struct da1469x_sleep_config sleep_config; 31 static uint32_t sys_clock_selection; 32 da1469x_is_wakeup_by_jtag(void)33static bool da1469x_is_wakeup_by_jtag(void) 34 { 35 return (da1469x_pdc_is_pending(pdc_idx_combo) && 36 !(NVIC->ISPR[0] & ((1 << CMAC2SYS_IRQn) | (1 << KEY_WKUP_GPIO_IRQn) | 37 (1 << VBUS_IRQn)))); 38 } 39 da1469x_is_sleep_allowed(void)40static bool da1469x_is_sleep_allowed(void) 41 { 42 if (wait_for_jtag) { 43 if (CRG_TOP->SYS_STAT_REG & CRG_TOP_SYS_STAT_REG_DBG_IS_ACTIVE_Msk) { 44 wait_for_jtag = false; 45 } 46 return false; 47 } 48 49 /* We can enter extended sleep only if running from RCX or XTAL32K, debugger is 50 * not attached and there are no interrupts pending. 51 */ 52 return (CRG_TOP->CLK_CTRL_REG & CRG_TOP_CLK_CTRL_REG_LP_CLK_SEL_Msk) && 53 !(CRG_TOP->SYS_STAT_REG & CRG_TOP_SYS_STAT_REG_DBG_IS_ACTIVE_Msk) && 54 !((NVIC->ISPR[0] & NVIC->ISER[0]) | (NVIC->ISPR[1] & NVIC->ISER[1])); 55 } 56 da1469x_sleep(void)57int da1469x_sleep(void) 58 { 59 int slept = 0; 60 61 if (!da1469x_is_sleep_allowed()) { 62 __DMB(); 63 __WFI(); 64 return 0; 65 } 66 67 /* PD_SYS will not be disabled here until we enter deep sleep - don't wait */ 68 if (!da1469x_pd_release_nowait(MCU_PD_DOMAIN_SYS)) { 69 __DMB(); 70 __WFI(); 71 } else { 72 da1469x_pdc_ack_all_m33(); 73 sys_clock_selection = CRG_TOP->CLK_CTRL_REG & CRG_TOP_CLK_CTRL_REG_SYS_CLK_SEL_Msk; 74 slept = da1469x_enter_sleep(); 75 if (slept) { 76 /* Watchdog is always resumed when PD_SYS is turned off, need to 77 * freeze it again if there's no one to feed it. 78 */ 79 GPREG->SET_FREEZE_REG = GPREG_SET_FREEZE_REG_FRZ_SYS_WDOG_Msk; 80 SYS_WDOG->WATCHDOG_REG = SYS_WDOG_WATCHDOG_REG_WDOG_VAL_Msk; 81 82 da1469x_pd_acquire(MCU_PD_DOMAIN_SYS); 83 if (da1469x_is_wakeup_by_jtag()) { 84 wait_for_jtag = 1; 85 } 86 if (sys_clock_selection != 1) { 87 da1469x_clock_sys_xtal32m_wait_to_settle(); 88 /* PLL requires that the current system clock be XTAL32M. */ 89 da1469x_clock_sys_xtal32m_switch(); 90 } 91 if (sys_clock_selection == 3 << CRG_TOP_CLK_CTRL_REG_SYS_CLK_SEL_Pos) { 92 da1469x_clock_sys_pll_enable(); 93 da1469x_clock_sys_pll_switch(); 94 } 95 } 96 } 97 98 /* 99 * The SoC did not enter the normal sleep state. Acquire PD_SYS without 100 * applying preferred settings. 101 */ 102 if (slept == 0) { 103 da1469x_pd_acquire_noconf(MCU_PD_DOMAIN_SYS); 104 } 105 106 return slept; 107 } 108 da1469x_sleep_config(const struct da1469x_sleep_config * config)109void da1469x_sleep_config(const struct da1469x_sleep_config *config) 110 { 111 sleep_config = *config; 112 113 pdc_idx_combo = da1469x_pdc_add(MCU_PDC_TRIGGER_COMBO, MCU_PDC_MASTER_M33, 114 sleep_config.enable_xtal_on_wakeup); 115 __ASSERT_NO_MSG(pdc_idx_combo >= 0); 116 da1469x_pdc_set(pdc_idx_combo); 117 da1469x_pdc_ack(pdc_idx_combo); 118 } 119