00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <rtai.h>
00024 #include <rtai_trace.h>
00025 #include <asm/arch/ep93xx_tsc.h>
00026
00027
00028
00029
00030
00031
00032
00033 int
00034 rt_request_timer(rt_timer_irq_handler_t handler, unsigned int tick, int i386_legacy_dummy)
00035 {
00036 unsigned long flags;
00037 int is_oneshot = (tick == 0);
00038
00039 TRACE_RTAI_TIMER(TRACE_RTAI_EV_TIMER_REQUEST, handler, tick);
00040
00041
00042 if (is_oneshot)
00043 tick = LATCH;
00044
00045 flags = rtai_critical_enter(NULL);
00046
00047
00048 outl(0, TIMER1CONTROL);
00049 outl(tick - 1, TIMER1LOAD);
00050
00051
00052 rt_times.tick_time = ({
00053 ep93xx_tsc_t t0;
00054 unsigned long target_offset;
00055 unsigned long t;
00056
00057
00058 do {
00059 t0.ll = ep93xx_rdtsc();
00060 unsigned long long const realtime_jiffies = (long long)(t0.ll * HZ) / (long)RTAI_TSC_FREQ;
00061 unsigned long const current_offset = t0.ll - (realtime_jiffies * RTAI_TSC_FREQ) / HZ;
00062 target_offset = ((RTAI_TSC_FREQ + HZ/2) / HZ) - current_offset;
00063 } while (target_offset < 10);
00064
00065
00066 do {
00067 t = inl(TIMER4VALUELOW);
00068 } while ((t - t0.u.low) < target_offset);
00069
00070
00071 outl((is_oneshot) ? 0x88 : 0xc8, TIMER1CONTROL);
00072
00073
00074 if (t < t0.u.low)
00075 ++t0.u.high;
00076 t0.u.low = t;
00077
00078 t0.ll;
00079 });
00080
00081
00082 outl(1, TIMER1CLEAR);
00083
00084
00085 if (is_oneshot) {
00086
00087 rt_times.linux_time = rtai_llimd(ep93xx_jiffies_done * LATCH, RTAI_TSC_FREQ, RTAI_TIMER_FREQ);
00088 rt_times.linux_tick = rtai_imuldiv(LATCH, RTAI_TSC_FREQ, RTAI_TIMER_FREQ);
00089 rt_times.periodic_tick = rt_times.linux_tick;
00090 } else {
00091
00092 rt_times.tick_time = rtai_llimd(rt_times.tick_time, RTAI_TIMER_FREQ, RTAI_TSC_FREQ);
00093 rt_times.linux_time = ep93xx_jiffies_done * LATCH;
00094 rt_times.linux_tick = LATCH;
00095 rt_times.periodic_tick = tick;
00096 }
00097 rt_times.intr_time = rt_times.tick_time + rt_times.periodic_tick;
00098
00099 rt_release_irq(RTAI_TIMER_IRQ);
00100 if (rt_request_irq(RTAI_TIMER_IRQ, (rt_irq_handler_t)handler, NULL, 0) < 0) {
00101 rtai_critical_exit(flags);
00102 return -EINVAL;
00103 }
00104
00105
00106
00107
00108
00109
00110
00111
00112 rtai_critical_exit(flags);
00113 return 0;
00114 }
00115
00116
00117
00118
00119
00120 void
00121 rt_free_timer(void)
00122 {
00123 unsigned long flags;
00124
00125 TRACE_RTAI_TIMER(TRACE_RTAI_EV_TIMER_FREE, 0, 0);
00126
00127 flags = rtai_critical_enter(NULL);
00128
00129
00130
00131
00132
00133 outl(0, TIMER1CONTROL);
00134
00135 outl(LATCH - 1, TIMER1LOAD);
00136
00137 outl(0xc8, TIMER1CONTROL);
00138
00139 outl(1, TIMER1CLEAR);
00140
00141 rt_release_irq(RTAI_TIMER_IRQ);
00142
00143 rtai_critical_exit(flags);
00144 }