00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
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;       
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         
00061 
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         
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         
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         
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;  
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;       
00103     at91_tc_write(AT91_TC_CMR, AT91_TC_TIMER_CLOCK3); 
00104     rt_set_timer_delay(__ipipe_mach_ticks_per_jiffy); 
00105     rt_release_irq(RTAI_TIMER_IRQ);     
00106     rtai_save_flags_and_cli(flags);     
00107     extern_timer_isr = NULL;        
00108     rtai_restore_flags(flags);      
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 }