1 /*
2 * Copyright (C) 2017-2024 Alibaba Group Holding Limited
3 */
4
5 /*******************************************************
6 * @file dw_timer.c
7 * @brief source file for timer csi driver
8 * @version V1.0
9 * @date 28. Apr 2020
10 * ******************************************************/
11
12 #include <csi_config.h>
13 #include <drv/timer.h>
14 #include <drv/irq.h>
15 #include "dw_timer_ll.h"
16
17 /**
18 \brief Timer interrupt handling function
19 \param[in] arg Callback function member variables
20 \return None
21 */
dw_timer_irq_handler(void * arg)22 void dw_timer_irq_handler(void *arg)
23 {
24 csi_timer_t *timer = (csi_timer_t *)arg;
25 dw_timer_regs_t *timer_base = (dw_timer_regs_t *)timer->dev.reg_base;
26
27 if (dw_timer_get_int_status(timer_base)) {
28 if (timer->callback) {
29 timer->callback(timer, timer->arg);
30 }
31
32 dw_timer_clear_irq(timer_base);
33 }
34 }
35 #if CONFIG_SUPPORT_NMI_DEMO
timer_clear_irq()36 void timer_clear_irq()
37 {
38 dw_timer_clear_irq((dw_timer_regs_t*)DW_TIMER4_BASE);
39 }
40 #endif
41 /**
42 \brief Initialize TIMER Interface. 1. Initializes the resources needed for the TIMER interface 2.registers callback function
43 \param[in] timer handle timer handle to operate
44 \param[in] idx timer index
45 \return error code \ref csi_error_t
46 */
csi_timer_init(csi_timer_t * timer,uint32_t idx)47 csi_error_t csi_timer_init(csi_timer_t *timer, uint32_t idx)
48 {
49 CSI_PARAM_CHK(timer, CSI_ERROR);
50
51 csi_error_t ret = CSI_OK;
52 dw_timer_regs_t *timer_base = NULL;
53
54 if (0 == target_get(DEV_DW_TIMER_TAG, idx, &timer->dev)) {
55 timer_base = (dw_timer_regs_t *)HANDLE_REG_BASE(timer);
56 memset((void *)timer_base, 0, sizeof(dw_timer_regs_t));
57
58 } else {
59 ret = CSI_ERROR;
60 }
61
62 return ret;
63 }
64 /**
65 \brief De-initialize TIMER Interface. stops operation and releases the software resources used by the interface
66 \param[in] timer handle timer handle to operate
67 \return None
68 */
csi_timer_uninit(csi_timer_t * timer)69 void csi_timer_uninit(csi_timer_t *timer)
70 {
71 CSI_PARAM_CHK_NORETVAL(timer);
72 dw_timer_regs_t *timer_base = (dw_timer_regs_t *)HANDLE_REG_BASE(timer);
73
74 memset((void *)timer_base, 0, sizeof(dw_timer_regs_t));
75 }
76 /**
77 \brief Start timer
78 \param[in] timer handle timer handle to operate
79 \param[in] timeout_us the timeout for timer
80 \return error code \ref csi_error_t
81 */
csi_timer_start(csi_timer_t * timer,uint32_t timeout_us)82 csi_error_t csi_timer_start(csi_timer_t *timer, uint32_t timeout_us)
83 {
84 CSI_PARAM_CHK(timer, CSI_ERROR);
85 CSI_PARAM_CHK(timeout_us, CSI_ERROR);
86 csi_error_t ret = CSI_OK;
87 dw_timer_regs_t *timer_base = (dw_timer_regs_t *)HANDLE_REG_BASE(timer);
88 uint32_t tmp_load = timeout_us * (soc_get_timer_freq((uint32_t)timer->dev.idx) / 1000000U);
89
90 dw_timer_set_mode_load(timer_base);
91 dw_timer_write_load(timer_base, tmp_load);
92
93 dw_timer_set_disable(timer_base);
94 dw_timer_set_enable(timer_base);
95 dw_timer_set_unmask(timer_base);
96
97 return ret;
98 }
99 /**
100 \brief Stop timer
101 \param[in] timer handle timer handle to operate
102 \return None
103 */
csi_timer_stop(csi_timer_t * timer)104 void csi_timer_stop(csi_timer_t *timer)
105 {
106 CSI_PARAM_CHK_NORETVAL(timer);
107
108 dw_timer_regs_t *timer_base;
109 timer_base = (dw_timer_regs_t *)HANDLE_REG_BASE(timer);
110
111 dw_timer_set_mask(timer_base);
112 dw_timer_set_disable(timer_base);
113 }
114 /**
115 \brief Get timer remaining value
116 \param[in] timer handle timer handle to operate
117 \return the remaining value
118 */
csi_timer_get_remaining_value(csi_timer_t * timer)119 uint32_t csi_timer_get_remaining_value(csi_timer_t *timer)
120 {
121 CSI_PARAM_CHK(timer, 0U);
122
123 dw_timer_regs_t *timer_base;
124 timer_base = (dw_timer_regs_t *)HANDLE_REG_BASE(timer);
125 return dw_timer_get_current(timer_base);
126 }
127 /**
128 \brief Get timer load value
129 \param[in] timer handle timer handle to operate
130 \return the load value
131 */
csi_timer_get_load_value(csi_timer_t * timer)132 uint32_t csi_timer_get_load_value(csi_timer_t *timer)
133 {
134 CSI_PARAM_CHK(timer, 0U);
135
136 dw_timer_regs_t *timer_base = (dw_timer_regs_t *)HANDLE_REG_BASE(timer);
137
138 return (dw_timer_read_load(timer_base));
139 }
140 /**
141 \brief Check timer is running
142 \param[in] timer handle timer handle to operate
143 \return true->running, false->stopped
144 */
csi_timer_is_running(csi_timer_t * timer)145 bool csi_timer_is_running(csi_timer_t *timer)
146 {
147 CSI_PARAM_CHK(timer, false);
148
149 dw_timer_regs_t *timer_base = (dw_timer_regs_t *)HANDLE_REG_BASE(timer);
150
151 return (dw_timer_get_enable(timer_base) ? true : false);
152 }
153
154 /**
155 \brief Attach the callback handler to timer
156 \param[in] timer operate handle.
157 \param[in] callback callback function
158 \param[in] arg callback's param
159 \return error code \ref csi_error_t
160 */
csi_timer_attach_callback(csi_timer_t * timer,void * callback,void * arg)161 csi_error_t csi_timer_attach_callback(csi_timer_t *timer, void *callback, void *arg)
162 {
163 CSI_PARAM_CHK(timer, CSI_ERROR);
164
165 timer->callback = callback;
166 timer->arg = arg;
167 csi_irq_attach((uint32_t)timer->dev.irq_num, &dw_timer_irq_handler, &timer->dev);
168 csi_irq_enable((uint32_t)timer->dev.irq_num);
169
170 return CSI_OK;
171 }
172
173 /**
174 \brief Detach the callback handler
175 \param[in] timer operate handle.
176 */
csi_timer_detach_callback(csi_timer_t * timer)177 void csi_timer_detach_callback(csi_timer_t *timer)
178 {
179 CSI_PARAM_CHK_NORETVAL(timer);
180
181 timer->callback = NULL;
182 timer->arg = NULL;
183 csi_irq_disable((uint32_t)timer->dev.irq_num);
184 csi_irq_detach((uint32_t)timer->dev.irq_num);
185 }
186
187 #ifdef CONFIG_PM
dw_timer_pm_action(csi_dev_t * dev,csi_pm_dev_action_t action)188 csi_error_t dw_timer_pm_action(csi_dev_t *dev, csi_pm_dev_action_t action)
189 {
190 CSI_PARAM_CHK(dev, CSI_ERROR);
191
192 csi_error_t ret = CSI_OK;
193 csi_pm_dev_t *pm_dev = &dev->pm_dev;
194
195 switch (action) {
196 case PM_DEV_SUSPEND:
197 csi_pm_dev_save_regs(pm_dev->reten_mem, (uint32_t *)dev->reg_base, 1U);
198 csi_pm_dev_save_regs(pm_dev->reten_mem + 1, (uint32_t *)(dev->reg_base + 8U), 1U);
199 break;
200
201 case PM_DEV_RESUME:
202 csi_pm_dev_restore_regs(pm_dev->reten_mem, (uint32_t *)dev->reg_base, 1U);
203 csi_pm_dev_restore_regs(pm_dev->reten_mem + 1, (uint32_t *)(dev->reg_base + 8U), 1U);
204 break;
205
206 default:
207 ret = CSI_ERROR;
208 break;
209 }
210
211 return ret;
212 }
213
csi_timer_enable_pm(csi_timer_t * timer)214 csi_error_t csi_timer_enable_pm(csi_timer_t *timer)
215 {
216 return csi_pm_dev_register(&timer->dev, dw_timer_pm_action, 8U, 0U);
217 }
218
csi_timer_disable_pm(csi_timer_t * timer)219 void csi_timer_disable_pm(csi_timer_t *timer)
220 {
221 csi_pm_dev_unregister(&timer->dev);
222 }
223 #endif
224
225