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
00030
00031 #include <linux/sched.h>
00032 #include <linux/interrupt.h>
00033 #include <linux/init.h>
00034 #include <asm/mach/irq.h>
00035 #include <asm/system.h>
00036 #include <rtai.h>
00037 #include <asm-arm/arch-imx/timex.h>
00038 #include <asm-arm/arch-imx/rtai_timer.h>
00039 #include <rtai_trace.h>
00040
00041 volatile union rtai_tsc rtai_tsc;
00042 EXPORT_SYMBOL(rtai_tsc);
00043 static int (*saved_adeos_timer_handler)(int irq, void *dev_id, struct pt_regs *regs);
00044
00045
00046 volatile union rtai_tsc lx_timer;
00047
00048 unsigned long split_timer (void) {
00049 lx_timer.tsc = rt_times.linux_time;
00050 return lx_timer.hltsc[0];
00051 }
00052
00053 int soft_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
00054 {
00055 long flags;
00056
00057 rdtsc();
00058
00059 local_irq_save(flags);
00060
00061 do_timer(regs);
00062 split_timer();
00063
00064 local_irq_restore(flags);
00065
00066 return IRQ_HANDLED;
00067 }
00068
00069 int rt_request_timer(rt_timer_irq_handler_t handler, unsigned tick, int use_apic)
00070 {
00071 RTIME t;
00072 unsigned long flags;
00073
00074 TRACE_RTAI_TIMER(TRACE_RTAI_EV_TIMER_REQUEST, handler, tick);
00075
00076 flags = rtai_critical_enter(NULL);
00077
00078
00079 rtai_tsc.tsc = 0;
00080 do {} while ((signed long)(IMX_TCMP(0) - IMX_TCN(0)) > 0);
00081
00082
00083 rt_times.linux_tick = LATCH;
00084 rt_times.periodic_tick = (tick > 0 && tick < (RTIME)rt_times.linux_tick) ? tick : rt_times.linux_tick;
00085 rt_times.tick_time = t = rdtsc();
00086 rt_times.intr_time = t + rt_times.periodic_tick;
00087 rt_times.linux_time = t + rt_times.linux_tick;
00088
00089
00090
00091
00092
00093 rt_set_timer_delay(rt_times.periodic_tick);
00094
00095 saved_adeos_timer_handler = xchg(&irq_desc[TIMER_8254_IRQ].action->handler, (void *)soft_timer_interrupt);
00096
00097 rt_free_global_irq(TIMER_8254_IRQ);
00098
00099 rt_request_global_irq(TIMER_8254_IRQ, handler);
00100
00101
00102 rt_pend_linux_irq(TIMER_8254_IRQ);
00103 rtai_critical_exit(flags);
00104
00105 return 0;
00106 }
00107
00108 void rt_free_timer(void)
00109 {
00110 unsigned long flags;
00111
00112 if(saved_adeos_timer_handler == NULL)
00113 return;
00114
00115 TRACE_RTAI_TIMER(TRACE_RTAI_EV_TIMER_FREE, 0, 0);
00116
00117 flags = rtai_critical_enter(NULL);
00118
00119 rt_free_global_irq(TIMER_8254_IRQ);
00120 irq_desc[TIMER_8254_IRQ].action->handler =(void*)saved_adeos_timer_handler ;
00121
00122 rtai_critical_exit(flags);
00123 }