1 /*
2  * Copyright (c) 2021 Vestas Wind Systems A/S
3  * Copyright (c) 2021, NXP
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #include <zephyr/kernel.h>
9 #include <zephyr/logging/log.h>
10 #include <zephyr/pm/pm.h>
11 #include <soc.h>
12 
13 LOG_MODULE_DECLARE(power, CONFIG_PM_LOG_LEVEL);
14 
15 #ifdef CONFIG_XIP
wait_for_flash_prefetch_and_idle(void)16 __ramfunc static void wait_for_flash_prefetch_and_idle(void)
17 {
18 	uint32_t i;
19 
20 	for (i = 0; i < 8; i++) {
21 		arch_nop();
22 	}
23 
24 	k_cpu_idle();
25 }
26 #endif /* CONFIG_XIP */
27 
pm_state_set(enum pm_state state,uint8_t substate_id)28 void pm_state_set(enum pm_state state, uint8_t substate_id)
29 {
30 	switch (state) {
31 	case PM_STATE_RUNTIME_IDLE:
32 		k_cpu_idle();
33 		break;
34 	case PM_STATE_SUSPEND_TO_IDLE:
35 		/* Set partial stop mode and enable deep sleep */
36 		SMC->STOPCTRL = SMC_STOPCTRL_PSTOPO(substate_id);
37 		SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
38 #ifdef CONFIG_XIP
39 		wait_for_flash_prefetch_and_idle();
40 #else /* CONFIG_XIP */
41 		k_cpu_idle();
42 #endif /* !CONFIG_XIP */
43 
44 		if (SMC->PMCTRL & SMC_PMCTRL_STOPA_MASK) {
45 			LOG_DBG("partial stop aborted");
46 		}
47 		break;
48 	default:
49 		LOG_WRN("Unsupported power state %u", state);
50 		break;
51 	}
52 }
53 
pm_state_exit_post_ops(enum pm_state state,uint8_t substate_id)54 void pm_state_exit_post_ops(enum pm_state state, uint8_t substate_id)
55 {
56 	ARG_UNUSED(substate_id);
57 
58 	if (state == PM_STATE_SUSPEND_TO_IDLE) {
59 		/* Disable deep sleep upon exit */
60 		SCB->SCR &= ~(SCB_SCR_SLEEPDEEP_Msk);
61 	}
62 
63 	irq_unlock(0);
64 }
65