1 /*
2  * Copyright (c) 2021 Vestas Wind Systems A/S
3  * Copyright 2021, 2024 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 
wait_for_flash_prefetch_and_idle(void)15 __ramfunc static void wait_for_flash_prefetch_and_idle(void)
16 {
17 	uint32_t i;
18 
19 	for (i = 0; i < 8; i++) {
20 		arch_nop();
21 	}
22 
23 	k_cpu_idle();
24 }
25 
pm_state_set(enum pm_state state,uint8_t substate_id)26 void pm_state_set(enum pm_state state, uint8_t substate_id)
27 {
28 	switch (state) {
29 	case PM_STATE_RUNTIME_IDLE:
30 		k_cpu_idle();
31 		break;
32 	case PM_STATE_SUSPEND_TO_IDLE:
33 		/* Set partial stop mode and enable deep sleep */
34 		SMC->STOPCTRL = SMC_STOPCTRL_PSTOPO(substate_id);
35 		SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
36 		if (IS_ENABLED(CONFIG_XIP)) {
37 			wait_for_flash_prefetch_and_idle();
38 		} else {
39 			k_cpu_idle();
40 		}
41 		if (SMC->PMCTRL & SMC_PMCTRL_STOPA_MASK) {
42 			LOG_DBG("partial stop aborted");
43 		}
44 		break;
45 	default:
46 		LOG_WRN("Unsupported power state %u", state);
47 		break;
48 	}
49 }
50 
pm_state_exit_post_ops(enum pm_state state,uint8_t substate_id)51 void pm_state_exit_post_ops(enum pm_state state, uint8_t substate_id)
52 {
53 	ARG_UNUSED(substate_id);
54 
55 	if (state == PM_STATE_SUSPEND_TO_IDLE) {
56 		/* Disable deep sleep upon exit */
57 		SCB->SCR &= ~(SCB_SCR_SLEEPDEEP_Msk);
58 	}
59 
60 	irq_unlock(0);
61 }
62