summaryrefslogtreecommitdiff
path: root/firmware/target
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target')
-rw-r--r--firmware/target/arm/s3c2440/gigabeat-fx/kernel-meg-fx.c51
-rw-r--r--firmware/target/arm/s3c2440/gigabeat-fx/timer-meg-fx.c127
-rw-r--r--firmware/target/arm/s3c2440/gigabeat-fx/timer-target.h39
-rw-r--r--firmware/target/arm/system-arm.h44
4 files changed, 229 insertions, 32 deletions
diff --git a/firmware/target/arm/s3c2440/gigabeat-fx/kernel-meg-fx.c b/firmware/target/arm/s3c2440/gigabeat-fx/kernel-meg-fx.c
index 9df90a2344..39e4efab49 100644
--- a/firmware/target/arm/s3c2440/gigabeat-fx/kernel-meg-fx.c
+++ b/firmware/target/arm/s3c2440/gigabeat-fx/kernel-meg-fx.c
@@ -1,13 +1,49 @@
1#include "config.h"
2#include "system.h"
1#include "kernel.h" 3#include "kernel.h"
4#include "timer.h"
2#include "thread.h" 5#include "thread.h"
3 6
4#include <stdio.h>
5#include "lcd.h"
6
7extern void (*tick_funcs[MAX_NUM_TICK_TASKS])(void); 7extern void (*tick_funcs[MAX_NUM_TICK_TASKS])(void);
8 8
9void timer4(void) { 9void tick_start(unsigned int interval_in_ms)
10 int i; 10{
11 /*
12 * Based on default PCLK of 49.1568MHz - scaling chosen to give
13 * remainder-free result for tick interval of 10ms (100Hz)
14 * Timer input clock frequency =
15 * fPCLK / {prescaler value+1} / {divider value}
16 * TIMER_FREQ = 49156800 / 2
17 * 13300 = TIMER_FREQ / 231 / 8
18 * 49156800 = 19*(11)*(7)*7*5*5*(3)*2*2*2*2*2*2
19 * 231 = 11*7*3
20 */
21
22 /* stop timer 4 */
23 TCON &= ~(1 << 20);
24 /* Set the count for timer 4 */
25 TCNTB4 = (TIMER_FREQ / 231 / 8) * interval_in_ms / 1000;
26 /* Set the the prescaler value for timers 2,3, and 4 */
27 TCFG0 = (TCFG0 & ~0xff00) | ((231-1) << 8);
28 /* MUX4 = 1/16 */
29 TCFG1 = (TCFG1 & ~0xff0000) | 0x030000;
30 /* set manual bit */
31 TCON |= 1 << 21;
32 /* reset manual bit */
33 TCON &= ~(1 << 21);
34 /* interval mode */
35 TCON |= 1 << 22;
36 /* start timer 4 */
37 TCON |= (1 << 20);
38
39 /* timer 4 unmask interrupts */
40 INTMSK &= ~TIMER4_MASK;
41}
42
43void TIMER4(void)
44{
45 int i;
46
11 /* Run through the list of tick tasks */ 47 /* Run through the list of tick tasks */
12 for(i = 0; i < MAX_NUM_TICK_TASKS; i++) 48 for(i = 0; i < MAX_NUM_TICK_TASKS; i++)
13 { 49 {
@@ -19,7 +55,6 @@ void timer4(void) {
19 55
20 current_tick++; 56 current_tick++;
21 57
22 /* following needs to be fixed. */ 58 SRCPND = TIMER4_MASK;
23 /*wake_up_thread();*/ 59 INTPND = TIMER4_MASK;
24} 60}
25
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 */
27void TIMER0(void)
28{
29 if (pfn_timer != NULL)
30 pfn_timer();
31
32 SRCPND = TIMER0_MASK;
33 INTPND = TIMER0_MASK;
34}
35
36static 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
49bool __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
87bool __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
122void __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}
diff --git a/firmware/target/arm/s3c2440/gigabeat-fx/timer-target.h b/firmware/target/arm/s3c2440/gigabeat-fx/timer-target.h
new file mode 100644
index 0000000000..e9f330cf8e
--- /dev/null
+++ b/firmware/target/arm/s3c2440/gigabeat-fx/timer-target.h
@@ -0,0 +1,39 @@
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#ifndef TIMER_TARGET_H
20#define TIMER_TARGET_H
21
22/* timer is based on PCLK and minimum division is 2 */
23#define TIMER_FREQ (49156800/2)
24
25bool __timer_set(long cycles, bool set);
26bool __timer_register(void);
27void __timer_unregister(void);
28
29#define __TIMER_SET(cycles, set) \
30 __timer_set(cycles, set)
31
32#define __TIMER_REGISTER(reg_prio, unregister_callback, cycles, \
33 int_prio, timer_callback) \
34 __timer_register()
35
36#define __TIMER_UNREGISTER(...) \
37 __timer_unregister()
38
39#endif /* TIMER_TARGET_H */
diff --git a/firmware/target/arm/system-arm.h b/firmware/target/arm/system-arm.h
index 99cab9e1a3..37c367fdc4 100644
--- a/firmware/target/arm/system-arm.h
+++ b/firmware/target/arm/system-arm.h
@@ -87,23 +87,6 @@ static inline uint32_t swap_odd_even32(uint32_t value)
87 return value; 87 return value;
88} 88}
89 89
90#define HIGHEST_IRQ_LEVEL (0x80)
91
92static inline int set_irq_level(int level)
93{
94 unsigned long cpsr;
95 int oldlevel;
96 /* Read the old level and set the new one */
97 asm volatile (
98 "mrs %1, cpsr \n"
99 "bic %0, %1, #0x80 \n"
100 "orr %0, %0, %2 \n"
101 "msr cpsr_c, %0 \n"
102 : "=&r,r"(cpsr), "=&r,r"(oldlevel) : "r,i"(level & 0x80)
103 );
104 return oldlevel;
105}
106
107static inline void set_fiq_handler(void(*fiq_handler)(void)) 90static inline void set_fiq_handler(void(*fiq_handler)(void))
108{ 91{
109 /* Install the FIQ handler */ 92 /* Install the FIQ handler */
@@ -133,22 +116,35 @@ static inline void disable_fiq(void)
133} 116}
134 117
135/* This one returns the old status */ 118/* This one returns the old status */
136#define FIQ_ENABLED 0x00 119#define IRQ_ENABLED 0x00
137#define FIQ_DISABLED 0x40 120#define IRQ_DISABLED 0x80
138static inline int set_fiq_status(int status) 121#define IRQ_STATUS 0x80
122#define FIQ_ENABLED 0x00
123#define FIQ_DISABLED 0x40
124#define FIQ_STATUS 0x40
125#define IRQ_FIQ_ENABLED 0x00
126#define IRQ_FIQ_DISABLED 0xc0
127#define IRQ_FIQ_STATUS 0xc0
128#define HIGHEST_IRQ_LEVEL IRQ_DISABLED
129
130#define set_irq_level(status) set_interrupt_status((status), IRQ_STATUS)
131#define set_fiq_status(status) set_interrupt_status((status), FIQ_STATUS)
132
133static inline int set_interrupt_status(int status, int mask)
139{ 134{
140 unsigned long cpsr; 135 unsigned long cpsr;
141 int oldstatus; 136 int oldstatus;
142 /* Read the old level and set the new one */ 137 /* Read the old levels and set the new ones */
143 asm volatile ( 138 asm volatile (
144 "mrs %1, cpsr \n" 139 "mrs %1, cpsr \n"
145 "bic %0, %1, #0x40 \n" 140 "bic %0, %1, %[mask] \n"
146 "orr %0, %0, %2 \n" 141 "orr %0, %0, %2 \n"
147 "msr cpsr_c, %0 \n" 142 "msr cpsr_c, %0 \n"
148 : "=&r,r"(cpsr), "=&r,r"(oldstatus) : "r,i"(status & 0x40) 143 : "=&r,r"(cpsr), "=&r,r"(oldstatus)
144 : "r,i"(status & mask), [mask]"i,i"(mask)
149 ); 145 );
146
150 return oldstatus; 147 return oldstatus;
151} 148}
152 149
153
154#endif /* SYSTEM_ARM_H */ 150#endif /* SYSTEM_ARM_H */