diff options
author | Michael Sevakis <jethead71@rockbox.org> | 2007-07-06 21:36:32 +0000 |
---|---|---|
committer | Michael Sevakis <jethead71@rockbox.org> | 2007-07-06 21:36:32 +0000 |
commit | 4ae87c8b8ab7ddbd286f5288adaddcaf0a187e31 (patch) | |
tree | d3880b9f53a5c38d2211a1b8812724bf96913c4c | |
parent | cbed7a2cd21bb2715b39ebcd3015147a9d7ff3c2 (diff) | |
download | rockbox-4ae87c8b8ab7ddbd286f5288adaddcaf0a187e31.tar.gz rockbox-4ae87c8b8ab7ddbd286f5288adaddcaf0a187e31.zip |
Gigabeat: Add timer functionality. Rework tick timer setup to be exactly 100Hz. Metronome should work now but some pcm changes are needed to have faster tocks work correctly (in the works).
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@13806 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r-- | firmware/SOURCES | 2 | ||||
-rw-r--r-- | firmware/export/timer.h | 7 | ||||
-rw-r--r-- | firmware/kernel.c | 36 | ||||
-rw-r--r-- | firmware/target/arm/s3c2440/gigabeat-fx/kernel-meg-fx.c | 51 | ||||
-rw-r--r-- | firmware/target/arm/s3c2440/gigabeat-fx/timer-meg-fx.c | 127 | ||||
-rw-r--r-- | firmware/target/arm/s3c2440/gigabeat-fx/timer-target.h | 39 | ||||
-rw-r--r-- | firmware/target/arm/system-arm.h | 44 | ||||
-rw-r--r-- | firmware/timer.c | 43 |
8 files changed, 265 insertions, 84 deletions
diff --git a/firmware/SOURCES b/firmware/SOURCES index 644b7d7148..7e26ca0bc4 100644 --- a/firmware/SOURCES +++ b/firmware/SOURCES | |||
@@ -520,10 +520,12 @@ target/arm/s3c2440/gigabeat-fx/ata-meg-fx.c | |||
520 | target/arm/s3c2440/gigabeat-fx/backlight-meg-fx.c | 520 | target/arm/s3c2440/gigabeat-fx/backlight-meg-fx.c |
521 | target/arm/s3c2440/gigabeat-fx/button-meg-fx.c | 521 | target/arm/s3c2440/gigabeat-fx/button-meg-fx.c |
522 | target/arm/s3c2440/gigabeat-fx/i2c-meg-fx.c | 522 | target/arm/s3c2440/gigabeat-fx/i2c-meg-fx.c |
523 | target/arm/s3c2440/gigabeat-fx/kernel-meg-fx.c | ||
523 | target/arm/s3c2440/gigabeat-fx/lcd-as-meg-fx.S | 524 | target/arm/s3c2440/gigabeat-fx/lcd-as-meg-fx.S |
524 | target/arm/s3c2440/gigabeat-fx/lcd-meg-fx.c | 525 | target/arm/s3c2440/gigabeat-fx/lcd-meg-fx.c |
525 | target/arm/s3c2440/gigabeat-fx/power-meg-fx.c | 526 | target/arm/s3c2440/gigabeat-fx/power-meg-fx.c |
526 | target/arm/s3c2440/gigabeat-fx/sc606-meg-fx.c | 527 | target/arm/s3c2440/gigabeat-fx/sc606-meg-fx.c |
528 | target/arm/s3c2440/gigabeat-fx/timer-meg-fx.c | ||
527 | target/arm/s3c2440/gigabeat-fx/usb-meg-fx.c | 529 | target/arm/s3c2440/gigabeat-fx/usb-meg-fx.c |
528 | target/arm/s3c2440/gigabeat-fx/wmcodec-meg-fx.c | 530 | target/arm/s3c2440/gigabeat-fx/wmcodec-meg-fx.c |
529 | target/arm/s3c2440/gigabeat-fx/dma_start.c | 531 | target/arm/s3c2440/gigabeat-fx/dma_start.c |
diff --git a/firmware/export/timer.h b/firmware/export/timer.h index 35994ce5f2..63f0567165 100644 --- a/firmware/export/timer.h +++ b/firmware/export/timer.h | |||
@@ -25,7 +25,6 @@ | |||
25 | 25 | ||
26 | #ifndef SIMULATOR | 26 | #ifndef SIMULATOR |
27 | 27 | ||
28 | |||
29 | #if defined(CPU_PP) | 28 | #if defined(CPU_PP) |
30 | /* Portalplayer chips use a microsecond timer. */ | 29 | /* Portalplayer chips use a microsecond timer. */ |
31 | #define TIMER_FREQ 1000000 | 30 | #define TIMER_FREQ 1000000 |
@@ -34,6 +33,8 @@ | |||
34 | #define TIMER_FREQ (CPU_FREQ/2) | 33 | #define TIMER_FREQ (CPU_FREQ/2) |
35 | #elif CONFIG_CPU == PNX0101 | 34 | #elif CONFIG_CPU == PNX0101 |
36 | #define TIMER_FREQ 3000000 | 35 | #define TIMER_FREQ 3000000 |
36 | #elif CONFIG_CPU == S3C2440 | ||
37 | #include "timer-target.h" | ||
37 | #else | 38 | #else |
38 | #define TIMER_FREQ CPU_FREQ | 39 | #define TIMER_FREQ CPU_FREQ |
39 | #endif | 40 | #endif |
@@ -46,5 +47,9 @@ void timers_adjust_prescale(int multiplier, bool enable_irq); | |||
46 | #endif | 47 | #endif |
47 | void timer_unregister(void); | 48 | void timer_unregister(void); |
48 | 49 | ||
50 | /* For target-specific interface use */ | ||
51 | extern void (*pfn_timer)(void); | ||
52 | extern void (*pfn_unregister)(void); | ||
53 | |||
49 | #endif /* !SIMULATOR */ | 54 | #endif /* !SIMULATOR */ |
50 | #endif /* __TIMER_H__ */ | 55 | #endif /* __TIMER_H__ */ |
diff --git a/firmware/kernel.c b/firmware/kernel.c index 2d4ccde267..b1a4e62a81 100644 --- a/firmware/kernel.c +++ b/firmware/kernel.c | |||
@@ -29,7 +29,7 @@ | |||
29 | volatile long current_tick NOCACHEDATA_ATTR = 0; | 29 | volatile long current_tick NOCACHEDATA_ATTR = 0; |
30 | #endif | 30 | #endif |
31 | 31 | ||
32 | static void (*tick_funcs[MAX_NUM_TICK_TASKS])(void); | 32 | void (*tick_funcs[MAX_NUM_TICK_TASKS])(void); |
33 | 33 | ||
34 | /* This array holds all queues that are initiated. It is used for broadcast. */ | 34 | /* This array holds all queues that are initiated. It is used for broadcast. */ |
35 | static struct event_queue *all_queues[32] NOCACHEBSS_ATTR; | 35 | static struct event_queue *all_queues[32] NOCACHEBSS_ATTR; |
@@ -708,40 +708,6 @@ void tick_start(unsigned int interval_in_ms) | |||
708 | 708 | ||
709 | TIMER0.ctrl |= 0x80; /* Enable the counter */ | 709 | TIMER0.ctrl |= 0x80; /* Enable the counter */ |
710 | } | 710 | } |
711 | #elif CONFIG_CPU == S3C2440 | ||
712 | void tick_start(unsigned int interval_in_ms) | ||
713 | { | ||
714 | TCON &= ~(1 << 20); // stop timer 4 | ||
715 | // TODO: this constant depends on dividers settings inherited from | ||
716 | // firmware. Set them explicitly somwhere. | ||
717 | TCNTB4 = 12193 * interval_in_ms / 1000; | ||
718 | TCON |= 1 << 21; // set manual bit | ||
719 | TCON &= ~(1 << 21); // reset manual bit | ||
720 | TCON |= 1 << 22; //interval mode | ||
721 | TCON |= (1 << 20); // start timer 4 | ||
722 | |||
723 | INTMOD &= ~(1 << 14); // timer 4 to IRQ mode | ||
724 | INTMSK &= ~(1 << 14); // timer 4 unmask interrupts | ||
725 | } | ||
726 | |||
727 | void TIMER4(void) | ||
728 | { | ||
729 | int i; | ||
730 | |||
731 | SRCPND = TIMER4_MASK; | ||
732 | INTPND = TIMER4_MASK; | ||
733 | |||
734 | /* Run through the list of tick tasks */ | ||
735 | for(i = 0; i < MAX_NUM_TICK_TASKS; i++) | ||
736 | { | ||
737 | if(tick_funcs[i]) | ||
738 | { | ||
739 | tick_funcs[i](); | ||
740 | } | ||
741 | } | ||
742 | |||
743 | current_tick++; | ||
744 | } | ||
745 | #endif | 711 | #endif |
746 | 712 | ||
747 | int tick_add_task(void (*f)(void)) | 713 | int tick_add_task(void (*f)(void)) |
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 | |||
7 | extern void (*tick_funcs[MAX_NUM_TICK_TASKS])(void); | 7 | extern void (*tick_funcs[MAX_NUM_TICK_TASKS])(void); |
8 | 8 | ||
9 | void timer4(void) { | 9 | void 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 | |||
43 | void 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 */ | ||
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 | } | ||
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 | |||
25 | bool __timer_set(long cycles, bool set); | ||
26 | bool __timer_register(void); | ||
27 | void __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 | |||
92 | static 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 | |||
107 | static inline void set_fiq_handler(void(*fiq_handler)(void)) | 90 | static 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 |
138 | static 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 | |||
133 | static 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 */ |
diff --git a/firmware/timer.c b/firmware/timer.c index ca23cb890c..1ac16b697a 100644 --- a/firmware/timer.c +++ b/firmware/timer.c | |||
@@ -22,10 +22,11 @@ | |||
22 | #include "cpu.h" | 22 | #include "cpu.h" |
23 | #include "system.h" | 23 | #include "system.h" |
24 | #include "timer.h" | 24 | #include "timer.h" |
25 | #include "logf.h" | ||
25 | 26 | ||
26 | static int timer_prio = -1; | 27 | static int timer_prio = -1; |
27 | static void (*pfn_timer)(void) = NULL; /* timer callback */ | 28 | void (*pfn_timer)(void) = NULL; /* timer callback */ |
28 | static void (*pfn_unregister)(void) = NULL; /* unregister callback */ | 29 | void (*pfn_unregister)(void) = NULL; /* unregister callback */ |
29 | #ifdef CPU_COLDFIRE | 30 | #ifdef CPU_COLDFIRE |
30 | static int base_prescale; | 31 | static int base_prescale; |
31 | #elif defined CPU_PP || CONFIG_CPU == PNX0101 | 32 | #elif defined CPU_PP || CONFIG_CPU == PNX0101 |
@@ -123,9 +124,9 @@ static bool timer_set(long cycles, bool start) | |||
123 | } | 124 | } |
124 | else | 125 | else |
125 | cycles_new = cycles; | 126 | cycles_new = cycles; |
126 | #endif | ||
127 | 127 | ||
128 | #if CONFIG_CPU == SH7034 | 128 | return true; |
129 | #elif CONFIG_CPU == SH7034 | ||
129 | if (prescale > 8) | 130 | if (prescale > 8) |
130 | return false; | 131 | return false; |
131 | 132 | ||
@@ -150,6 +151,7 @@ static bool timer_set(long cycles, bool start) | |||
150 | TCNT4 = 0; | 151 | TCNT4 = 0; |
151 | and_b(~0x01, &TSR4); /* clear an eventual interrupt */ | 152 | and_b(~0x01, &TSR4); /* clear an eventual interrupt */ |
152 | 153 | ||
154 | return true; | ||
153 | #elif defined CPU_COLDFIRE | 155 | #elif defined CPU_COLDFIRE |
154 | if (prescale > 4096/CPUFREQ_MAX_MULT) | 156 | if (prescale > 4096/CPUFREQ_MAX_MULT) |
155 | return false; | 157 | return false; |
@@ -186,6 +188,8 @@ static bool timer_set(long cycles, bool start) | |||
186 | if (start || (TCN1 >= TRR1)) | 188 | if (start || (TCN1 >= TRR1)) |
187 | TCN1 = 0; /* reset the timer */ | 189 | TCN1 = 0; /* reset the timer */ |
188 | TER1 = 0xff; /* clear all events */ | 190 | TER1 = 0xff; /* clear all events */ |
191 | |||
192 | return true; | ||
189 | #elif defined(CPU_PP) | 193 | #elif defined(CPU_PP) |
190 | if (cycles > 0x20000000 || cycles < 2) | 194 | if (cycles > 0x20000000 || cycles < 2) |
191 | return false; | 195 | return false; |
@@ -203,11 +207,10 @@ static bool timer_set(long cycles, bool start) | |||
203 | else | 207 | else |
204 | cycles_new = cycles; | 208 | cycles_new = cycles; |
205 | 209 | ||
206 | #elif CONFIG_CPU == S3C2440 /* TODO: Implement for the Gigabeat */ | ||
207 | (void)start; | ||
208 | (void)cycles; | ||
209 | #endif /* CONFIG_CPU */ | ||
210 | return true; | 210 | return true; |
211 | #elif CONFIG_CPU == S3C2440 | ||
212 | return __TIMER_SET(cycles, start); | ||
213 | #endif /* CONFIG_CPU */ | ||
211 | } | 214 | } |
212 | 215 | ||
213 | #ifdef CPU_COLDFIRE | 216 | #ifdef CPU_COLDFIRE |
@@ -236,16 +239,9 @@ bool timer_register(int reg_prio, void (*unregister_callback)(void), | |||
236 | if (reg_prio <= timer_prio || cycles == 0) | 239 | if (reg_prio <= timer_prio || cycles == 0) |
237 | return false; | 240 | return false; |
238 | 241 | ||
239 | #if defined(CPU_PP) || (CONFIG_CPU==PNX0101) || (CONFIG_CPU==S3C2440) | ||
240 | /* TODO: Implement for PortalPlayer and iFP (if possible) */ | ||
241 | (void)int_prio; | ||
242 | #endif | ||
243 | |||
244 | #if CONFIG_CPU == SH7034 | 242 | #if CONFIG_CPU == SH7034 |
245 | if (int_prio < 1 || int_prio > 15) | 243 | if (int_prio < 1 || int_prio > 15) |
246 | return false; | 244 | return false; |
247 | #elif defined CPU_COLDFIRE | ||
248 | (void)int_prio; | ||
249 | #endif | 245 | #endif |
250 | 246 | ||
251 | if (!timer_set(cycles, true)) | 247 | if (!timer_set(cycles, true)) |
@@ -258,18 +254,31 @@ bool timer_register(int reg_prio, void (*unregister_callback)(void), | |||
258 | #if CONFIG_CPU == SH7034 | 254 | #if CONFIG_CPU == SH7034 |
259 | IPRD = (IPRD & 0xFF0F) | int_prio << 4; /* interrupt priority */ | 255 | IPRD = (IPRD & 0xFF0F) | int_prio << 4; /* interrupt priority */ |
260 | or_b(0x10, &TSTR); /* start timer 4 */ | 256 | or_b(0x10, &TSTR); /* start timer 4 */ |
257 | return true; | ||
261 | #elif defined CPU_COLDFIRE | 258 | #elif defined CPU_COLDFIRE |
262 | ICR2 = 0x90; /* interrupt on level 4.0 */ | 259 | ICR2 = 0x90; /* interrupt on level 4.0 */ |
263 | and_l(~(1<<10), &IMR); | 260 | and_l(~(1<<10), &IMR); |
264 | TMR1 |= 1; /* start timer */ | 261 | TMR1 |= 1; /* start timer */ |
262 | return true; | ||
265 | #elif defined(CPU_PP) | 263 | #elif defined(CPU_PP) |
266 | /* unmask interrupt source */ | 264 | /* unmask interrupt source */ |
267 | CPU_INT_EN = TIMER2_MASK; | 265 | CPU_INT_EN = TIMER2_MASK; |
266 | return true; | ||
268 | #elif CONFIG_CPU == PNX0101 | 267 | #elif CONFIG_CPU == PNX0101 |
269 | irq_set_int_handler(IRQ_TIMER1, TIMER1_ISR); | 268 | irq_set_int_handler(IRQ_TIMER1, TIMER1_ISR); |
270 | irq_enable_int(IRQ_TIMER1); | 269 | irq_enable_int(IRQ_TIMER1); |
271 | #endif | ||
272 | return true; | 270 | return true; |
271 | #elif CONFIG_CPU == S3C2440 | ||
272 | return __TIMER_REGISTER(reg_prio, unregister_callback, cycles, | ||
273 | int_prio, timer_callback); | ||
274 | #endif | ||
275 | /* Cover for targets that don't use all these */ | ||
276 | (void)reg_prio; | ||
277 | (void)unregister_callback; | ||
278 | (void)cycles; | ||
279 | /* TODO: Implement for PortalPlayer and iFP (if possible) */ | ||
280 | (void)int_prio; | ||
281 | (void)timer_callback; | ||
273 | } | 282 | } |
274 | 283 | ||
275 | bool timer_set_period(long cycles) | 284 | bool timer_set_period(long cycles) |
@@ -291,6 +300,8 @@ void timer_unregister(void) | |||
291 | #elif CONFIG_CPU == PNX0101 | 300 | #elif CONFIG_CPU == PNX0101 |
292 | TIMER1.ctrl &= ~0x80; /* disable timer 1 */ | 301 | TIMER1.ctrl &= ~0x80; /* disable timer 1 */ |
293 | irq_disable_int(5); | 302 | irq_disable_int(5); |
303 | #elif CONFIG_CPU == S3C2440 | ||
304 | __TIMER_UNREGISTER(); | ||
294 | #endif | 305 | #endif |
295 | pfn_timer = NULL; | 306 | pfn_timer = NULL; |
296 | pfn_unregister = NULL; | 307 | pfn_unregister = NULL; |