| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1 | /* | 
|  | 2 | * include/asm-sh/processor.h | 
|  | 3 | * | 
|  | 4 | * Copyright (C) 1999, 2000  Niibe Yutaka | 
|  | 5 | * Copyright (C) 2002, 2003  Paul Mundt | 
|  | 6 | */ | 
|  | 7 |  | 
|  | 8 | #ifndef __ASM_SH_PROCESSOR_H | 
|  | 9 | #define __ASM_SH_PROCESSOR_H | 
|  | 10 | #ifdef __KERNEL__ | 
|  | 11 |  | 
| Chase Venters | f6dc8c5 | 2006-07-08 11:10:29 -0500 | [diff] [blame] | 12 | #include <linux/compiler.h> | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 13 | #include <asm/page.h> | 
|  | 14 | #include <asm/types.h> | 
|  | 15 | #include <asm/cache.h> | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 16 | #include <asm/ptrace.h> | 
| Paul Mundt | 315bb96 | 2006-09-27 18:22:53 +0900 | [diff] [blame] | 17 | #include <asm/cpu-features.h> | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 18 |  | 
|  | 19 | /* | 
|  | 20 | * Default implementation of macro that returns current | 
|  | 21 | * instruction pointer ("program counter"). | 
|  | 22 | */ | 
|  | 23 | #define current_text_addr() ({ void *pc; __asm__("mova	1f, %0\n1:":"=z" (pc)); pc; }) | 
|  | 24 |  | 
|  | 25 | /* Core Processor Version Register */ | 
|  | 26 | #define CCN_PVR		0xff000030 | 
|  | 27 | #define CCN_CVR		0xff000040 | 
|  | 28 | #define CCN_PRR		0xff000044 | 
|  | 29 |  | 
|  | 30 | /* | 
|  | 31 | *  CPU type and hardware bug flags. Kept separately for each CPU. | 
|  | 32 | * | 
|  | 33 | *  Each one of these also needs a CONFIG_CPU_SUBTYPE_xxx entry | 
| Paul Mundt | de02797 | 2006-02-01 03:06:02 -0800 | [diff] [blame] | 34 | *  in arch/sh/mm/Kconfig, as well as an entry in arch/sh/kernel/setup.c | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 35 | *  for parsing the subtype in get_cpu_subtype(). | 
|  | 36 | */ | 
|  | 37 | enum cpu_type { | 
|  | 38 | /* SH-2 types */ | 
| Yoshinori Sato | b229632 | 2006-11-05 16:18:08 +0900 | [diff] [blame] | 39 | CPU_SH7604, CPU_SH7619, | 
|  | 40 |  | 
|  | 41 | /* SH-2A types */ | 
|  | 42 | CPU_SH7206, | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 43 |  | 
|  | 44 | /* SH-3 types */ | 
| Paul Mundt | e5723e0 | 2006-09-27 17:38:11 +0900 | [diff] [blame] | 45 | CPU_SH7705, CPU_SH7706, CPU_SH7707, | 
|  | 46 | CPU_SH7708, CPU_SH7708S, CPU_SH7708R, | 
|  | 47 | CPU_SH7709, CPU_SH7709A, CPU_SH7710, | 
|  | 48 | CPU_SH7729, CPU_SH7300, | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 49 |  | 
|  | 50 | /* SH-4 types */ | 
|  | 51 | CPU_SH7750, CPU_SH7750S, CPU_SH7750R, CPU_SH7751, CPU_SH7751R, | 
|  | 52 | CPU_SH7760, CPU_ST40RA, CPU_ST40GX1, CPU_SH4_202, CPU_SH4_501, | 
| Paul Mundt | b552c7e | 2006-11-20 14:14:29 +0900 | [diff] [blame] | 53 |  | 
|  | 54 | /* SH-4A types */ | 
| Paul Mundt | 41504c3 | 2006-12-11 20:28:03 +0900 | [diff] [blame] | 55 | CPU_SH7770, CPU_SH7780, CPU_SH7781, CPU_SH7785, | 
|  | 56 |  | 
|  | 57 | /* SH4AL-DSP types */ | 
|  | 58 | CPU_SH73180, CPU_SH7343, CPU_SH7722, | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 59 |  | 
|  | 60 | /* Unknown subtype */ | 
|  | 61 | CPU_SH_NONE | 
|  | 62 | }; | 
|  | 63 |  | 
|  | 64 | struct sh_cpuinfo { | 
| Paul Mundt | 72c3554 | 2006-09-27 18:27:43 +0900 | [diff] [blame] | 65 | unsigned int type; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 66 | unsigned long loops_per_jiffy; | 
| Paul Mundt | aec5e0e | 2006-12-25 09:51:47 +0900 | [diff] [blame] | 67 | unsigned long asid_cache; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 68 |  | 
| Paul Mundt | 72c3554 | 2006-09-27 18:27:43 +0900 | [diff] [blame] | 69 | struct cache_info icache;	/* Primary I-cache */ | 
|  | 70 | struct cache_info dcache;	/* Primary D-cache */ | 
|  | 71 | struct cache_info scache;	/* Secondary cache */ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 72 |  | 
|  | 73 | unsigned long flags; | 
| Paul Mundt | 72c3554 | 2006-09-27 18:27:43 +0900 | [diff] [blame] | 74 | } __attribute__ ((aligned(SMP_CACHE_BYTES))); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 75 |  | 
|  | 76 | extern struct sh_cpuinfo boot_cpu_data; | 
|  | 77 |  | 
|  | 78 | #ifdef CONFIG_SMP | 
|  | 79 | extern struct sh_cpuinfo cpu_data[]; | 
|  | 80 | #define current_cpu_data cpu_data[smp_processor_id()] | 
|  | 81 | #else | 
|  | 82 | #define cpu_data (&boot_cpu_data) | 
|  | 83 | #define current_cpu_data boot_cpu_data | 
|  | 84 | #endif | 
|  | 85 |  | 
|  | 86 | /* | 
|  | 87 | * User space process size: 2GB. | 
|  | 88 | * | 
|  | 89 | * Since SH7709 and SH7750 have "area 7", we can't use 0x7c000000--0x7fffffff | 
|  | 90 | */ | 
|  | 91 | #define TASK_SIZE	0x7c000000UL | 
|  | 92 |  | 
|  | 93 | /* This decides where the kernel will search for a free chunk of vm | 
|  | 94 | * space during mmap's. | 
|  | 95 | */ | 
|  | 96 | #define TASK_UNMAPPED_BASE	(TASK_SIZE / 3) | 
|  | 97 |  | 
|  | 98 | /* | 
|  | 99 | * Bit of SR register | 
|  | 100 | * | 
|  | 101 | * FD-bit: | 
|  | 102 | *     When it's set, it means the processor doesn't have right to use FPU, | 
|  | 103 | *     and it results exception when the floating operation is executed. | 
|  | 104 | * | 
|  | 105 | * IMASK-bit: | 
|  | 106 | *     Interrupt level mask | 
|  | 107 | */ | 
|  | 108 | #define SR_FD		0x00008000 | 
|  | 109 | #define SR_DSP		0x00001000 | 
|  | 110 | #define SR_IMASK	0x000000f0 | 
|  | 111 |  | 
|  | 112 | /* | 
|  | 113 | * FPU structure and data | 
|  | 114 | */ | 
|  | 115 |  | 
|  | 116 | struct sh_fpu_hard_struct { | 
|  | 117 | unsigned long fp_regs[16]; | 
|  | 118 | unsigned long xfp_regs[16]; | 
|  | 119 | unsigned long fpscr; | 
|  | 120 | unsigned long fpul; | 
|  | 121 |  | 
|  | 122 | long status; /* software status information */ | 
|  | 123 | }; | 
|  | 124 |  | 
|  | 125 | /* Dummy fpu emulator  */ | 
|  | 126 | struct sh_fpu_soft_struct { | 
|  | 127 | unsigned long fp_regs[16]; | 
|  | 128 | unsigned long xfp_regs[16]; | 
|  | 129 | unsigned long fpscr; | 
|  | 130 | unsigned long fpul; | 
|  | 131 |  | 
|  | 132 | unsigned char lookahead; | 
|  | 133 | unsigned long entry_pc; | 
|  | 134 | }; | 
|  | 135 |  | 
|  | 136 | union sh_fpu_union { | 
|  | 137 | struct sh_fpu_hard_struct hard; | 
|  | 138 | struct sh_fpu_soft_struct soft; | 
|  | 139 | }; | 
|  | 140 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 141 | struct thread_struct { | 
| Stuart Menefy | b5a1bcb | 2006-11-21 13:34:04 +0900 | [diff] [blame] | 142 | /* Saved registers when thread is descheduled */ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 143 | unsigned long sp; | 
|  | 144 | unsigned long pc; | 
|  | 145 |  | 
| Stuart Menefy | b5a1bcb | 2006-11-21 13:34:04 +0900 | [diff] [blame] | 146 | /* Hardware debugging registers */ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 147 | unsigned long ubc_pc; | 
|  | 148 |  | 
|  | 149 | /* floating point info */ | 
|  | 150 | union sh_fpu_union fpu; | 
|  | 151 | }; | 
|  | 152 |  | 
| Paul Mundt | 2991be7 | 2006-09-27 17:07:07 +0900 | [diff] [blame] | 153 | typedef struct { | 
|  | 154 | unsigned long seg; | 
|  | 155 | } mm_segment_t; | 
|  | 156 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 157 | /* Count of active tasks with UBC settings */ | 
|  | 158 | extern int ubc_usercnt; | 
|  | 159 |  | 
|  | 160 | #define INIT_THREAD  {						\ | 
| Stuart Menefy | b5a1bcb | 2006-11-21 13:34:04 +0900 | [diff] [blame] | 161 | .sp = sizeof(init_stack) + (long) &init_stack,		\ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 162 | } | 
|  | 163 |  | 
|  | 164 | /* | 
|  | 165 | * Do necessary setup to start up a newly executed thread. | 
|  | 166 | */ | 
|  | 167 | #define start_thread(regs, new_pc, new_sp)	 \ | 
|  | 168 | set_fs(USER_DS);			 \ | 
| Paul Mundt | de02797 | 2006-02-01 03:06:02 -0800 | [diff] [blame] | 169 | regs->pr = 0;				 \ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 170 | regs->sr = SR_FD;	/* User mode. */ \ | 
|  | 171 | regs->pc = new_pc;			 \ | 
|  | 172 | regs->regs[15] = new_sp | 
|  | 173 |  | 
|  | 174 | /* Forward declaration, a strange C thing */ | 
|  | 175 | struct task_struct; | 
|  | 176 | struct mm_struct; | 
|  | 177 |  | 
|  | 178 | /* Free all resources held by a thread. */ | 
|  | 179 | extern void release_thread(struct task_struct *); | 
|  | 180 |  | 
|  | 181 | /* Prepare to copy thread state - unlazy all lazy status */ | 
|  | 182 | #define prepare_to_copy(tsk)	do { } while (0) | 
|  | 183 |  | 
|  | 184 | /* | 
|  | 185 | * create a kernel thread without removing it from tasklists | 
|  | 186 | */ | 
|  | 187 | extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); | 
|  | 188 |  | 
|  | 189 | /* Copy and release all segment info associated with a VM */ | 
|  | 190 | #define copy_segments(p, mm)	do { } while(0) | 
|  | 191 | #define release_segments(mm)	do { } while(0) | 
|  | 192 |  | 
|  | 193 | /* | 
|  | 194 | * FPU lazy state save handling. | 
|  | 195 | */ | 
|  | 196 |  | 
|  | 197 | static __inline__ void disable_fpu(void) | 
|  | 198 | { | 
|  | 199 | unsigned long __dummy; | 
|  | 200 |  | 
|  | 201 | /* Set FD flag in SR */ | 
|  | 202 | __asm__ __volatile__("stc	sr, %0\n\t" | 
|  | 203 | "or	%1, %0\n\t" | 
|  | 204 | "ldc	%0, sr" | 
|  | 205 | : "=&r" (__dummy) | 
|  | 206 | : "r" (SR_FD)); | 
|  | 207 | } | 
|  | 208 |  | 
|  | 209 | static __inline__ void enable_fpu(void) | 
|  | 210 | { | 
|  | 211 | unsigned long __dummy; | 
|  | 212 |  | 
|  | 213 | /* Clear out FD flag in SR */ | 
|  | 214 | __asm__ __volatile__("stc	sr, %0\n\t" | 
|  | 215 | "and	%1, %0\n\t" | 
|  | 216 | "ldc	%0, sr" | 
|  | 217 | : "=&r" (__dummy) | 
|  | 218 | : "r" (~SR_FD)); | 
|  | 219 | } | 
|  | 220 |  | 
|  | 221 | static __inline__ void release_fpu(struct pt_regs *regs) | 
|  | 222 | { | 
|  | 223 | regs->sr |= SR_FD; | 
|  | 224 | } | 
|  | 225 |  | 
|  | 226 | static __inline__ void grab_fpu(struct pt_regs *regs) | 
|  | 227 | { | 
|  | 228 | regs->sr &= ~SR_FD; | 
|  | 229 | } | 
|  | 230 |  | 
|  | 231 | #ifdef CONFIG_CPU_SH4 | 
|  | 232 | extern void save_fpu(struct task_struct *__tsk, struct pt_regs *regs); | 
|  | 233 | #else | 
|  | 234 | #define save_fpu(tsk)	do { } while (0) | 
|  | 235 | #endif | 
|  | 236 |  | 
| Paul Mundt | de02797 | 2006-02-01 03:06:02 -0800 | [diff] [blame] | 237 | #define unlazy_fpu(tsk, regs) do {			\ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 238 | if (test_tsk_thread_flag(tsk, TIF_USEDFPU)) {	\ | 
| Paul Mundt | de02797 | 2006-02-01 03:06:02 -0800 | [diff] [blame] | 239 | save_fpu(tsk, regs);			\ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 240 | }						\ | 
|  | 241 | } while (0) | 
|  | 242 |  | 
| Paul Mundt | de02797 | 2006-02-01 03:06:02 -0800 | [diff] [blame] | 243 | #define clear_fpu(tsk, regs) do {				\ | 
|  | 244 | if (test_tsk_thread_flag(tsk, TIF_USEDFPU)) {		\ | 
|  | 245 | clear_tsk_thread_flag(tsk, TIF_USEDFPU);	\ | 
|  | 246 | release_fpu(regs);				\ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 247 | }							\ | 
|  | 248 | } while (0) | 
|  | 249 |  | 
|  | 250 | /* Double presision, NANS as NANS, rounding to nearest, no exceptions */ | 
|  | 251 | #define FPSCR_INIT  0x00080000 | 
|  | 252 |  | 
|  | 253 | #define	FPSCR_CAUSE_MASK	0x0001f000	/* Cause bits */ | 
|  | 254 | #define	FPSCR_FLAG_MASK		0x0000007c	/* Flag bits */ | 
|  | 255 |  | 
|  | 256 | /* | 
|  | 257 | * Return saved PC of a blocked thread. | 
|  | 258 | */ | 
|  | 259 | #define thread_saved_pc(tsk)	(tsk->thread.pc) | 
|  | 260 |  | 
| Paul Mundt | 6b00223 | 2006-10-12 17:07:45 +0900 | [diff] [blame] | 261 | void show_trace(struct task_struct *tsk, unsigned long *sp, | 
|  | 262 | struct pt_regs *regs); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 263 | extern unsigned long get_wchan(struct task_struct *p); | 
|  | 264 |  | 
| Stuart Menefy | c9f0b1c | 2006-11-24 12:53:02 +0900 | [diff] [blame] | 265 | #define KSTK_EIP(tsk)  (task_pt_regs(tsk)->pc) | 
|  | 266 | #define KSTK_ESP(tsk)  (task_pt_regs(tsk)->regs[15]) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 267 |  | 
|  | 268 | #define cpu_sleep()	__asm__ __volatile__ ("sleep" : : : "memory") | 
| Chase Venters | f6dc8c5 | 2006-07-08 11:10:29 -0500 | [diff] [blame] | 269 | #define cpu_relax()	barrier() | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 270 |  | 
| Paul Mundt | e86d6b6 | 2006-09-27 14:20:54 +0900 | [diff] [blame] | 271 | #if defined(CONFIG_CPU_SH2A) || defined(CONFIG_CPU_SH3) || \ | 
|  | 272 | defined(CONFIG_CPU_SH4) | 
|  | 273 | #define PREFETCH_STRIDE		L1_CACHE_BYTES | 
|  | 274 | #define ARCH_HAS_PREFETCH | 
|  | 275 | #define ARCH_HAS_PREFETCHW | 
|  | 276 | static inline void prefetch(void *x) | 
|  | 277 | { | 
|  | 278 | __asm__ __volatile__ ("pref @%0\n\t" : : "r" (x) : "memory"); | 
|  | 279 | } | 
|  | 280 |  | 
|  | 281 | #define prefetchw(x)	prefetch(x) | 
|  | 282 | #endif | 
|  | 283 |  | 
| Paul Mundt | 19f9a34 | 2006-09-27 18:33:49 +0900 | [diff] [blame] | 284 | #ifdef CONFIG_VSYSCALL | 
|  | 285 | extern int vsyscall_init(void); | 
|  | 286 | #else | 
|  | 287 | #define vsyscall_init() do { } while (0) | 
|  | 288 | #endif | 
|  | 289 |  | 
| Paul Mundt | 11c1965 | 2006-12-25 10:19:56 +0900 | [diff] [blame] | 290 | /* arch/sh/kernel/setup.c */ | 
|  | 291 | const char *get_cpu_subtype(struct sh_cpuinfo *c); | 
|  | 292 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 293 | #endif /* __KERNEL__ */ | 
|  | 294 | #endif /* __ASM_SH_PROCESSOR_H */ |