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