# rtai_timer.h

    00001 /* 020222 asm-arm/arch-sa1100/timer.h - ARM/SA1100 specific timer
    00002 Don't include directly - it's included through asm-arm/rtai.h
    00003
    00004 COPYRIGHT (C) 2002 Guennadi Liakhovetski, DSA GmbH (gl@dsa-ac.de)
    00005 COPYRIGHT (C) 2002 Wolfgang Müller (wolfgang.mueller@dsa-ac.de)
    00006 Copyright (c) 2001 Alex Züpke, SYSGO RTS GmbH (azu@sysgo.de)
    00007
    00008 This program is free software; you can redistribute it and/or modify
    00009 it under the terms of version 2 of the GNU General Public License as
    00010 published by the Free Software Foundation.
    00011
    00012 This program is distributed in the hope that it will be useful,
    00013 but WITHOUT ANY WARRANTY; without even the implied warranty of
    00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    00015 GNU General Public License for more details.
    00016
    00017 You should have received a copy of the GNU General Public License
    00018 along with this program; if not, write to the Free Software
    00019 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    00020 */
    00021 /*
    00022 --------------------------------------------------------------------------
    00023 Acknowledgements
    00024 - Paolo Mantegazza      (mantegazza@aero.polimi.it)
    00025         creator of RTAI
    00026 */
    00027
    00028 #ifndef _ASM_ARCH_RTAI_TIMER_H_
    00029 #define _ASM_ARCH_RTAI_TIMER_H_
    00030
    00031 #include <asm/proc/hard_system.h>
    00032 #include <linux/time.h>
    00033 #include <linux/timex.h>
    00034
    00035 #define CPU_FREQ (tuned.cpu_freq)
    00036
    00037 static inline int timer_irq_ack( void )
    00038 {
    00039         OSSR = OSSR_M0;
    00040         rt_unmask_irq(TIMER_8254_IRQ);
    00041         if ( (int)(OSCR - OSMR0) < 0 )
    00042                 /* This is what just happened: we were setting a next timer interrupt
    00043                    in the scheduler, while a previously configured timer-interrupt
    00044                    happened, so, just restore the correct value of the match register and
    00045                    proceed as usual. Yes, we will have to re-calculate the next interrupt. */
    00046                 OSMR0 = OSCR - 1;
    00047         return 0;
    00048 }
    00049
    00050 union rtai_tsc {
    00051         unsigned long long tsc;
    00052         unsigned long hltsc[2];
    00053 };
    00054 extern volatile union rtai_tsc rtai_tsc;
    00055
    00056 static inline RTIME rdtsc(void)
    00057 {
    00058         RTIME ts;
    00059         unsigned long flags, count;
    00060
    00061         hard_save_flags_and_cli(flags);
    00062
    00063         if ( ( count = OSCR ) < rtai_tsc.hltsc[0] )
    00064                 rtai_tsc.hltsc[1]++;
    00065         rtai_tsc.hltsc[0] = count;
    00066         ts = rtai_tsc.tsc;
    00067         hard_restore_flags(flags);
    00068
    00069         return ts;
    00070 }
    00071
    00072 #define PROTECT_TIMER
    00073
    00074 #if 0
    00075 #define REG_BASE  0xfa000000
    00076 #define REG_OSMR0 0x00000000
    00077 #define REG_OSCR  0x00000010
    00078 #define REG_OSSR  0x00000014
    00079 #define REG_ICMR  0x00050004
    00080 static inline void rt_set_timer_match_reg(int delay)
    00081 {
    00082         unsigned long flags;
    00083
    00084         hard_save_flags_cli( flags );
    00085
    00086         __asm__ __volatile__ (
    00087         "mov    r2, #0xfa000000         @ REG_BASE\n"
    00088 #ifdef PROTECT_TIMER
    00089 "       cmp     %0, %2                  @ if ( delay > LATCH || delay < 0 )"
    00090 "       movhi   %0, %2                  @       delay = LATCH;\n"
    00091 #endif
    00092 "       teq     %0, #0                  @ if ( delay == 0 ) {"
    00093 "       ldreq   r1, [r2, #0]            @       r1 = OSMR0;"
    00094 "       addeq   r0, r1, %1              @       r0 = r1 + rt_times.periodic_tick;"
    00095 "       ldrne   r0, [r2, #0x10]         @ } else { r0 = OSCR;"
    00096 "       addne   r0, r0, %0              @       r0 = r0 + delay; }"
    00097 "       str     r0, [r2, #0]            @ OSMR0 = r0;\n"
    00098                 :
    00099                 : "r" (delay), "r" (rt_times.periodic_tick), "r" (LATCH)
    00100                 : "r0", "r1", "r2", "memory", "cc" );
    00101
    00102         hard_restore_flags( flags );
    00103 }
    00104
    00105 #else
    00106 /* Current version */
    00107 static inline void rt_set_timer_match_reg(int delay)
    00108 {
    00109         unsigned long flags;
    00110         unsigned long next_match;
    00111
    00112 #ifdef PROTECT_TIMER
    00113         if ( delay > LATCH )
    00114                 delay = LATCH;
    00115 #endif
    00116
    00117         hard_save_flags_cli(flags);
    00118
    00119         if ( delay )
    00120                 next_match = OSMR0 = delay + OSCR;
    00121 //              next_match = OSMR0 = delay + rtai_tsc.hltsc[0];
    00122         else
    00123                 next_match = ( OSMR0 += rt_times.periodic_tick );
    00124 //              next_match = OSMR0 = ((unsigned long *)&rt_times.intr_time)[0];
    00125
    00126 #ifdef PROTECT_TIMER
    00127         while ((int)(next_match - OSCR) < SETUP_TIME_TICKS ) {
    00128                 OSSR = OSSR_M0;  /* Clear match on timer 0 */
    00129                 next_match = OSMR0 = OSCR + 2 * SETUP_TIME_TICKS;
    00130         }
    00131 #endif
    00132
    00133         hard_restore_flags(flags);
    00134 }
    00135 #endif
    00136
    00137 #define rt_set_timer_delay(x)  rt_set_timer_match_reg(x)
    00138
    00139 #endif