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