| 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 */ | 
| Paul Mundt | b9601c5 | 2007-06-08 11:55:28 +0900 | [diff] [blame] | 39 | CPU_SH7619, | 
| Yoshinori Sato | b229632 | 2006-11-05 16:18:08 +0900 | [diff] [blame] | 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, | 
| Nobuhiro Iwamatsu | 9465a54 | 2007-03-27 18:13:51 +0900 | [diff] [blame] | 47 | CPU_SH7709, CPU_SH7709A, CPU_SH7710, CPU_SH7712, | 
| Markus Brunner | 3ea6bc3 | 2007-08-20 08:59:33 +0900 | [diff] [blame] | 48 | CPU_SH7720, CPU_SH7729, | 
| 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, | 
| Paul Mundt | f966918 | 2007-11-07 11:05:32 +0900 | [diff] [blame] | 52 | CPU_SH7760, 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 | 2b1bd1a | 2007-06-20 18:27:10 +0900 | [diff] [blame] | 55 | CPU_SH7770, CPU_SH7780, CPU_SH7781, CPU_SH7785, CPU_SHX3, | 
| Paul Mundt | 41504c3 | 2006-12-11 20:28:03 +0900 | [diff] [blame] | 56 |  | 
|  | 57 | /* SH4AL-DSP types */ | 
| Magnus Damm | 870e8a2 | 2007-07-25 10:49:21 +0900 | [diff] [blame] | 58 | 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 | 2278caa | 2007-10-30 17:28:52 +0900 | [diff] [blame] | 74 | } __attribute__ ((aligned(L1_CACHE_BYTES))); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 75 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 76 | extern struct sh_cpuinfo cpu_data[]; | 
| Paul Mundt | 2d4a73d | 2007-09-21 18:01:40 +0900 | [diff] [blame] | 77 | #define boot_cpu_data cpu_data[0] | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 78 | #define current_cpu_data cpu_data[smp_processor_id()] | 
| Paul Mundt | 2d4a73d | 2007-09-21 18:01:40 +0900 | [diff] [blame] | 79 | #define raw_current_cpu_data cpu_data[raw_smp_processor_id()] | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 80 |  | 
|  | 81 | /* | 
|  | 82 | * User space process size: 2GB. | 
|  | 83 | * | 
|  | 84 | * Since SH7709 and SH7750 have "area 7", we can't use 0x7c000000--0x7fffffff | 
|  | 85 | */ | 
|  | 86 | #define TASK_SIZE	0x7c000000UL | 
|  | 87 |  | 
|  | 88 | /* This decides where the kernel will search for a free chunk of vm | 
|  | 89 | * space during mmap's. | 
|  | 90 | */ | 
|  | 91 | #define TASK_UNMAPPED_BASE	(TASK_SIZE / 3) | 
|  | 92 |  | 
|  | 93 | /* | 
|  | 94 | * Bit of SR register | 
|  | 95 | * | 
|  | 96 | * FD-bit: | 
|  | 97 | *     When it's set, it means the processor doesn't have right to use FPU, | 
|  | 98 | *     and it results exception when the floating operation is executed. | 
|  | 99 | * | 
|  | 100 | * IMASK-bit: | 
|  | 101 | *     Interrupt level mask | 
|  | 102 | */ | 
|  | 103 | #define SR_FD		0x00008000 | 
|  | 104 | #define SR_DSP		0x00001000 | 
|  | 105 | #define SR_IMASK	0x000000f0 | 
|  | 106 |  | 
|  | 107 | /* | 
|  | 108 | * FPU structure and data | 
|  | 109 | */ | 
|  | 110 |  | 
|  | 111 | struct sh_fpu_hard_struct { | 
|  | 112 | unsigned long fp_regs[16]; | 
|  | 113 | unsigned long xfp_regs[16]; | 
|  | 114 | unsigned long fpscr; | 
|  | 115 | unsigned long fpul; | 
|  | 116 |  | 
|  | 117 | long status; /* software status information */ | 
|  | 118 | }; | 
|  | 119 |  | 
|  | 120 | /* Dummy fpu emulator  */ | 
|  | 121 | struct sh_fpu_soft_struct { | 
|  | 122 | unsigned long fp_regs[16]; | 
|  | 123 | unsigned long xfp_regs[16]; | 
|  | 124 | unsigned long fpscr; | 
|  | 125 | unsigned long fpul; | 
|  | 126 |  | 
|  | 127 | unsigned char lookahead; | 
|  | 128 | unsigned long entry_pc; | 
|  | 129 | }; | 
|  | 130 |  | 
|  | 131 | union sh_fpu_union { | 
|  | 132 | struct sh_fpu_hard_struct hard; | 
|  | 133 | struct sh_fpu_soft_struct soft; | 
|  | 134 | }; | 
|  | 135 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 136 | struct thread_struct { | 
| Stuart Menefy | b5a1bcb | 2006-11-21 13:34:04 +0900 | [diff] [blame] | 137 | /* Saved registers when thread is descheduled */ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 138 | unsigned long sp; | 
|  | 139 | unsigned long pc; | 
|  | 140 |  | 
| Stuart Menefy | b5a1bcb | 2006-11-21 13:34:04 +0900 | [diff] [blame] | 141 | /* Hardware debugging registers */ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 142 | unsigned long ubc_pc; | 
|  | 143 |  | 
|  | 144 | /* floating point info */ | 
|  | 145 | union sh_fpu_union fpu; | 
|  | 146 | }; | 
|  | 147 |  | 
| Paul Mundt | 2991be7 | 2006-09-27 17:07:07 +0900 | [diff] [blame] | 148 | typedef struct { | 
|  | 149 | unsigned long seg; | 
|  | 150 | } mm_segment_t; | 
|  | 151 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 152 | /* Count of active tasks with UBC settings */ | 
|  | 153 | extern int ubc_usercnt; | 
|  | 154 |  | 
|  | 155 | #define INIT_THREAD  {						\ | 
| Stuart Menefy | b5a1bcb | 2006-11-21 13:34:04 +0900 | [diff] [blame] | 156 | .sp = sizeof(init_stack) + (long) &init_stack,		\ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 157 | } | 
|  | 158 |  | 
|  | 159 | /* | 
|  | 160 | * Do necessary setup to start up a newly executed thread. | 
|  | 161 | */ | 
|  | 162 | #define start_thread(regs, new_pc, new_sp)	 \ | 
|  | 163 | set_fs(USER_DS);			 \ | 
| Paul Mundt | de02797 | 2006-02-01 03:06:02 -0800 | [diff] [blame] | 164 | regs->pr = 0;				 \ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 165 | regs->sr = SR_FD;	/* User mode. */ \ | 
|  | 166 | regs->pc = new_pc;			 \ | 
|  | 167 | regs->regs[15] = new_sp | 
|  | 168 |  | 
|  | 169 | /* Forward declaration, a strange C thing */ | 
|  | 170 | struct task_struct; | 
|  | 171 | struct mm_struct; | 
|  | 172 |  | 
|  | 173 | /* Free all resources held by a thread. */ | 
|  | 174 | extern void release_thread(struct task_struct *); | 
|  | 175 |  | 
|  | 176 | /* Prepare to copy thread state - unlazy all lazy status */ | 
|  | 177 | #define prepare_to_copy(tsk)	do { } while (0) | 
|  | 178 |  | 
|  | 179 | /* | 
|  | 180 | * create a kernel thread without removing it from tasklists | 
|  | 181 | */ | 
|  | 182 | extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); | 
|  | 183 |  | 
|  | 184 | /* Copy and release all segment info associated with a VM */ | 
|  | 185 | #define copy_segments(p, mm)	do { } while(0) | 
|  | 186 | #define release_segments(mm)	do { } while(0) | 
|  | 187 |  | 
|  | 188 | /* | 
|  | 189 | * FPU lazy state save handling. | 
|  | 190 | */ | 
|  | 191 |  | 
|  | 192 | static __inline__ void disable_fpu(void) | 
|  | 193 | { | 
|  | 194 | unsigned long __dummy; | 
|  | 195 |  | 
|  | 196 | /* Set FD flag in SR */ | 
|  | 197 | __asm__ __volatile__("stc	sr, %0\n\t" | 
|  | 198 | "or	%1, %0\n\t" | 
|  | 199 | "ldc	%0, sr" | 
|  | 200 | : "=&r" (__dummy) | 
|  | 201 | : "r" (SR_FD)); | 
|  | 202 | } | 
|  | 203 |  | 
|  | 204 | static __inline__ void enable_fpu(void) | 
|  | 205 | { | 
|  | 206 | unsigned long __dummy; | 
|  | 207 |  | 
|  | 208 | /* Clear out FD flag in SR */ | 
|  | 209 | __asm__ __volatile__("stc	sr, %0\n\t" | 
|  | 210 | "and	%1, %0\n\t" | 
|  | 211 | "ldc	%0, sr" | 
|  | 212 | : "=&r" (__dummy) | 
|  | 213 | : "r" (~SR_FD)); | 
|  | 214 | } | 
|  | 215 |  | 
|  | 216 | static __inline__ void release_fpu(struct pt_regs *regs) | 
|  | 217 | { | 
|  | 218 | regs->sr |= SR_FD; | 
|  | 219 | } | 
|  | 220 |  | 
|  | 221 | static __inline__ void grab_fpu(struct pt_regs *regs) | 
|  | 222 | { | 
|  | 223 | regs->sr &= ~SR_FD; | 
|  | 224 | } | 
|  | 225 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 226 | extern void save_fpu(struct task_struct *__tsk, struct pt_regs *regs); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 227 |  | 
| Paul Mundt | de02797 | 2006-02-01 03:06:02 -0800 | [diff] [blame] | 228 | #define unlazy_fpu(tsk, regs) do {			\ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 229 | if (test_tsk_thread_flag(tsk, TIF_USEDFPU)) {	\ | 
| Paul Mundt | de02797 | 2006-02-01 03:06:02 -0800 | [diff] [blame] | 230 | save_fpu(tsk, regs);			\ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 231 | }						\ | 
|  | 232 | } while (0) | 
|  | 233 |  | 
| Paul Mundt | de02797 | 2006-02-01 03:06:02 -0800 | [diff] [blame] | 234 | #define clear_fpu(tsk, regs) do {				\ | 
|  | 235 | if (test_tsk_thread_flag(tsk, TIF_USEDFPU)) {		\ | 
|  | 236 | clear_tsk_thread_flag(tsk, TIF_USEDFPU);	\ | 
|  | 237 | release_fpu(regs);				\ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 238 | }							\ | 
|  | 239 | } while (0) | 
|  | 240 |  | 
|  | 241 | /* Double presision, NANS as NANS, rounding to nearest, no exceptions */ | 
|  | 242 | #define FPSCR_INIT  0x00080000 | 
|  | 243 |  | 
|  | 244 | #define	FPSCR_CAUSE_MASK	0x0001f000	/* Cause bits */ | 
|  | 245 | #define	FPSCR_FLAG_MASK		0x0000007c	/* Flag bits */ | 
|  | 246 |  | 
|  | 247 | /* | 
|  | 248 | * Return saved PC of a blocked thread. | 
|  | 249 | */ | 
|  | 250 | #define thread_saved_pc(tsk)	(tsk->thread.pc) | 
|  | 251 |  | 
| Paul Mundt | 6b00223 | 2006-10-12 17:07:45 +0900 | [diff] [blame] | 252 | void show_trace(struct task_struct *tsk, unsigned long *sp, | 
|  | 253 | struct pt_regs *regs); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 254 | extern unsigned long get_wchan(struct task_struct *p); | 
|  | 255 |  | 
| Stuart Menefy | c9f0b1c | 2006-11-24 12:53:02 +0900 | [diff] [blame] | 256 | #define KSTK_EIP(tsk)  (task_pt_regs(tsk)->pc) | 
|  | 257 | #define KSTK_ESP(tsk)  (task_pt_regs(tsk)->regs[15]) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 258 |  | 
|  | 259 | #define cpu_sleep()	__asm__ __volatile__ ("sleep" : : : "memory") | 
| Chase Venters | f6dc8c5 | 2006-07-08 11:10:29 -0500 | [diff] [blame] | 260 | #define cpu_relax()	barrier() | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 261 |  | 
| Paul Mundt | e86d6b6 | 2006-09-27 14:20:54 +0900 | [diff] [blame] | 262 | #if defined(CONFIG_CPU_SH2A) || defined(CONFIG_CPU_SH3) || \ | 
|  | 263 | defined(CONFIG_CPU_SH4) | 
|  | 264 | #define PREFETCH_STRIDE		L1_CACHE_BYTES | 
|  | 265 | #define ARCH_HAS_PREFETCH | 
|  | 266 | #define ARCH_HAS_PREFETCHW | 
|  | 267 | static inline void prefetch(void *x) | 
|  | 268 | { | 
|  | 269 | __asm__ __volatile__ ("pref @%0\n\t" : : "r" (x) : "memory"); | 
|  | 270 | } | 
|  | 271 |  | 
|  | 272 | #define prefetchw(x)	prefetch(x) | 
|  | 273 | #endif | 
|  | 274 |  | 
| Paul Mundt | 19f9a34 | 2006-09-27 18:33:49 +0900 | [diff] [blame] | 275 | #ifdef CONFIG_VSYSCALL | 
|  | 276 | extern int vsyscall_init(void); | 
|  | 277 | #else | 
|  | 278 | #define vsyscall_init() do { } while (0) | 
|  | 279 | #endif | 
|  | 280 |  | 
| Paul Mundt | 11c1965 | 2006-12-25 10:19:56 +0900 | [diff] [blame] | 281 | /* arch/sh/kernel/setup.c */ | 
|  | 282 | const char *get_cpu_subtype(struct sh_cpuinfo *c); | 
|  | 283 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 284 | #endif /* __KERNEL__ */ | 
|  | 285 | #endif /* __ASM_SH_PROCESSOR_H */ |