1 /*
2 * Copyright (c) 2015 Stefan Kristiansson
3 *
4 * Use of this source code is governed by a MIT-style
5 * license that can be found in the LICENSE file or at
6 * https://opensource.org/licenses/MIT
7 */
8 #include <lk/trace.h>
9 #include <lk/err.h>
10 #include <kernel/thread.h>
11 #include <platform/timer.h>
12 #include <platform/debug.h>
13 #include <sys/types.h>
14 #include <arch/or1k.h>
15
16 #define LOCAL_TRACE 0
17
18 static platform_timer_callback timer_cb;
19 static void *timer_arg;
20
21 static uint32_t timer_freq;
22
23 static volatile uint64_t ticks = 0;
24
platform_set_periodic_timer(platform_timer_callback callback,void * arg,lk_time_t interval)25 status_t platform_set_periodic_timer(platform_timer_callback callback, void *arg, lk_time_t interval) {
26 LTRACEF("cb %p, arg %p, interval %u\n", callback, arg, interval);
27
28 uint32_t ttmr = (uint64_t)timer_freq * interval / 1000;
29 LTRACEF("count 0x%x\n", ttmr);
30
31 timer_cb = callback;
32 timer_arg = arg;
33
34 /* disable timer before doing changes */
35 mtspr(OR1K_SPR_TICK_TTMR_ADDR, 0);
36 /* reset timer counter */
37 mtspr(OR1K_SPR_TICK_TTCR_ADDR, 0);
38 /* enable timer with given interval in 'restart' mode */
39 ttmr = OR1K_SPR_TICK_TTMR_MODE_SET(ttmr | OR1K_SPR_TICK_TTMR_IE_MASK,
40 OR1K_SPR_TICK_TTMR_MODE_RESTART);
41 mtspr(OR1K_SPR_TICK_TTMR_ADDR, ttmr);
42
43 return NO_ERROR;
44 }
45
current_time_hires(void)46 lk_bigtime_t current_time_hires(void) {
47 return (lk_bigtime_t)ticks * 10000;
48 }
49
current_time(void)50 lk_time_t current_time(void) {
51 return (lk_time_t)ticks * 10;
52 }
53
platform_tick(void)54 enum handler_return platform_tick(void) {
55 ticks++;
56
57 /* clear pending interrupt flag */
58 mtspr(OR1K_SPR_TICK_TTMR_ADDR,
59 mfspr(OR1K_SPR_TICK_TTMR_ADDR) & ~(OR1K_SPR_TICK_TTMR_IP_MASK));
60
61 return timer_cb(timer_arg, ticks * 10);
62 }
63
or1k_ticktimer_init(uint32_t freq)64 void or1k_ticktimer_init(uint32_t freq) {
65 timer_freq = freq;
66 /* disable timer */
67 mtspr(OR1K_SPR_TICK_TTMR_ADDR, 0);
68 /* reset timer counter */
69 mtspr(OR1K_SPR_TICK_TTCR_ADDR, 0);
70 /* clear pending interrupt flag */
71 mtspr(OR1K_SPR_TICK_TTMR_ADDR,
72 mfspr(OR1K_SPR_TICK_TTMR_ADDR) & ~(OR1K_SPR_TICK_TTMR_IP_MASK));
73 }
74