summaryrefslogtreecommitdiff
path: root/firmware/target/arm/tcc780x/timer-tcc780x.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/arm/tcc780x/timer-tcc780x.c')
-rw-r--r--firmware/target/arm/tcc780x/timer-tcc780x.c62
1 files changed, 52 insertions, 10 deletions
diff --git a/firmware/target/arm/tcc780x/timer-tcc780x.c b/firmware/target/arm/tcc780x/timer-tcc780x.c
index 17956131c0..ca6613a3ff 100644
--- a/firmware/target/arm/tcc780x/timer-tcc780x.c
+++ b/firmware/target/arm/tcc780x/timer-tcc780x.c
@@ -25,40 +25,82 @@
25#include "timer.h" 25#include "timer.h"
26#include "logf.h" 26#include "logf.h"
27 27
28/* Use the TC32 counter [sourced by Xin:12Mhz] for this timer, as it's the 28static const int prescale_shifts[] = {1, 2, 3, 4, 5, 10, 12};
29 only one that allows a 32-bit counter (Timer0-5 are 16/20 bit only). */
30 29
31bool __timer_set(long cycles, bool start) 30bool __timer_set(long cycles, bool start)
32{ 31{
33 (void)cycles; 32 bool found = false;
34 (void)start; 33
35 return false; 34 int prescale_option = 0;
35 int actual_cycles = 0;
36
37 /* Use the first prescale that fits Timer4's 20-bit counter */
38 while (!found && prescale_option < 7)
39 {
40 actual_cycles = cycles >> prescale_shifts[prescale_option];
41
42 if (actual_cycles < 0x100000)
43 found = true;
44 else
45 prescale_option++;
46 }
47
48 if (!found)
49 return false;
50
51 /* Stop the timer and set new prescale & ref count */
52 TCFG(4) &= ~TCFG_EN;
53 TCFG(4) = prescale_option << TCFG_SEL;
54 TREF(4) = actual_cycles;
55
56 if (start && pfn_unregister != NULL)
57 {
58 pfn_unregister();
59 pfn_unregister = NULL;
60 }
61
62 return true;
36} 63}
37 64
38bool __timer_register(void) 65bool __timer_register(void)
39{ 66{
40 return false; 67 int oldstatus = disable_interrupt_save(IRQ_STATUS);
68
69 TCFG(4) |= TCFG_CLEAR | TCFG_IEN | TCFG_EN;
70
71 restore_interrupt(oldstatus);
72
73 return true;
41} 74}
42 75
43void __timer_unregister(void) 76void __timer_unregister(void)
44{ 77{
78 int oldstatus = disable_interrupt_save(IRQ_STATUS);
79
80 TCFG(4) &= ~TCFG_EN;
81
82 restore_interrupt(oldstatus);
45} 83}
46 84
47 85
48/* Timer interrupt processing - all timers (inc. tick) have a single IRQ */ 86/* Timer interrupt processing - all timers (inc. tick) have a single IRQ */
49void TIMER0(void) 87void TIMER0(void)
50{ 88{
51 if (TIREQ & TF0) /* Timer0 reached ref value */ 89 if (TIREQ & TIREQ_TF0) /* Timer0 reached ref value */
52 { 90 {
53 /* Run through the list of tick tasks */ 91 /* Run through the list of tick tasks */
54 call_tick_tasks(); 92 call_tick_tasks();
55 93
56 /* reset Timer 0 IRQ & ref flags */ 94 /* reset Timer 0 IRQ & ref flags */
57 TIREQ |= TI0 | TF0; 95 TIREQ = TIREQ_TI0 | TIREQ_TF0;
58 } 96 }
59 97
60 if (TC32IRQ & (1<<3)) /* end of TC32 prescale */ 98 if (TIREQ & TIREQ_TF4) /* Timer4 reached ref value */
61 { 99 {
62 /* dispatch timer */ 100 /* dispatch user timer */
101 if (pfn_timer != NULL)
102 pfn_timer();
103
104 TIREQ = TIREQ_TI4 | TIREQ_TF4;
63 } 105 }
64} 106}