blob: e5e9a0f8619ae6dd3355e9ab38de0adcb185684e [file] [log] [blame]
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +02001/*
2 * Copyright (c) 2018, Arm Limited. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <arch.h>
8#include <arch_helpers.h>
9#include <arm_gic.h>
10#include <debug.h>
11#include <errno.h>
12#include <irq.h>
13#include <mmio.h>
14#include <platform.h>
15#include <platform_def.h>
16#include <power_management.h>
17#include <sgi.h>
18#include <spinlock.h>
19#include <stddef.h>
20#include <sys/types.h>
21#include <tftf.h>
22#include <timer.h>
23
24
25/* Helper macros */
26#define TIMER_STEP_VALUE (plat_timer_info->timer_step_value)
27#define TIMER_IRQ (plat_timer_info->timer_irq)
28#define PROGRAM_TIMER(a) plat_timer_info->program(a)
29#define INVALID_CORE UINT32_MAX
30#define INVALID_TIME UINT64_MAX
31#define MAX_TIME_OUT_MS 10000
32
33/*
34 * Pointer containing available timer information for the platform.
35 */
36static const plat_timer_t *plat_timer_info;
37/*
38 * Interrupt requested time by cores in terms of absolute time.
39 */
40static volatile unsigned long long interrupt_req_time[PLATFORM_CORE_COUNT];
41/*
42 * Contains the target core number of the timer interrupt.
43 */
44static unsigned int current_prog_core = INVALID_CORE;
45/*
46 * Lock to get a consistent view for programming the timer
47 */
48static spinlock_t timer_lock;
49/*
50 * Number of system ticks per millisec
51 */
52static unsigned int systicks_per_ms;
53
54/*
55 * Stores per CPU timer handler invoked on expiration of the requested timeout.
56 */
57static irq_handler_t timer_handler[PLATFORM_CORE_COUNT];
58
59/* Helper function */
60static inline unsigned long long get_current_time_ms(void)
61{
62 assert(systicks_per_ms);
63 return mmio_read_64(SYS_CNT_BASE1 + CNTPCT_LO) / systicks_per_ms;
64}
65
66static inline unsigned long long get_current_prog_time(void)
67{
68 return current_prog_core == INVALID_CORE ?
69 0 : interrupt_req_time[current_prog_core];
70}
71
72int tftf_initialise_timer(void)
73{
74 int rc;
75 unsigned int i;
76
77 /*
78 * Get platform specific timer information
79 */
80 rc = plat_initialise_timer_ops(&plat_timer_info);
81 if (rc) {
82 ERROR("%s %d: No timer data found\n", __func__, __LINE__);
83 return rc;
84 }
85
86 /* Systems can't support single tick as a step value */
87 assert(TIMER_STEP_VALUE);
88
89 /* Initialise the array to max possible time */
90 for (i = 0; i < PLATFORM_CORE_COUNT; i++)
91 interrupt_req_time[i] = INVALID_TIME;
92
93 tftf_irq_register_handler(TIMER_IRQ, tftf_timer_framework_handler);
94 arm_gic_set_intr_priority(TIMER_IRQ, GIC_HIGHEST_NS_PRIORITY);
95 arm_gic_intr_enable(TIMER_IRQ);
96
97 /* Save the systicks per millisecond */
98 systicks_per_ms = read_cntfrq_el0() / 1000;
99
100 return 0;
101}
102
103/*
104 * It returns the core number of next timer request to be serviced or
105 * -1 if there is no request from any core. The next service request
106 * is the core whose interrupt needs to be fired first.
107 */
108static inline unsigned int get_lowest_req_core(void)
109{
110 unsigned long long lowest_timer = INVALID_TIME;
111 unsigned int lowest_core_req = INVALID_CORE;
112 unsigned int i;
113
114 /*
115 * If 2 cores requested same value, give precedence
116 * to the core with lowest core number
117 */
118 for (i = 0; i < PLATFORM_CORE_COUNT; i++) {
119 if (interrupt_req_time[i] < lowest_timer) {
120 lowest_timer = interrupt_req_time[i];
121 lowest_core_req = i;
122 }
123 }
124
125 return lowest_core_req;
126}
127
128int tftf_program_timer(unsigned long time_out_ms)
129{
130 unsigned int core_pos;
131 unsigned long long current_time;
132 u_register_t flags;
133 int rc = 0;
134
135 /*
136 * Some timer implementations have a very small max timeouts due to
137 * this if a request is asked for greater than the max time supported
138 * by them either it has to be broken down and remembered or use
139 * some other technique. Since that use case is not intended and
140 * and to make the timer framework simple, max timeout requests
141 * accepted by timer implementations can't be greater than
142 * 10 seconds. Hence, all timer peripherals used in timer framework
143 * has to support a timeout with interval of at least MAX_TIMEOUT.
144 */
145 if ((time_out_ms > MAX_TIME_OUT_MS) || (time_out_ms == 0)) {
146 ERROR("%s : Greater than max timeout request\n", __func__);
147 return -1;
148 } else if (time_out_ms < TIMER_STEP_VALUE) {
149 time_out_ms = TIMER_STEP_VALUE;
150 }
151
152 core_pos = platform_get_core_pos(read_mpidr_el1());
153 /* A timer interrupt request is already available for the core */
154 assert(interrupt_req_time[core_pos] == INVALID_TIME);
155
156 flags = read_daif();
157 disable_irq();
158 spin_lock(&timer_lock);
159
160 assert((current_prog_core < PLATFORM_CORE_COUNT) ||
161 (current_prog_core == INVALID_CORE));
162
163 /*
164 * Read time after acquiring timer_lock to account for any time taken
165 * by lock contention.
166 */
167 current_time = get_current_time_ms();
168
169 /* Update the requested time */
170 interrupt_req_time[core_pos] = current_time + time_out_ms;
171
172 VERBOSE("Need timer interrupt at: %lld current_prog_time:%lld\n"
173 " current time: %lld\n", interrupt_req_time[core_pos],
174 get_current_prog_time(),
175 get_current_time_ms());
176
177 /*
178 * If the interrupt request time is less than the current programmed
179 * by timer_step_value or timer is not programmed. Program it with
180 * requested time and retarget the timer interrupt to the current
181 * core.
182 */
183 if ((!get_current_prog_time()) || (interrupt_req_time[core_pos] <
184 (get_current_prog_time() - TIMER_STEP_VALUE))) {
185
186 arm_gic_set_intr_target(TIMER_IRQ, core_pos);
187
188 rc = PROGRAM_TIMER(time_out_ms);
189 /* We don't expect timer programming to fail */
190 if (rc)
191 ERROR("%s %d: rc = %d\n", __func__, __LINE__, rc);
192
193 current_prog_core = core_pos;
194 }
195
196 spin_unlock(&timer_lock);
197 /* Restore DAIF flags */
198 write_daif(flags);
199 isb();
200
201 return rc;
202}
203
204int tftf_program_timer_and_suspend(unsigned long milli_secs,
205 unsigned int pwr_state,
206 int *timer_rc, int *suspend_rc)
207{
208 int rc = 0;
209 u_register_t flags;
210
211 /* Default to successful return codes */
212 int timer_rc_val = 0;
213 int suspend_rc_val = PSCI_E_SUCCESS;
214
215 /* Preserve DAIF flags. IRQs need to be disabled for this to work. */
216 flags = read_daif();
217 disable_irq();
218
219 /*
220 * Even with IRQs masked, the timer IRQ will wake the CPU up.
221 *
222 * If the timer IRQ happens before entering suspend mode (because the
223 * timer took too long to program, for example) the fact that the IRQ is
224 * pending will prevent the CPU from entering suspend mode and not being
225 * able to wake up.
226 */
227 timer_rc_val = tftf_program_timer(milli_secs);
228 if (timer_rc_val == 0) {
229 suspend_rc_val = tftf_cpu_suspend(pwr_state);
230 if (suspend_rc_val != PSCI_E_SUCCESS) {
231 rc = -1;
232 INFO("%s %d: suspend_rc = %d\n", __func__, __LINE__,
233 suspend_rc_val);
234 }
235 } else {
236 rc = -1;
237 INFO("%s %d: timer_rc = %d\n", __func__, __LINE__, timer_rc_val);
238 }
239
240 /* Restore previous DAIF flags */
241 write_daif(flags);
242 isb();
243
244 if (timer_rc)
245 *timer_rc = timer_rc_val;
246 if (suspend_rc)
247 *suspend_rc = suspend_rc_val;
248 /*
249 * If IRQs were disabled when calling this function, the timer IRQ
250 * handler won't be called and the timer interrupt will be pending, but
251 * that isn't necessarily a problem.
252 */
253
254 return rc;
255}
256
257int tftf_program_timer_and_sys_suspend(unsigned long milli_secs,
258 int *timer_rc, int *suspend_rc)
259{
260 int rc = 0;
261 u_register_t flags;
262
263 /* Default to successful return codes */
264 int timer_rc_val = 0;
265 int suspend_rc_val = PSCI_E_SUCCESS;
266
267 /* Preserve DAIF flags. IRQs need to be disabled for this to work. */
268 flags = read_daif();
269 disable_irq();
270
271 /*
272 * Even with IRQs masked, the timer IRQ will wake the CPU up.
273 *
274 * If the timer IRQ happens before entering suspend mode (because the
275 * timer took too long to program, for example) the fact that the IRQ is
276 * pending will prevent the CPU from entering suspend mode and not being
277 * able to wake up.
278 */
279 timer_rc_val = tftf_program_timer(milli_secs);
280 if (timer_rc_val == 0) {
281 suspend_rc_val = tftf_system_suspend();
282 if (suspend_rc_val != PSCI_E_SUCCESS) {
283 rc = -1;
284 INFO("%s %d: suspend_rc = %d\n", __func__, __LINE__,
285 suspend_rc_val);
286 }
287 } else {
288 rc = -1;
289 INFO("%s %d: timer_rc = %d\n", __func__, __LINE__, timer_rc_val);
290 }
291
292 /* Restore previous DAIF flags */
293 write_daif(flags);
294 isb();
295
296 /*
297 * If IRQs were disabled when calling this function, the timer IRQ
298 * handler won't be called and the timer interrupt will be pending, but
299 * that isn't necessarily a problem.
300 */
301 if (timer_rc)
302 *timer_rc = timer_rc_val;
303 if (suspend_rc)
304 *suspend_rc = suspend_rc_val;
305
306 return rc;
307}
308
309int tftf_timer_sleep(unsigned long milli_secs)
310{
311 int ret, power_state;
312 uint32_t stateid;
313
314 ret = tftf_psci_make_composite_state_id(MPIDR_AFFLVL0,
315 PSTATE_TYPE_STANDBY, &stateid);
316 if (ret != PSCI_E_SUCCESS)
317 return -1;
318
319 power_state = tftf_make_psci_pstate(MPIDR_AFFLVL0, PSTATE_TYPE_STANDBY,
320 stateid);
321 ret = tftf_program_timer_and_suspend(milli_secs, power_state,
322 NULL, NULL);
323 if (ret != 0)
324 return -1;
325
326 return 0;
327}
328
329int tftf_cancel_timer(void)
330{
331 unsigned int core_pos = platform_get_core_pos(read_mpidr_el1());
332 unsigned int next_timer_req_core_pos;
333 unsigned long long current_time;
334 u_register_t flags;
335 int rc = 0;
336
337 /*
338 * IRQ is disabled so that if a timer is fired after taking a lock,
339 * it will remain pending and a core does not hit IRQ handler trying
340 * to acquire an already locked spin_lock causing dead lock.
341 */
342 flags = read_daif();
343 disable_irq();
344 spin_lock(&timer_lock);
345
346 interrupt_req_time[core_pos] = INVALID_TIME;
347
348 if (core_pos == current_prog_core) {
349 /*
350 * Cancel the programmed interrupt at the peripheral. If the
351 * timer interrupt is level triggered and fired this also
352 * deactivates the pending interrupt.
353 */
354 rc = plat_timer_info->cancel();
355 /* We don't expect cancel timer to fail */
356 if (rc) {
357 ERROR("%s %d: rc = %d\n", __func__, __LINE__, rc);
358 goto exit;
359 }
360
361 /*
362 * For edge triggered interrupts, if an IRQ is fired before
363 * cancel timer is executed, the signal remains pending. So,
364 * clear the Timer IRQ if it is already pending.
365 */
366 if (arm_gic_is_intr_pending(TIMER_IRQ))
367 arm_gic_intr_clear(TIMER_IRQ);
368
369 /* Get next timer consumer */
370 next_timer_req_core_pos = get_lowest_req_core();
371 if (next_timer_req_core_pos != INVALID_CORE) {
372
373 /* Retarget to the next_timer_req_core_pos */
374 arm_gic_set_intr_target(TIMER_IRQ, next_timer_req_core_pos);
375 current_prog_core = next_timer_req_core_pos;
376
377 current_time = get_current_time_ms();
378
379 /*
380 * If the next timer request is lesser than or in a
381 * window of TIMER_STEP_VALUE from current time,
382 * program it to fire after TIMER_STEP_VALUE.
383 */
384 if (interrupt_req_time[next_timer_req_core_pos] >
385 current_time + TIMER_STEP_VALUE)
386 rc = PROGRAM_TIMER(interrupt_req_time[next_timer_req_core_pos] - current_time);
387 else
388 rc = PROGRAM_TIMER(TIMER_STEP_VALUE);
389 VERBOSE("Cancel and program new timer for core_pos: "
390 "%d %lld\n",
391 next_timer_req_core_pos,
392 get_current_prog_time());
393 /* We don't expect timer programming to fail */
394 if (rc)
395 ERROR("%s %d: rc = %d\n", __func__, __LINE__, rc);
396 } else {
397 current_prog_core = INVALID_CORE;
398 VERBOSE("Cancelling timer : %d\n", core_pos);
399 }
400 }
401exit:
402 spin_unlock(&timer_lock);
403
404 /* Restore DAIF flags */
405 write_daif(flags);
406 isb();
407
408 return rc;
409}
410
411int tftf_timer_framework_handler(void *data)
412{
413 unsigned int handler_core_pos = platform_get_core_pos(read_mpidr_el1());
414 unsigned int next_timer_req_core_pos;
415 unsigned long long current_time;
416 int rc = 0;
417
418 assert(interrupt_req_time[handler_core_pos] != INVALID_TIME);
419 spin_lock(&timer_lock);
420
421 current_time = get_current_time_ms();
422 /* Check if we interrupt is targeted correctly */
423 assert(handler_core_pos == current_prog_core);
424
425 interrupt_req_time[handler_core_pos] = INVALID_TIME;
426
427 /* Execute the driver handler */
428 if (plat_timer_info->handler)
429 plat_timer_info->handler();
430
431 if (arm_gic_is_intr_pending(TIMER_IRQ)) {
432 /*
433 * We might never manage to acquire the printf lock here
434 * (because we are in ISR context) but we're gonna panic right
435 * after anyway so it doesn't really matter.
436 */
437 ERROR("Timer IRQ still pending. Fatal error.\n");
438 panic();
439 }
440
441 /*
442 * Execute the handler requested by the core, the handlers for the
443 * other cores will be executed as part of handling IRQ_WAKE_SGI.
444 */
445 if (timer_handler[handler_core_pos])
446 timer_handler[handler_core_pos](data);
447
448 /* Send interrupts to all the CPUS in the min time block */
449 for (int i = 0; i < PLATFORM_CORE_COUNT; i++) {
450 if ((interrupt_req_time[i] <=
451 (current_time + TIMER_STEP_VALUE))) {
452 interrupt_req_time[i] = INVALID_TIME;
453 tftf_send_sgi(IRQ_WAKE_SGI, i);
454 }
455 }
456
457 /* Get the next lowest requested timer core and program it */
458 next_timer_req_core_pos = get_lowest_req_core();
459 if (next_timer_req_core_pos != INVALID_CORE) {
460 /* Check we have not exceeded the time for next core */
461 assert(interrupt_req_time[next_timer_req_core_pos] >
462 current_time);
463 arm_gic_set_intr_target(TIMER_IRQ, next_timer_req_core_pos);
464 rc = PROGRAM_TIMER(interrupt_req_time[next_timer_req_core_pos]
465 - current_time);
466 }
467 /* Update current program core to the newer one */
468 current_prog_core = next_timer_req_core_pos;
469
470 spin_unlock(&timer_lock);
471
472 return rc;
473}
474
475int tftf_timer_register_handler(irq_handler_t irq_handler)
476{
477 unsigned int core_pos = platform_get_core_pos(read_mpidr_el1());
478 int ret;
479
480 /* Validate no handler is registered */
481 assert(!timer_handler[core_pos]);
482 timer_handler[core_pos] = irq_handler;
483
484 /*
485 * Also register same handler to IRQ_WAKE_SGI, as it can be waken
486 * by it.
487 */
488 ret = tftf_irq_register_handler(IRQ_WAKE_SGI, irq_handler);
489 assert(!ret);
490
491 return ret;
492}
493
494int tftf_timer_unregister_handler(void)
495{
496 unsigned int core_pos = platform_get_core_pos(read_mpidr_el1());
497 int ret;
498
499 /*
500 * Unregister the handler for IRQ_WAKE_SGI also
501 */
502 ret = tftf_irq_unregister_handler(IRQ_WAKE_SGI);
503 assert(!ret);
504 /* Validate a handler is registered */
505 assert(timer_handler[core_pos]);
506 timer_handler[core_pos] = 0;
507
508 return ret;
509}
510
511unsigned int tftf_get_timer_irq(void)
512{
513 /*
514 * Check if the timer info is initialised
515 */
516 assert(TIMER_IRQ);
517 return TIMER_IRQ;
518}
519
520unsigned int tftf_get_timer_step_value(void)
521{
522 assert(TIMER_STEP_VALUE);
523
524 return TIMER_STEP_VALUE;
525}
526
527/*
528 * There are 4 cases that could happen when a system is resuming from system
529 * suspend. The cases are:
530 * 1. The resumed core is the last core to power down and the
531 * timer interrupt was targeted to it. In this case, target the
532 * interrupt to our core and set the appropriate priority and enable it.
533 *
534 * 2. The resumed core was the last core to power down but the timer interrupt
535 * is targeted to another core because of timer request grouping within
536 * TIMER_STEP_VALUE. In this case, re-target the interrupt to our core
537 * and set the appropriate priority and enable it
538 *
539 * 3. The system suspend request was down-graded by firmware and the timer
540 * interrupt is targeted to another core which woke up first. In this case,
541 * that core will wake us up and the interrupt_req_time[] corresponding to
542 * our core will be cleared. In this case, no need to do anything as GIC
543 * state is preserved.
544 *
545 * 4. The system suspend is woken up by another external interrupt other
546 * than the timer framework interrupt. In this case, just enable the
547 * timer interrupt and set the correct priority at GICD.
548 */
549void tftf_timer_gic_state_restore(void)
550{
551 unsigned int core_pos = platform_get_core_pos(read_mpidr_el1());
552 spin_lock(&timer_lock);
553
554 arm_gic_set_intr_priority(TIMER_IRQ, GIC_HIGHEST_NS_PRIORITY);
555 arm_gic_intr_enable(TIMER_IRQ);
556
557 /* Check if the programmed core is the woken up core */
558 if (interrupt_req_time[core_pos] == INVALID_TIME) {
559 INFO("The programmed core is not the one woken up\n");
560 } else {
561 current_prog_core = core_pos;
562 arm_gic_set_intr_target(TIMER_IRQ, core_pos);
563 }
564
565 spin_unlock(&timer_lock);
566}
567