# rtai_timer.h

    00001 /*
    00002  * /include/asm/arch/mach-clps711x/timer.h
    00003  *
    00004  * Don't include directly - it's included through asm-arm/rtai.h
    00005  *
    00006  * Copyright (c) 2002 Thomas Gleixner, autronix automation <gleixner@autronix.de>
    00007  * Copyright (c) 2002, Alex Züpke, SYSGO RTS GmbH (azu@sysgo.de)
    00008  *
    00009 This program is free software; you can redistribute it and/or modify
    00010 it under the terms of version 2 of the GNU General Public License as
    00011 published by the Free Software Foundation.
    00012
    00013 This program is distributed in the hope that it will be useful,
    00014 but WITHOUT ANY WARRANTY; without even the implied warranty of
    00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    00016 GNU General Public License for more details.
    00017
    00018 You should have received a copy of the GNU General Public License
    00019 along with this program; if not, write to the Free Software
    00020 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    00021  *
    00022  * This are the mach_clps711x (ARM7) timer inlines for
    00023  * RTAI Real Time Application Interface
    00024  *
    00025  * Thanks to Guennadi Liakhovetski, DSA GmbH (gl@dsa-ac.de) for review and
    00026  * a helping hand in unterstanding RTAI.
    00027  *
    00028  * TODO's:      Beautify, test, test, test
    00029  */
    00030 /*
    00031 --------------------------------------------------------------------------
    00032 Acknowledgements
    00033 - Paolo Mantegazza      (mantegazza@aero.polimi.it)
    00034         creator of RTAI
    00035 */
    00036 #ifndef _ASM_ARCH_RTAI_TIMER_H_
    00037 #define _ASM_ARCH_RTAI_TIMER_H_
    00038
    00039 #include <asm/proc/hard_system.h>
    00040 #include <linux/sched.h>
    00041
    00042 #define CPU_FREQ (tuned.cpu_freq)
    00043 #define CHECK_TC2_BOUNDS
    00044 #define DEBUG_INLINE 0
    00045 #if DEBUG_INLINE > 0
    00046 #define DI1(x) x
    00047 #else
    00048 #define DI1(x)
    00049 #endif
    00050
    00051 extern unsigned long rtai_lasttsc;
    00052 extern unsigned long rtai_TC2latch;
    00053 extern union rtai_tsc rtai_tsc;
    00054
    00055 union rtai_tsc {
    00056         unsigned long long tsc;
    00057         unsigned long hltsc[2];
    00058 };
    00059
    00060 static inline int timer_irq_ack( void )
    00061 {
    00062         return 0;
    00063 }
    00064
    00065 /*
    00066 *       rdtsc reads RTAI's timestampcounter. We use Timer/Counter TC1 on
    00067 *       cpls711x (Cirrus Logic) ARM7 cpu's. This timer is not used by
    00068 *       Linux, but it maybe used by other drivers. Check this out first.
    00069 *       The timer runs free counting down,with a wrap around every 128 ms
    00070 *       If we don't get here within 64ms, we have killed our timebase.
    00071 *       But if we miss this for 64ms our box is killed anyway -)
    00072 *
    00073 */
    00074 static inline unsigned long long rdtsc(void)
    00075 {
    00076         unsigned long flags, ticks, act;
    00077
    00078         // we read the 16 bit timer and calc ts on this value
    00079         hard_save_flags_and_cli(flags);
    00080         act = ( unsigned long) (clps_readl(TC1D) & 0xffff);
    00081         /* take care of underflows */
    00082         ticks = (rtai_lasttsc < act) ? (0x10000 - act + rtai_lasttsc) : (rtai_lasttsc - act);
    00083         rtai_lasttsc = act;
    00084         rtai_tsc.tsc += (unsigned long long) ticks;
    00085         hard_restore_flags(flags);
    00086         return rtai_tsc.tsc;
    00087 }
    00088
    00089
    00090 /*
    00091 *       set the timer latch for timer/counter TC2
    00092 *       we check the bounds, as long as we are in testphase
    00093 *       Switch this off by undef CHECK_TC2_BOUNDS
    00094 */
    00095 static inline void rt_set_timer_latch(unsigned long delay)
    00096 {
    00097         unsigned long flags;
    00098         RTIME diff;
    00099
    00100         // set 16 bit LATCH
    00101         hard_save_flags_cli(flags);
    00102
    00103         diff = rt_times.intr_time - rdtsc();
    00104         /* we have missed the deadline already */
    00105         if (diff < 0)
    00106                 diff = 1;
    00107
    00108         DI1( if (delay > LATCH) {
    00109                 printk("rt_set_timer_latch delay > LATCH :%ld\n",delay);
    00110                 delay = LATCH;
    00111         });
    00112
    00113         rtai_TC2latch = (!delay ? ((unsigned long*)(&diff))[0] : delay);
    00114 #ifdef CHECK_TC2_BOUNDS
    00115         if (rtai_TC2latch > LATCH) {
    00116                 DI1(printk("rt_set_timer_latch > LATCH :%ld\n",rtai_TC2latch));
    00117                 rtai_TC2latch = LATCH;
    00118         }
    00119 #endif
    00120         /* This bound check is essential, remove it and you get in trouble */
    00121         if (!rtai_TC2latch) {
    00122                 DI1(printk("rt_set_timer_latch < 1 :%ld\n",rtai_TC2latch));
    00123                 rtai_TC2latch = 1;
    00124         }
    00125         clps_writel(0,TC2EOI);
    00126         clps_writel(rtai_TC2latch, TC2D);
    00127         clps_writel((clps_readl(INTMR1)|0x200), INTMR1);
    00128         hard_restore_flags(flags);
    00129 }
    00130
    00131 #define rt_set_timer_delay(x)  rt_set_timer_latch(x)
    00132
    00133 #endif