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 }