diff options
Diffstat (limited to 'firmware/target/arm/s3c2440/gigabeat-fx/timer-meg-fx.c')
-rw-r--r-- | firmware/target/arm/s3c2440/gigabeat-fx/timer-meg-fx.c | 127 |
1 files changed, 127 insertions, 0 deletions
diff --git a/firmware/target/arm/s3c2440/gigabeat-fx/timer-meg-fx.c b/firmware/target/arm/s3c2440/gigabeat-fx/timer-meg-fx.c new file mode 100644 index 0000000000..4654c7c845 --- /dev/null +++ b/firmware/target/arm/s3c2440/gigabeat-fx/timer-meg-fx.c | |||
@@ -0,0 +1,127 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2007 by Michael Sevakis | ||
11 | * | ||
12 | * All files in this archive are subject to the GNU General Public License. | ||
13 | * See the file COPYING in the source tree root for full license agreement. | ||
14 | * | ||
15 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
16 | * KIND, either express or implied. | ||
17 | * | ||
18 | ****************************************************************************/ | ||
19 | #include "config.h" | ||
20 | #include "cpu.h" | ||
21 | #include "system.h" | ||
22 | #include "timer.h" | ||
23 | #include "logf.h" | ||
24 | |||
25 | /* GPB0/TOUT0 should already have been configured as output so that pin | ||
26 | should not be a functional pin and TIMER0 output unseen there */ | ||
27 | void TIMER0(void) | ||
28 | { | ||
29 | if (pfn_timer != NULL) | ||
30 | pfn_timer(); | ||
31 | |||
32 | SRCPND = TIMER0_MASK; | ||
33 | INTPND = TIMER0_MASK; | ||
34 | } | ||
35 | |||
36 | static void stop_timer(void) | ||
37 | { | ||
38 | /* mask interrupt */ | ||
39 | INTMSK |= TIMER0_MASK; | ||
40 | |||
41 | /* stop any running TIMER0 */ | ||
42 | TCON &= ~(1 << 0); | ||
43 | |||
44 | /* clear pending */ | ||
45 | SRCPND = TIMER0_MASK; | ||
46 | INTPND = TIMER0_MASK; | ||
47 | } | ||
48 | |||
49 | bool __timer_set(long cycles, bool start) | ||
50 | { | ||
51 | bool retval = false; | ||
52 | |||
53 | /* Find the minimum factor that puts the counter in range 1-65535 */ | ||
54 | unsigned int prescaler = (cycles + 65534) / 65535; | ||
55 | |||
56 | /* Maximum divider setting is x / 256 / 16 = x / 4096 */ | ||
57 | if (prescaler <= 4096) | ||
58 | { | ||
59 | int oldlevel; | ||
60 | unsigned int divider; | ||
61 | |||
62 | if (start && pfn_unregister != NULL) | ||
63 | { | ||
64 | pfn_unregister(); | ||
65 | pfn_unregister = NULL; | ||
66 | } | ||
67 | |||
68 | oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL); | ||
69 | |||
70 | TCMPB0 = 0; | ||
71 | TCNTB0 = (unsigned int)cycles / prescaler; | ||
72 | |||
73 | /* Max prescale is 255+1 */ | ||
74 | for (divider = 0; prescaler > 256; prescaler >>= 1, divider++); | ||
75 | |||
76 | TCFG0 = (TCFG0 & ~0xff) | (prescaler - 1); | ||
77 | TCFG1 = (TCFG1 & ~0xf) | divider; | ||
78 | |||
79 | set_irq_level(oldlevel); | ||
80 | |||
81 | retval = true; | ||
82 | } | ||
83 | |||
84 | return retval; | ||
85 | } | ||
86 | |||
87 | bool __timer_register(void) | ||
88 | { | ||
89 | bool retval = true; | ||
90 | |||
91 | int oldstatus = set_interrupt_status(IRQ_FIQ_DISABLED, IRQ_FIQ_STATUS); | ||
92 | |||
93 | stop_timer(); | ||
94 | |||
95 | /* neurosis - make sure something didn't set GPB0 to TOUT0 */ | ||
96 | if ((GPBCON & 0x3) != 0x2) | ||
97 | { | ||
98 | /* manual update: on (to reset count) */ | ||
99 | TCON |= (1 << 1); | ||
100 | /* dead zone: off, inverter: off, manual off */ | ||
101 | TCON &= ~((1 << 4) | (1 << 2) | (1 << 1)); | ||
102 | /* interval mode (auto reload): on */ | ||
103 | TCON |= (1 << 3); | ||
104 | /* start timer */ | ||
105 | TCON |= (1 << 0); | ||
106 | /* unmask interrupt */ | ||
107 | INTMSK &= ~TIMER0_MASK; | ||
108 | } | ||
109 | |||
110 | if (!(TCON & (1 << 0))) | ||
111 | { | ||
112 | /* timer could not be started due to config error */ | ||
113 | logf("Timer error: GPB0 set to TOUT0"); | ||
114 | retval = false; | ||
115 | } | ||
116 | |||
117 | set_interrupt_status(oldstatus, IRQ_FIQ_STATUS); | ||
118 | |||
119 | return retval; | ||
120 | } | ||
121 | |||
122 | void __timer_unregister(void) | ||
123 | { | ||
124 | int oldstatus = set_interrupt_status(IRQ_FIQ_DISABLED, IRQ_FIQ_STATUS); | ||
125 | stop_timer(); | ||
126 | set_interrupt_status(oldstatus, IRQ_FIQ_STATUS); | ||
127 | } | ||