138889Sjdp/* 238889Sjdp * arch/xtensa/kernel/setup.c 3218822Sdim * 4218822Sdim * This file is subject to the terms and conditions of the GNU General Public 5218822Sdim * License. See the file "COPYING" in the main directory of this archive 6130561Sobrien * for more details. 7130561Sobrien * 8130561Sobrien * Copyright (C) 1995 Linus Torvalds 938889Sjdp * Copyright (C) 2001 - 2005 Tensilica Inc. 10130561Sobrien * Copyright (C) 2014 - 2016 Cadence Design Systems Inc. 1138889Sjdp * 12130561Sobrien * Chris Zankel <chris@zankel.net> 13130561Sobrien * Joe Taylor <joe@tensilica.com, joetylr@yahoo.com> 14130561Sobrien * Kevin Chea 15130561Sobrien * Marc Gauthier<marc@tensilica.com> <marc@alumni.uwaterloo.ca> 16130561Sobrien */ 17130561Sobrien 18130561Sobrien#include <linux/errno.h> 19130561Sobrien#include <linux/init.h> 20130561Sobrien#include <linux/mm.h> 21130561Sobrien#include <linux/proc_fs.h> 22130561Sobrien#include <linux/kernel.h> 23130561Sobrien#include <linux/percpu.h> 24130561Sobrien#include <linux/reboot.h> 25130561Sobrien#include <linux/cpu.h> 26130561Sobrien#include <linux/of.h> 27130561Sobrien#include <linux/of_fdt.h> 28130561Sobrien 29130561Sobrien#if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE) 30130561Sobrien# include <linux/console.h> 31130561Sobrien#endif 32130561Sobrien 33130561Sobrien#ifdef CONFIG_PROC_FS 34130561Sobrien# include <linux/seq_file.h> 35130561Sobrien#endif 36130561Sobrien 3738889Sjdp#include <asm/bootparam.h> 3838889Sjdp#include <asm/kasan.h> 3938889Sjdp#include <asm/mmu_context.h> 4038889Sjdp#include <asm/page.h> 4138889Sjdp#include <asm/param.h> 4238889Sjdp#include <asm/platform.h> 4338889Sjdp#include <asm/processor.h> 4438889Sjdp#include <asm/sections.h> 4538889Sjdp#include <asm/setup.h> 4638889Sjdp#include <asm/smp.h> 4738889Sjdp#include <asm/sysmem.h> 4838889Sjdp#include <asm/timex.h> 4938889Sjdp#include <asm/traps.h> 5038889Sjdp 5138889Sjdp#ifdef CONFIG_BLK_DEV_INITRD 5238889Sjdpextern unsigned long initrd_start; 5338889Sjdpextern unsigned long initrd_end; 5438889Sjdpextern int initrd_below_start_ok; 5538889Sjdp#endif 5638889Sjdp 5738889Sjdp#ifdef CONFIG_USE_OF 5838889Sjdpvoid *dtb_start = __dtb_start; 5938889Sjdp#endif 6038889Sjdp 6138889Sjdpextern unsigned long loops_per_jiffy; 62218822Sdim 63218822Sdim/* Command line specified as configuration option. */ 64218822Sdim 6538889Sjdpstatic char __initdata command_line[COMMAND_LINE_SIZE]; 6638889Sjdp 67218822Sdim#ifdef CONFIG_CMDLINE_BOOL 68218822Sdimstatic char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE; 69218822Sdim#endif 70218822Sdim 71218822Sdim#ifdef CONFIG_PARSE_BOOTPARAM 7238889Sjdp/* 73218822Sdim * Boot parameter parsing. 74218822Sdim * 75218822Sdim * The Xtensa port uses a list of variable-sized tags to pass data to 76218822Sdim * the kernel. The first tag must be a BP_TAG_FIRST tag for the list 7738889Sjdp * to be recognised. The list is terminated with a zero-sized 78218822Sdim * BP_TAG_LAST tag. 79218822Sdim */ 80218822Sdim 8138889Sjdptypedef struct tagtable { 82218822Sdim u32 tag; 83218822Sdim int (*parse)(const bp_tag_t*); 84218822Sdim} tagtable_t; 85218822Sdim 86218822Sdim#define __tagtable(tag, fn) static tagtable_t __tagtable_##fn \ 87218822Sdim __section(".taglist") __attribute__((used)) = { tag, fn } 88218822Sdim 89218822Sdim/* parse current tag */ 90218822Sdim 91218822Sdimstatic int __init parse_tag_mem(const bp_tag_t *tag) 92218822Sdim{ 9338889Sjdp struct bp_meminfo *mi = (struct bp_meminfo *)(tag->data); 94218822Sdim 95218822Sdim if (mi->type != MEMORY_TYPE_CONVENTIONAL) 96218822Sdim return -1; 9738889Sjdp 98218822Sdim return memblock_add(mi->start, mi->end - mi->start); 99218822Sdim} 100218822Sdim 101218822Sdim__tagtable(BP_TAG_MEMORY, parse_tag_mem); 10238889Sjdp 103218822Sdim#ifdef CONFIG_BLK_DEV_INITRD 104218822Sdim 105218822Sdimstatic int __init parse_tag_initrd(const bp_tag_t* tag) 10638889Sjdp{ 107218822Sdim struct bp_meminfo *mi = (struct bp_meminfo *)(tag->data); 108218822Sdim 109218822Sdim initrd_start = (unsigned long)__va(mi->start); 110218822Sdim initrd_end = (unsigned long)__va(mi->end); 11138889Sjdp 112218822Sdim return 0; 11338889Sjdp} 114218822Sdim 115218822Sdim__tagtable(BP_TAG_INITRD, parse_tag_initrd); 116218822Sdim 117218822Sdim#endif /* CONFIG_BLK_DEV_INITRD */ 11838889Sjdp 119218822Sdim#ifdef CONFIG_USE_OF 120218822Sdim 121218822Sdimstatic int __init parse_tag_fdt(const bp_tag_t *tag) 122218822Sdim{ 12338889Sjdp dtb_start = __va(tag->data[0]); 124218822Sdim return 0; 125218822Sdim} 126218822Sdim 127130561Sobrien__tagtable(BP_TAG_FDT, parse_tag_fdt); 128218822Sdim 129218822Sdim#endif /* CONFIG_USE_OF */ 130218822Sdim 131218822Sdimstatic int __init parse_tag_cmdline(const bp_tag_t* tag) 13238889Sjdp{ 133218822Sdim strscpy(command_line, (char *)(tag->data), COMMAND_LINE_SIZE); 134218822Sdim return 0; 135218822Sdim} 13638889Sjdp 137218822Sdim__tagtable(BP_TAG_COMMAND_LINE, parse_tag_cmdline); 138130561Sobrien 139218822Sdimstatic int __init parse_bootparam(const bp_tag_t* tag) 140218822Sdim{ 141218822Sdim extern tagtable_t __tagtable_begin, __tagtable_end; 142218822Sdim tagtable_t *t; 143218822Sdim 144218822Sdim /* Boot parameters must start with a BP_TAG_FIRST tag. */ 145218822Sdim 146218822Sdim if (tag->id != BP_TAG_FIRST) { 147218822Sdim pr_warn("Invalid boot parameters!\n"); 148218822Sdim return 0; 149218822Sdim } 150218822Sdim 151218822Sdim tag = (bp_tag_t*)((unsigned long)tag + sizeof(bp_tag_t) + tag->size); 152218822Sdim 153218822Sdim /* Parse all tags. */ 154218822Sdim 155218822Sdim while (tag != NULL && tag->id != BP_TAG_LAST) { 15638889Sjdp for (t = &__tagtable_begin; t < &__tagtable_end; t++) { 157218822Sdim if (tag->id == t->tag) { 158218822Sdim t->parse(tag); 159218822Sdim break; 160218822Sdim } 161218822Sdim } 162218822Sdim if (t == &__tagtable_end) 163218822Sdim pr_warn("Ignoring tag 0x%08x\n", tag->id); 164218822Sdim tag = (bp_tag_t*)((unsigned long)(tag + 1) + tag->size); 16538889Sjdp } 16638889Sjdp 167218822Sdim return 0; 168218822Sdim} 169218822Sdim#else 170218822Sdimstatic int __init parse_bootparam(const bp_tag_t *tag) 171218822Sdim{ 172218822Sdim pr_info("Ignoring boot parameters at %p\n", tag); 17338889Sjdp return 0; 174218822Sdim} 175218822Sdim#endif 176218822Sdim 17738889Sjdp#ifdef CONFIG_USE_OF 178218822Sdim 179218822Sdim#if !XCHAL_HAVE_PTP_MMU || XCHAL_HAVE_SPANNING_WAY 180218822Sdimunsigned long xtensa_kio_paddr = XCHAL_KIO_DEFAULT_PADDR; 181218822SdimEXPORT_SYMBOL(xtensa_kio_paddr); 182218822Sdim 183218822Sdimstatic int __init xtensa_dt_io_area(unsigned long node, const char *uname, 184218822Sdim int depth, void *data) 185218822Sdim{ 186218822Sdim const __be32 *ranges; 187218822Sdim int len; 188218822Sdim 189218822Sdim if (depth > 1) 190218822Sdim return 0; 191218822Sdim 19238889Sjdp if (!of_flat_dt_is_compatible(node, "simple-bus")) 193218822Sdim return 0; 194218822Sdim 195218822Sdim ranges = of_get_flat_dt_prop(node, "ranges", &len); 196218822Sdim if (!ranges) 19738889Sjdp return 1; 198218822Sdim if (len == 0) 199218822Sdim return 1; 200218822Sdim 201218822Sdim xtensa_kio_paddr = of_read_ulong(ranges+1, 1); 202218822Sdim /* round down to nearest 256MB boundary */ 20338889Sjdp xtensa_kio_paddr &= 0xf0000000; 204218822Sdim 205218822Sdim init_kio(); 206218822Sdim 207218822Sdim return 1; 208218822Sdim} 209218822Sdim#else 210218822Sdimstatic int __init xtensa_dt_io_area(unsigned long node, const char *uname, 211218822Sdim int depth, void *data) 212218822Sdim{ 213218822Sdim return 1; 21438889Sjdp} 215218822Sdim#endif 216218822Sdim 21738889Sjdpvoid __init early_init_devtree(void *params) 218218822Sdim{ 21938889Sjdp early_init_dt_scan(params); 220218822Sdim of_scan_flat_dt(xtensa_dt_io_area, NULL); 221218822Sdim 222218822Sdim if (!command_line[0]) 223218822Sdim strscpy(command_line, boot_command_line, COMMAND_LINE_SIZE); 224218822Sdim} 22538889Sjdp 226218822Sdim#endif /* CONFIG_USE_OF */ 227218822Sdim 228218822Sdim/* 229218822Sdim * Initialize architecture. (Early stage) 230218822Sdim */ 231218822Sdim 23238889Sjdpvoid __init init_arch(bp_tag_t *bp_start) 233218822Sdim{ 23438889Sjdp /* Initialize basic exception handling if configuration may need it */ 235218822Sdim 236218822Sdim if (IS_ENABLED(CONFIG_KASAN) || 237218822Sdim IS_ENABLED(CONFIG_XTENSA_LOAD_STORE)) 238218822Sdim early_trap_init(); 239218822Sdim 240218822Sdim /* Initialize MMU. */ 241218822Sdim 242218822Sdim init_mmu(); 243218822Sdim 244218822Sdim /* Initialize initial KASAN shadow map */ 245218822Sdim 246218822Sdim kasan_early_init(); 247218822Sdim 24838889Sjdp /* Parse boot parameters */ 249218822Sdim 250218822Sdim if (bp_start) 251218822Sdim parse_bootparam(bp_start); 252218822Sdim 253218822Sdim#ifdef CONFIG_USE_OF 254218822Sdim early_init_devtree(dtb_start); 25538889Sjdp#endif 256218822Sdim 257218822Sdim#ifdef CONFIG_CMDLINE_BOOL 25838889Sjdp if (!command_line[0]) 259218822Sdim strscpy(command_line, default_command_line, COMMAND_LINE_SIZE); 260218822Sdim#endif 261218822Sdim 26238889Sjdp /* Early hook for platforms */ 263218822Sdim 264218822Sdim platform_init(bp_start); 265218822Sdim} 26638889Sjdp 267218822Sdim/* 268218822Sdim * Initialize system. Setup memory and reserve regions. 269130561Sobrien */ 270218822Sdim 271218822Sdimstatic inline int __init_memblock mem_reserve(unsigned long start, 272218822Sdim unsigned long end) 273218822Sdim{ 274218822Sdim return memblock_reserve(start, end - start); 275218822Sdim} 276218822Sdim 277218822Sdimvoid __init setup_arch(char **cmdline_p) 278218822Sdim{ 279218822Sdim pr_info("config ID: %08x:%08x\n", 280130561Sobrien xtensa_get_sr(SREG_EPC), xtensa_get_sr(SREG_EXCSAVE)); 281218822Sdim if (xtensa_get_sr(SREG_EPC) != XCHAL_HW_CONFIGID0 || 282218822Sdim xtensa_get_sr(SREG_EXCSAVE) != XCHAL_HW_CONFIGID1) 283218822Sdim pr_info("built for config ID: %08x:%08x\n", 284218822Sdim XCHAL_HW_CONFIGID0, XCHAL_HW_CONFIGID1); 285218822Sdim 286218822Sdim *cmdline_p = command_line; 28738889Sjdp platform_setup(cmdline_p); 288218822Sdim strscpy(boot_command_line, *cmdline_p, COMMAND_LINE_SIZE); 289218822Sdim 290218822Sdim /* Reserve some memory regions */ 291218822Sdim 292218822Sdim#ifdef CONFIG_BLK_DEV_INITRD 293218822Sdim if (initrd_start < initrd_end && 294218822Sdim !mem_reserve(__pa(initrd_start), __pa(initrd_end))) 295218822Sdim initrd_below_start_ok = 1; 296218822Sdim else 297218822Sdim initrd_start = 0; 298218822Sdim#endif 299218822Sdim 300218822Sdim mem_reserve(__pa(_stext), __pa(_end)); 301218822Sdim#ifdef CONFIG_XIP_KERNEL 302218822Sdim#ifdef CONFIG_VECTORS_ADDR 303218822Sdim mem_reserve(__pa(_xip_text_start), __pa(_xip_text_end)); 304218822Sdim#endif 30538889Sjdp mem_reserve(__pa(_xip_start), __pa(_xip_end)); 306218822Sdim#endif 307218822Sdim 308218822Sdim#ifdef CONFIG_VECTORS_ADDR 309218822Sdim#ifdef SUPPORT_WINDOWED 310218822Sdim mem_reserve(__pa(_WindowVectors_text_start), 311218822Sdim __pa(_WindowVectors_text_end)); 31238889Sjdp#endif 313130561Sobrien 314130561Sobrien mem_reserve(__pa(_DebugInterruptVector_text_start), 315218822Sdim __pa(_DebugInterruptVector_text_end)); 316130561Sobrien 317218822Sdim mem_reserve(__pa(_KernelExceptionVector_text_start), 318218822Sdim __pa(_KernelExceptionVector_text_end)); 319218822Sdim 320218822Sdim mem_reserve(__pa(_UserExceptionVector_text_start), 321218822Sdim __pa(_UserExceptionVector_text_end)); 322218822Sdim 323218822Sdim mem_reserve(__pa(_DoubleExceptionVector_text_start), 324 __pa(_DoubleExceptionVector_text_end)); 325 326 mem_reserve(__pa(_exception_text_start), 327 __pa(_exception_text_end)); 328#if XCHAL_EXCM_LEVEL >= 2 329 mem_reserve(__pa(_Level2InterruptVector_text_start), 330 __pa(_Level2InterruptVector_text_end)); 331#endif 332#if XCHAL_EXCM_LEVEL >= 3 333 mem_reserve(__pa(_Level3InterruptVector_text_start), 334 __pa(_Level3InterruptVector_text_end)); 335#endif 336#if XCHAL_EXCM_LEVEL >= 4 337 mem_reserve(__pa(_Level4InterruptVector_text_start), 338 __pa(_Level4InterruptVector_text_end)); 339#endif 340#if XCHAL_EXCM_LEVEL >= 5 341 mem_reserve(__pa(_Level5InterruptVector_text_start), 342 __pa(_Level5InterruptVector_text_end)); 343#endif 344#if XCHAL_EXCM_LEVEL >= 6 345 mem_reserve(__pa(_Level6InterruptVector_text_start), 346 __pa(_Level6InterruptVector_text_end)); 347#endif 348 349#endif /* CONFIG_VECTORS_ADDR */ 350 351#ifdef CONFIG_SECONDARY_RESET_VECTOR 352 mem_reserve(__pa(_SecondaryResetVector_text_start), 353 __pa(_SecondaryResetVector_text_end)); 354#endif 355 parse_early_param(); 356 bootmem_init(); 357 kasan_init(); 358 unflatten_and_copy_device_tree(); 359 360#ifdef CONFIG_SMP 361 smp_init_cpus(); 362#endif 363 364 paging_init(); 365 zones_init(); 366 367#ifdef CONFIG_VT 368# if defined(CONFIG_VGA_CONSOLE) 369 conswitchp = &vga_con; 370# endif 371#endif 372} 373 374static DEFINE_PER_CPU(struct cpu, cpu_data); 375 376static int __init topology_init(void) 377{ 378 int i; 379 380 for_each_possible_cpu(i) { 381 struct cpu *cpu = &per_cpu(cpu_data, i); 382 cpu->hotpluggable = !!i; 383 register_cpu(cpu, i); 384 } 385 386 return 0; 387} 388subsys_initcall(topology_init); 389 390void cpu_reset(void) 391{ 392#if XCHAL_HAVE_PTP_MMU && IS_ENABLED(CONFIG_MMU) 393 local_irq_disable(); 394 /* 395 * We have full MMU: all autoload ways, ways 7, 8 and 9 of DTLB must 396 * be flushed. 397 * Way 4 is not currently used by linux. 398 * Ways 5 and 6 shall not be touched on MMUv2 as they are hardwired. 399 * Way 5 shall be flushed and way 6 shall be set to identity mapping 400 * on MMUv3. 401 */ 402 local_flush_tlb_all(); 403 invalidate_page_directory(); 404#if XCHAL_HAVE_SPANNING_WAY 405 /* MMU v3 */ 406 { 407 unsigned long vaddr = (unsigned long)cpu_reset; 408 unsigned long paddr = __pa(vaddr); 409 unsigned long tmpaddr = vaddr + SZ_512M; 410 unsigned long tmp0, tmp1, tmp2, tmp3; 411 412 /* 413 * Find a place for the temporary mapping. It must not be 414 * in the same 512MB region with vaddr or paddr, otherwise 415 * there may be multihit exception either on entry to the 416 * temporary mapping, or on entry to the identity mapping. 417 * (512MB is the biggest page size supported by TLB.) 418 */ 419 while (((tmpaddr ^ paddr) & -SZ_512M) == 0) 420 tmpaddr += SZ_512M; 421 422 /* Invalidate mapping in the selected temporary area */ 423 if (itlb_probe(tmpaddr) & BIT(ITLB_HIT_BIT)) 424 invalidate_itlb_entry(itlb_probe(tmpaddr)); 425 if (itlb_probe(tmpaddr + PAGE_SIZE) & BIT(ITLB_HIT_BIT)) 426 invalidate_itlb_entry(itlb_probe(tmpaddr + PAGE_SIZE)); 427 428 /* 429 * Map two consecutive pages starting at the physical address 430 * of this function to the temporary mapping area. 431 */ 432 write_itlb_entry(__pte((paddr & PAGE_MASK) | 433 _PAGE_HW_VALID | 434 _PAGE_HW_EXEC | 435 _PAGE_CA_BYPASS), 436 tmpaddr & PAGE_MASK); 437 write_itlb_entry(__pte(((paddr & PAGE_MASK) + PAGE_SIZE) | 438 _PAGE_HW_VALID | 439 _PAGE_HW_EXEC | 440 _PAGE_CA_BYPASS), 441 (tmpaddr & PAGE_MASK) + PAGE_SIZE); 442 443 /* Reinitialize TLB */ 444 __asm__ __volatile__ ("movi %0, 1f\n\t" 445 "movi %3, 2f\n\t" 446 "add %0, %0, %4\n\t" 447 "add %3, %3, %5\n\t" 448 "jx %0\n" 449 /* 450 * No literal, data or stack access 451 * below this point 452 */ 453 "1:\n\t" 454 /* Initialize *tlbcfg */ 455 "movi %0, 0\n\t" 456 "wsr %0, itlbcfg\n\t" 457 "wsr %0, dtlbcfg\n\t" 458 /* Invalidate TLB way 5 */ 459 "movi %0, 4\n\t" 460 "movi %1, 5\n" 461 "1:\n\t" 462 "iitlb %1\n\t" 463 "idtlb %1\n\t" 464 "add %1, %1, %6\n\t" 465 "addi %0, %0, -1\n\t" 466 "bnez %0, 1b\n\t" 467 /* Initialize TLB way 6 */ 468 "movi %0, 7\n\t" 469 "addi %1, %9, 3\n\t" 470 "addi %2, %9, 6\n" 471 "1:\n\t" 472 "witlb %1, %2\n\t" 473 "wdtlb %1, %2\n\t" 474 "add %1, %1, %7\n\t" 475 "add %2, %2, %7\n\t" 476 "addi %0, %0, -1\n\t" 477 "bnez %0, 1b\n\t" 478 "isync\n\t" 479 /* Jump to identity mapping */ 480 "jx %3\n" 481 "2:\n\t" 482 /* Complete way 6 initialization */ 483 "witlb %1, %2\n\t" 484 "wdtlb %1, %2\n\t" 485 /* Invalidate temporary mapping */ 486 "sub %0, %9, %7\n\t" 487 "iitlb %0\n\t" 488 "add %0, %0, %8\n\t" 489 "iitlb %0" 490 : "=&a"(tmp0), "=&a"(tmp1), "=&a"(tmp2), 491 "=&a"(tmp3) 492 : "a"(tmpaddr - vaddr), 493 "a"(paddr - vaddr), 494 "a"(SZ_128M), "a"(SZ_512M), 495 "a"(PAGE_SIZE), 496 "a"((tmpaddr + SZ_512M) & PAGE_MASK) 497 : "memory"); 498 } 499#endif 500#endif 501 __asm__ __volatile__ ("movi a2, 0\n\t" 502 "wsr a2, icountlevel\n\t" 503 "movi a2, 0\n\t" 504 "wsr a2, icount\n\t" 505#if XCHAL_NUM_IBREAK > 0 506 "wsr a2, ibreakenable\n\t" 507#endif 508#if XCHAL_HAVE_LOOPS 509 "wsr a2, lcount\n\t" 510#endif 511 "movi a2, 0x1f\n\t" 512 "wsr a2, ps\n\t" 513 "isync\n\t" 514 "jx %0\n\t" 515 : 516 : "a" (XCHAL_RESET_VECTOR_VADDR) 517 : "a2"); 518 for (;;) 519 ; 520} 521 522void machine_restart(char * cmd) 523{ 524 local_irq_disable(); 525 smp_send_stop(); 526 do_kernel_restart(cmd); 527 pr_err("Reboot failed -- System halted\n"); 528 while (1) 529 cpu_relax(); 530} 531 532void machine_halt(void) 533{ 534 local_irq_disable(); 535 smp_send_stop(); 536 do_kernel_power_off(); 537 while (1) 538 cpu_relax(); 539} 540 541void machine_power_off(void) 542{ 543 local_irq_disable(); 544 smp_send_stop(); 545 do_kernel_power_off(); 546 while (1) 547 cpu_relax(); 548} 549#ifdef CONFIG_PROC_FS 550 551/* 552 * Display some core information through /proc/cpuinfo. 553 */ 554 555static int 556c_show(struct seq_file *f, void *slot) 557{ 558 /* high-level stuff */ 559 seq_printf(f, "CPU count\t: %u\n" 560 "CPU list\t: %*pbl\n" 561 "vendor_id\t: Tensilica\n" 562 "model\t\t: Xtensa " XCHAL_HW_VERSION_NAME "\n" 563 "core ID\t\t: " XCHAL_CORE_ID "\n" 564 "build ID\t: 0x%x\n" 565 "config ID\t: %08x:%08x\n" 566 "byte order\t: %s\n" 567 "cpu MHz\t\t: %lu.%02lu\n" 568 "bogomips\t: %lu.%02lu\n", 569 num_online_cpus(), 570 cpumask_pr_args(cpu_online_mask), 571 XCHAL_BUILD_UNIQUE_ID, 572 xtensa_get_sr(SREG_EPC), xtensa_get_sr(SREG_EXCSAVE), 573 XCHAL_HAVE_BE ? "big" : "little", 574 ccount_freq/1000000, 575 (ccount_freq/10000) % 100, 576 loops_per_jiffy/(500000/HZ), 577 (loops_per_jiffy/(5000/HZ)) % 100); 578 seq_puts(f, "flags\t\t: " 579#if XCHAL_HAVE_NMI 580 "nmi " 581#endif 582#if XCHAL_HAVE_DEBUG 583 "debug " 584# if XCHAL_HAVE_OCD 585 "ocd " 586# endif 587#if XCHAL_HAVE_TRAX 588 "trax " 589#endif 590#if XCHAL_NUM_PERF_COUNTERS 591 "perf " 592#endif 593#endif 594#if XCHAL_HAVE_DENSITY 595 "density " 596#endif 597#if XCHAL_HAVE_BOOLEANS 598 "boolean " 599#endif 600#if XCHAL_HAVE_LOOPS 601 "loop " 602#endif 603#if XCHAL_HAVE_NSA 604 "nsa " 605#endif 606#if XCHAL_HAVE_MINMAX 607 "minmax " 608#endif 609#if XCHAL_HAVE_SEXT 610 "sext " 611#endif 612#if XCHAL_HAVE_CLAMPS 613 "clamps " 614#endif 615#if XCHAL_HAVE_MAC16 616 "mac16 " 617#endif 618#if XCHAL_HAVE_MUL16 619 "mul16 " 620#endif 621#if XCHAL_HAVE_MUL32 622 "mul32 " 623#endif 624#if XCHAL_HAVE_MUL32_HIGH 625 "mul32h " 626#endif 627#if XCHAL_HAVE_FP 628 "fpu " 629#endif 630#if XCHAL_HAVE_S32C1I 631 "s32c1i " 632#endif 633#if XCHAL_HAVE_EXCLUSIVE 634 "exclusive " 635#endif 636 "\n"); 637 638 /* Registers. */ 639 seq_printf(f,"physical aregs\t: %d\n" 640 "misc regs\t: %d\n" 641 "ibreak\t\t: %d\n" 642 "dbreak\t\t: %d\n" 643 "perf counters\t: %d\n", 644 XCHAL_NUM_AREGS, 645 XCHAL_NUM_MISC_REGS, 646 XCHAL_NUM_IBREAK, 647 XCHAL_NUM_DBREAK, 648 XCHAL_NUM_PERF_COUNTERS); 649 650 651 /* Interrupt. */ 652 seq_printf(f,"num ints\t: %d\n" 653 "ext ints\t: %d\n" 654 "int levels\t: %d\n" 655 "timers\t\t: %d\n" 656 "debug level\t: %d\n", 657 XCHAL_NUM_INTERRUPTS, 658 XCHAL_NUM_EXTINTERRUPTS, 659 XCHAL_NUM_INTLEVELS, 660 XCHAL_NUM_TIMERS, 661 XCHAL_DEBUGLEVEL); 662 663 /* Cache */ 664 seq_printf(f,"icache line size: %d\n" 665 "icache ways\t: %d\n" 666 "icache size\t: %d\n" 667 "icache flags\t: " 668#if XCHAL_ICACHE_LINE_LOCKABLE 669 "lock " 670#endif 671 "\n" 672 "dcache line size: %d\n" 673 "dcache ways\t: %d\n" 674 "dcache size\t: %d\n" 675 "dcache flags\t: " 676#if XCHAL_DCACHE_IS_WRITEBACK 677 "writeback " 678#endif 679#if XCHAL_DCACHE_LINE_LOCKABLE 680 "lock " 681#endif 682 "\n", 683 XCHAL_ICACHE_LINESIZE, 684 XCHAL_ICACHE_WAYS, 685 XCHAL_ICACHE_SIZE, 686 XCHAL_DCACHE_LINESIZE, 687 XCHAL_DCACHE_WAYS, 688 XCHAL_DCACHE_SIZE); 689 690 return 0; 691} 692 693/* 694 * We show only CPU #0 info. 695 */ 696static void * 697c_start(struct seq_file *f, loff_t *pos) 698{ 699 return (*pos == 0) ? (void *)1 : NULL; 700} 701 702static void * 703c_next(struct seq_file *f, void *v, loff_t *pos) 704{ 705 ++*pos; 706 return c_start(f, pos); 707} 708 709static void 710c_stop(struct seq_file *f, void *v) 711{ 712} 713 714const struct seq_operations cpuinfo_op = 715{ 716 .start = c_start, 717 .next = c_next, 718 .stop = c_stop, 719 .show = c_show, 720}; 721 722#endif /* CONFIG_PROC_FS */ 723