diff --git a/firmware/SOURCES b/firmware/SOURCES index 8e3f1ea549..b2fbfa13f2 100644 --- a/firmware/SOURCES +++ b/firmware/SOURCES @@ -332,6 +332,7 @@ target/coldfire/memset16-coldfire.S #endif target/coldfire/kernel-coldfire.c target/coldfire/system-coldfire.c +target/coldfire/timer-coldfire.c #ifndef BOOTLOADER target/coldfire/pcm-coldfire.c #endif /* BOOTLOADER */ diff --git a/firmware/export/timer.h b/firmware/export/timer.h index e36baa1e1f..b758f57ae5 100644 --- a/firmware/export/timer.h +++ b/firmware/export/timer.h @@ -28,12 +28,10 @@ #if defined(CPU_PP) /* Portalplayer chips use a microsecond timer. */ #define TIMER_FREQ 1000000 -#elif defined(CPU_COLDFIRE) - /* timer is based on busclk == cpuclk/2 */ - #define TIMER_FREQ (CPU_FREQ/2) #elif CONFIG_CPU == S3C2440 || CONFIG_CPU == DM320 || CONFIG_CPU == TCC7801 \ || defined(CPU_TCC77X) || CONFIG_CPU == AS3525 || CONFIG_CPU == IMX31L \ - || CONFIG_CPU == JZ4732 || CONFIG_CPU == PNX0101 + || CONFIG_CPU == JZ4732 || CONFIG_CPU == PNX0101 \ + || defined(CPU_COLDFIRE) #include "timer-target.h" #elif defined(SIMULATOR) #define TIMER_FREQ 1000000 diff --git a/firmware/target/coldfire/timer-coldfire.c b/firmware/target/coldfire/timer-coldfire.c new file mode 100644 index 0000000000..ef9fd9ea7a --- /dev/null +++ b/firmware/target/coldfire/timer-coldfire.c @@ -0,0 +1,119 @@ +/*************************************************************************** +* __________ __ ___. +* Open \______ \ ____ ____ | | _\_ |__ _______ ___ +* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / +* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < +* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ +* \/ \/ \/ \/ \/ +* $Id$ +* +* Copyright (C) 2005 Jens Arnold +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY +* KIND, either express or implied. +* +****************************************************************************/ + +#include + +#include "config.h" +#include "system.h" +#include "cpu.h" +#include "timer.h" +#include "timer-target.h" + +static int base_prescale; + +void TIMER1(void) __attribute__ ((interrupt_handler)); +void TIMER1(void) +{ + if (pfn_timer != NULL) + pfn_timer(); + TER1 = 0xff; /* clear all events */ +} + +bool __timer_set(long cycles, bool start) +{ + int phi = 0; /* bits for the prescaler */ + int prescale = 1; + + while (cycles > 0x10000) + { + prescale <<= 1; + cycles >>= 1; + } + + if (prescale > 4096/CPUFREQ_MAX_MULT) + return false; + + if (prescale > 256/CPUFREQ_MAX_MULT) + { + phi = 0x05; /* prescale sysclk/16, timer enabled */ + prescale >>= 4; + } + else + phi = 0x03; /* prescale sysclk, timer enabled */ + + base_prescale = prescale; + prescale *= (cpu_frequency / CPU_FREQ); + + if (start) + { + if (pfn_unregister != NULL) + { + pfn_unregister(); + pfn_unregister = NULL; + } + phi &= ~1; /* timer disabled at start */ + + /* If it is already enabled, writing a 0 to the RST bit will clear + the register, so we clear RST explicitly before writing the real + data. */ + TMR1 = 0; + } + + /* We are using timer 1 */ + TMR1 = 0x0018 | (unsigned short)phi | ((unsigned short)(prescale - 1) << 8); + TRR1 = (unsigned short)(cycles - 1); + if (start || (TCN1 >= TRR1)) + TCN1 = 0; /* reset the timer */ + TER1 = 0xff; /* clear all events */ + + return true; +} + +bool __timer_start(void) +{ + ICR2 = 0x90; /* interrupt on level 4.0 */ + and_l(~(1<<10), &IMR); + TMR1 |= 1; /* start timer */ + return true; +} + +void __timer_stop(void) +{ + TMR1 = 0; /* disable timer 1 */ + or_l((1<<10), &IMR); /* disable interrupt */ +} + +void timers_adjust_prescale(int multiplier, bool enable_irq) +{ + /* tick timer */ + TMR0 = (TMR0 & 0x00ef) + | ((unsigned short)(multiplier - 1) << 8) + | (enable_irq ? 0x10 : 0); + + if (pfn_timer) + { + /* user timer */ + int prescale = base_prescale * multiplier; + TMR1 = (TMR1 & 0x00ef) + | ((unsigned short)(prescale - 1) << 8) + | (enable_irq ? 0x10 : 0); + } +} diff --git a/firmware/target/coldfire/timer-target.h b/firmware/target/coldfire/timer-target.h new file mode 100644 index 0000000000..29488887e8 --- /dev/null +++ b/firmware/target/coldfire/timer-target.h @@ -0,0 +1,40 @@ +/*************************************************************************** +* __________ __ ___. +* Open \______ \ ____ ____ | | _\_ |__ _______ ___ +* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / +* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < +* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ +* \/ \/ \/ \/ \/ +* $Id$ +* +* Copyright (C) 2005 Jens Arnold +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY +* KIND, either express or implied. +* +****************************************************************************/ +#ifndef TIMER_TARGET_H +#define TIMER_TARGET_H + +bool __timer_set(long cycles, bool start); +bool __timer_start(void); +void __timer_stop(void); + +/* timer is based on busclk == cpuclk/2 */ +#define TIMER_FREQ (CPU_FREQ/2) + +#define __TIMER_SET(cycles, set) \ + __timer_set(cycles, set) + +#define __TIMER_START() \ + __timer_start() + +#define __TIMER_STOP(...) \ + __timer_stop() + +#endif /* TIMER_TARGET_H */ diff --git a/firmware/timer.c b/firmware/timer.c index 089deffbd4..34b410c017 100644 --- a/firmware/timer.c +++ b/firmware/timer.c @@ -29,9 +29,7 @@ static int timer_prio = -1; void SHAREDBSS_ATTR (*pfn_timer)(void) = NULL; /* timer callback */ void SHAREDBSS_ATTR (*pfn_unregister)(void) = NULL; /* unregister callback */ -#ifdef CPU_COLDFIRE -static int base_prescale; -#elif defined CPU_PP +#if defined CPU_PP static long SHAREDBSS_ATTR cycles_new = 0; #endif @@ -52,14 +50,6 @@ void IMIA4(void) pfn_timer(); and_b(~0x01, &TSR4); /* clear the interrupt */ } -#elif defined CPU_COLDFIRE -void TIMER1(void) __attribute__ ((interrupt_handler)); -void TIMER1(void) -{ - if (pfn_timer != NULL) - pfn_timer(); - TER1 = 0xff; /* clear all events */ -} #elif defined(CPU_PP) void TIMER2(void) { @@ -82,21 +72,17 @@ void TIMER2(void) static bool timer_set(long cycles, bool start) { -#if CONFIG_CPU == SH7034 || defined(CPU_COLDFIRE) +#if CONFIG_CPU == SH7034 int phi = 0; /* bits for the prescaler */ int prescale = 1; while (cycles > 0x10000) { /* work out the smallest prescaler that makes it fit */ -#if CONFIG_CPU == SH7034 phi++; -#endif prescale <<= 1; cycles >>= 1; } -#endif -#if CONFIG_CPU == SH7034 if (prescale > 8) return false; @@ -121,44 +107,6 @@ static bool timer_set(long cycles, bool start) TCNT4 = 0; and_b(~0x01, &TSR4); /* clear an eventual interrupt */ - return true; -#elif defined CPU_COLDFIRE - if (prescale > 4096/CPUFREQ_MAX_MULT) - return false; - - if (prescale > 256/CPUFREQ_MAX_MULT) - { - phi = 0x05; /* prescale sysclk/16, timer enabled */ - prescale >>= 4; - } - else - phi = 0x03; /* prescale sysclk, timer enabled */ - - base_prescale = prescale; - prescale *= (cpu_frequency / CPU_FREQ); - - if (start) - { - if (pfn_unregister != NULL) - { - pfn_unregister(); - pfn_unregister = NULL; - } - phi &= ~1; /* timer disabled at start */ - - /* If it is already enabled, writing a 0 to the RST bit will clear - the register, so we clear RST explicitly before writing the real - data. */ - TMR1 = 0; - } - - /* We are using timer 1 */ - TMR1 = 0x0018 | (unsigned short)phi | ((unsigned short)(prescale - 1) << 8); - TRR1 = (unsigned short)(cycles - 1); - if (start || (TCN1 >= TRR1)) - TCN1 = 0; /* reset the timer */ - TER1 = 0xff; /* clear all events */ - return true; #elif defined(CPU_PP) if (cycles > 0x20000000 || cycles < 2) @@ -185,25 +133,6 @@ static bool timer_set(long cycles, bool start) #endif /* CONFIG_CPU */ } -#ifdef CPU_COLDFIRE -void timers_adjust_prescale(int multiplier, bool enable_irq) -{ - /* tick timer */ - TMR0 = (TMR0 & 0x00ef) - | ((unsigned short)(multiplier - 1) << 8) - | (enable_irq ? 0x10 : 0); - - if (pfn_timer) - { - /* user timer */ - int prescale = base_prescale * multiplier; - TMR1 = (TMR1 & 0x00ef) - | ((unsigned short)(prescale - 1) << 8) - | (enable_irq ? 0x10 : 0); - } -} -#endif - /* Register a user timer, called every TIMER_FREQ cycles */ bool timer_register(int reg_prio, void (*unregister_callback)(void), long cycles, int int_prio, void (*timer_callback)(void) @@ -228,11 +157,6 @@ bool timer_register(int reg_prio, void (*unregister_callback)(void), IPRD = (IPRD & 0xFF0F) | int_prio << 4; /* interrupt priority */ or_b(0x10, &TSTR); /* start timer 4 */ return true; -#elif defined CPU_COLDFIRE - ICR2 = 0x90; /* interrupt on level 4.0 */ - and_l(~(1<<10), &IMR); - TMR1 |= 1; /* start timer */ - return true; #elif defined(CPU_PP) /* unmask interrupt source */ #if NUM_CORES > 1 @@ -264,9 +188,6 @@ void timer_unregister(void) #if CONFIG_CPU == SH7034 and_b(~0x10, &TSTR); /* stop the timer 4 */ IPRD = (IPRD & 0xFF0F); /* disable interrupt */ -#elif defined CPU_COLDFIRE - TMR1 = 0; /* disable timer 1 */ - or_l((1<<10), &IMR); /* disable interrupt */ #elif defined(CPU_PP) TIMER2_CFG = 0; /* stop timer 2 */ CPU_INT_DIS = TIMER2_MASK;