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