summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--firmware/SOURCES1
-rw-r--r--firmware/export/timer.h10
-rw-r--r--firmware/target/arm/timer-pp.c87
-rw-r--r--firmware/target/arm/timer-target.h52
-rw-r--r--firmware/timer.c71
5 files changed, 154 insertions, 67 deletions
diff --git a/firmware/SOURCES b/firmware/SOURCES
index 239eb92a92..975e2b8688 100644
--- a/firmware/SOURCES
+++ b/firmware/SOURCES
@@ -394,6 +394,7 @@ target/arm/as3525/pcm-as3525.c
394 394
395#if defined(CPU_PP) 395#if defined(CPU_PP)
396target/arm/kernel-pp.c 396target/arm/kernel-pp.c
397target/arm/timer-pp.c
397#if CONFIG_CPU == PP5002 398#if CONFIG_CPU == PP5002
398target/arm/system-pp5002.c 399target/arm/system-pp5002.c
399#elif defined CPU_PP502x 400#elif defined CPU_PP502x
diff --git a/firmware/export/timer.h b/firmware/export/timer.h
index f3faf0908e..678d9ad8c6 100644
--- a/firmware/export/timer.h
+++ b/firmware/export/timer.h
@@ -25,19 +25,19 @@
25#include <stdbool.h> 25#include <stdbool.h>
26#include "config.h" 26#include "config.h"
27 27
28#if defined(CPU_PP) 28#if defined(SIMULATOR)
29 /* Portalplayer chips use a microsecond timer. */
30 #define TIMER_FREQ 1000000 29 #define TIMER_FREQ 1000000
31#elif CONFIG_CPU == S3C2440 || CONFIG_CPU == DM320 || CONFIG_CPU == TCC7801 \ 30#elif CONFIG_CPU == S3C2440 || CONFIG_CPU == DM320 || CONFIG_CPU == TCC7801 \
32 || defined(CPU_TCC77X) || CONFIG_CPU == AS3525 || CONFIG_CPU == IMX31L \ 31 || defined(CPU_TCC77X) || CONFIG_CPU == AS3525 || CONFIG_CPU == IMX31L \
33 || CONFIG_CPU == JZ4732 || CONFIG_CPU == PNX0101 \ 32 || CONFIG_CPU == JZ4732 || CONFIG_CPU == PNX0101 \
34 || defined(CPU_COLDFIRE) || CONFIG_CPU == SH7034 33 || defined(CPU_COLDFIRE) || CONFIG_CPU == SH7034 || defined(CPU_PP)
35 #include "timer-target.h" 34 #include "timer-target.h"
36#elif defined(SIMULATOR) 35#else
37 #define TIMER_FREQ 1000000 36 #warning "Target without timer-target.h"
38#endif 37#endif
39 38
40#ifndef TIMER_FREQ 39#ifndef TIMER_FREQ
40 #warning "TIMER_FREQ not defined"
41 #define TIMER_FREQ CPU_FREQ 41 #define TIMER_FREQ CPU_FREQ
42#endif 42#endif
43bool timer_register(int reg_prio, void (*unregister_callback)(void), 43bool timer_register(int reg_prio, void (*unregister_callback)(void),
diff --git a/firmware/target/arm/timer-pp.c b/firmware/target/arm/timer-pp.c
new file mode 100644
index 0000000000..01c691f79e
--- /dev/null
+++ b/firmware/target/arm/timer-pp.c
@@ -0,0 +1,87 @@
1/***************************************************************************
2* __________ __ ___.
3* Open \______ \ ____ ____ | | _\_ |__ _______ ___
4* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7* \/ \/ \/ \/ \/
8* $Id$
9*
10* Copyright (C) 2006 Thom Johansen
11*
12* This program is free software; you can redistribute it and/or
13* modify it under the terms of the GNU General Public License
14* as published by the Free Software Foundation; either version 2
15* of the License, or (at your option) any later version.
16*
17* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18* KIND, either express or implied.
19*
20****************************************************************************/
21
22#include "cpu.h"
23#include "system.h"
24#include "timer.h"
25#include "timer-target.h"
26
27static long SHAREDBSS_ATTR cycles_new = 0;
28
29void TIMER2(void)
30{
31 TIMER2_VAL; /* ACK interrupt */
32 if (cycles_new > 0)
33 {
34 TIMER2_CFG = 0xc0000000 | (cycles_new - 1);
35 cycles_new = 0;
36 }
37 if (pfn_timer != NULL)
38 {
39 cycles_new = -1;
40 /* "lock" the variable, in case timer_set_period()
41 * is called within pfn_timer() */
42 pfn_timer();
43 cycles_new = 0;
44 }
45}
46
47bool __timer_set(long cycles, bool start)
48{
49 if (cycles > 0x20000000 || cycles < 2)
50 return false;
51
52 if (start)
53 {
54 if (pfn_unregister != NULL)
55 {
56 pfn_unregister();
57 pfn_unregister = NULL;
58 }
59 CPU_INT_DIS = TIMER2_MASK;
60 COP_INT_DIS = TIMER2_MASK;
61 }
62 if (start || (cycles_new == -1)) /* within isr, cycles_new is "locked" */
63 TIMER2_CFG = 0xc0000000 | (cycles - 1); /* enable timer */
64 else
65 cycles_new = cycles;
66
67 return true;
68}
69
70bool __timer_start(IF_COP_VOID(int core))
71{
72 /* unmask interrupt source */
73#if NUM_CORES > 1
74 if (core == COP)
75 COP_INT_EN = TIMER2_MASK;
76 else
77#endif
78 CPU_INT_EN = TIMER2_MASK;
79 return true;
80}
81
82void __timer_stop(void)
83{
84 TIMER2_CFG = 0; /* stop timer 2 */
85 CPU_INT_DIS = TIMER2_MASK;
86 COP_INT_DIS = TIMER2_MASK;
87}
diff --git a/firmware/target/arm/timer-target.h b/firmware/target/arm/timer-target.h
new file mode 100644
index 0000000000..6801cfe783
--- /dev/null
+++ b/firmware/target/arm/timer-target.h
@@ -0,0 +1,52 @@
1/***************************************************************************
2* __________ __ ___.
3* Open \______ \ ____ ____ | | _\_ |__ _______ ___
4* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7* \/ \/ \/ \/ \/
8* $Id$
9*
10* Copyright (C) 2006 Thom Johansen
11*
12* This program is free software; you can redistribute it and/or
13* modify it under the terms of the GNU General Public License
14* as published by the Free Software Foundation; either version 2
15* of the License, or (at your option) any later version.
16*
17* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18* KIND, either express or implied.
19*
20****************************************************************************/
21#ifndef TIMER_TARGET_H
22#define TIMER_TARGET_H
23
24#include "config.h"
25
26/* FIXME : this header is PP specific */
27#ifndef CPU_PP
28#error "PP specific header"
29#endif
30
31bool __timer_set(long cycles, bool start);
32bool __timer_start(IF_COP_VOID(int core));
33void __timer_stop(void);
34
35/* Portalplayer chips use a microsecond timer. */
36#define TIMER_FREQ 1000000
37
38#define __TIMER_SET(cycles, set) \
39 __timer_set(cycles, set)
40
41#if NUM_CORES > 1
42#define __TIMER_START(int_prio, core) \
43 __timer_start(core)
44#else
45#define __TIMER_START(int_prio) \
46 __timer_start()
47#endif
48
49#define __TIMER_STOP(...) \
50 __timer_stop()
51
52#endif /* TIMER_TARGET_H */
diff --git a/firmware/timer.c b/firmware/timer.c
index 044b871b3f..8cd165bd35 100644
--- a/firmware/timer.c
+++ b/firmware/timer.c
@@ -29,64 +29,22 @@
29static int timer_prio = -1; 29static int timer_prio = -1;
30void SHAREDBSS_ATTR (*pfn_timer)(void) = NULL; /* timer callback */ 30void SHAREDBSS_ATTR (*pfn_timer)(void) = NULL; /* timer callback */
31void SHAREDBSS_ATTR (*pfn_unregister)(void) = NULL; /* unregister callback */ 31void SHAREDBSS_ATTR (*pfn_unregister)(void) = NULL; /* unregister callback */
32#if defined CPU_PP
33static long SHAREDBSS_ATTR cycles_new = 0;
34#endif
35 32
36#ifndef __TIMER_SET 33#ifndef __TIMER_SET
37/* Define these if not defined by target to make the #else cases compile 34/* Define these if not defined by target to make the #else cases compile
38 * even if the target doesn't have them implemented. */ 35 * even if the target doesn't have them implemented. */
39#define __TIMER_SET(cycles, set) false 36#define __TIMER_SET(cycles, set) false
40#define __TIMER_START() false 37#if NUM_CORES > 1
41#define __TIMER_STOP(...) 38#define __TIMER_START(int_prio, core) false
39#else
40#define __TIMER_START(int_prio) false
41#endif
42#define __TIMER_STOP()
42#endif 43#endif
43
44/* interrupt handler */
45#if defined(CPU_PP)
46void TIMER2(void)
47{
48 TIMER2_VAL; /* ACK interrupt */
49 if (cycles_new > 0)
50 {
51 TIMER2_CFG = 0xc0000000 | (cycles_new - 1);
52 cycles_new = 0;
53 }
54 if (pfn_timer != NULL)
55 {
56 cycles_new = -1;
57 /* "lock" the variable, in case timer_set_period()
58 * is called within pfn_timer() */
59 pfn_timer();
60 cycles_new = 0;
61 }
62}
63#endif /* CONFIG_CPU */
64 44
65static bool timer_set(long cycles, bool start) 45static bool timer_set(long cycles, bool start)
66{ 46{
67#if defined(CPU_PP)
68 if (cycles > 0x20000000 || cycles < 2)
69 return false;
70
71 if (start)
72 {
73 if (pfn_unregister != NULL)
74 {
75 pfn_unregister();
76 pfn_unregister = NULL;
77 }
78 CPU_INT_DIS = TIMER2_MASK;
79 COP_INT_DIS = TIMER2_MASK;
80 }
81 if (start || (cycles_new == -1)) /* within isr, cycles_new is "locked" */
82 TIMER2_CFG = 0xc0000000 | (cycles - 1); /* enable timer */
83 else
84 cycles_new = cycles;
85
86 return true;
87#else
88 return __TIMER_SET(cycles, start); 47 return __TIMER_SET(cycles, start);
89#endif /* CONFIG_CPU */
90} 48}
91 49
92/* Register a user timer, called every <cycles> TIMER_FREQ cycles */ 50/* Register a user timer, called every <cycles> TIMER_FREQ cycles */
@@ -109,18 +67,12 @@ bool timer_register(int reg_prio, void (*unregister_callback)(void),
109 pfn_unregister = unregister_callback; 67 pfn_unregister = unregister_callback;
110 timer_prio = reg_prio; 68 timer_prio = reg_prio;
111 69
112#if defined(CPU_PP)
113 /* unmask interrupt source */
114#if NUM_CORES > 1 70#if NUM_CORES > 1
115 if (core == COP) 71 return __TIMER_START(int_prio, core);
116 COP_INT_EN = TIMER2_MASK;
117 else
118#endif
119 CPU_INT_EN = TIMER2_MASK;
120 return true;
121#else 72#else
122 return __TIMER_START(int_prio); 73 return __TIMER_START(int_prio);
123#endif 74#endif
75
124 /* Cover for targets that don't use all these */ 76 /* Cover for targets that don't use all these */
125 (void)reg_prio; 77 (void)reg_prio;
126 (void)unregister_callback; 78 (void)unregister_callback;
@@ -137,13 +89,8 @@ bool timer_set_period(long cycles)
137 89
138void timer_unregister(void) 90void timer_unregister(void)
139{ 91{
140#if defined(CPU_PP)
141 TIMER2_CFG = 0; /* stop timer 2 */
142 CPU_INT_DIS = TIMER2_MASK;
143 COP_INT_DIS = TIMER2_MASK;
144#else
145 __TIMER_STOP(); 92 __TIMER_STOP();
146#endif 93
147 pfn_timer = NULL; 94 pfn_timer = NULL;
148 pfn_unregister = NULL; 95 pfn_unregister = NULL;
149 timer_prio = -1; 96 timer_prio = -1;