base/arch/arm/hal/mach-at91/at91-timer.c

Go to the documentation of this file.
00001 /* rtai/arch/arm/mach-at91/at91-timer.c
00002 COPYRIGHT (C) 2002 Guennadi Liakhovetski, DSA GmbH (gl@dsa-ac.de)
00003 COPYRIGHT (C) 2002 Wolfgang Müller (wolfgang.mueller@dsa-ac.de)
00004 Copyright (c) 2001 Alex Züpke, SYSGO RTS GmbH (azu@sysgo.de)
00005 Copyright (c) 2005 Luca Pizzi, (lucapizzi@hotmail.com)
00006 Copyright (c) 2005 Stefano Gafforelli, (stefano.gafforelli@tiscali.it)
00007 Copyright (C) 2007 Adeneo
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 /*
00023 --------------------------------------------------------------------------
00024 Acknowledgements
00025 - Paolo Mantegazza  (mantegazza@aero.polimi.it)
00026     creator of RTAI 
00027 */
00028 
00029 #include <linux/sched.h>
00030 #include <linux/interrupt.h>
00031 #include <linux/init.h>
00032 #include <asm/mach/irq.h>
00033 #include <asm/system.h>
00034 #include <rtai.h>
00035 #include <asm/arch/timex.h>
00036 #include <asm/arch/rtai_timer.h>
00037 #include <rtai_trace.h>
00038 
00039 #include <asm/arch/rtai_timer.h>
00040 
00041 extern int (*extern_timer_isr)(struct pt_regs *regs);
00042 extern int rtai_timer_handler(struct pt_regs *regs);
00043 
00044 unsigned int rt_periodic;
00045 EXPORT_SYMBOL(rt_periodic);
00046 
00047 int rt_request_timer (void (*handler)(void), unsigned tick, int use_apic)
00048 {
00049     unsigned long flags;
00050 
00051     flags = rtai_critical_enter(NULL);
00052 
00053     __ipipe_mach_timerstolen = 1;       // no need to reprogram timer on timer_tick() call
00054 
00055     rt_times.tick_time = rtai_rdtsc();
00056     rt_times.linux_tick = __ipipe_mach_ticks_per_jiffy;
00057     if (tick > 0) {
00058         rt_periodic = 1;
00059 
00060         /* Periodic setup --
00061         Use the built-in Adeos service directly. */
00062         if (tick > __ipipe_mach_ticks_per_jiffy) {
00063             tick = __ipipe_mach_ticks_per_jiffy;
00064         }
00065         rt_times.intr_time = rt_times.tick_time + tick;
00066         rt_times.linux_time = rt_times.tick_time + rt_times.linux_tick;
00067         rt_times.periodic_tick = tick;
00068 
00069         /* Prepare TCx to reload automaticly on RC compare */
00070         at91_tc_write(AT91_TC_CCR, AT91_TC_CLKDIS);
00071         at91_tc_write(AT91_TC_CMR, AT91_TC_TIMER_CLOCK3 | AT91_TC_WAVESEL_UP_AUTO | AT91_TC_WAVE);
00072         at91_tc_write(AT91_TC_RC, rt_times.periodic_tick);
00073         at91_tc_write(AT91_TC_CCR, AT91_TC_CLKEN | AT91_TC_SWTRG);
00074     } else {
00075         rt_periodic = 0;
00076 
00077         /* Oneshot setup. */
00078         rt_times.intr_time = rt_times.tick_time + rt_times.linux_tick;
00079         rt_times.linux_time = rt_times.tick_time + rt_times.linux_tick;
00080         rt_times.periodic_tick = rt_times.linux_tick;
00081 
00082         /* Prepare TCx behaviour as oneshot timer */
00083         at91_tc_write(AT91_TC_CMR, AT91_TC_TIMER_CLOCK3);
00084         rt_set_timer_delay(rt_times.periodic_tick);
00085     }
00086 
00087         rt_release_irq(RTAI_TIMER_IRQ);
00088 
00089     rt_request_irq(RTAI_TIMER_IRQ, (rt_irq_handler_t)handler, NULL, 0);
00090     extern_timer_isr = rtai_timer_handler;  // shunt for ipipe.c __ipipe_grab_irq
00091 
00092     rtai_critical_exit(flags);
00093 
00094         return 0;
00095 }
00096 
00097 void rt_free_timer (void)
00098 {
00099     unsigned long flags;
00100 
00101     rt_periodic = 0;
00102     __ipipe_mach_timerstolen = 0;       // ipipe can reprogram timer for Linux now
00103     at91_tc_write(AT91_TC_CMR, AT91_TC_TIMER_CLOCK3); // back to oneshot mode
00104     rt_set_timer_delay(__ipipe_mach_ticks_per_jiffy); // regular timer delay
00105     rt_release_irq(RTAI_TIMER_IRQ);     // free this irq
00106     rtai_save_flags_and_cli(flags);     // critical section
00107     extern_timer_isr = NULL;        // let ipipe run as normally
00108     rtai_restore_flags(flags);      // end of critical section
00109 }
00110 
00111 int rtai_calibrate_TC (void)
00112 {
00113     unsigned long flags;
00114     RTIME t, dt;
00115     int i;
00116 
00117     flags = rtai_critical_enter(NULL);
00118     rt_set_timer_delay(LATCH);
00119     t = rtai_rdtsc();
00120     for (i = 0; i < 10000; i++) { 
00121         rt_set_timer_delay(LATCH);
00122     }
00123     dt = rtai_rdtsc() - t;
00124     rtai_critical_exit(flags);
00125 
00126     return rtai_imuldiv(dt, 100000, RTAI_CPU_FREQ);
00127 }

Generated on Tue Feb 2 17:46:04 2010 for RTAI API by  doxygen 1.4.7