# 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/timer.h>
    00034 #include <asm/mach/irq.h>
    00035 #include <linux/timex.h>
    00036
    00037 #define CPU_FREQ (tuned.cpu_freq)
    00038
    00039 static inline int timer_irq_ack( void )
    00040 {
    00041         OSSR = OSSR_M0;
    00042         rt_unmask_irq(TIMER_8254_IRQ);
    00043         if ( (int)(OSCR - OSMR0) < 0 )
    00044                 /* This is what just happened: we were setting a next timer interrupt
    00045                    in the scheduler, while a previously configured timer-interrupt
    00046                    happened, so, just restore the correct value of the match register and
    00047                    proceed as usual. Yes, we will have to re-calculate the next interrupt. */
    00048                 OSMR0 = OSCR - 1;
    00049         return 0;
    00050 }
    00051
    00052 union rtai_tsc {
    00053         unsigned long long tsc;
    00054         unsigned long hltsc[2];
    00055 };
    00056 extern volatile union rtai_tsc rtai_tsc;
    00057
    00058 static inline RTIME rdtsc(void)
    00059 {
    00060         RTIME ts;
    00061         unsigned long flags, count;
    00062
    00063         hard_save_flags_and_cli(flags);
    00064
    00065         if ( ( count = OSCR ) < rtai_tsc.hltsc[0] )
    00066                 rtai_tsc.hltsc[1]++;
    00067         rtai_tsc.hltsc[0] = count;
    00068         ts = rtai_tsc.tsc;
    00069         hard_restore_flags(flags);
    00070
    00071         return ts;
    00072 }
    00073
    00074 #define PROTECT_TIMER
    00075
    00076 #if 0
    00077 #define REG_BASE  0xf8000000
    00078 #define REG_OSMR0 0x00000000
    00079 #define REG_OSCR  0x00000010
    00080 #define REG_OSSR  0x00000014
    00081 #define REG_ICMR  0x00050004
    00082 static inline void rt_set_timer_match_reg(int delay)
    00083 {
    00084         unsigned long flags;
    00085
    00086         hard_save_flags_cli( flags );
    00087
    00088         __asm__ __volatile__ (
    00089         "mov    r2, #0xfa000000         @ REG_BASE\n"
    00090 #ifdef PROTECT_TIMER
    00091 "       cmp     %0, %2                  @ if ( delay > LATCH || delay < 0 )\n"
    00092 "       movhi   %0, %2                  @       delay = LATCH;\n"
    00093 #endif
    00094 "       teq     %0, #0                  @ if ( delay == 0 ) {\n"
    00095 "       ldreq   r1, [r2, #0]            @       r1 = OSMR0;\n"
    00096 "       addeq   r0, r1, %1              @       r0 = r1 + rt_times.periodic_tick;\n"
    00097 "       ldrne   r0, [r2, #0x10]         @ } else { r0 = OSCR;\n"
    00098 "       addne   r0, r0, %0              @       r0 = r0 + delay; }\n"
    00099 "       str     r0, [r2, #0]            @ OSMR0 = r0;\n"
    00100                 :
    00101                 : "r" (delay), "r" (rt_times.periodic_tick), "r" (LATCH)
    00102                 : "r0", "r1", "r2", "memory", "cc" );
    00103
    00104         hard_restore_flags( flags );
    00105 }
    00106
    00107 #else
    00108 /* Current version */
    00109 static inline void rt_set_timer_match_reg(int delay)
    00110 {
    00111         unsigned long flags;
    00112         unsigned long next_match;
    00113
    00114 #ifdef PROTECT_TIMER
    00115         if ( delay > LATCH )
    00116                 delay = LATCH;
    00117 #endif
    00118
    00119         hard_save_flags_cli(flags);
    00120
    00121         if ( delay )
    00122                 next_match = OSMR0 = delay + OSCR;
    00123 //              next_match = OSMR0 = delay + rtai_tsc.hltsc[0];
    00124         else
    00125                 next_match = ( OSMR0 += rt_times.periodic_tick );
    00126 //              next_match = OSMR0 = ((unsigned long *)&rt_times.intr_time)[0];
    00127
    00128 #ifdef PROTECT_TIMER
    00129         while ((int)(next_match - OSCR) < 2 * SETUP_TIME_TICKS ) {
    00130                 OSSR = OSSR_M0;  /* Clear match on timer 0 */
    00131                 next_match = OSMR0 = OSCR + 4 * SETUP_TIME_TICKS;
    00132         }
    00133 #endif
    00134
    00135         hard_restore_flags(flags);
    00136 }
    00137 #endif
    00138
    00139 #define rt_set_timer_delay(x)  rt_set_timer_match_reg(x)
    00140
    00141 #endif