Intel® Quark™ Microcontroller Software Interface 1.4.0 Intel® Quark™ Microcontroller BSP

- Main Page
- Modules
- Data Structures
- Files

- File List

qm_aon_counters.c
1 /*
2 * {% copyright %}
3 */
4
5 #include "qm_aon_counters.h"
6
7 #if (HAS_SOC_CONTEXT_RETENTION)
8 #include "power_states.h"
9 #endif /* HAS_SOC_CONTEXT_RETENTION */
10
11 static void (*callback[QM_AONC_NUM])(void *) = {NULL};
12 static void *callback_data[QM_AONC_NUM];
13
14 #ifndef UNIT_TEST
15 qm_aonc_reg_t *qm_aonc[QM_AONC_NUM] = {((qm_aonc_reg_t *)QM_AONC_0_BASE),
16 #if (NUM_AONC_CONTROLLERS > 1)
17 ((qm_aonc_reg_t *)QM_AONC_1_BASE)
18 #endif /* NUM_AONC_CONTROLLERS >1 */
19 };
20 #endif /* UNIT_TEST */
21
22 #define BUSY_CHECK(_aonc)
23
24 #if (FIX_2 || FIX_3)
25 /* Cannot write to clear bit twice in one RTC clock cycle. */
26
27 static void wait_single_cycle(const qm_aonc_t aonc)
28 {
29 uint32_t aonc_cfg, initial_cnt;
30
31 /* Ensure the AON counter is enabled */
32 aonc_cfg = QM_AONC[aonc]->aonc_cfg;
33 QM_AONC[aonc]->aonc_cfg |= QM_AONC_ENABLE;
34 initial_cnt = QM_AONC[aonc]->aonc_cnt;
35
36 while (initial_cnt == QM_AONC[aonc]->aonc_cnt) {
37 }
38
39 QM_AONC[aonc]->aonc_cfg = aonc_cfg;
40 }
41 #endif /* (FIX_2 || FIX_3) */
42
43 #if (FIX_3)
44 #define CLEAR_CHECK(_aonc) \
45 while (QM_AONC[(_aonc)]->aonpt_ctrl & QM_AONPT_CLR) { \
46 } \
47 wait_single_cycle(_aonc);
48
49 #define RESET_CHECK(_aonc) \
50 while (QM_AONC[(_aonc)]->aonpt_ctrl & QM_AONPT_RST) { \
51 } \
52 wait_single_cycle(_aonc);
53 #else /* FIX_3 */
54 #define CLEAR_CHECK(_aonc) \
55 while (QM_AONC[(_aonc)]->aonpt_ctrl & QM_AONPT_CLR) { \
56 }
57
58 #define RESET_CHECK(_aonc) \
59 while (QM_AONC[(_aonc)]->aonpt_ctrl & QM_AONPT_RST) { \
60 }
61 #endif /* FIX_3 */
62
63 #define AONPT_CLEAR(_aonc) \
64 /* Clear the alarm and wait for it to complete. */ \
65 QM_AONC[(_aonc)]->aonpt_ctrl |= QM_AONPT_CLR; \
66 CLEAR_CHECK(_aonc) \
67 BUSY_CHECK(_aonc)
68
69 /* AONPT requires one RTC clock edge before first timer reset. */
70 static __inline__ void pt_reset(const qm_aonc_t aonc)
71 {
72 #if (FIX_2)
73 uint32_t aonc_cfg;
74 static bool first_run = true;
75
76 /*
77 * After Power on Reset, it is required to wait for one RTC clock cycle
78 * before asserting QM_AONPT_CTRL_RST. Note the AON counter is enabled
79 * with an initial value of 0 at Power on Reset.
80 */
81 if (first_run) {
82 first_run = false;
83 /* Ensure the AON counter is enabled */
84 aonc_cfg = QM_AONC[aonc]->aonc_cfg;
85 QM_AONC[aonc]->aonc_cfg |= QM_AONC_ENABLE;
86
87 while (0 == QM_AONC[aonc]->aonc_cnt) {
88 }
89
90 QM_AONC[aonc]->aonc_cfg = aonc_cfg;
91 }
92 #endif /* FIX_2 */
93
94 /* Reset the counter. */
95 QM_AONC[aonc]->aonpt_ctrl |= QM_AONPT_RST;
96 RESET_CHECK(aonc);
97 BUSY_CHECK(aonc);
98 }
99
100 /* AONPT requires one RTC clock edge before first timer reset. */
101 #define AONPT_RESET(_aonc) pt_reset((_aonc))
102
103 QM_ISR_DECLARE(qm_aonpt_0_isr)
104 {
105 qm_aonc_t aonc;
106
107 #if (HAS_SOC_CONTEXT_RETENTION)
108 if (QM_SCSS_GP->gps0 & QM_GPS0_POWER_STATES_MASK) {
109 qm_power_soc_restore();
110 }
111 #endif
112
113 /*
114 * Check each always on counter for the interrupt status and calls
115 * the callback if it has been set.
116 */
117 for (aonc = QM_AONC_0; aonc < QM_AONC_NUM; aonc++) {
118 if ((QM_AONC[aonc]->aonpt_stat & QM_AONPT_INTERRUPT)) {
119 if (callback[aonc]) {
120 (*callback[aonc])(callback_data[aonc]);
121 }
122 /* Clear pending interrupt. */
123 AONPT_CLEAR(aonc);
124 }
125 }
126
127 QM_ISR_EOI(QM_IRQ_AONPT_0_INT_VECTOR);
128 }
129
130 int qm_aonc_enable(const qm_aonc_t aonc)
131 {
132 QM_CHECK(aonc < QM_AONC_NUM, -EINVAL);
133 QM_CHECK(aonc >= QM_AONC_0, -EINVAL);
134
135 QM_AONC[aonc]->aonc_cfg = QM_AONC_ENABLE;
136
137 return 0;
138 }
139
140 int qm_aonc_disable(const qm_aonc_t aonc)
141 {
142 QM_CHECK(aonc < QM_AONC_NUM, -EINVAL);
143 QM_CHECK(aonc >= QM_AONC_0, -EINVAL);
144
145 QM_AONC[aonc]->aonc_cfg = QM_AONC_DISABLE;
146
147 return 0;
148 }
149
150 int qm_aonc_get_value(const qm_aonc_t aonc, uint32_t *const val)
151 {
152 QM_CHECK(aonc < QM_AONC_NUM, -EINVAL);
153 QM_CHECK(aonc >= QM_AONC_0, -EINVAL);
154 QM_CHECK(val != NULL, -EINVAL);
155
156 *val = QM_AONC[aonc]->aonc_cnt;
157 return 0;
158 }
159
160 int qm_aonpt_set_config(const qm_aonc_t aonc,
161 const qm_aonpt_config_t *const cfg)
162 {
163 QM_CHECK(aonc < QM_AONC_NUM, -EINVAL);
164 QM_CHECK(aonc >= QM_AONC_0, -EINVAL);
165 QM_CHECK(cfg != NULL, -EINVAL);
166
167 QM_AONC[aonc]->aonpt_cfg = cfg->count;
168
169 /* Clear pending interrupts. */
170 AONPT_CLEAR(aonc);
171
172 if (cfg->int_en) {
173 callback[aonc] = cfg->callback;
174 callback_data[aonc] = cfg->callback_data;
175 } else {
176 callback[aonc] = NULL;
177 }
178
179 AONPT_RESET(aonc);
180
181 return 0;
182 }
183
184 int qm_aonpt_get_value(const qm_aonc_t aonc, uint32_t *const val)
185 {
186 QM_CHECK(aonc < QM_AONC_NUM, -EINVAL);
187 QM_CHECK(aonc >= QM_AONC_0, -EINVAL);
188 QM_CHECK(val != NULL, -EINVAL);
189
190 *val = QM_AONC[aonc]->aonpt_cnt;
191
192 return 0;
193 }
194
195 int qm_aonpt_get_status(const qm_aonc_t aonc, qm_aonpt_status_t *const status)
196 {
197 QM_CHECK(aonc < QM_AONC_NUM, -EINVAL);
198 QM_CHECK(aonc >= QM_AONC_0, -EINVAL);
199 QM_CHECK(status != NULL, -EINVAL);
200
201 if (QM_AONC[aonc]->aonpt_stat & QM_AONPT_INTERRUPT) {
202 *status = QM_AONPT_EXPIRED;
203 } else {
204 *status = QM_AONPT_READY;
205 }
206
207 return 0;
208 }
209
210 int qm_aonpt_clear(const qm_aonc_t aonc)
211 {
212 QM_CHECK(aonc < QM_AONC_NUM, -EINVAL);
213 QM_CHECK(aonc >= QM_AONC_0, -EINVAL);
214
215 /*
216 * Clear pending interrupt and poll until the command has been
217 * completed.
218 */
219 AONPT_CLEAR(aonc);
220
221 return 0;
222 }
223
224 int qm_aonpt_reset(const qm_aonc_t aonc)
225 {
226 QM_CHECK(aonc < QM_AONC_NUM, -EINVAL);
227 QM_CHECK(aonc >= QM_AONC_0, -EINVAL);
228
229 AONPT_RESET(aonc);
230
231 return 0;
232 }
233
234 #if (ENABLE_RESTORE_CONTEXT)
235 int qm_aonpt_save_context(const qm_aonc_t aonc, qm_aonc_context_t *const ctx)
236 {
237 QM_CHECK(aonc < QM_AONC_NUM, -EINVAL);
238 QM_CHECK(ctx != NULL, -EINVAL);
239
240 (void)aonc;
241 (void)ctx;
242
243 return 0;
244 }
245
246 int qm_aonpt_restore_context(const qm_aonc_t aonc,
247 const qm_aonc_context_t *const ctx)
248 {
249 uint32_t int_aonpt_mask;
250 QM_CHECK(aonc < QM_AONC_NUM, -EINVAL);
251 QM_CHECK(ctx != NULL, -EINVAL);
252
253 (void)aonc;
254 (void)ctx;
255
256 /* The interrupt router registers are sticky and retain their
257 * values across warm resets, so we don't need to save them.
258 * But for wake capable peripherals, if their interrupts are
259 * configured to be edge sensitive, the wake event will be lost
260 * by the time the interrupt controller is reconfigured, while
261 * the interrupt is still pending. By masking and unmasking again
262 * the corresponding routing register, the interrupt is forwarded
263 * to the core and the ISR will be serviced as expected.
264 */
265 int_aonpt_mask = QM_INTERRUPT_ROUTER->aonpt_0_int_mask;
266 QM_INTERRUPT_ROUTER->aonpt_0_int_mask = 0xFFFFFFFF;
267 QM_INTERRUPT_ROUTER->aonpt_0_int_mask = int_aonpt_mask;
268
269 return 0;
270 }
271 #else
272 int qm_aonpt_save_context(const qm_aonc_t aonc, qm_aonc_context_t *const ctx)
273 {
274 (void)aonc;
275 (void)ctx;
276
277 return 0;
278 }
279
280 int qm_aonpt_restore_context(const qm_aonc_t aonc,
281 const qm_aonc_context_t *const ctx)
282 {
283 (void)aonc;
284 (void)ctx;
285
286 return 0;
287 }
288 #endif /* ENABLE_RESTORE_CONTEXT */
qm_aonc_disable
int qm_aonc_disable(const qm_aonc_t aonc)
Disable the Always-on Counter.
Definition: qm_aon_counters.c:140
qm_power_soc_restore
void qm_power_soc_restore(void)
Restore system state after sleep or deep sleep.
Definition: power_states.c:402
qm_aonpt_clear
int qm_aonpt_clear(const qm_aonc_t aonc)
Clear the status of the Always-on Periodic Timer.
Definition: qm_aon_counters.c:210
qm_aonpt_config_t::count
uint32_t count
Time to count down from in clock cycles.
Definition: qm_aon_counters.h:41
qm_aonpt_config_t::callback
void(* callback)(void *data)
User callback.
Definition: qm_aon_counters.h:49
QM_ISR_DECLARE
QM_ISR_DECLARE(qm_aonpt_0_isr)
ISR for Always-on Periodic Timer 0 interrupt.
Definition: qm_aon_counters.c:103
qm_aonpt_config_t::callback_data
void * callback_data
Callback data.
Definition: qm_aon_counters.h:50
qm_aonpt_status_t
qm_aonpt_status_t
Always on counter status.
Definition: qm_aon_counters.h:26
qm_aonc_enable
int qm_aonc_enable(const qm_aonc_t aonc)
Enable the Always-on Counter.
Definition: qm_aon_counters.c:130
qm_aonpt_get_status
int qm_aonpt_get_status(const qm_aonc_t aonc, qm_aonpt_status_t *const status)
Get the current status of an Always-on Periodic Timer.
Definition: qm_aon_counters.c:195
qm_aonc_get_value
int qm_aonc_get_value(const qm_aonc_t aonc, uint32_t *const val)
Get the current value of the Always-on Counter.
Definition: qm_aon_counters.c:150
qm_aonc_reg_t
Always-on Counter Controller register map.
Definition: qm_soc_regs.h:258
qm_aonpt_save_context
int qm_aonpt_save_context(const qm_aonc_t aonc, qm_aonc_context_t *const ctx)
Save the Always-on Periodic Timer context.
Definition: qm_aon_counters.c:235
QM_AONPT_READY
Default Timer Status.
Definition: qm_aon_counters.h:30
qm_aonpt_get_value
int qm_aonpt_get_value(const qm_aonc_t aonc, uint32_t *const val)
Get the current value of the Always-on Periodic Timer.
Definition: qm_aon_counters.c:184
QM_AONPT_EXPIRED
Timer expired.
Definition: qm_aon_counters.h:34
qm_aonpt_config_t::int_en
bool int_en
Enable/disable the interrupts.
Definition: qm_aon_counters.h:42
qm_aonpt_config_t
QM Always-on Periodic Timer configuration type.
Definition: qm_aon_counters.h:40
qm_aonpt_reset
int qm_aonpt_reset(const qm_aonc_t aonc)
Reset the Always-on Periodic Timer back to the configured value.
Definition: qm_aon_counters.c:224
qm_aonpt_set_config
int qm_aonpt_set_config(const qm_aonc_t aonc, const qm_aonpt_config_t *const cfg)
Set the Always-on Periodic Timer configuration.
Definition: qm_aon_counters.c:160
qm_aonpt_restore_context
int qm_aonpt_restore_context(const qm_aonc_t aonc, const qm_aonc_context_t *const ctx)
Restore the Always-on Periodic Timer context.
Definition: qm_aon_counters.c:246
qm_aonc_t
qm_aonc_t
Number of Always-on counter controllers.
Definition: qm_soc_regs.h:255