5 #include "power_states.h"
7 #include "qm_comparator.h"
11 #include "soc_watch.h"
14 uint32_t ac_power_save;
15 uint32_t clk_gate_save;
16 uint32_t sys_clk_ctl_save;
17 uint32_t osc0_cfg_save;
18 uint32_t osc1_cfg_save;
19 uint32_t adc_mode_save;
21 uint32_t flash_tmg_save;
22 uint32_t ext_clock_save;
24 uint32_t pmux_slew_save;
27 static power_context_t power_context;
40 __asm__ __volatile__(
"sti\n\t"
44 static void clear_all_pending_interrupts(
void)
47 QM_SCSS_CMP->cmp_stat_clr = -1;
50 QM_RTC[QM_RTC_0]->rtc_eoi;
53 QM_PWM[QM_PWM_0]->timerseoi;
56 QM_GPIO[QM_GPIO_0]->gpio_porta_eoi = -1;
62 power_context.ac_power_save = QM_SCSS_CMP->cmp_pwr;
63 power_context.clk_gate_save = QM_SCSS_CCU->ccu_periph_clk_gate_ctl;
64 power_context.sys_clk_ctl_save = QM_SCSS_CCU->ccu_sys_clk_ctl;
65 power_context.osc0_cfg_save = QM_SCSS_CCU->osc0_cfg1;
66 power_context.adc_mode_save = QM_ADC->adc_op_mode;
67 power_context.flash_tmg_save = QM_FLASH[QM_FLASH_0]->tmg_ctrl;
68 power_context.lp_clk_save = QM_SCSS_CCU->ccu_lp_clk_ctl;
70 QM_SCSS_GP->gps0 |= QM_GPS0_POWER_STATE_SLEEP;
73 clear_all_pending_interrupts();
78 QM_SCSS_CMP->cmp_pwr &= QM_AC_HP_COMPARATORS_MASK;
85 QM_SCSS_CCU->ccu_lp_clk_ctl &= ~QM_WAKE_PROBE_MODE_MASK;
87 QM_SCSS_CCU->wake_mask = 0;
94 QM_SCSS_CCU->ccu_lp_clk_ctl &=
95 ~(QM_HYB_OSC_PD_LATCH_EN | QM_RTC_OSC_PD_LATCH_EN);
102 QM_SCSS_CCU->ccu_lp_clk_ctl |=
103 QM_CCU_EXIT_TO_HYBOSC | QM_CCU_MEM_HALT_EN | QM_CCU_CPU_HALT_EN;
150 QM_FLASH[QM_FLASH_0]->tmg_ctrl = power_context.flash_tmg_save;
153 QM_SCSS_CCU->ccu_sys_clk_ctl = power_context.sys_clk_ctl_save;
155 QM_SCSS_CCU->ccu_sys_clk_ctl &=
156 ~(QM_CCU_SYS_CLK_DIV_EN | QM_CCU_RTC_CLK_DIV_EN);
157 QM_SCSS_CCU->ccu_sys_clk_ctl |=
158 QM_CCU_SYS_CLK_DIV_EN | QM_CCU_RTC_CLK_DIV_EN;
163 while (!(QM_SCSS_CCU->osc0_stat1 &
164 (QM_OSC0_LOCK_SI | QM_OSC0_LOCK_XTAL))) {
168 QM_SCSS_CCU->osc0_cfg1 = power_context.osc0_cfg_save;
169 QM_SCSS_CCU->ccu_periph_clk_gate_ctl = power_context.clk_gate_save;
173 QM_SCSS_CMP->cmp_pwr = power_context.ac_power_save;
174 QM_ADC->adc_op_mode = power_context.adc_mode_save;
175 QM_SCSS_CCU->ccu_lp_clk_ctl = power_context.lp_clk_save;
177 QM_SCSS_GP->gps0 &= ~QM_GPS0_POWER_STATE_SLEEP;
183 power_context.ac_power_save = QM_SCSS_CMP->cmp_pwr;
184 power_context.clk_gate_save = QM_SCSS_CCU->ccu_periph_clk_gate_ctl;
185 power_context.sys_clk_ctl_save = QM_SCSS_CCU->ccu_sys_clk_ctl;
186 power_context.osc0_cfg_save = QM_SCSS_CCU->osc0_cfg1;
187 power_context.osc1_cfg_save = QM_SCSS_CCU->osc1_cfg0;
188 power_context.adc_mode_save = QM_ADC->adc_op_mode;
189 power_context.aon_vr_save = QM_SCSS_PMU->aon_vr;
190 power_context.flash_tmg_save = QM_FLASH[QM_FLASH_0]->tmg_ctrl;
191 power_context.pmux_slew_save = QM_SCSS_PMUX->pmux_slew[0];
192 power_context.ext_clock_save = QM_SCSS_CCU->ccu_ext_clock_ctl;
193 power_context.lp_clk_save = QM_SCSS_CCU->ccu_lp_clk_ctl;
195 QM_SCSS_GP->gps0 |= QM_GPS0_POWER_STATE_DEEP_SLEEP;
198 clear_all_pending_interrupts();
204 switch (wake_event) {
206 QM_SCSS_CCU->wake_mask =
207 SET_ALL_BITS & ~QM_CCU_WAKE_MASK_RTC_BIT;
211 QM_SCSS_CCU->wake_mask = SET_ALL_BITS &
212 ~(QM_CCU_WAKE_MASK_COMPARATOR_BIT |
213 QM_CCU_WAKE_MASK_GPIO_BIT);
220 QM_SCSS_CMP->cmp_pwr &= QM_AC_HP_COMPARATORS_MASK;
226 QM_SCSS_CCU->ccu_ext_clock_ctl = 0;
230 QM_SCSS_PMUX->pmux_slew[0] = 0;
235 QM_SCSS_CCU->osc1_cfg0 &= ~QM_OSC1_PD;
243 QM_SCSS_CCU->ccu_lp_clk_ctl &= ~QM_HYB_OSC_PD_LATCH_EN;
248 QM_SCSS_CCU->ccu_lp_clk_ctl |=
249 QM_CCU_EXIT_TO_HYBOSC | QM_CCU_MEM_HALT_EN | QM_CCU_CPU_HALT_EN;
253 QM_SCSS_CCU->osc0_cfg1 |= QM_OSC0_PD;
256 QM_SCSS_CCU->ccu_gpio_db_clk_ctl &= ~QM_CCU_GPIO_DB_CLK_EN;
259 QM_SCSS_CCU->osc0_cfg0 |= QM_SI_OSC_1V2_MODE;
263 QM_FLASH[QM_FLASH_0]->ctrl |= QM_FLASH_LVE_MODE;
267 QM_SCSS_PMU->aon_vr =
268 (QM_AON_VR_PASS_CODE |
269 (power_context.aon_vr_save & QM_AON_VR_VSEL_MASK) |
270 QM_AON_VR_VSEL_1V35);
272 QM_SCSS_PMU->aon_vr = (QM_AON_VR_PASS_CODE | QM_SCSS_PMU->aon_vr |
273 QM_AON_VR_ROK_BUF_VREG_MASK);
276 QM_SCSS_PMU->aon_vr =
277 (QM_AON_VR_PASS_CODE | QM_SCSS_PMU->aon_vr | QM_AON_VR_VSTRB);
280 __asm__ __volatile__(
"nop");
283 QM_SCSS_PMU->aon_vr =
284 (QM_AON_VR_PASS_CODE | (QM_SCSS_PMU->aon_vr & ~QM_AON_VR_VSTRB));
287 __asm__ __volatile__(
"nop");
319 QM_FLASH[QM_FLASH_0]->tmg_ctrl = power_context.flash_tmg_save;
323 QM_SCSS_PMU->aon_vr =
324 (QM_AON_VR_PASS_CODE | (QM_SCSS_PMU->aon_vr & QM_AON_VR_VSEL_MASK) |
325 QM_AON_VR_VSEL_1V8 | QM_AON_VR_ROK_BUF_VREG_MASK);
328 QM_SCSS_PMU->aon_vr =
329 (QM_AON_VR_PASS_CODE | QM_SCSS_PMU->aon_vr | QM_AON_VR_VSTRB);
332 __asm__ __volatile__(
"nop");
335 QM_SCSS_PMU->aon_vr =
336 (QM_AON_VR_PASS_CODE | (QM_SCSS_PMU->aon_vr & ~QM_AON_VR_VSTRB));
339 __asm__ __volatile__(
"nop");
342 QM_SCSS_PMU->aon_vr =
343 (QM_AON_VR_PASS_CODE |
344 (QM_SCSS_PMU->aon_vr & ~QM_AON_VR_ROK_BUF_VREG_MASK));
347 __asm__ __volatile__(
"nop");
350 while (!(QM_SCSS_PMU->aon_vr & QM_AON_VR_ROK_BUF_VREG_STATUS)) {
354 QM_SCSS_CCU->osc0_cfg0 &= ~QM_SI_OSC_1V2_MODE;
357 QM_FLASH[QM_FLASH_0]->ctrl &= ~QM_FLASH_LVE_MODE;
360 QM_SCSS_CCU->ccu_sys_clk_ctl = power_context.sys_clk_ctl_save;
362 QM_SCSS_CCU->ccu_sys_clk_ctl &=
363 ~(QM_CCU_SYS_CLK_DIV_EN | QM_CCU_RTC_CLK_DIV_EN);
364 QM_SCSS_CCU->ccu_sys_clk_ctl |=
365 QM_CCU_SYS_CLK_DIV_EN | QM_CCU_RTC_CLK_DIV_EN;
368 while (!(QM_SCSS_CCU->osc0_stat1 &
369 (QM_OSC0_LOCK_SI | QM_OSC0_LOCK_XTAL))) {
377 QM_SCSS_CCU->ccu_gpio_db_clk_ctl |= QM_CCU_GPIO_DB_CLK_EN;
380 QM_SCSS_CCU->osc0_cfg1 = power_context.osc0_cfg_save;
381 QM_SCSS_CCU->ccu_periph_clk_gate_ctl = power_context.clk_gate_save;
382 QM_SCSS_CCU->osc1_cfg0 = power_context.osc1_cfg_save;
387 QM_SCSS_CMP->cmp_pwr = power_context.ac_power_save;
388 QM_ADC->adc_op_mode = power_context.adc_mode_save;
390 QM_SCSS_PMUX->pmux_slew[0] = power_context.pmux_slew_save;
391 QM_SCSS_CCU->ccu_ext_clock_ctl = power_context.ext_clock_save;
392 QM_SCSS_CCU->ccu_lp_clk_ctl = power_context.lp_clk_save;
398 QM_SCSS_CCU->wake_mask = SET_ALL_BITS;
399 QM_SCSS_GP->gps0 &= ~QM_GPS0_POWER_STATE_DEEP_SLEEP;
408 if (QM_SCSS_GP->gps0 & QM_GPS0_POWER_STATE_SLEEP) {
410 }
else if (QM_SCSS_GP->gps0 & QM_GPS0_POWER_STATE_DEEP_SLEEP) {
418 volatile uint32_t i = 32;
419 volatile uint32_t reg;
423 QM_SCSS_PMU->aon_vr |=
424 (QM_AON_VR_PASS_CODE | QM_AON_VR_ROK_BUF_VREG_MASK);
425 QM_SCSS_PMU->aon_vr |=
426 (QM_AON_VR_PASS_CODE | QM_AON_VR_VREG_SEL);
430 reg = QM_SCSS_PMU->aon_vr & ~QM_AON_VR_VREG_SEL;
431 QM_SCSS_PMU->aon_vr = QM_AON_VR_PASS_CODE | reg;
434 __asm__ __volatile__(
"nop");
436 reg = QM_SCSS_PMU->aon_vr & ~QM_AON_VR_ROK_BUF_VREG_MASK;
437 QM_SCSS_PMU->aon_vr = QM_AON_VR_PASS_CODE | reg;
int clk_sys_set_mode(const clk_sys_mode_t mode, const clk_sys_div_t div)
Set clock mode and divisor.
void qm_power_soc_restore(void)
Restore system state after sleep or deep sleep.
GPIO Debounce Clock Enable.
int qm_rar_set_mode(const qm_rar_state_t mode)
Change operating mode of RAR.
int clk_periph_enable(const clk_periph_t clocks)
Enable clocks for peripherals / registers.
0x024 CCU Ext Clock Gate Ctl.
0x018 Perip Clock Gate Ctl.
0x02C Clock Control register.
Peripheral Clock Gate Enable.
SPI Master 0 Clock Enable.
void qm_power_soc_deep_sleep(const qm_power_wake_event_t wake_event)
Put SoC to deep sleep.
void qm_power_soc_deep_sleep_restore(void)
Enter SoC deep sleep state and restore after wake up.
Use GPIO/Comparator as wake source.
0x000 OSC0_CFG1 register.
int clk_periph_disable(const clk_periph_t clocks)
Disable clocks for peripherals / registers.
qm_rar_state_t
RAR modes type.
void qm_power_soc_sleep(void)
Put SoC to sleep.
qm_power_wake_event_t
Wake source for deep sleep mode type.
I2C Master 0 Clock Gate Enable.
SPI Slave Clock Gate Enable.
I2C Master 0 Clock Enable.
void qm_power_soc_sleep_restore(void)
Enter SoC sleep state and restore after wake up.
int qm_adc_set_mode(const qm_adc_t adc, const qm_adc_mode_t mode)
Switch operating mode of ADC.
SPI Master 0 Clock Gate Enable.
void qm_power_cpu_halt(void)
Put CPU in halt state.
0x038 System Clock Control.
4MHz Hybrid Oscillator Clock.