linux/arch/xtensa/kernel/setup.c
<<
>>
Prefs
   1/*
   2 * arch/xtensa/kernel/setup.c
   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 * Copyright (C) 2014 - 2016  Cadence Design Systems Inc.
  11 *
  12 * Chris Zankel <chris@zankel.net>
  13 * Joe Taylor   <joe@tensilica.com, joetylr@yahoo.com>
  14 * Kevin Chea
  15 * Marc Gauthier<marc@tensilica.com> <marc@alumni.uwaterloo.ca>
  16 */
  17
  18#include <linux/errno.h>
  19#include <linux/init.h>
  20#include <linux/mm.h>
  21#include <linux/proc_fs.h>
  22#include <linux/screen_info.h>
  23#include <linux/kernel.h>
  24#include <linux/percpu.h>
  25#include <linux/cpu.h>
  26#include <linux/of.h>
  27#include <linux/of_fdt.h>
  28
  29#if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE)
  30# include <linux/console.h>
  31#endif
  32
  33#ifdef CONFIG_PROC_FS
  34# include <linux/seq_file.h>
  35#endif
  36
  37#include <asm/bootparam.h>
  38#include <asm/kasan.h>
  39#include <asm/mmu_context.h>
  40#include <asm/pgtable.h>
  41#include <asm/processor.h>
  42#include <asm/timex.h>
  43#include <asm/platform.h>
  44#include <asm/page.h>
  45#include <asm/setup.h>
  46#include <asm/param.h>
  47#include <asm/smp.h>
  48#include <asm/sysmem.h>
  49
  50#if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE)
  51struct screen_info screen_info = {
  52        .orig_x = 0,
  53        .orig_y = 24,
  54        .orig_video_cols = 80,
  55        .orig_video_lines = 24,
  56        .orig_video_isVGA = 1,
  57        .orig_video_points = 16,
  58};
  59#endif
  60
  61#ifdef CONFIG_BLK_DEV_INITRD
  62extern unsigned long initrd_start;
  63extern unsigned long initrd_end;
  64extern int initrd_below_start_ok;
  65#endif
  66
  67#ifdef CONFIG_OF
  68void *dtb_start = __dtb_start;
  69#endif
  70
  71extern unsigned long loops_per_jiffy;
  72
  73/* Command line specified as configuration option. */
  74
  75static char __initdata command_line[COMMAND_LINE_SIZE];
  76
  77#ifdef CONFIG_CMDLINE_BOOL
  78static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
  79#endif
  80
  81#ifdef CONFIG_PARSE_BOOTPARAM
  82/*
  83 * Boot parameter parsing.
  84 *
  85 * The Xtensa port uses a list of variable-sized tags to pass data to
  86 * the kernel. The first tag must be a BP_TAG_FIRST tag for the list
  87 * to be recognised. The list is terminated with a zero-sized
  88 * BP_TAG_LAST tag.
  89 */
  90
  91typedef struct tagtable {
  92        u32 tag;
  93        int (*parse)(const bp_tag_t*);
  94} tagtable_t;
  95
  96#define __tagtable(tag, fn) static tagtable_t __tagtable_##fn           \
  97        __attribute__((used, section(".taglist"))) = { tag, fn }
  98
  99/* parse current tag */
 100
 101static int __init parse_tag_mem(const bp_tag_t *tag)
 102{
 103        struct bp_meminfo *mi = (struct bp_meminfo *)(tag->data);
 104
 105        if (mi->type != MEMORY_TYPE_CONVENTIONAL)
 106                return -1;
 107
 108        return memblock_add(mi->start, mi->end - mi->start);
 109}
 110
 111__tagtable(BP_TAG_MEMORY, parse_tag_mem);
 112
 113#ifdef CONFIG_BLK_DEV_INITRD
 114
 115static int __init parse_tag_initrd(const bp_tag_t* tag)
 116{
 117        struct bp_meminfo *mi = (struct bp_meminfo *)(tag->data);
 118
 119        initrd_start = (unsigned long)__va(mi->start);
 120        initrd_end = (unsigned long)__va(mi->end);
 121
 122        return 0;
 123}
 124
 125__tagtable(BP_TAG_INITRD, parse_tag_initrd);
 126
 127#endif /* CONFIG_BLK_DEV_INITRD */
 128
 129#ifdef CONFIG_OF
 130
 131static int __init parse_tag_fdt(const bp_tag_t *tag)
 132{
 133        dtb_start = __va(tag->data[0]);
 134        return 0;
 135}
 136
 137__tagtable(BP_TAG_FDT, parse_tag_fdt);
 138
 139#endif /* CONFIG_OF */
 140
 141static int __init parse_tag_cmdline(const bp_tag_t* tag)
 142{
 143        strlcpy(command_line, (char *)(tag->data), COMMAND_LINE_SIZE);
 144        return 0;
 145}
 146
 147__tagtable(BP_TAG_COMMAND_LINE, parse_tag_cmdline);
 148
 149static int __init parse_bootparam(const bp_tag_t* tag)
 150{
 151        extern tagtable_t __tagtable_begin, __tagtable_end;
 152        tagtable_t *t;
 153
 154        /* Boot parameters must start with a BP_TAG_FIRST tag. */
 155
 156        if (tag->id != BP_TAG_FIRST) {
 157                pr_warn("Invalid boot parameters!\n");
 158                return 0;
 159        }
 160
 161        tag = (bp_tag_t*)((unsigned long)tag + sizeof(bp_tag_t) + tag->size);
 162
 163        /* Parse all tags. */
 164
 165        while (tag != NULL && tag->id != BP_TAG_LAST) {
 166                for (t = &__tagtable_begin; t < &__tagtable_end; t++) {
 167                        if (tag->id == t->tag) {
 168                                t->parse(tag);
 169                                break;
 170                        }
 171                }
 172                if (t == &__tagtable_end)
 173                        pr_warn("Ignoring tag 0x%08x\n", tag->id);
 174                tag = (bp_tag_t*)((unsigned long)(tag + 1) + tag->size);
 175        }
 176
 177        return 0;
 178}
 179#else
 180static int __init parse_bootparam(const bp_tag_t *tag)
 181{
 182        pr_info("Ignoring boot parameters at %p\n", tag);
 183        return 0;
 184}
 185#endif
 186
 187#ifdef CONFIG_OF
 188
 189#if !XCHAL_HAVE_PTP_MMU || XCHAL_HAVE_SPANNING_WAY
 190unsigned long xtensa_kio_paddr = XCHAL_KIO_DEFAULT_PADDR;
 191EXPORT_SYMBOL(xtensa_kio_paddr);
 192
 193static int __init xtensa_dt_io_area(unsigned long node, const char *uname,
 194                int depth, void *data)
 195{
 196        const __be32 *ranges;
 197        int len;
 198
 199        if (depth > 1)
 200                return 0;
 201
 202        if (!of_flat_dt_is_compatible(node, "simple-bus"))
 203                return 0;
 204
 205        ranges = of_get_flat_dt_prop(node, "ranges", &len);
 206        if (!ranges)
 207                return 1;
 208        if (len == 0)
 209                return 1;
 210
 211        xtensa_kio_paddr = of_read_ulong(ranges+1, 1);
 212        /* round down to nearest 256MB boundary */
 213        xtensa_kio_paddr &= 0xf0000000;
 214
 215        init_kio();
 216
 217        return 1;
 218}
 219#else
 220static int __init xtensa_dt_io_area(unsigned long node, const char *uname,
 221                int depth, void *data)
 222{
 223        return 1;
 224}
 225#endif
 226
 227void __init early_init_devtree(void *params)
 228{
 229        early_init_dt_scan(params);
 230        of_scan_flat_dt(xtensa_dt_io_area, NULL);
 231
 232        if (!command_line[0])
 233                strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE);
 234}
 235
 236#endif /* CONFIG_OF */
 237
 238/*
 239 * Initialize architecture. (Early stage)
 240 */
 241
 242void __init init_arch(bp_tag_t *bp_start)
 243{
 244        /* Initialize MMU. */
 245
 246        init_mmu();
 247
 248        /* Initialize initial KASAN shadow map */
 249
 250        kasan_early_init();
 251
 252        /* Parse boot parameters */
 253
 254        if (bp_start)
 255                parse_bootparam(bp_start);
 256
 257#ifdef CONFIG_OF
 258        early_init_devtree(dtb_start);
 259#endif
 260
 261#ifdef CONFIG_CMDLINE_BOOL
 262        if (!command_line[0])
 263                strlcpy(command_line, default_command_line, COMMAND_LINE_SIZE);
 264#endif
 265
 266        /* Early hook for platforms */
 267
 268        platform_init(bp_start);
 269}
 270
 271/*
 272 * Initialize system. Setup memory and reserve regions.
 273 */
 274
 275extern char _end[];
 276extern char _stext[];
 277extern char _WindowVectors_text_start;
 278extern char _WindowVectors_text_end;
 279extern char _DebugInterruptVector_text_start;
 280extern char _DebugInterruptVector_text_end;
 281extern char _KernelExceptionVector_text_start;
 282extern char _KernelExceptionVector_text_end;
 283extern char _UserExceptionVector_text_start;
 284extern char _UserExceptionVector_text_end;
 285extern char _DoubleExceptionVector_text_start;
 286extern char _DoubleExceptionVector_text_end;
 287#if XCHAL_EXCM_LEVEL >= 2
 288extern char _Level2InterruptVector_text_start;
 289extern char _Level2InterruptVector_text_end;
 290#endif
 291#if XCHAL_EXCM_LEVEL >= 3
 292extern char _Level3InterruptVector_text_start;
 293extern char _Level3InterruptVector_text_end;
 294#endif
 295#if XCHAL_EXCM_LEVEL >= 4
 296extern char _Level4InterruptVector_text_start;
 297extern char _Level4InterruptVector_text_end;
 298#endif
 299#if XCHAL_EXCM_LEVEL >= 5
 300extern char _Level5InterruptVector_text_start;
 301extern char _Level5InterruptVector_text_end;
 302#endif
 303#if XCHAL_EXCM_LEVEL >= 6
 304extern char _Level6InterruptVector_text_start;
 305extern char _Level6InterruptVector_text_end;
 306#endif
 307#ifdef CONFIG_SMP
 308extern char _SecondaryResetVector_text_start;
 309extern char _SecondaryResetVector_text_end;
 310#endif
 311#ifdef CONFIG_XIP_KERNEL
 312extern char _xip_start[];
 313extern char _xip_end[];
 314#endif
 315
 316static inline int __init_memblock mem_reserve(unsigned long start,
 317                                              unsigned long end)
 318{
 319        return memblock_reserve(start, end - start);
 320}
 321
 322void __init setup_arch(char **cmdline_p)
 323{
 324        pr_info("config ID: %08x:%08x\n",
 325                xtensa_get_sr(SREG_EPC), xtensa_get_sr(SREG_EXCSAVE));
 326        if (xtensa_get_sr(SREG_EPC) != XCHAL_HW_CONFIGID0 ||
 327            xtensa_get_sr(SREG_EXCSAVE) != XCHAL_HW_CONFIGID1)
 328                pr_info("built for config ID: %08x:%08x\n",
 329                        XCHAL_HW_CONFIGID0, XCHAL_HW_CONFIGID1);
 330
 331        *cmdline_p = command_line;
 332        platform_setup(cmdline_p);
 333        strlcpy(boot_command_line, *cmdline_p, COMMAND_LINE_SIZE);
 334
 335        /* Reserve some memory regions */
 336
 337#ifdef CONFIG_BLK_DEV_INITRD
 338        if (initrd_start < initrd_end &&
 339            !mem_reserve(__pa(initrd_start), __pa(initrd_end)))
 340                initrd_below_start_ok = 1;
 341        else
 342                initrd_start = 0;
 343#endif
 344
 345        mem_reserve(__pa(_stext), __pa(_end));
 346#ifdef CONFIG_XIP_KERNEL
 347        mem_reserve(__pa(_xip_start), __pa(_xip_end));
 348#endif
 349
 350#ifdef CONFIG_VECTORS_OFFSET
 351        mem_reserve(__pa(&_WindowVectors_text_start),
 352                    __pa(&_WindowVectors_text_end));
 353
 354        mem_reserve(__pa(&_DebugInterruptVector_text_start),
 355                    __pa(&_DebugInterruptVector_text_end));
 356
 357        mem_reserve(__pa(&_KernelExceptionVector_text_start),
 358                    __pa(&_KernelExceptionVector_text_end));
 359
 360        mem_reserve(__pa(&_UserExceptionVector_text_start),
 361                    __pa(&_UserExceptionVector_text_end));
 362
 363        mem_reserve(__pa(&_DoubleExceptionVector_text_start),
 364                    __pa(&_DoubleExceptionVector_text_end));
 365
 366#if XCHAL_EXCM_LEVEL >= 2
 367        mem_reserve(__pa(&_Level2InterruptVector_text_start),
 368                    __pa(&_Level2InterruptVector_text_end));
 369#endif
 370#if XCHAL_EXCM_LEVEL >= 3
 371        mem_reserve(__pa(&_Level3InterruptVector_text_start),
 372                    __pa(&_Level3InterruptVector_text_end));
 373#endif
 374#if XCHAL_EXCM_LEVEL >= 4
 375        mem_reserve(__pa(&_Level4InterruptVector_text_start),
 376                    __pa(&_Level4InterruptVector_text_end));
 377#endif
 378#if XCHAL_EXCM_LEVEL >= 5
 379        mem_reserve(__pa(&_Level5InterruptVector_text_start),
 380                    __pa(&_Level5InterruptVector_text_end));
 381#endif
 382#if XCHAL_EXCM_LEVEL >= 6
 383        mem_reserve(__pa(&_Level6InterruptVector_text_start),
 384                    __pa(&_Level6InterruptVector_text_end));
 385#endif
 386
 387#endif /* CONFIG_VECTORS_OFFSET */
 388
 389#ifdef CONFIG_SMP
 390        mem_reserve(__pa(&_SecondaryResetVector_text_start),
 391                    __pa(&_SecondaryResetVector_text_end));
 392#endif
 393        parse_early_param();
 394        bootmem_init();
 395        kasan_init();
 396        unflatten_and_copy_device_tree();
 397
 398#ifdef CONFIG_SMP
 399        smp_init_cpus();
 400#endif
 401
 402        paging_init();
 403        zones_init();
 404
 405#ifdef CONFIG_VT
 406# if defined(CONFIG_VGA_CONSOLE)
 407        conswitchp = &vga_con;
 408# elif defined(CONFIG_DUMMY_CONSOLE)
 409        conswitchp = &dummy_con;
 410# endif
 411#endif
 412}
 413
 414static DEFINE_PER_CPU(struct cpu, cpu_data);
 415
 416static int __init topology_init(void)
 417{
 418        int i;
 419
 420        for_each_possible_cpu(i) {
 421                struct cpu *cpu = &per_cpu(cpu_data, i);
 422                cpu->hotpluggable = !!i;
 423                register_cpu(cpu, i);
 424        }
 425
 426        return 0;
 427}
 428subsys_initcall(topology_init);
 429
 430void cpu_reset(void)
 431{
 432#if XCHAL_HAVE_PTP_MMU && IS_ENABLED(CONFIG_MMU)
 433        local_irq_disable();
 434        /*
 435         * We have full MMU: all autoload ways, ways 7, 8 and 9 of DTLB must
 436         * be flushed.
 437         * Way 4 is not currently used by linux.
 438         * Ways 5 and 6 shall not be touched on MMUv2 as they are hardwired.
 439         * Way 5 shall be flushed and way 6 shall be set to identity mapping
 440         * on MMUv3.
 441         */
 442        local_flush_tlb_all();
 443        invalidate_page_directory();
 444#if XCHAL_HAVE_SPANNING_WAY
 445        /* MMU v3 */
 446        {
 447                unsigned long vaddr = (unsigned long)cpu_reset;
 448                unsigned long paddr = __pa(vaddr);
 449                unsigned long tmpaddr = vaddr + SZ_512M;
 450                unsigned long tmp0, tmp1, tmp2, tmp3;
 451
 452                /*
 453                 * Find a place for the temporary mapping. It must not be
 454                 * in the same 512MB region with vaddr or paddr, otherwise
 455                 * there may be multihit exception either on entry to the
 456                 * temporary mapping, or on entry to the identity mapping.
 457                 * (512MB is the biggest page size supported by TLB.)
 458                 */
 459                while (((tmpaddr ^ paddr) & -SZ_512M) == 0)
 460                        tmpaddr += SZ_512M;
 461
 462                /* Invalidate mapping in the selected temporary area */
 463                if (itlb_probe(tmpaddr) & BIT(ITLB_HIT_BIT))
 464                        invalidate_itlb_entry(itlb_probe(tmpaddr));
 465                if (itlb_probe(tmpaddr + PAGE_SIZE) & BIT(ITLB_HIT_BIT))
 466                        invalidate_itlb_entry(itlb_probe(tmpaddr + PAGE_SIZE));
 467
 468                /*
 469                 * Map two consecutive pages starting at the physical address
 470                 * of this function to the temporary mapping area.
 471                 */
 472                write_itlb_entry(__pte((paddr & PAGE_MASK) |
 473                                       _PAGE_HW_VALID |
 474                                       _PAGE_HW_EXEC |
 475                                       _PAGE_CA_BYPASS),
 476                                 tmpaddr & PAGE_MASK);
 477                write_itlb_entry(__pte(((paddr & PAGE_MASK) + PAGE_SIZE) |
 478                                       _PAGE_HW_VALID |
 479                                       _PAGE_HW_EXEC |
 480                                       _PAGE_CA_BYPASS),
 481                                 (tmpaddr & PAGE_MASK) + PAGE_SIZE);
 482
 483                /* Reinitialize TLB */
 484                __asm__ __volatile__ ("movi     %0, 1f\n\t"
 485                                      "movi     %3, 2f\n\t"
 486                                      "add      %0, %0, %4\n\t"
 487                                      "add      %3, %3, %5\n\t"
 488                                      "jx       %0\n"
 489                                      /*
 490                                       * No literal, data or stack access
 491                                       * below this point
 492                                       */
 493                                      "1:\n\t"
 494                                      /* Initialize *tlbcfg */
 495                                      "movi     %0, 0\n\t"
 496                                      "wsr      %0, itlbcfg\n\t"
 497                                      "wsr      %0, dtlbcfg\n\t"
 498                                      /* Invalidate TLB way 5 */
 499                                      "movi     %0, 4\n\t"
 500                                      "movi     %1, 5\n"
 501                                      "1:\n\t"
 502                                      "iitlb    %1\n\t"
 503                                      "idtlb    %1\n\t"
 504                                      "add      %1, %1, %6\n\t"
 505                                      "addi     %0, %0, -1\n\t"
 506                                      "bnez     %0, 1b\n\t"
 507                                      /* Initialize TLB way 6 */
 508                                      "movi     %0, 7\n\t"
 509                                      "addi     %1, %9, 3\n\t"
 510                                      "addi     %2, %9, 6\n"
 511                                      "1:\n\t"
 512                                      "witlb    %1, %2\n\t"
 513                                      "wdtlb    %1, %2\n\t"
 514                                      "add      %1, %1, %7\n\t"
 515                                      "add      %2, %2, %7\n\t"
 516                                      "addi     %0, %0, -1\n\t"
 517                                      "bnez     %0, 1b\n\t"
 518                                      "isync\n\t"
 519                                      /* Jump to identity mapping */
 520                                      "jx       %3\n"
 521                                      "2:\n\t"
 522                                      /* Complete way 6 initialization */
 523                                      "witlb    %1, %2\n\t"
 524                                      "wdtlb    %1, %2\n\t"
 525                                      /* Invalidate temporary mapping */
 526                                      "sub      %0, %9, %7\n\t"
 527                                      "iitlb    %0\n\t"
 528                                      "add      %0, %0, %8\n\t"
 529                                      "iitlb    %0"
 530                                      : "=&a"(tmp0), "=&a"(tmp1), "=&a"(tmp2),
 531                                        "=&a"(tmp3)
 532                                      : "a"(tmpaddr - vaddr),
 533                                        "a"(paddr - vaddr),
 534                                        "a"(SZ_128M), "a"(SZ_512M),
 535                                        "a"(PAGE_SIZE),
 536                                        "a"((tmpaddr + SZ_512M) & PAGE_MASK)
 537                                      : "memory");
 538        }
 539#endif
 540#endif
 541        __asm__ __volatile__ ("movi     a2, 0\n\t"
 542                              "wsr      a2, icountlevel\n\t"
 543                              "movi     a2, 0\n\t"
 544                              "wsr      a2, icount\n\t"
 545#if XCHAL_NUM_IBREAK > 0
 546                              "wsr      a2, ibreakenable\n\t"
 547#endif
 548#if XCHAL_HAVE_LOOPS
 549                              "wsr      a2, lcount\n\t"
 550#endif
 551                              "movi     a2, 0x1f\n\t"
 552                              "wsr      a2, ps\n\t"
 553                              "isync\n\t"
 554                              "jx       %0\n\t"
 555                              :
 556                              : "a" (XCHAL_RESET_VECTOR_VADDR)
 557                              : "a2");
 558        for (;;)
 559                ;
 560}
 561
 562void machine_restart(char * cmd)
 563{
 564        platform_restart();
 565}
 566
 567void machine_halt(void)
 568{
 569        platform_halt();
 570        while (1);
 571}
 572
 573void machine_power_off(void)
 574{
 575        platform_power_off();
 576        while (1);
 577}
 578#ifdef CONFIG_PROC_FS
 579
 580/*
 581 * Display some core information through /proc/cpuinfo.
 582 */
 583
 584static int
 585c_show(struct seq_file *f, void *slot)
 586{
 587        /* high-level stuff */
 588        seq_printf(f, "CPU count\t: %u\n"
 589                      "CPU list\t: %*pbl\n"
 590                      "vendor_id\t: Tensilica\n"
 591                      "model\t\t: Xtensa " XCHAL_HW_VERSION_NAME "\n"
 592                      "core ID\t\t: " XCHAL_CORE_ID "\n"
 593                      "build ID\t: 0x%x\n"
 594                      "config ID\t: %08x:%08x\n"
 595                      "byte order\t: %s\n"
 596                      "cpu MHz\t\t: %lu.%02lu\n"
 597                      "bogomips\t: %lu.%02lu\n",
 598                      num_online_cpus(),
 599                      cpumask_pr_args(cpu_online_mask),
 600                      XCHAL_BUILD_UNIQUE_ID,
 601                      xtensa_get_sr(SREG_EPC), xtensa_get_sr(SREG_EXCSAVE),
 602                      XCHAL_HAVE_BE ?  "big" : "little",
 603                      ccount_freq/1000000,
 604                      (ccount_freq/10000) % 100,
 605                      loops_per_jiffy/(500000/HZ),
 606                      (loops_per_jiffy/(5000/HZ)) % 100);
 607        seq_puts(f, "flags\t\t: "
 608#if XCHAL_HAVE_NMI
 609                     "nmi "
 610#endif
 611#if XCHAL_HAVE_DEBUG
 612                     "debug "
 613# if XCHAL_HAVE_OCD
 614                     "ocd "
 615# endif
 616#endif
 617#if XCHAL_HAVE_DENSITY
 618                     "density "
 619#endif
 620#if XCHAL_HAVE_BOOLEANS
 621                     "boolean "
 622#endif
 623#if XCHAL_HAVE_LOOPS
 624                     "loop "
 625#endif
 626#if XCHAL_HAVE_NSA
 627                     "nsa "
 628#endif
 629#if XCHAL_HAVE_MINMAX
 630                     "minmax "
 631#endif
 632#if XCHAL_HAVE_SEXT
 633                     "sext "
 634#endif
 635#if XCHAL_HAVE_CLAMPS
 636                     "clamps "
 637#endif
 638#if XCHAL_HAVE_MAC16
 639                     "mac16 "
 640#endif
 641#if XCHAL_HAVE_MUL16
 642                     "mul16 "
 643#endif
 644#if XCHAL_HAVE_MUL32
 645                     "mul32 "
 646#endif
 647#if XCHAL_HAVE_MUL32_HIGH
 648                     "mul32h "
 649#endif
 650#if XCHAL_HAVE_FP
 651                     "fpu "
 652#endif
 653#if XCHAL_HAVE_S32C1I
 654                     "s32c1i "
 655#endif
 656#if XCHAL_HAVE_EXCLUSIVE
 657                     "exclusive "
 658#endif
 659                     "\n");
 660
 661        /* Registers. */
 662        seq_printf(f,"physical aregs\t: %d\n"
 663                     "misc regs\t: %d\n"
 664                     "ibreak\t\t: %d\n"
 665                     "dbreak\t\t: %d\n",
 666                     XCHAL_NUM_AREGS,
 667                     XCHAL_NUM_MISC_REGS,
 668                     XCHAL_NUM_IBREAK,
 669                     XCHAL_NUM_DBREAK);
 670
 671
 672        /* Interrupt. */
 673        seq_printf(f,"num ints\t: %d\n"
 674                     "ext ints\t: %d\n"
 675                     "int levels\t: %d\n"
 676                     "timers\t\t: %d\n"
 677                     "debug level\t: %d\n",
 678                     XCHAL_NUM_INTERRUPTS,
 679                     XCHAL_NUM_EXTINTERRUPTS,
 680                     XCHAL_NUM_INTLEVELS,
 681                     XCHAL_NUM_TIMERS,
 682                     XCHAL_DEBUGLEVEL);
 683
 684        /* Cache */
 685        seq_printf(f,"icache line size: %d\n"
 686                     "icache ways\t: %d\n"
 687                     "icache size\t: %d\n"
 688                     "icache flags\t: "
 689#if XCHAL_ICACHE_LINE_LOCKABLE
 690                     "lock "
 691#endif
 692                     "\n"
 693                     "dcache line size: %d\n"
 694                     "dcache ways\t: %d\n"
 695                     "dcache size\t: %d\n"
 696                     "dcache flags\t: "
 697#if XCHAL_DCACHE_IS_WRITEBACK
 698                     "writeback "
 699#endif
 700#if XCHAL_DCACHE_LINE_LOCKABLE
 701                     "lock "
 702#endif
 703                     "\n",
 704                     XCHAL_ICACHE_LINESIZE,
 705                     XCHAL_ICACHE_WAYS,
 706                     XCHAL_ICACHE_SIZE,
 707                     XCHAL_DCACHE_LINESIZE,
 708                     XCHAL_DCACHE_WAYS,
 709                     XCHAL_DCACHE_SIZE);
 710
 711        return 0;
 712}
 713
 714/*
 715 * We show only CPU #0 info.
 716 */
 717static void *
 718c_start(struct seq_file *f, loff_t *pos)
 719{
 720        return (*pos == 0) ? (void *)1 : NULL;
 721}
 722
 723static void *
 724c_next(struct seq_file *f, void *v, loff_t *pos)
 725{
 726        return NULL;
 727}
 728
 729static void
 730c_stop(struct seq_file *f, void *v)
 731{
 732}
 733
 734const struct seq_operations cpuinfo_op =
 735{
 736        .start  = c_start,
 737        .next   = c_next,
 738        .stop   = c_stop,
 739        .show   = c_show,
 740};
 741
 742#endif /* CONFIG_PROC_FS */
 743