1 /*
2  * Copyright (c) 2024 Ambiq Micro Inc.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <soc.h>
8 
9 #include <zephyr/drivers/interrupt_controller/gic.h>
10 #include <zephyr/kernel.h>
11 #include <zephyr/logging/log.h>
12 #include <zephyr/pm/pm.h>
13 #include <zephyr/init.h>
14 
15 /* ambiq-sdk includes */
16 #include <am_mcu_apollo.h>
17 
18 LOG_MODULE_DECLARE(soc, CONFIG_SOC_LOG_LEVEL);
19 
pm_state_set(enum pm_state state,uint8_t substate_id)20 void pm_state_set(enum pm_state state, uint8_t substate_id)
21 {
22 	ARG_UNUSED(substate_id);
23 
24 	__disable_irq();
25 	__set_BASEPRI(0);
26 
27 	switch (state) {
28 	case PM_STATE_SUSPEND_TO_IDLE:
29 		/* Put ARM core to normal sleep. */
30 		am_hal_sysctrl_sleep(AM_HAL_SYSCTRL_SLEEP_NORMAL);
31 		break;
32 	case PM_STATE_SUSPEND_TO_RAM:
33 		/* Put ARM core to deep sleep. */
34 		/* Cotex-m: power down, register value preserve.*/
35 		/* Cache: power down*/
36 		/* Flash: power down*/
37 		/* Sram: retention*/
38 		am_hal_sysctrl_sleep(AM_HAL_SYSCTRL_SLEEP_DEEP);
39 		break;
40 	default:
41 		LOG_DBG("Unsupported power state %u", state);
42 		break;
43 	}
44 }
45 
46 /**
47  * @brief PM State Exit Post Operations
48  *
49  * For PM_STATE_SUSPEND_TO_IDLE:
50  *   Nothing is needed after soc woken up.
51  *
52  * For PM_STATE_SUSPEND_TO_RAM:
53  *   Flash, cache, sram automatically switch
54  *   to active state on wake up
55  *
56  * @param state PM State
57  * @param substate_id Unused
58  *
59  */
pm_state_exit_post_ops(enum pm_state state,uint8_t substate_id)60 void pm_state_exit_post_ops(enum pm_state state, uint8_t substate_id)
61 {
62 	ARG_UNUSED(substate_id);
63 
64 	__enable_irq();
65 	irq_unlock(0);
66 }
67 
ambiq_power_init(void)68 void ambiq_power_init(void)
69 {
70 	/* Enable flash.
71 	 * Currently all flash area is powered on, but we should only enable the used flash area and
72 	 * put unused flash in power down mode.
73 	 */
74 	if (am_hal_pwrctrl_memory_enable(AM_HAL_PWRCTRL_MEM_FLASH_MAX)) {
75 		__ASSERT(0, "Failed to enable FLASH!");
76 	}
77 
78 	/* Enable SRAM.
79 	 * Currently all SRAM area is powered on, but we should only enable the used ram area and
80 	 * put unused ram in power down mode.
81 	 */
82 	if (am_hal_pwrctrl_memory_enable(AM_HAL_PWRCTRL_MEM_SRAM_MAX)) {
83 		__ASSERT(0, "Failed to enable SRAM!");
84 	}
85 
86 	/* For optimal Deep Sleep current, configure cache to be powered-down in deepsleep. */
87 	am_hal_pwrctrl_memory_deepsleep_powerdown(AM_HAL_PWRCTRL_MEM_CACHE);
88 
89 	/* Power off all flash area, when go to deep sleep.*/
90 	am_hal_pwrctrl_memory_deepsleep_powerdown(AM_HAL_PWRCTRL_MEM_FLASH_MAX);
91 
92 	/* Keep the used SRAM area in retention mode. */
93 	am_hal_pwrctrl_memory_deepsleep_powerdown(AM_HAL_PWRCTRL_MEM_SRAM_MAX);
94 	am_hal_pwrctrl_memory_deepsleep_retain(AM_HAL_PWRCTRL_MEM_SRAM_MAX);
95 
96 #if defined(CONFIG_SOC_APOLLO3P_BLUE)
97 	/*
98 	 * If user has enabled AM_HAL_SYSCTRL_DEEPSLEEP_WA in am_hal_sysctrl.h
99 	 * this will allow user to acheive lower current draw in deepsleep
100 	 */
101 	am_hal_sysctrl_control(AM_HAL_SYSCTRL_CONTROL_DEEPSLEEP_MINPWR_EN, 0);
102 #endif
103 }
104