rtai-core/include/asm-cris/rtai.h

00001 /*
00002 Copyright (C) 2002,2003 Axis Communications AB
00003 
00004 Authors: Martin P Andersson (martin.andersson@linux.nu)
00005          Jens-Henrik Lindskov (mumrick@linux.nu)
00006 
00007 This program is free software; you can redistribute it and/or modify
00008 it under the terms of version 2 of the GNU General Public License as
00009 published by the Free Software Foundation.
00010 
00011 This program is distributed in the hope that it will be useful,
00012 but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 GNU General Public License for more details.
00015 
00016 You should have received a copy of the GNU General Public License
00017 along with this program; if not, write to the Free Software
00018 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019 
00020 --------------------------------------------------------------------------
00021 Acknowledgements
00022 - Paolo Mantegazza      (mantegazza@aero.polimi.it)
00023         creator of RTAI 
00024 --------------------------------------------------------------------------
00025 */
00026 
00027 #ifndef _RTAI_ASM_CRIS_RTAI_H_
00028 #define _RTAI_ASM_CRIS_RTAI_H_
00029 
00030 #include <rtai_types.h>
00031 
00032 /* Just to make things compile */
00033 
00034 #define smp_num_cpus 1
00035 #define RTAI_1_IPI  -1
00036 #define RTAI_2_IPI  -1
00037 #define RTAI_3_IPI  -1
00038 #define RTAI_4_IPI  -1
00039 
00040 /* '8254' is used to maintain compatibility with generic code */
00041 
00042 #define NR_RT_CPUS     1
00043 #define hard_cpu_id()  0
00044 #define TIMER_8254_IRQ 2 /* Timer irq == 2 on ETRAX */
00045 #define RT_TIME_END 0x7fffffffffffffffLL
00046 
00047 /*
00048  * unsigned long long multiplication
00049  */
00050 static inline unsigned long long ullmul(unsigned long m0, unsigned long m1)
00051 {
00052         unsigned long long res;
00053 
00054         res = (unsigned long long)m0 * (unsigned long long)m1;
00055 
00056         return res;
00057 }
00058 
00059 /*
00060  * unsigned long long division
00061  */
00062 static inline unsigned long long ulldiv(unsigned long long ull, 
00063                                         unsigned long uld, unsigned long *r)
00064 {
00065         unsigned long long q = ull/(unsigned long long) uld;
00066 
00067         *r = (unsigned long) (ull - q * (unsigned long long) uld);
00068 
00069         return q;       
00070 }
00071 
00072 /*
00073  * int multiplication and division
00074  */
00075 static inline int imuldiv(unsigned long i, unsigned long mult, 
00076                           unsigned long div)
00077 {
00078         unsigned long q , r;
00079         unsigned long long m;
00080 
00081         if ( mult == div )
00082                 return i;
00083 
00084         m = ((unsigned long long) i * (unsigned long long) mult);
00085         q = (unsigned long) (m / (unsigned long long) div);
00086         r = (unsigned long) (m - (unsigned long long) q * 
00087                              (unsigned long long) div );
00088 
00089         return (r + r) < div ? q : q + 1;
00090 }
00091 
00095 static inline unsigned long long llimd(unsigned long long ull, 
00096                                        unsigned long mult, unsigned long div)
00097 {
00098         unsigned long long low, high, q;
00099         unsigned long r;
00100 
00101         low  = ullmul(((unsigned long *)&ull)[0], mult);
00102         high = ullmul(((unsigned long *)&ull)[1], mult);
00103         q = ulldiv(high,div,&r) << 32;
00104         high = ((unsigned long long) r) << 32;
00105         q += ulldiv( high + low, div , &r);
00106         return (r + r) < div ? q : q + 1;
00107 }
00108 
00109 #ifdef __KERNEL__
00110 
00111 #ifndef __cplusplus
00112 #include <asm/irq.h>
00113 #include <asm/timex.h>
00114 #include <linux/kernel.h>
00115 #include <asm/rtai_atomic.h>
00116 #include <linux/spinlock.h>
00117 #endif /* !__cplusplus */
00118 
00119 extern unsigned long r_timer_ctrl_shadow;
00120 
00121 /* Interrupt flag is bit 5 on CRIS */
00122 #define IFLAG 5
00123 #define IMASK (1 << IFLAG)
00124 
00125 /* Both are needed by the generic code */
00126 #define hard_save_flags_and_cli(x) hard_save_flags_cli((x))
00127 
00128 #define rt_spin_lock(lock)
00129 #define rt_spin_unlock(lock)
00130 
00131 static inline unsigned long hard_lock_all(void)
00132 {
00133         unsigned long flags;
00134         hard_save_flags_cli(flags);
00135         return flags;
00136 }
00137 
00138 #define hard_unlock_all(flags) hard_restore_flags((flags))
00139 
00140 static inline unsigned int rt_spin_lock_irqsave(spinlock_t *lock)          
00141 {
00142         unsigned long flags;
00143         hard_save_flags_cli(flags);
00144         return flags;
00145 }
00146 
00147 static inline void rt_spin_unlock_irqrestore(unsigned long flags,
00148                                              spinlock_t *lock)
00149 {
00150         hard_restore_flags(flags);
00151 }
00152 
00153 static inline void rt_spin_lock_irq(volatile spinlock_t *lock)          
00154 {
00155         hard_cli(); 
00156         rt_spin_lock(lock);
00157 }
00158 
00159 static inline void rt_spin_unlock_irq(volatile spinlock_t *lock)
00160 {
00161         rt_spin_unlock(lock);
00162         hard_sti();
00163 }
00164 
00165 static inline void rt_global_cli(void)
00166 {
00167         hard_cli();
00168 }
00169 
00170 static inline void rt_global_sti(void)
00171 {
00172         hard_sti();
00173 }
00174 
00175 /*
00176  * Save whether the IMASK was set or not in flags
00177  */
00178 static inline void rt_global_save_flags(unsigned long *flags)
00179 {
00180         unsigned long hflags;
00181 
00182         hard_save_flags(hflags);
00183 
00184         hflags = hflags & IMASK; /* The interrupts were enabled? */
00185         
00186         *flags = hflags;
00187 }
00188 
00189 /*
00190  * Do cli and return whether the IMASK was set or not before
00191  */
00192 static inline int rt_global_save_flags_and_cli(void)
00193 {
00194         unsigned long flags;
00195 
00196         hard_save_flags_cli(flags);
00197 
00198         return (flags & IMASK);
00199 }
00200 
00201 /*
00202  * If interrupts are enabled in flags then enable them again
00203  */
00204 static inline void rt_global_restore_flags(unsigned long flags)
00205 {
00206         if (flags & IMASK){
00207                 hard_sti();
00208         }
00209         else{
00210                 hard_cli();
00211         }
00212 }
00213 
00214 static __inline__ void set_bit_non_atomic(int nr, int* addr) 
00215 {
00216         *addr |= (1 << nr);
00217 }
00218 
00219 static __inline__ void set_bit_atomic(int nr, int* addr) 
00220 {
00221         unsigned long flags;
00222         hard_save_flags_cli(flags);
00223         *addr |= (1 << nr);
00224         hard_restore_flags(flags);
00225 }
00226 
00227 static __inline__ void clear_bit_non_atomic(int nr, int* addr)
00228 {
00229         *addr &= ~(1 << nr);
00230 }
00231 
00232 static __inline__ void clear_bit_atomic(int nr, int* addr)
00233 {
00234         unsigned long flags;
00235         hard_save_flags_cli(flags);
00236         *addr &= ~(1 << nr);
00237         hard_restore_flags(flags);
00238 }
00239 
00240 /* 
00241 --------------------------------------------------------------------------
00242 */
00243 
00244 extern unsigned int rtai_delay;     /* Current timer divide factor on timer0 */
00245 extern unsigned long long rtai_tsc; /* timer0 ticks since we started counting*/
00246 extern unsigned int rtai_lastcount; /* Last read value on *R_TIMER0_DATA */
00247 
00248 /*
00249  * ETRAX 100LX lacks a cycle counter.
00250  * This does _NOT_ work if there is a process blocking the interrupts during 
00251  * more than one wrap of the timer.
00252  * This is a very short time and a potential source of problems.
00253  * ETRAX 100LX needs a bigger timer counter in hardware.
00254  */
00255 static inline unsigned long long rdtsc(void)
00256 {
00257         RTIME ts;
00258         unsigned long flags;
00259         unsigned int count, ticks;
00260 
00261 #ifdef CONFIG_ETRAX_DISABLE_CASCADED_TIMERS_IN_RTAI
00262         /* Read the 8 bit count value. */
00263         count = *R_TIMER0_DATA;
00264 #else
00265         /* Read the 16 bit count value. */
00266         count = *R_TIMER01_DATA;
00267 #endif
00268         
00269         flags = hard_lock_all();
00270 
00271         /* No timer wrap, just a count down.
00272          * Read the timer interrupt to make sure, because the interrupts 
00273          * could be disabled at this moment.
00274          * If the interrupts are disabled for to long this will fail. */
00275         if ( count < rtai_lastcount && 
00276              !(*R_VECT_READ & IO_STATE(R_VECT_READ, timer0, active)) ){
00277                 ticks = rtai_lastcount - count;
00278         }
00279         /* A timer wrap */
00280         else {
00281                 ticks = rtai_delay - rtai_lastcount + count;
00282         }
00283         rtai_lastcount = count;
00284         rtai_tsc += (unsigned long long) ticks;
00285 
00286         ts = rtai_tsc;
00287         hard_unlock_all(flags);
00288 
00289         return ts;
00290 }
00291 
00292 /*
00293  * Set the timer divide factor to delay if x=!0
00294  * On cris we have a timer counter which wraps around by
00295  * itself so there is nothing to do when delay==0.
00296  * Some archs have to reprogram the timer every period,
00297  * therefore this function can be called with 0
00298  * We use both timers cascaded in this 
00299  */
00300 static inline void rt_set_timer_delay(unsigned int delay)
00301 {
00302         if (delay<=0)
00303                 return;
00304 
00305 #ifdef CONFIG_ETRAX_DISABLE_CASCADED_TIMERS_IN_RTAI
00306         /* 8 bit counter */
00307         if (delay>255)
00308                 delay = 0;
00309 #else
00310         /* 16 bit counter */
00311         if (delay>65535)
00312                 delay = 0;
00313 #endif
00314                 
00315         /* So that no ticks are lost when the timer is reprogrammed. */
00316         rdtsc();
00317 
00318 #ifdef CONFIG_ETRAX_DISABLE_CASCADED_TIMERS_IN_RTAI
00319         /* Clear the corresponding fields of the shadow. */
00320         r_timer_ctrl_shadow = r_timer_ctrl_shadow & (
00321                 ~IO_FIELD(R_TIMER_CTRL, timerdiv0, 255) &
00322                 ~IO_STATE(R_TIMER_CTRL, tm0, reserved));
00323 
00324         /* Stop the timers and load the new timerdiv0 and timerdiv1 */
00325         *R_TIMER_CTRL = r_timer_ctrl_shadow              | 
00326                 IO_FIELD(R_TIMER_CTRL, timerdiv0, delay) | 
00327                 IO_STATE(R_TIMER_CTRL, tm0, stop_ld);
00328 
00329         /* Restart the timer and save the changes to r_timer_ctrl_shadow */
00330         *R_TIMER_CTRL = r_timer_ctrl_shadow = r_timer_ctrl_shadow | 
00331                 IO_FIELD(R_TIMER_CTRL, timerdiv0, delay)          | 
00332                 IO_STATE(R_TIMER_CTRL, tm0, run);
00333 #else
00334         /* Clear the corresponding fields of the shadow. */
00335         r_timer_ctrl_shadow = r_timer_ctrl_shadow & (
00336                 ~IO_FIELD(R_TIMER_CTRL, timerdiv1, 255) &
00337                 ~IO_STATE(R_TIMER_CTRL, tm1, reserved)  &
00338                 ~IO_FIELD(R_TIMER_CTRL, timerdiv0, 255) &
00339                 ~IO_STATE(R_TIMER_CTRL, tm0, reserved));
00340 
00341         /* Stop the timers and load the new timerdiv0 and timerdiv1 */
00342         *R_TIMER_CTRL = r_timer_ctrl_shadow                     | 
00343                 IO_FIELD(R_TIMER_CTRL, timerdiv1, delay>>8)     | 
00344                 IO_STATE(R_TIMER_CTRL, tm1, stop_ld)            |
00345                 IO_FIELD(R_TIMER_CTRL, timerdiv0, 0xff & delay) | 
00346                 IO_STATE(R_TIMER_CTRL, tm0, stop_ld);
00347 
00348         /* Restart the timer and save the changes to r_timer_ctrl_shadow */
00349         *R_TIMER_CTRL = r_timer_ctrl_shadow = r_timer_ctrl_shadow | 
00350                 IO_FIELD(R_TIMER_CTRL, timerdiv1, delay>>8)       | 
00351                 IO_STATE(R_TIMER_CTRL, tm1, run)                  |
00352                 IO_FIELD(R_TIMER_CTRL, timerdiv0, 0xff & delay)   | 
00353                 IO_STATE(R_TIMER_CTRL, tm0, run);
00354 
00355 #endif
00356                 
00357         /* Update the delays for use in rdtsc. */
00358         rtai_delay = delay;
00359         rtai_lastcount = delay;
00360 }
00361 
00362 #ifdef CONFIG_ETRAX_DISABLE_CASCADED_TIMERS_IN_RTAI
00363 #define FREQ_8254 25000 /* 25 MHz with a prescale of 1000 (kernel >=2.4.19) */
00364 #else /* !CONFIG_ETRAX_DISABLE_CASCADED_TIMERS_IN_RTAI */
00365 #define FREQ_8254 6250000 /* 25 MHz with a prescale of 4 */
00366 #endif /* CONFIG_ETRAX_DISABLE_CASCADED_TIMERS_IN_RTAI */
00367 
00368 #define SETUP_TIME_8254 2800
00369 #define LATENCY_8254    2800
00370 #define CPU_FREQ        FREQ_8254
00371 #define FREQ_APIC       FREQ_8254
00372 
00373 #define NR_GLOBAL_IRQS  NR_IRQS
00374 #define NR_CPU_OWN_IRQS NR_GLOBAL_IRQS
00375 
00376 /* Floating point related stuff. There are */
00377 /* no floating point registers on CRIS */
00378 #define save_cr0_and_clts(x)
00379 #define restore_cr0(x)
00380 #define enable_fpu(x)
00381 #define save_fpenv(x)
00382 #define restore_fpenv(x)
00383 
00384 typedef struct cris_fpu_env { unsigned long fpu_regs[1]; } FPU_ENV;
00385 
00386 /* Need to be declared but can be empty */
00387 #define DECLR_8254_TSC_EMULATION
00388 #define TICK_8254_TSC_EMULATION
00389 #define SETUP_8254_TSC_EMULATION
00390 #define CLEAR_8254_TSC_EMULATION
00391 
00392 extern struct calibration_data tuned;
00393 struct calibration_data {
00394         unsigned int cpu_freq;
00395         unsigned int apic_freq;
00396         int latency;
00397         int setup_time_TIMER_CPUNIT;
00398         int setup_time_TIMER_UNIT;
00399         int timers_tol[NR_RT_CPUS];
00400 };
00401 
00402 struct apic_timer_setup_data {
00403         int mode;
00404         int count;
00405 };
00406 
00407 /* FIX: Trap handling. This is not implemented in RTAI/CRIS yet. */
00408 #define RTAI_NR_TRAPS 32
00409 static inline RT_TRAP_HANDLER rt_set_rtai_trap_handler(RT_TRAP_HANDLER handler)
00410 {
00411         return (RT_TRAP_HANDLER) 0;
00412 }
00413 
00414 extern struct rt_times rt_times;
00415 
00416 #define ffnz(ul) (ffs(ul)-1)
00417 
00418 /* 
00419 --------------------------------------------------------------------------
00420 */
00421 
00422 #define rt_assign_irq_to_cpu(irq, cpu)
00423 #define rt_reset_irq_to_sym_mode(irq)
00424 
00425 extern int rt_request_global_irq(unsigned int irq, void (*handler)(void));
00426 extern int rt_free_global_irq(unsigned int irq);
00427 extern void rt_ack_irq(unsigned int irq);
00428 extern void rt_mask_and_ack_irq(unsigned int irq);
00429 extern void rt_unmask_irq(unsigned int irq);
00430 extern unsigned int rt_startup_irq(unsigned int irq);
00431 extern void rt_shutdown_irq(unsigned int irq);
00432 extern void rt_enable_irq(unsigned int irq);
00433 extern void rt_disable_irq(unsigned int irq);
00434 extern int rt_request_linux_irq(unsigned int irq,
00435        void (*linux_handler)(int irq, void *dev_id, struct pt_regs *regs),
00436        char *linux_handler_id, void *dev_id);
00437 extern int rt_free_linux_irq(unsigned int irq, void *dev_id);
00438 extern int rt_request_srq(unsigned int label, void (*rtai_handler)(void), 
00439                           long long (*user_handler)(unsigned long whatever));
00440 extern int rt_free_srq(unsigned int srq);
00441 extern void rt_pend_linux_irq(unsigned int irq);
00442 extern void rt_pend_linux_srq(unsigned int srq);
00443 #define rt_request_cpu_own_irq(irq, handler) rt_request_global_irq((irq), (handler))
00444 #define rt_free_cpu_own_irq(irq) rt_free_global_irq((irq))
00445 extern void rt_request_timer(void (*handler)(void), unsigned int tick, 
00446                              int apic);
00447 extern void rt_free_timer(void);
00448 extern void rt_mount_rtai(void);
00449 extern void rt_umount_rtai(void);
00450 extern int rt_printk(const char *format, ...);
00451 extern int rtai_print_to_screen(const char *format, ...);
00452 extern void rt_switch_to_linux(int cpuid);
00453 extern void rt_switch_to_real_time(int cpuid);
00454 extern int rt_is_linux(void);
00455 
00456 #endif /* __KERNEL__ */
00457 
00458 #define RTAI_DEFAULT_TICK    200000
00459 #define RTAI_DEFAULT_STACKSZ 1000
00460 
00461 #endif /* !_RTAI_ASM_CRIS_RTAI_H_ */

Generated on Sat Jul 24 19:36:02 2004 for RTAI API by doxygen 1.3.4