1 /*
2  * Copyright (c) 2019 Winner Microelectronics Co., Ltd.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2019-03-13     tyx          first version
9  */
10 
11 #include <rthw.h>
12 #include <rtthread.h>
13 #include <rtdevice.h>
14 #include "drv_standby.h"
15 
16 #ifdef BSP_USING_STANDBY
17 #include "wm_type_def.h"
18 #include "wm_cpu.h"
19 #include "wm_pmu.h"
20 #include "wm_irq.h"
21 #include "wm_regs.h"
22 
23 typedef volatile unsigned long vu32;
24 #define M32(adr)    (*((vu32*) (adr)))
25 typedef void (*rom_standby_func)(void);
26 
27 static const rom_standby_func pm_standby = (rom_standby_func)0x499;
28 
29 #ifdef __ICCARM__
30 extern void standby_idr(void);
31 #endif
32 
33 #if (1 == GCC_COMPILE)
wm_pm_standby(void)34 void wm_pm_standby(void)
35 {
36     __asm volatile (
37         " cpsid            i    \n"  /* disable irq*/
38         " dsb                   \n"
39         " ldr r0, =0X499        \n"
40         " bx r0                 \n"
41         " movs r0, #0x00        \n"
42         " isb                   \n"
43     );
44 }
45 #endif
46 
47 /**
48  * This function will put w60x into run/shutdown mode.
49  *
50  * @param timeout How many OS Ticks that MCU can sleep
51  */
sys_start_standby(int ms)52 void sys_start_standby(int ms)
53 {
54     rt_uint32_t val;
55     int timeout = ms;
56 
57     RT_ASSERT(timeout > 0);
58 
59     tls_pmu_clk_select(0);
60 
61     if (timeout <= 65535)
62     {
63         /* Enter PM_TIMER_MODE */
64         tls_irq_enable(PMU_TIMER1_INT);
65         tls_pmu_timer1_stop();
66         tls_pmu_timer1_start(timeout);
67     }
68     else if(timeout <= 65535000)
69     {
70         timeout /= 1000;
71         tls_irq_enable(PMU_TIMER0_INT);
72         tls_pmu_timer0_stop();
73         tls_pmu_timer0_start(timeout);
74     }
75     else
76     {
77         return;
78     }
79     tls_irq_enable(PMU_GPIO_WAKEUP_INT);    //Open interrupt by default to clear the interrupt flag for IO wake-up
80     val = tls_reg_read32(HR_PMU_PS_CR);
81     val |= 0x01;
82     tls_reg_write32(HR_PMU_PS_CR, val);
83 }
84 
85 #ifdef RT_USING_FINSH
86 #include <finsh.h>
87 #include <stdlib.h>
standby(uint8_t argc,char ** argv)88 static void standby(uint8_t argc, char **argv)
89 {
90     if (argc != 2)
91     {
92         rt_kprintf("Usage: standby timeout(ms)\n");
93         rt_kprintf("eg   : standby 5000\n");
94     }
95     else
96     {
97         sys_start_standby(atoi(argv[1]));
98     }
99 }
100 MSH_CMD_EXPORT(standby, sleep system);
101 #endif /* RT_USING_FINSH */
102 
103 #endif /* BSP_USING_STANDBY */
104