diff options
author | Michael Sevakis <jethead71@rockbox.org> | 2009-01-05 00:00:29 +0000 |
---|---|---|
committer | Michael Sevakis <jethead71@rockbox.org> | 2009-01-05 00:00:29 +0000 |
commit | e2876ee4e2ff260e616863b2c54004516743e766 (patch) | |
tree | 4abaff62e18b6a15302391c45eb60ab5174ee4dd /firmware | |
parent | 6d5823f964d8cc2b030d7a713d355f3132e41c45 (diff) | |
download | rockbox-e2876ee4e2ff260e616863b2c54004516743e766.tar.gz rockbox-e2876ee4e2ff260e616863b2c54004516743e766.zip |
Gigabeat S: Get timer API working. metronome will work now.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@19676 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware')
-rw-r--r-- | firmware/SOURCES | 3 | ||||
-rw-r--r-- | firmware/export/timer.h | 2 | ||||
-rw-r--r-- | firmware/target/arm/imx31/gigabeat-s/timer-imx31.c | 112 | ||||
-rw-r--r-- | firmware/target/arm/imx31/gigabeat-s/timer-target.h | 41 | ||||
-rw-r--r-- | firmware/timer.c | 18 |
5 files changed, 166 insertions, 10 deletions
diff --git a/firmware/SOURCES b/firmware/SOURCES index 7cbb3c7c18..c8f824a849 100644 --- a/firmware/SOURCES +++ b/firmware/SOURCES | |||
@@ -768,9 +768,10 @@ target/arm/imx31/gigabeat-s/system-imx31.c | |||
768 | target/arm/imx31/gigabeat-s/usb-imx31.c | 768 | target/arm/imx31/gigabeat-s/usb-imx31.c |
769 | target/arm/imx31/gigabeat-s/wmcodec-imx31.c | 769 | target/arm/imx31/gigabeat-s/wmcodec-imx31.c |
770 | #ifndef BOOTLOADER | 770 | #ifndef BOOTLOADER |
771 | target/arm/imx31/gigabeat-s/pcm-imx31.c | ||
772 | target/arm/imx31/gigabeat-s/audio-gigabeat-s.c | 771 | target/arm/imx31/gigabeat-s/audio-gigabeat-s.c |
773 | target/arm/imx31/gigabeat-s/fmradio-i2c-gigabeat-s.c | 772 | target/arm/imx31/gigabeat-s/fmradio-i2c-gigabeat-s.c |
773 | target/arm/imx31/gigabeat-s/pcm-imx31.c | ||
774 | target/arm/imx31/gigabeat-s/timer-imx31.c | ||
774 | #endif | 775 | #endif |
775 | #endif /* SIMULATOR */ | 776 | #endif /* SIMULATOR */ |
776 | #endif /* GIGABEAT_S */ | 777 | #endif /* GIGABEAT_S */ |
diff --git a/firmware/export/timer.h b/firmware/export/timer.h index f9aa650071..258ab1767a 100644 --- a/firmware/export/timer.h +++ b/firmware/export/timer.h | |||
@@ -34,7 +34,7 @@ | |||
34 | #elif CONFIG_CPU == PNX0101 | 34 | #elif CONFIG_CPU == PNX0101 |
35 | #define TIMER_FREQ 3000000 | 35 | #define TIMER_FREQ 3000000 |
36 | #elif CONFIG_CPU == S3C2440 || CONFIG_CPU == DM320 || CONFIG_CPU == TCC7801 \ | 36 | #elif CONFIG_CPU == S3C2440 || CONFIG_CPU == DM320 || CONFIG_CPU == TCC7801 \ |
37 | || defined(CPU_TCC77X) || CONFIG_CPU == AS3525 | 37 | || defined(CPU_TCC77X) || CONFIG_CPU == AS3525 || CONFIG_CPU == IMX31L |
38 | #include "timer-target.h" | 38 | #include "timer-target.h" |
39 | #elif defined(SIMULATOR) | 39 | #elif defined(SIMULATOR) |
40 | #define TIMER_FREQ 1000000 | 40 | #define TIMER_FREQ 1000000 |
diff --git a/firmware/target/arm/imx31/gigabeat-s/timer-imx31.c b/firmware/target/arm/imx31/gigabeat-s/timer-imx31.c new file mode 100644 index 0000000000..f32e0e841b --- /dev/null +++ b/firmware/target/arm/imx31/gigabeat-s/timer-imx31.c | |||
@@ -0,0 +1,112 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2007 by Michael Sevakis | ||
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 | #include "config.h" | ||
22 | #include "system.h" | ||
23 | #include "timer.h" | ||
24 | #include "clkctl-imx31.h" | ||
25 | #include "avic-imx31.h" | ||
26 | |||
27 | static void __attribute__((interrupt("IRQ"))) EPIT2_HANDLER(void) | ||
28 | { | ||
29 | EPITSR2 = EPITSR_OCIF; /* Clear the pending status */ | ||
30 | |||
31 | if (pfn_timer != NULL) | ||
32 | pfn_timer(); | ||
33 | } | ||
34 | |||
35 | static void stop_timer(bool clock_off) | ||
36 | { | ||
37 | /* Ensure clock gating on (before touching any module registers) */ | ||
38 | imx31_clkctl_module_clock_gating(CG_EPIT2, CGM_ON_ALL); | ||
39 | /* Disable insterrupt */ | ||
40 | avic_disable_int(EPIT2); | ||
41 | /* Clear wakeup mask */ | ||
42 | CLKCTL_WIMR0 &= ~WIM_IPI_INT_EPIT2; | ||
43 | /* Disable counter */ | ||
44 | EPITCR2 &= ~(EPITCR_OCIEN | EPITCR_EN); | ||
45 | /* Clear pending */ | ||
46 | EPITSR2 = EPITSR_OCIF; | ||
47 | |||
48 | if (clock_off) | ||
49 | { | ||
50 | /* Final stop, not reset; don't clock module any longer */ | ||
51 | imx31_clkctl_module_clock_gating(CG_EPIT2, CGM_OFF); | ||
52 | } | ||
53 | } | ||
54 | |||
55 | bool _timer_set(long cycles, bool start) | ||
56 | { | ||
57 | /* Maximum cycle count expressible in the cycles parameter is 2^31-1 | ||
58 | * and the modulus counter is capable of 2^32-1 and as a result there is | ||
59 | * no requirement to use a prescaler > 1. This gives a frequency range of | ||
60 | * ~0.015366822Hz - 66000000Hz. The highest input frequency gives the | ||
61 | * greatest possible accuracy anyway. */ | ||
62 | int oldstatus = disable_interrupt_save(IRQ_FIQ_STATUS); | ||
63 | |||
64 | /* Halt timer if running - leave module clock enabled */ | ||
65 | stop_timer(false); | ||
66 | |||
67 | if (start && pfn_unregister != NULL) | ||
68 | { | ||
69 | pfn_unregister(); | ||
70 | pfn_unregister = NULL; | ||
71 | } | ||
72 | |||
73 | /* CLKSRC = ipg_clk, | ||
74 | * EPIT output disconnected, | ||
75 | * Enabled in wait mode | ||
76 | * Prescale 1 for 66MHz | ||
77 | * Reload from modulus register, | ||
78 | * Count from load value */ | ||
79 | EPITCR2 = EPITCR_CLKSRC_IPG_CLK | EPITCR_WAITEN | EPITCR_IOVW | | ||
80 | EPITCR_PRESCALER(1-1) | EPITCR_RLD | EPITCR_ENMOD; | ||
81 | EPITLR2 = cycles; | ||
82 | /* Event when counter reaches 0 */ | ||
83 | EPITCMPR2 = 0; | ||
84 | |||
85 | restore_interrupt(oldstatus); | ||
86 | return true; | ||
87 | } | ||
88 | |||
89 | bool _timer_register(void) | ||
90 | { | ||
91 | int oldstatus = disable_interrupt_save(IRQ_FIQ_STATUS); | ||
92 | |||
93 | /* Halt timer if running - leave module clock enabled */ | ||
94 | stop_timer(false); | ||
95 | |||
96 | /* Enable interrupt */ | ||
97 | EPITCR2 |= EPITCR_OCIEN; | ||
98 | avic_enable_int(EPIT2, IRQ, 8, EPIT2_HANDLER); | ||
99 | /* Start timer */ | ||
100 | EPITCR2 |= EPITCR_EN; | ||
101 | |||
102 | restore_interrupt(oldstatus); | ||
103 | return true; | ||
104 | } | ||
105 | |||
106 | void _timer_unregister(void) | ||
107 | { | ||
108 | int oldstatus = disable_interrupt_save(IRQ_FIQ_STATUS); | ||
109 | /* Halt timer if running - stop module clock */ | ||
110 | stop_timer(true); | ||
111 | restore_interrupt(oldstatus); | ||
112 | } | ||
diff --git a/firmware/target/arm/imx31/gigabeat-s/timer-target.h b/firmware/target/arm/imx31/gigabeat-s/timer-target.h new file mode 100644 index 0000000000..92a3ee350d --- /dev/null +++ b/firmware/target/arm/imx31/gigabeat-s/timer-target.h | |||
@@ -0,0 +1,41 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2007 by Michael Sevakis | ||
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 | /* timer is based on ipg_clk */ | ||
25 | #define TIMER_FREQ (66000000) | ||
26 | |||
27 | bool _timer_set(long cycles, bool set); | ||
28 | bool _timer_register(void); | ||
29 | void _timer_unregister(void); | ||
30 | |||
31 | #define __TIMER_SET(cycles, set) \ | ||
32 | _timer_set(cycles, set) | ||
33 | |||
34 | #define __TIMER_REGISTER(reg_prio, unregister_callback, cycles, \ | ||
35 | int_prio, timer_callback) \ | ||
36 | _timer_register() | ||
37 | |||
38 | #define __TIMER_UNREGISTER(...) \ | ||
39 | _timer_unregister() | ||
40 | |||
41 | #endif /* TIMER_TARGET_H */ | ||
diff --git a/firmware/timer.c b/firmware/timer.c index a11cd10b7e..e9f11b6ae7 100644 --- a/firmware/timer.c +++ b/firmware/timer.c | |||
@@ -35,6 +35,15 @@ static int base_prescale; | |||
35 | static long SHAREDBSS_ATTR cycles_new = 0; | 35 | static long SHAREDBSS_ATTR cycles_new = 0; |
36 | #endif | 36 | #endif |
37 | 37 | ||
38 | #ifndef __TIMER_SET | ||
39 | /* Define these if not defined by target to make the #else cases compile | ||
40 | * even if the target doesn't have them implemented. */ | ||
41 | #define __TIMER_SET(cycles, set) false | ||
42 | #define __TIMER_REGISTER(reg_prio, unregister_callback, cycles, \ | ||
43 | int_prio, timer_callback) false | ||
44 | #define __TIMER_UNREGISTER(...) | ||
45 | #endif | ||
46 | |||
38 | /* interrupt handler */ | 47 | /* interrupt handler */ |
39 | #if CONFIG_CPU == SH7034 | 48 | #if CONFIG_CPU == SH7034 |
40 | void IMIA4(void) __attribute__((interrupt_handler)); | 49 | void IMIA4(void) __attribute__((interrupt_handler)); |
@@ -245,10 +254,6 @@ static bool timer_set(long cycles, bool start) | |||
245 | cycles_new = cycles; | 254 | cycles_new = cycles; |
246 | 255 | ||
247 | return true; | 256 | return true; |
248 | #elif (CONFIG_CPU == IMX31L) | ||
249 | /* TODO */ | ||
250 | (void)cycles; (void)start; | ||
251 | return false; | ||
252 | #else | 257 | #else |
253 | return __TIMER_SET(cycles, start); | 258 | return __TIMER_SET(cycles, start); |
254 | #endif /* CONFIG_CPU */ | 259 | #endif /* CONFIG_CPU */ |
@@ -319,9 +324,6 @@ bool timer_register(int reg_prio, void (*unregister_callback)(void), | |||
319 | CGU_PERI |= CGU_TIMER1_CLOCK_ENABLE; /* enable peripheral */ | 324 | CGU_PERI |= CGU_TIMER1_CLOCK_ENABLE; /* enable peripheral */ |
320 | VIC_INT_ENABLE |= INTERRUPT_TIMER1; | 325 | VIC_INT_ENABLE |= INTERRUPT_TIMER1; |
321 | return true; | 326 | return true; |
322 | #elif CONFIG_CPU == IMX31L | ||
323 | /* TODO */ | ||
324 | return false; | ||
325 | #else | 327 | #else |
326 | return __TIMER_REGISTER(reg_prio, unregister_callback, cycles, | 328 | return __TIMER_REGISTER(reg_prio, unregister_callback, cycles, |
327 | int_prio, timer_callback); | 329 | int_prio, timer_callback); |
@@ -359,7 +361,7 @@ void timer_unregister(void) | |||
359 | TIMER1_CONTROL &= 0x10; /* disable timer 1 (don't modify bit 4) */ | 361 | TIMER1_CONTROL &= 0x10; /* disable timer 1 (don't modify bit 4) */ |
360 | VIC_INT_EN_CLEAR = INTERRUPT_TIMER1; /* disable interrupt */ | 362 | VIC_INT_EN_CLEAR = INTERRUPT_TIMER1; /* disable interrupt */ |
361 | CGU_PERI &= ~CGU_TIMER1_CLOCK_ENABLE; /* disable peripheral */ | 363 | CGU_PERI &= ~CGU_TIMER1_CLOCK_ENABLE; /* disable peripheral */ |
362 | #elif CONFIG_CPU == S3C2440 || CONFIG_CPU == DM320 | 364 | #else |
363 | __TIMER_UNREGISTER(); | 365 | __TIMER_UNREGISTER(); |
364 | #endif | 366 | #endif |
365 | pfn_timer = NULL; | 367 | pfn_timer = NULL; |