2 * Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 /******************************************************************************
18 * @brief CSI Source File for Embedded Flash Driver
21 ******************************************************************************/
27 #include "drv_eflash.h"
30 #define ERR_PMU(errno) (CSI_DRV_ERRNO_PMU_BASE | errno)
31 #define PMU_NULL_PARAM_CHK(para) \
34 return ERR_PMU(EDRV_PARAMETER); \
43 pmu_action_cb_t callback[32];
46 extern int32_t target_get_pmu(int32_t idx, uint32_t *base, uint32_t *irq);
47 extern int32_t arch_do_cpu_save(void);
48 extern int32_t arch_do_cpu_resume(void);
49 extern int32_t arch_resume_context(void);
51 static ck_pmu_priv_t pmu_handle[CONFIG_PMU_NUM];
52 static uint32_t s_callback_count = 0;
53 #define CONFIG_PMU_REGISTER_NUM_SAVE 19
54 static uint32_t pmu_regs_saved[CONFIG_PMU_REGISTER_NUM_SAVE];
56 #define CONFIG_CPU_REGISTER_NUM_SAVE 27
57 uint32_t arch_cpu_saved[CONFIG_CPU_REGISTER_NUM_SAVE];
58 /* Driver Capabilities */
60 static const pmu_capabilities_t driver_capabilities = {
61 .event_ready = 1, /* event_ready */
62 .data_width = 2, /* data_width = 0:8-bit, 1:16-bit, 2:32-bit */
63 .erase_chip = 0 /* erase_chip */
70 static void do_prepare_sleep_action(int32_t idx)
73 volatile ck_pmu_reg_t *pbase = (ck_pmu_reg_t *)pmu_handle[idx].base;
74 for (i = 0; i < sizeof(pmu_regs_saved)/4; i++) {
75 pmu_regs_saved[i] = *((volatile uint32_t *)pbase + i);
79 static void do_wakeup_sleep_action(int32_t idx)
82 volatile ck_pmu_reg_t *pbase = (ck_pmu_reg_t *)pmu_handle[idx].base;
83 *((volatile uint32_t *)pbase + 5) = pmu_regs_saved[5];
84 while((*((volatile uint32_t *)pbase + 6) & 0xf) != 0xf);
85 *((volatile uint32_t *)pbase + 11) = pmu_regs_saved[11];
86 while((*((volatile uint32_t *)pbase + 6) & 0x1f) != 0x1f);
87 for (i = 0; i < sizeof(pmu_regs_saved)/4; i++) {
88 if (i != 5 && i != 11) {
89 *((volatile uint32_t *)pbase + i) = pmu_regs_saved[i];
95 static uint8_t s_action[CONFIG_PMU_NUM] = {0x0};
96 int32_t ck_pmu_power_manager(int32_t idx)
98 if (!(s_action[idx] % 2)) {
99 do_prepare_sleep_action(idx);
102 do_wakeup_sleep_action(idx);
108 int32_t ck_pmu_act_callback(pmu_handle_t handle, pmu_event_e event)
110 ck_pmu_priv_t *pmu_priv = handle;
112 for (i = 0; i < s_callback_count; i++) {
113 if (pmu_priv->callback[i]) {
114 pmu_priv->callback[i](event);
118 if (i != s_callback_count) {
124 void resume_context_from_stop_mode(void)
126 ck_pmu_priv_t *pmu_priv = &pmu_handle[0];
127 // ck_pmu_power_manager(PMU_EVENT_SLEEP_DONE);
128 // ck_pmu_act_callback(pmu_priv, PMU_EVENT_SLEEP_DONE);
129 *((volatile uint32_t *)0x50006100) |= 0xa0000000;
131 pmu_priv->cb(pmu_priv->idx, PMU_EVENT_SLEEP_DONE, PMU_MODE_STDBY);
134 arch_do_cpu_resume();
137 #define CONFIG_LPM_RESUME_ADDR 0x1003f7f0
138 void set_resume_func(uint32_t *func)
140 eflash_handle_t eflash = csi_eflash_initialize(0, NULL);
141 csi_eflash_erase_sector(eflash, CONFIG_LPM_RESUME_ADDR);
142 csi_eflash_program(eflash, CONFIG_LPM_RESUME_ADDR, &func, 4);
154 void soc_sleep(pmu_handle_t handle, lpm_mode_t mode)
157 tee_lpm_mode_e lpm_mode = 0;
159 if (mode == WAIT_MODE) {
160 lpm_mode = TEE_LPM_MODE_WAIT;
161 } else if (mode == DOZE_MODE) {
162 lpm_mode = TEE_LPM_MODE_DOZE;
163 } else if (mode == STOP_MODE) {
164 lpm_mode = TEE_LPM_MODE_STOP;
165 } else if (mode == STANDBY_MODE) {
166 lpm_mode = TEE_LPM_MODE_STANDBY;
168 lpm_mode = TEE_LPM_MODE_WAIT;
171 csi_tee_enter_lpm(0, 0, lpm_mode);
173 if (mode == STOP_MODE) {
174 resume_context_from_stop_mode();
178 ck_pmu_priv_t *pmu_priv = handle;
179 ck_pmu_reg_t *pmu_reg = (ck_pmu_reg_t *)pmu_priv->base;
181 if (mode == WAIT_MODE) {
182 pmu_reg->LPCR |= CONFIG_PMU_ENTER_WAIT_MODE;
184 } else if (mode == DOZE_MODE) {
185 pmu_reg->LPCR |= CONFIG_PMU_ENTER_DOZE_MODE;
187 } else if (mode == STOP_MODE) {
188 pmu_reg->LPCR |= CONFIG_PMU_ENTER_STOP_MODE;
190 } else if (mode == STANDBY_MODE) {
191 pmu_reg->LPCR |= CONFIG_PMU_ENTER_STANDBY_MODE;
194 pmu_reg->LPCR |= CONFIG_PMU_ENTER_WAIT_MODE;
202 \brief Initialize PMU Interface. 1. Initializes the resources needed for the PMU interface 2.registers event callback function
203 \param[in] idx device id
204 \param[in] cb_event Pointer to \ref pmu_event_cb_t
205 \return pointer to pmu handle
207 pmu_handle_t drv_pmu_initialize(int32_t idx, pmu_event_cb_t cb_event)
209 if (idx < 0 || idx >= CONFIG_PMU_NUM) {
213 /* obtain the pmu information */
216 int32_t real_idx = target_get_pmu(idx, &base, &irq);
218 if (real_idx != idx) {
222 ck_pmu_priv_t *pmu_priv = &pmu_handle[idx];
224 /* initialize the pmu context */
226 pmu_priv->base = base;
228 pmu_priv->cb = cb_event;
230 return (pmu_handle_t)pmu_priv;
234 \brief De-initialize PMU Interface. stops operation and releases the software resources used by the interface
235 \param[in] handle pmu handle to operate.
238 int32_t drv_pmu_uninitialize(pmu_handle_t handle)
240 PMU_NULL_PARAM_CHK(handle);
242 ck_pmu_priv_t *pmu_priv = handle;
248 int32_t drv_pmu_power_control(int32_t idx, csi_power_stat_e state)
256 ck_pmu_power_manager(idx);
257 // csi_pmu_register_module(dw_usart_power_manager);
267 \brief Get driver capabilities.
268 \param[in] idx device id
269 \return \ref pmu_capabilities_t
272 pmu_capabilities_t csi_pmu_get_capabilities(int32_t idx)
274 if (idx < 0 || idx >= CONFIG_PMU_NUM) {
275 pmu_capabilities_t ret;
276 memset(&ret, 0, sizeof(pmu_capabilities_t));
280 return driver_capabilities;
284 \brief choose the pmu mode to enter
285 \param[in] handle pmu handle to operate.
286 \param[in] mode \ref pmu_mode_e
289 int32_t drv_pmu_enter_sleep(pmu_handle_t handle, pmu_mode_e mode)
291 PMU_NULL_PARAM_CHK(handle);
297 soc_sleep(handle, WAIT_MODE);
299 case PMU_MODE_DORMANT:
300 // soc_sleep(handle, DOZE_MODE);
301 if (arch_do_cpu_save() == 0) {
302 *(volatile unsigned int *)(0xe000e1c0) = 0xffffffff; // reload wakeup_IRQ
303 *(volatile unsigned int *)(0xe000e280) = 0xffffffff; // clear pend IRQ
304 soc_sleep(handle, STOP_MODE);
308 *(volatile unsigned int *)(0xe000e1c0) = 0xffffffff; // reload wakeup_IRQ
309 *(volatile unsigned int *)(0xe000e280) = 0xffffffff; // clear pend IRQ
310 soc_sleep(handle, STANDBY_MODE);
312 case PMU_MODE_SHUTDOWN:
313 *(volatile unsigned int *)(0xe000e1c0) = 0xffffffff; // reload wakeup_IRQ
314 *(volatile unsigned int *)(0xe000e280) = 0xffffffff; // clear pend IRQ
315 soc_sleep(handle, STANDBY_MODE);
318 return ERR_PMU(EDRV_PARAMETER);
325 \brief register module to action pmu event
326 \param[in] handle pmu handle to operate.
327 \param[in] callback Pointer to \ref pmu_action_cb_t
330 int32_t drv_pmu_register_module(pmu_action_cb_t callback)
332 ck_pmu_priv_t *pmu_priv = (ck_pmu_priv_t *)&pmu_handle[0];
334 if (callback == NULL) {
335 return ERR_PMU(EDRV_PARAMETER);
337 pmu_priv->callback[s_callback_count] = callback;
343 \brief Config the wakeup source.
344 \param[in] handle pmu handle to operate
345 \param[in] type \ref pmu_wakeup_type
346 \param[in] pol \ref pmu_wakeup_pol
347 \param[in] enable flag control the wakeup source is enable or not
350 int32_t drv_pmu_config_wakeup_source(pmu_handle_t handle, uint32_t irq_num, pmu_wakeup_type_e type, pmu_wakeup_pol_e pol, uint8_t enable)
352 PMU_NULL_PARAM_CHK(handle);
355 // csi_vic_enable_irq(irq_num);
356 // csi_vic_enable_sirq(irq_num);
357 // csi_vic_set_wakeup_irq(irq_num);
358 drv_nvic_set_wakeup_irq(irq_num);
360 // csi_vic_disable_irq(irq_num);
361 // csi_vic_disable_sirq(irq_num);
362 drv_nvic_clear_wakeup_irq(irq_num);
363 // csi_vic_clear_wakeup_irq(irq_num);