2005-04-17 02:20:36 +04:00
/*
* include / asm - sh / processor . h
*
* Copyright ( C ) 1999 , 2000 Niibe Yutaka
* Copyright ( C ) 2002 , 2003 Paul Mundt
*/
# ifndef __ASM_SH_PROCESSOR_H
# define __ASM_SH_PROCESSOR_H
# ifdef __KERNEL__
2006-07-08 20:10:29 +04:00
# include <linux/compiler.h>
2005-04-17 02:20:36 +04:00
# include <asm/page.h>
# include <asm/types.h>
# include <asm/cache.h>
# include <asm/ptrace.h>
2006-09-27 13:22:53 +04:00
# include <asm/cpu-features.h>
2005-04-17 02:20:36 +04:00
/*
* Default implementation of macro that returns current
* instruction pointer ( " program counter " ) .
*/
# define current_text_addr() ({ void *pc; __asm__("mova 1f, %0\n1:":"=z" (pc)); pc; })
/* Core Processor Version Register */
# define CCN_PVR 0xff000030
# define CCN_CVR 0xff000040
# define CCN_PRR 0xff000044
/*
* CPU type and hardware bug flags . Kept separately for each CPU .
*
* Each one of these also needs a CONFIG_CPU_SUBTYPE_xxx entry
2006-02-01 14:06:02 +03:00
* in arch / sh / mm / Kconfig , as well as an entry in arch / sh / kernel / setup . c
2005-04-17 02:20:36 +04:00
* for parsing the subtype in get_cpu_subtype ( ) .
*/
enum cpu_type {
/* SH-2 types */
2006-11-05 10:18:08 +03:00
CPU_SH7604 , CPU_SH7619 ,
/* SH-2A types */
CPU_SH7206 ,
2005-04-17 02:20:36 +04:00
/* SH-3 types */
2006-09-27 12:38:11 +04:00
CPU_SH7705 , CPU_SH7706 , CPU_SH7707 ,
CPU_SH7708 , CPU_SH7708S , CPU_SH7708R ,
CPU_SH7709 , CPU_SH7709A , CPU_SH7710 ,
CPU_SH7729 , CPU_SH7300 ,
2005-04-17 02:20:36 +04:00
/* SH-4 types */
CPU_SH7750 , CPU_SH7750S , CPU_SH7750R , CPU_SH7751 , CPU_SH7751R ,
CPU_SH7760 , CPU_ST40RA , CPU_ST40GX1 , CPU_SH4_202 , CPU_SH4_501 ,
2006-11-20 08:14:29 +03:00
/* SH-4A types */
2006-09-27 12:38:11 +04:00
CPU_SH73180 , CPU_SH7343 , CPU_SH7770 , CPU_SH7780 , CPU_SH7781 ,
2006-11-20 08:14:29 +03:00
CPU_SH7785 ,
2005-04-17 02:20:36 +04:00
/* Unknown subtype */
CPU_SH_NONE
} ;
struct sh_cpuinfo {
2006-09-27 13:27:43 +04:00
unsigned int type ;
2005-04-17 02:20:36 +04:00
unsigned long loops_per_jiffy ;
2006-09-27 13:27:43 +04:00
struct cache_info icache ; /* Primary I-cache */
struct cache_info dcache ; /* Primary D-cache */
struct cache_info scache ; /* Secondary cache */
2005-04-17 02:20:36 +04:00
unsigned long flags ;
2006-09-27 13:27:43 +04:00
} __attribute__ ( ( aligned ( SMP_CACHE_BYTES ) ) ) ;
2005-04-17 02:20:36 +04:00
extern struct sh_cpuinfo boot_cpu_data ;
# ifdef CONFIG_SMP
extern struct sh_cpuinfo cpu_data [ ] ;
# define current_cpu_data cpu_data[smp_processor_id()]
# else
# define cpu_data (&boot_cpu_data)
# define current_cpu_data boot_cpu_data
# endif
/*
* User space process size : 2 GB .
*
* Since SH7709 and SH7750 have " area 7 " , we can ' t use 0x7c000000 - - 0x7fffffff
*/
# define TASK_SIZE 0x7c000000UL
/* This decides where the kernel will search for a free chunk of vm
* space during mmap ' s .
*/
# define TASK_UNMAPPED_BASE (TASK_SIZE / 3)
/*
* Bit of SR register
*
* FD - bit :
* When it ' s set , it means the processor doesn ' t have right to use FPU ,
* and it results exception when the floating operation is executed .
*
* IMASK - bit :
* Interrupt level mask
*/
# define SR_FD 0x00008000
# define SR_DSP 0x00001000
# define SR_IMASK 0x000000f0
/*
* FPU structure and data
*/
struct sh_fpu_hard_struct {
unsigned long fp_regs [ 16 ] ;
unsigned long xfp_regs [ 16 ] ;
unsigned long fpscr ;
unsigned long fpul ;
long status ; /* software status information */
} ;
/* Dummy fpu emulator */
struct sh_fpu_soft_struct {
unsigned long fp_regs [ 16 ] ;
unsigned long xfp_regs [ 16 ] ;
unsigned long fpscr ;
unsigned long fpul ;
unsigned char lookahead ;
unsigned long entry_pc ;
} ;
union sh_fpu_union {
struct sh_fpu_hard_struct hard ;
struct sh_fpu_soft_struct soft ;
} ;
struct thread_struct {
2006-11-21 07:34:04 +03:00
/* Saved registers when thread is descheduled */
2005-04-17 02:20:36 +04:00
unsigned long sp ;
unsigned long pc ;
2006-11-21 07:34:04 +03:00
/* Hardware debugging registers */
2005-04-17 02:20:36 +04:00
unsigned long ubc_pc ;
/* floating point info */
union sh_fpu_union fpu ;
} ;
2006-09-27 12:07:07 +04:00
typedef struct {
unsigned long seg ;
} mm_segment_t ;
2005-04-17 02:20:36 +04:00
/* Count of active tasks with UBC settings */
extern int ubc_usercnt ;
# define INIT_THREAD { \
2006-11-21 07:34:04 +03:00
. sp = sizeof ( init_stack ) + ( long ) & init_stack , \
2005-04-17 02:20:36 +04:00
}
/*
* Do necessary setup to start up a newly executed thread .
*/
# define start_thread(regs, new_pc, new_sp) \
set_fs ( USER_DS ) ; \
2006-02-01 14:06:02 +03:00
regs - > pr = 0 ; \
2005-04-17 02:20:36 +04:00
regs - > sr = SR_FD ; /* User mode. */ \
regs - > pc = new_pc ; \
regs - > regs [ 15 ] = new_sp
/* Forward declaration, a strange C thing */
struct task_struct ;
struct mm_struct ;
/* Free all resources held by a thread. */
extern void release_thread ( struct task_struct * ) ;
/* Prepare to copy thread state - unlazy all lazy status */
# define prepare_to_copy(tsk) do { } while (0)
/*
* create a kernel thread without removing it from tasklists
*/
extern int kernel_thread ( int ( * fn ) ( void * ) , void * arg , unsigned long flags ) ;
/* Copy and release all segment info associated with a VM */
# define copy_segments(p, mm) do { } while(0)
# define release_segments(mm) do { } while(0)
/*
* FPU lazy state save handling .
*/
static __inline__ void disable_fpu ( void )
{
unsigned long __dummy ;
/* Set FD flag in SR */
__asm__ __volatile__ ( " stc sr, %0 \n \t "
" or %1, %0 \n \t "
" ldc %0, sr "
: " =&r " ( __dummy )
: " r " ( SR_FD ) ) ;
}
static __inline__ void enable_fpu ( void )
{
unsigned long __dummy ;
/* Clear out FD flag in SR */
__asm__ __volatile__ ( " stc sr, %0 \n \t "
" and %1, %0 \n \t "
" ldc %0, sr "
: " =&r " ( __dummy )
: " r " ( ~ SR_FD ) ) ;
}
static __inline__ void release_fpu ( struct pt_regs * regs )
{
regs - > sr | = SR_FD ;
}
static __inline__ void grab_fpu ( struct pt_regs * regs )
{
regs - > sr & = ~ SR_FD ;
}
# ifdef CONFIG_CPU_SH4
extern void save_fpu ( struct task_struct * __tsk , struct pt_regs * regs ) ;
# else
# define save_fpu(tsk) do { } while (0)
# endif
2006-02-01 14:06:02 +03:00
# define unlazy_fpu(tsk, regs) do { \
2005-04-17 02:20:36 +04:00
if ( test_tsk_thread_flag ( tsk , TIF_USEDFPU ) ) { \
2006-02-01 14:06:02 +03:00
save_fpu ( tsk , regs ) ; \
2005-04-17 02:20:36 +04:00
} \
} while ( 0 )
2006-02-01 14:06:02 +03:00
# define clear_fpu(tsk, regs) do { \
if ( test_tsk_thread_flag ( tsk , TIF_USEDFPU ) ) { \
clear_tsk_thread_flag ( tsk , TIF_USEDFPU ) ; \
release_fpu ( regs ) ; \
2005-04-17 02:20:36 +04:00
} \
} while ( 0 )
/* Double presision, NANS as NANS, rounding to nearest, no exceptions */
# define FPSCR_INIT 0x00080000
# define FPSCR_CAUSE_MASK 0x0001f000 /* Cause bits */
# define FPSCR_FLAG_MASK 0x0000007c /* Flag bits */
/*
* Return saved PC of a blocked thread .
*/
# define thread_saved_pc(tsk) (tsk->thread.pc)
2006-10-12 12:07:45 +04:00
void show_trace ( struct task_struct * tsk , unsigned long * sp ,
struct pt_regs * regs ) ;
2005-04-17 02:20:36 +04:00
extern unsigned long get_wchan ( struct task_struct * p ) ;
2006-11-24 06:53:02 +03:00
# define KSTK_EIP(tsk) (task_pt_regs(tsk)->pc)
# define KSTK_ESP(tsk) (task_pt_regs(tsk)->regs[15])
2005-04-17 02:20:36 +04:00
# define cpu_sleep() __asm__ __volatile__ ("sleep" : : : "memory")
2006-07-08 20:10:29 +04:00
# define cpu_relax() barrier()
2005-04-17 02:20:36 +04:00
2006-09-27 09:20:54 +04:00
# if defined(CONFIG_CPU_SH2A) || defined(CONFIG_CPU_SH3) || \
defined ( CONFIG_CPU_SH4 )
# define PREFETCH_STRIDE L1_CACHE_BYTES
# define ARCH_HAS_PREFETCH
# define ARCH_HAS_PREFETCHW
static inline void prefetch ( void * x )
{
__asm__ __volatile__ ( " pref @%0 \n \t " : : " r " ( x ) : " memory " ) ;
}
# define prefetchw(x) prefetch(x)
# endif
2006-09-27 13:33:49 +04:00
# ifdef CONFIG_VSYSCALL
extern int vsyscall_init ( void ) ;
# else
# define vsyscall_init() do { } while (0)
# endif
2005-04-17 02:20:36 +04:00
# endif /* __KERNEL__ */
# endif /* __ASM_SH_PROCESSOR_H */