| Chris Zankel | 5a0015d | 2005-06-23 22:01:16 -0700 | [diff] [blame] | 1 | /* | 
| Uwe Zeisberger | f30c226 | 2006-10-03 23:01:26 +0200 | [diff] [blame] | 2 |  * arch/xtensa/kernel/setup.c | 
| Chris Zankel | 5a0015d | 2005-06-23 22:01:16 -0700 | [diff] [blame] | 3 |  * | 
 | 4 |  * This file is subject to the terms and conditions of the GNU General Public | 
 | 5 |  * License.  See the file "COPYING" in the main directory of this archive | 
 | 6 |  * for more details. | 
 | 7 |  * | 
 | 8 |  * Copyright (C) 1995  Linus Torvalds | 
 | 9 |  * Copyright (C) 2001 - 2005  Tensilica Inc. | 
 | 10 |  * | 
 | 11 |  * Chris Zankel	<chris@zankel.net> | 
 | 12 |  * Joe Taylor	<joe@tensilica.com, joetylr@yahoo.com> | 
 | 13 |  * Kevin Chea | 
 | 14 |  * Marc Gauthier<marc@tensilica.com> <marc@alumni.uwaterloo.ca> | 
 | 15 |  */ | 
 | 16 |  | 
| Chris Zankel | 5a0015d | 2005-06-23 22:01:16 -0700 | [diff] [blame] | 17 | #include <linux/errno.h> | 
 | 18 | #include <linux/init.h> | 
| Andrea Righi | 27ac792 | 2008-07-23 21:28:13 -0700 | [diff] [blame] | 19 | #include <linux/mm.h> | 
| Chris Zankel | 5a0015d | 2005-06-23 22:01:16 -0700 | [diff] [blame] | 20 | #include <linux/proc_fs.h> | 
| Jon Smirl | 894673e | 2006-07-10 04:44:13 -0700 | [diff] [blame] | 21 | #include <linux/screen_info.h> | 
| Chris Zankel | 5a0015d | 2005-06-23 22:01:16 -0700 | [diff] [blame] | 22 | #include <linux/bootmem.h> | 
 | 23 | #include <linux/kernel.h> | 
 | 24 |  | 
 | 25 | #if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE) | 
 | 26 | # include <linux/console.h> | 
 | 27 | #endif | 
 | 28 |  | 
 | 29 | #ifdef CONFIG_RTC | 
 | 30 | # include <linux/timex.h> | 
 | 31 | #endif | 
 | 32 |  | 
 | 33 | #ifdef CONFIG_PROC_FS | 
 | 34 | # include <linux/seq_file.h> | 
 | 35 | #endif | 
 | 36 |  | 
 | 37 | #include <asm/system.h> | 
 | 38 | #include <asm/bootparam.h> | 
 | 39 | #include <asm/pgtable.h> | 
 | 40 | #include <asm/processor.h> | 
 | 41 | #include <asm/timex.h> | 
 | 42 | #include <asm/platform.h> | 
 | 43 | #include <asm/page.h> | 
 | 44 | #include <asm/setup.h> | 
| Chris Zankel | de4f6e5 | 2007-05-31 17:47:01 -0700 | [diff] [blame] | 45 | #include <asm/param.h> | 
| Chris Zankel | 5a0015d | 2005-06-23 22:01:16 -0700 | [diff] [blame] | 46 |  | 
| Alexey Dobriyan | 5a891ed | 2009-03-10 12:55:49 -0700 | [diff] [blame] | 47 | #include <platform/hardware.h> | 
 | 48 |  | 
| Chris Zankel | 5a0015d | 2005-06-23 22:01:16 -0700 | [diff] [blame] | 49 | #if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE) | 
 | 50 | struct screen_info screen_info = { 0, 24, 0, 0, 0, 80, 0, 0, 0, 24, 1, 16}; | 
 | 51 | #endif | 
 | 52 |  | 
 | 53 | #ifdef CONFIG_BLK_DEV_FD | 
 | 54 | extern struct fd_ops no_fd_ops; | 
 | 55 | struct fd_ops *fd_ops; | 
 | 56 | #endif | 
 | 57 |  | 
| Chris Zankel | 5a0015d | 2005-06-23 22:01:16 -0700 | [diff] [blame] | 58 | extern struct rtc_ops no_rtc_ops; | 
 | 59 | struct rtc_ops *rtc_ops; | 
 | 60 |  | 
| Chris Zankel | 5a0015d | 2005-06-23 22:01:16 -0700 | [diff] [blame] | 61 | #ifdef CONFIG_BLK_DEV_INITRD | 
 | 62 | extern void *initrd_start; | 
 | 63 | extern void *initrd_end; | 
 | 64 | extern void *__initrd_start; | 
 | 65 | extern void *__initrd_end; | 
 | 66 | int initrd_is_mapped = 0; | 
 | 67 | extern int initrd_below_start_ok; | 
 | 68 | #endif | 
 | 69 |  | 
 | 70 | unsigned char aux_device_present; | 
 | 71 | extern unsigned long loops_per_jiffy; | 
 | 72 |  | 
 | 73 | /* Command line specified as configuration option. */ | 
 | 74 |  | 
| Alon Bar-Lev | d3e9cce | 2007-02-12 00:54:25 -0800 | [diff] [blame] | 75 | static char __initdata command_line[COMMAND_LINE_SIZE]; | 
| Chris Zankel | 5a0015d | 2005-06-23 22:01:16 -0700 | [diff] [blame] | 76 |  | 
 | 77 | #ifdef CONFIG_CMDLINE_BOOL | 
 | 78 | static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE; | 
 | 79 | #endif | 
 | 80 |  | 
 | 81 | sysmem_info_t __initdata sysmem; | 
 | 82 |  | 
 | 83 | #ifdef CONFIG_BLK_DEV_INITRD | 
 | 84 | int initrd_is_mapped; | 
 | 85 | #endif | 
 | 86 |  | 
| Johannes Weiner | e5083a6 | 2009-03-04 16:21:31 +0100 | [diff] [blame] | 87 | #ifdef CONFIG_MMU | 
| Chris Zankel | 5a0015d | 2005-06-23 22:01:16 -0700 | [diff] [blame] | 88 | extern void init_mmu(void); | 
| Johannes Weiner | e5083a6 | 2009-03-04 16:21:31 +0100 | [diff] [blame] | 89 | #else | 
 | 90 | static inline void init_mmu(void) { } | 
 | 91 | #endif | 
 | 92 |  | 
 | 93 | extern void zones_init(void); | 
| Chris Zankel | 5a0015d | 2005-06-23 22:01:16 -0700 | [diff] [blame] | 94 |  | 
 | 95 | /* | 
 | 96 |  * Boot parameter parsing. | 
 | 97 |  * | 
 | 98 |  * The Xtensa port uses a list of variable-sized tags to pass data to | 
 | 99 |  * the kernel. The first tag must be a BP_TAG_FIRST tag for the list | 
 | 100 |  * to be recognised. The list is terminated with a zero-sized | 
 | 101 |  * BP_TAG_LAST tag. | 
 | 102 |  */ | 
 | 103 |  | 
 | 104 | typedef struct tagtable { | 
 | 105 | 	u32 tag; | 
 | 106 | 	int (*parse)(const bp_tag_t*); | 
 | 107 | } tagtable_t; | 
 | 108 |  | 
 | 109 | #define __tagtable(tag, fn) static tagtable_t __tagtable_##fn 		\ | 
 | 110 | 	__attribute__((unused, __section__(".taglist"))) = { tag, fn } | 
 | 111 |  | 
 | 112 | /* parse current tag */ | 
 | 113 |  | 
 | 114 | static int __init parse_tag_mem(const bp_tag_t *tag) | 
 | 115 | { | 
 | 116 | 	meminfo_t *mi = (meminfo_t*)(tag->data); | 
 | 117 |  | 
 | 118 | 	if (mi->type != MEMORY_TYPE_CONVENTIONAL) | 
 | 119 | 		return -1; | 
 | 120 |  | 
 | 121 | 	if (sysmem.nr_banks >= SYSMEM_BANKS_MAX) { | 
 | 122 | 		printk(KERN_WARNING | 
 | 123 | 		       "Ignoring memory bank 0x%08lx size %ldKB\n", | 
 | 124 | 		       (unsigned long)mi->start, | 
 | 125 | 		       (unsigned long)mi->end - (unsigned long)mi->start); | 
 | 126 | 		return -EINVAL; | 
 | 127 | 	} | 
 | 128 | 	sysmem.bank[sysmem.nr_banks].type  = mi->type; | 
 | 129 | 	sysmem.bank[sysmem.nr_banks].start = PAGE_ALIGN(mi->start); | 
 | 130 | 	sysmem.bank[sysmem.nr_banks].end   = mi->end & PAGE_SIZE; | 
 | 131 | 	sysmem.nr_banks++; | 
 | 132 |  | 
 | 133 | 	return 0; | 
 | 134 | } | 
 | 135 |  | 
 | 136 | __tagtable(BP_TAG_MEMORY, parse_tag_mem); | 
 | 137 |  | 
 | 138 | #ifdef CONFIG_BLK_DEV_INITRD | 
 | 139 |  | 
 | 140 | static int __init parse_tag_initrd(const bp_tag_t* tag) | 
 | 141 | { | 
 | 142 | 	meminfo_t* mi; | 
 | 143 | 	mi = (meminfo_t*)(tag->data); | 
 | 144 | 	initrd_start = (void*)(mi->start); | 
 | 145 | 	initrd_end = (void*)(mi->end); | 
 | 146 |  | 
 | 147 | 	return 0; | 
 | 148 | } | 
 | 149 |  | 
 | 150 | __tagtable(BP_TAG_INITRD, parse_tag_initrd); | 
 | 151 |  | 
 | 152 | #endif /* CONFIG_BLK_DEV_INITRD */ | 
 | 153 |  | 
 | 154 | static int __init parse_tag_cmdline(const bp_tag_t* tag) | 
 | 155 | { | 
 | 156 | 	strncpy(command_line, (char*)(tag->data), COMMAND_LINE_SIZE); | 
 | 157 | 	command_line[COMMAND_LINE_SIZE - 1] = '\0'; | 
 | 158 | 	return 0; | 
 | 159 | } | 
 | 160 |  | 
 | 161 | __tagtable(BP_TAG_COMMAND_LINE, parse_tag_cmdline); | 
 | 162 |  | 
 | 163 | static int __init parse_bootparam(const bp_tag_t* tag) | 
 | 164 | { | 
 | 165 | 	extern tagtable_t __tagtable_begin, __tagtable_end; | 
 | 166 | 	tagtable_t *t; | 
 | 167 |  | 
 | 168 | 	/* Boot parameters must start with a BP_TAG_FIRST tag. */ | 
 | 169 |  | 
 | 170 | 	if (tag->id != BP_TAG_FIRST) { | 
 | 171 | 		printk(KERN_WARNING "Invalid boot parameters!\n"); | 
 | 172 | 		return 0; | 
 | 173 | 	} | 
 | 174 |  | 
 | 175 | 	tag = (bp_tag_t*)((unsigned long)tag + sizeof(bp_tag_t) + tag->size); | 
 | 176 |  | 
 | 177 | 	/* Parse all tags. */ | 
 | 178 |  | 
 | 179 | 	while (tag != NULL && tag->id != BP_TAG_LAST) { | 
 | 180 | 	 	for (t = &__tagtable_begin; t < &__tagtable_end; t++) { | 
 | 181 | 			if (tag->id == t->tag) { | 
 | 182 | 				t->parse(tag); | 
 | 183 | 				break; | 
 | 184 | 			} | 
 | 185 | 		} | 
 | 186 | 		if (t == &__tagtable_end) | 
 | 187 | 			printk(KERN_WARNING "Ignoring tag " | 
 | 188 | 			       "0x%08x\n", tag->id); | 
 | 189 | 		tag = (bp_tag_t*)((unsigned long)(tag + 1) + tag->size); | 
 | 190 | 	} | 
 | 191 |  | 
 | 192 | 	return 0; | 
 | 193 | } | 
 | 194 |  | 
 | 195 | /* | 
 | 196 |  * Initialize architecture. (Early stage) | 
 | 197 |  */ | 
 | 198 |  | 
 | 199 | void __init init_arch(bp_tag_t *bp_start) | 
 | 200 | { | 
 | 201 |  | 
 | 202 | #ifdef CONFIG_BLK_DEV_INITRD | 
 | 203 | 	initrd_start = &__initrd_start; | 
 | 204 | 	initrd_end = &__initrd_end; | 
 | 205 | #endif | 
 | 206 |  | 
 | 207 | 	sysmem.nr_banks = 0; | 
 | 208 |  | 
 | 209 | #ifdef CONFIG_CMDLINE_BOOL | 
 | 210 | 	strcpy(command_line, default_command_line); | 
 | 211 | #endif | 
 | 212 |  | 
 | 213 | 	/* Parse boot parameters */ | 
 | 214 |  | 
 | 215 |         if (bp_start) | 
 | 216 | 	  parse_bootparam(bp_start); | 
 | 217 |  | 
 | 218 | 	if (sysmem.nr_banks == 0) { | 
 | 219 | 		sysmem.nr_banks = 1; | 
 | 220 | 		sysmem.bank[0].start = PLATFORM_DEFAULT_MEM_START; | 
 | 221 | 		sysmem.bank[0].end = PLATFORM_DEFAULT_MEM_START | 
 | 222 | 				     + PLATFORM_DEFAULT_MEM_SIZE; | 
 | 223 | 	} | 
 | 224 |  | 
 | 225 | 	/* Early hook for platforms */ | 
 | 226 |  | 
 | 227 | 	platform_init(bp_start); | 
 | 228 |  | 
 | 229 | 	/* Initialize MMU. */ | 
 | 230 |  | 
 | 231 | 	init_mmu(); | 
 | 232 | } | 
 | 233 |  | 
 | 234 | /* | 
 | 235 |  * Initialize system. Setup memory and reserve regions. | 
 | 236 |  */ | 
 | 237 |  | 
 | 238 | extern char _end; | 
 | 239 | extern char _stext; | 
 | 240 | extern char _WindowVectors_text_start; | 
 | 241 | extern char _WindowVectors_text_end; | 
 | 242 | extern char _DebugInterruptVector_literal_start; | 
 | 243 | extern char _DebugInterruptVector_text_end; | 
 | 244 | extern char _KernelExceptionVector_literal_start; | 
 | 245 | extern char _KernelExceptionVector_text_end; | 
 | 246 | extern char _UserExceptionVector_literal_start; | 
 | 247 | extern char _UserExceptionVector_text_end; | 
 | 248 | extern char _DoubleExceptionVector_literal_start; | 
 | 249 | extern char _DoubleExceptionVector_text_end; | 
 | 250 |  | 
 | 251 | void __init setup_arch(char **cmdline_p) | 
 | 252 | { | 
 | 253 | 	extern int mem_reserve(unsigned long, unsigned long, int); | 
 | 254 | 	extern void bootmem_init(void); | 
 | 255 |  | 
| Alon Bar-Lev | d3e9cce | 2007-02-12 00:54:25 -0800 | [diff] [blame] | 256 | 	memcpy(boot_command_line, command_line, COMMAND_LINE_SIZE); | 
 | 257 | 	boot_command_line[COMMAND_LINE_SIZE-1] = '\0'; | 
| Chris Zankel | 5a0015d | 2005-06-23 22:01:16 -0700 | [diff] [blame] | 258 | 	*cmdline_p = command_line; | 
 | 259 |  | 
 | 260 | 	/* Reserve some memory regions */ | 
 | 261 |  | 
 | 262 | #ifdef CONFIG_BLK_DEV_INITRD | 
 | 263 | 	if (initrd_start < initrd_end) { | 
 | 264 | 		initrd_is_mapped = mem_reserve(__pa(initrd_start), | 
 | 265 | 					       __pa(initrd_end), 0); | 
 | 266 | 		initrd_below_start_ok = 1; | 
 | 267 |  	} else { | 
 | 268 | 		initrd_start = 0; | 
 | 269 | 	} | 
 | 270 | #endif | 
 | 271 |  | 
 | 272 | 	mem_reserve(__pa(&_stext),__pa(&_end), 1); | 
 | 273 |  | 
 | 274 | 	mem_reserve(__pa(&_WindowVectors_text_start), | 
 | 275 | 		    __pa(&_WindowVectors_text_end), 0); | 
 | 276 |  | 
 | 277 | 	mem_reserve(__pa(&_DebugInterruptVector_literal_start), | 
 | 278 | 		    __pa(&_DebugInterruptVector_text_end), 0); | 
 | 279 |  | 
 | 280 | 	mem_reserve(__pa(&_KernelExceptionVector_literal_start), | 
 | 281 | 		    __pa(&_KernelExceptionVector_text_end), 0); | 
 | 282 |  | 
 | 283 | 	mem_reserve(__pa(&_UserExceptionVector_literal_start), | 
 | 284 | 		    __pa(&_UserExceptionVector_text_end), 0); | 
 | 285 |  | 
 | 286 | 	mem_reserve(__pa(&_DoubleExceptionVector_literal_start), | 
 | 287 | 		    __pa(&_DoubleExceptionVector_text_end), 0); | 
 | 288 |  | 
 | 289 | 	bootmem_init(); | 
 | 290 |  | 
 | 291 | 	platform_setup(cmdline_p); | 
 | 292 |  | 
 | 293 |  | 
 | 294 | 	paging_init(); | 
| Johannes Weiner | e5083a6 | 2009-03-04 16:21:31 +0100 | [diff] [blame] | 295 | 	zones_init(); | 
| Chris Zankel | 5a0015d | 2005-06-23 22:01:16 -0700 | [diff] [blame] | 296 |  | 
 | 297 | #ifdef CONFIG_VT | 
 | 298 | # if defined(CONFIG_VGA_CONSOLE) | 
 | 299 | 	conswitchp = &vga_con; | 
 | 300 | # elif defined(CONFIG_DUMMY_CONSOLE) | 
 | 301 | 	conswitchp = &dummy_con; | 
 | 302 | # endif | 
 | 303 | #endif | 
 | 304 |  | 
| Chris Zankel | 288a60c | 2005-09-22 21:44:23 -0700 | [diff] [blame] | 305 | #ifdef CONFIG_PCI | 
| Chris Zankel | 5a0015d | 2005-06-23 22:01:16 -0700 | [diff] [blame] | 306 | 	platform_pcibios_init(); | 
 | 307 | #endif | 
 | 308 | } | 
 | 309 |  | 
 | 310 | void machine_restart(char * cmd) | 
 | 311 | { | 
 | 312 | 	platform_restart(); | 
 | 313 | } | 
 | 314 |  | 
 | 315 | void machine_halt(void) | 
 | 316 | { | 
 | 317 | 	platform_halt(); | 
 | 318 | 	while (1); | 
 | 319 | } | 
 | 320 |  | 
 | 321 | void machine_power_off(void) | 
 | 322 | { | 
 | 323 | 	platform_power_off(); | 
 | 324 | 	while (1); | 
 | 325 | } | 
 | 326 | #ifdef CONFIG_PROC_FS | 
 | 327 |  | 
 | 328 | /* | 
 | 329 |  * Display some core information through /proc/cpuinfo. | 
 | 330 |  */ | 
 | 331 |  | 
 | 332 | static int | 
 | 333 | c_show(struct seq_file *f, void *slot) | 
 | 334 | { | 
 | 335 | 	/* high-level stuff */ | 
 | 336 | 	seq_printf(f,"processor\t: 0\n" | 
 | 337 | 		     "vendor_id\t: Tensilica\n" | 
| Chris Zankel | 173d668 | 2006-12-10 02:18:48 -0800 | [diff] [blame] | 338 | 		     "model\t\t: Xtensa " XCHAL_HW_VERSION_NAME "\n" | 
| Chris Zankel | 5a0015d | 2005-06-23 22:01:16 -0700 | [diff] [blame] | 339 | 		     "core ID\t\t: " XCHAL_CORE_ID "\n" | 
 | 340 | 		     "build ID\t: 0x%x\n" | 
 | 341 | 		     "byte order\t: %s\n" | 
 | 342 |  		     "cpu MHz\t\t: %lu.%02lu\n" | 
 | 343 | 		     "bogomips\t: %lu.%02lu\n", | 
 | 344 | 		     XCHAL_BUILD_UNIQUE_ID, | 
 | 345 | 		     XCHAL_HAVE_BE ?  "big" : "little", | 
 | 346 | 		     CCOUNT_PER_JIFFY/(1000000/HZ), | 
 | 347 | 		     (CCOUNT_PER_JIFFY/(10000/HZ)) % 100, | 
 | 348 | 		     loops_per_jiffy/(500000/HZ), | 
 | 349 | 		     (loops_per_jiffy/(5000/HZ)) % 100); | 
 | 350 |  | 
 | 351 | 	seq_printf(f,"flags\t\t: " | 
 | 352 | #if XCHAL_HAVE_NMI | 
 | 353 | 		     "nmi " | 
 | 354 | #endif | 
 | 355 | #if XCHAL_HAVE_DEBUG | 
 | 356 | 		     "debug " | 
 | 357 | # if XCHAL_HAVE_OCD | 
 | 358 | 		     "ocd " | 
 | 359 | # endif | 
 | 360 | #endif | 
 | 361 | #if XCHAL_HAVE_DENSITY | 
 | 362 | 	    	     "density " | 
 | 363 | #endif | 
 | 364 | #if XCHAL_HAVE_BOOLEANS | 
 | 365 | 		     "boolean " | 
 | 366 | #endif | 
 | 367 | #if XCHAL_HAVE_LOOPS | 
 | 368 | 		     "loop " | 
 | 369 | #endif | 
 | 370 | #if XCHAL_HAVE_NSA | 
 | 371 | 		     "nsa " | 
 | 372 | #endif | 
 | 373 | #if XCHAL_HAVE_MINMAX | 
 | 374 | 		     "minmax " | 
 | 375 | #endif | 
 | 376 | #if XCHAL_HAVE_SEXT | 
 | 377 | 		     "sext " | 
 | 378 | #endif | 
 | 379 | #if XCHAL_HAVE_CLAMPS | 
 | 380 | 		     "clamps " | 
 | 381 | #endif | 
 | 382 | #if XCHAL_HAVE_MAC16 | 
 | 383 | 		     "mac16 " | 
 | 384 | #endif | 
 | 385 | #if XCHAL_HAVE_MUL16 | 
 | 386 | 		     "mul16 " | 
 | 387 | #endif | 
 | 388 | #if XCHAL_HAVE_MUL32 | 
 | 389 | 		     "mul32 " | 
 | 390 | #endif | 
 | 391 | #if XCHAL_HAVE_MUL32_HIGH | 
 | 392 | 		     "mul32h " | 
 | 393 | #endif | 
 | 394 | #if XCHAL_HAVE_FP | 
 | 395 | 		     "fpu " | 
 | 396 | #endif | 
 | 397 | 		     "\n"); | 
 | 398 |  | 
 | 399 | 	/* Registers. */ | 
 | 400 | 	seq_printf(f,"physical aregs\t: %d\n" | 
 | 401 | 		     "misc regs\t: %d\n" | 
 | 402 | 		     "ibreak\t\t: %d\n" | 
 | 403 | 		     "dbreak\t\t: %d\n", | 
 | 404 | 		     XCHAL_NUM_AREGS, | 
 | 405 | 		     XCHAL_NUM_MISC_REGS, | 
 | 406 | 		     XCHAL_NUM_IBREAK, | 
 | 407 | 		     XCHAL_NUM_DBREAK); | 
 | 408 |  | 
 | 409 |  | 
 | 410 | 	/* Interrupt. */ | 
 | 411 | 	seq_printf(f,"num ints\t: %d\n" | 
 | 412 | 		     "ext ints\t: %d\n" | 
 | 413 | 		     "int levels\t: %d\n" | 
 | 414 | 		     "timers\t\t: %d\n" | 
 | 415 | 		     "debug level\t: %d\n", | 
 | 416 | 		     XCHAL_NUM_INTERRUPTS, | 
 | 417 | 		     XCHAL_NUM_EXTINTERRUPTS, | 
 | 418 | 		     XCHAL_NUM_INTLEVELS, | 
 | 419 | 		     XCHAL_NUM_TIMERS, | 
 | 420 | 		     XCHAL_DEBUGLEVEL); | 
 | 421 |  | 
| Chris Zankel | 5a0015d | 2005-06-23 22:01:16 -0700 | [diff] [blame] | 422 | 	/* Cache */ | 
 | 423 | 	seq_printf(f,"icache line size: %d\n" | 
 | 424 | 		     "icache ways\t: %d\n" | 
 | 425 | 		     "icache size\t: %d\n" | 
 | 426 | 		     "icache flags\t: " | 
 | 427 | #if XCHAL_ICACHE_LINE_LOCKABLE | 
 | 428 | 		     "lock" | 
 | 429 | #endif | 
 | 430 | 		     "\n" | 
 | 431 | 		     "dcache line size: %d\n" | 
 | 432 | 		     "dcache ways\t: %d\n" | 
 | 433 | 		     "dcache size\t: %d\n" | 
 | 434 | 		     "dcache flags\t: " | 
 | 435 | #if XCHAL_DCACHE_IS_WRITEBACK | 
 | 436 | 		     "writeback" | 
 | 437 | #endif | 
 | 438 | #if XCHAL_DCACHE_LINE_LOCKABLE | 
 | 439 | 		     "lock" | 
 | 440 | #endif | 
 | 441 | 		     "\n", | 
 | 442 | 		     XCHAL_ICACHE_LINESIZE, | 
 | 443 | 		     XCHAL_ICACHE_WAYS, | 
 | 444 | 		     XCHAL_ICACHE_SIZE, | 
 | 445 | 		     XCHAL_DCACHE_LINESIZE, | 
 | 446 | 		     XCHAL_DCACHE_WAYS, | 
 | 447 | 		     XCHAL_DCACHE_SIZE); | 
 | 448 |  | 
| Chris Zankel | 5a0015d | 2005-06-23 22:01:16 -0700 | [diff] [blame] | 449 | 	return 0; | 
 | 450 | } | 
 | 451 |  | 
 | 452 | /* | 
 | 453 |  * We show only CPU #0 info. | 
 | 454 |  */ | 
 | 455 | static void * | 
 | 456 | c_start(struct seq_file *f, loff_t *pos) | 
 | 457 | { | 
 | 458 | 	return (void *) ((*pos == 0) ? (void *)1 : NULL); | 
 | 459 | } | 
 | 460 |  | 
 | 461 | static void * | 
 | 462 | c_next(struct seq_file *f, void *v, loff_t *pos) | 
 | 463 | { | 
 | 464 | 	return NULL; | 
 | 465 | } | 
 | 466 |  | 
 | 467 | static void | 
 | 468 | c_stop(struct seq_file *f, void *v) | 
 | 469 | { | 
 | 470 | } | 
 | 471 |  | 
| Jan Engelhardt | 03a4482 | 2008-02-08 04:21:19 -0800 | [diff] [blame] | 472 | const struct seq_operations cpuinfo_op = | 
| Chris Zankel | 5a0015d | 2005-06-23 22:01:16 -0700 | [diff] [blame] | 473 | { | 
 | 474 | 	start:  c_start, | 
 | 475 | 	next:   c_next, | 
 | 476 | 	stop:   c_stop, | 
 | 477 | 	show:   c_show | 
 | 478 | }; | 
 | 479 |  | 
 | 480 | #endif /* CONFIG_PROC_FS */ | 
 | 481 |  |