]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - arch/xtensa/kernel/setup.c
xtensa: Fix build error due to missing include file
[mirror_ubuntu-artful-kernel.git] / arch / xtensa / kernel / setup.c
CommitLineData
5a0015d6 1/*
f30c2269 2 * arch/xtensa/kernel/setup.c
5a0015d6
CZ
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details.
7 *
8 * Copyright (C) 1995 Linus Torvalds
9 * Copyright (C) 2001 - 2005 Tensilica Inc.
10 *
11 * Chris Zankel <chris@zankel.net>
12 * Joe Taylor <joe@tensilica.com, joetylr@yahoo.com>
13 * Kevin Chea
14 * Marc Gauthier<marc@tensilica.com> <marc@alumni.uwaterloo.ca>
15 */
16
5a0015d6
CZ
17#include <linux/errno.h>
18#include <linux/init.h>
27ac792c 19#include <linux/mm.h>
5a0015d6 20#include <linux/proc_fs.h>
894673ee 21#include <linux/screen_info.h>
5a0015d6
CZ
22#include <linux/bootmem.h>
23#include <linux/kernel.h>
f615136c
MF
24#include <linux/percpu.h>
25#include <linux/cpu.h>
d02014b2 26#include <linux/of.h>
da844a81 27#include <linux/of_fdt.h>
da844a81 28
5a0015d6
CZ
29#if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE)
30# include <linux/console.h>
31#endif
32
33#ifdef CONFIG_RTC
34# include <linux/timex.h>
35#endif
36
37#ifdef CONFIG_PROC_FS
38# include <linux/seq_file.h>
39#endif
40
5a0015d6 41#include <asm/bootparam.h>
c8f3a7dc 42#include <asm/mmu_context.h>
5a0015d6
CZ
43#include <asm/pgtable.h>
44#include <asm/processor.h>
45#include <asm/timex.h>
46#include <asm/platform.h>
47#include <asm/page.h>
48#include <asm/setup.h>
de4f6e5b 49#include <asm/param.h>
00273125 50#include <asm/traps.h>
f615136c 51#include <asm/smp.h>
9ba067f9 52#include <asm/sysmem.h>
5a0015d6 53
5a891ed5
AD
54#include <platform/hardware.h>
55
5a0015d6
CZ
56#if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE)
57struct screen_info screen_info = { 0, 24, 0, 0, 0, 80, 0, 0, 0, 24, 1, 16};
58#endif
59
60#ifdef CONFIG_BLK_DEV_FD
61extern struct fd_ops no_fd_ops;
62struct fd_ops *fd_ops;
63#endif
64
5a0015d6
CZ
65extern struct rtc_ops no_rtc_ops;
66struct rtc_ops *rtc_ops;
67
5a0015d6 68#ifdef CONFIG_BLK_DEV_INITRD
29eb45a9
RH
69extern unsigned long initrd_start;
70extern unsigned long initrd_end;
5a0015d6
CZ
71int initrd_is_mapped = 0;
72extern int initrd_below_start_ok;
73#endif
74
da844a81 75#ifdef CONFIG_OF
da844a81
MF
76void *dtb_start = __dtb_start;
77#endif
78
5a0015d6
CZ
79unsigned char aux_device_present;
80extern unsigned long loops_per_jiffy;
81
82/* Command line specified as configuration option. */
83
d3e9ccea 84static char __initdata command_line[COMMAND_LINE_SIZE];
5a0015d6
CZ
85
86#ifdef CONFIG_CMDLINE_BOOL
87static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
88#endif
89
5a0015d6
CZ
90/*
91 * Boot parameter parsing.
92 *
93 * The Xtensa port uses a list of variable-sized tags to pass data to
94 * the kernel. The first tag must be a BP_TAG_FIRST tag for the list
95 * to be recognised. The list is terminated with a zero-sized
96 * BP_TAG_LAST tag.
97 */
98
99typedef struct tagtable {
100 u32 tag;
101 int (*parse)(const bp_tag_t*);
102} tagtable_t;
103
104#define __tagtable(tag, fn) static tagtable_t __tagtable_##fn \
f4349b6e 105 __attribute__((used, section(".taglist"))) = { tag, fn }
5a0015d6
CZ
106
107/* parse current tag */
108
da844a81
MF
109static int __init parse_tag_mem(const bp_tag_t *tag)
110{
9ba067f9 111 struct bp_meminfo *mi = (struct bp_meminfo *)(tag->data);
da844a81
MF
112
113 if (mi->type != MEMORY_TYPE_CONVENTIONAL)
114 return -1;
115
9ba067f9 116 return add_sysmem_bank(mi->start, mi->end);
da844a81
MF
117}
118
5a0015d6
CZ
119__tagtable(BP_TAG_MEMORY, parse_tag_mem);
120
121#ifdef CONFIG_BLK_DEV_INITRD
122
123static int __init parse_tag_initrd(const bp_tag_t* tag)
124{
9ba067f9
MF
125 struct bp_meminfo *mi = (struct bp_meminfo *)(tag->data);
126
29eb45a9
RH
127 initrd_start = (unsigned long)__va(mi->start);
128 initrd_end = (unsigned long)__va(mi->end);
5a0015d6
CZ
129
130 return 0;
131}
132
133__tagtable(BP_TAG_INITRD, parse_tag_initrd);
134
da844a81
MF
135#ifdef CONFIG_OF
136
137static int __init parse_tag_fdt(const bp_tag_t *tag)
138{
c5a771d0 139 dtb_start = __va(tag->data[0]);
da844a81
MF
140 return 0;
141}
142
143__tagtable(BP_TAG_FDT, parse_tag_fdt);
144
da844a81
MF
145#endif /* CONFIG_OF */
146
5a0015d6
CZ
147#endif /* CONFIG_BLK_DEV_INITRD */
148
149static int __init parse_tag_cmdline(const bp_tag_t* tag)
150{
da844a81 151 strlcpy(command_line, (char *)(tag->data), COMMAND_LINE_SIZE);
5a0015d6
CZ
152 return 0;
153}
154
155__tagtable(BP_TAG_COMMAND_LINE, parse_tag_cmdline);
156
157static int __init parse_bootparam(const bp_tag_t* tag)
158{
159 extern tagtable_t __tagtable_begin, __tagtable_end;
160 tagtable_t *t;
161
162 /* Boot parameters must start with a BP_TAG_FIRST tag. */
163
164 if (tag->id != BP_TAG_FIRST) {
165 printk(KERN_WARNING "Invalid boot parameters!\n");
166 return 0;
167 }
168
169 tag = (bp_tag_t*)((unsigned long)tag + sizeof(bp_tag_t) + tag->size);
170
171 /* Parse all tags. */
172
173 while (tag != NULL && tag->id != BP_TAG_LAST) {
174 for (t = &__tagtable_begin; t < &__tagtable_end; t++) {
175 if (tag->id == t->tag) {
176 t->parse(tag);
177 break;
178 }
179 }
180 if (t == &__tagtable_end)
181 printk(KERN_WARNING "Ignoring tag "
182 "0x%08x\n", tag->id);
183 tag = (bp_tag_t*)((unsigned long)(tag + 1) + tag->size);
184 }
185
186 return 0;
187}
188
da844a81 189#ifdef CONFIG_OF
7745fc1f 190bool __initdata dt_memory_scan = false;
da844a81 191
260c64bb 192#if !XCHAL_HAVE_PTP_MMU || XCHAL_HAVE_SPANNING_WAY
6cb97111
BS
193unsigned long xtensa_kio_paddr = XCHAL_KIO_DEFAULT_PADDR;
194EXPORT_SYMBOL(xtensa_kio_paddr);
195
196static int __init xtensa_dt_io_area(unsigned long node, const char *uname,
197 int depth, void *data)
198{
199 const __be32 *ranges;
9d0c4dfe 200 int len;
6cb97111
BS
201
202 if (depth > 1)
203 return 0;
204
205 if (!of_flat_dt_is_compatible(node, "simple-bus"))
206 return 0;
207
208 ranges = of_get_flat_dt_prop(node, "ranges", &len);
209 if (!ranges)
210 return 1;
211 if (len == 0)
212 return 1;
213
214 xtensa_kio_paddr = of_read_ulong(ranges+1, 1);
215 /* round down to nearest 256MB boundary */
216 xtensa_kio_paddr &= 0xf0000000;
217
218 return 1;
219}
220#else
221static int __init xtensa_dt_io_area(unsigned long node, const char *uname,
222 int depth, void *data)
223{
224 return 1;
225}
226#endif
227
da844a81
MF
228void __init early_init_dt_add_memory_arch(u64 base, u64 size)
229{
7745fc1f
RH
230 if (!dt_memory_scan)
231 return;
232
da844a81 233 size &= PAGE_MASK;
9ba067f9 234 add_sysmem_bank(base, base + size);
da844a81
MF
235}
236
237void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align)
238{
239 return __alloc_bootmem(size, align, 0);
240}
241
242void __init early_init_devtree(void *params)
243{
7745fc1f
RH
244 if (sysmem.nr_banks == 0)
245 dt_memory_scan = true;
da844a81 246
7745fc1f 247 early_init_dt_scan(params);
6cb97111 248 of_scan_flat_dt(xtensa_dt_io_area, NULL);
da844a81 249
7745fc1f
RH
250 if (!command_line[0])
251 strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE);
da844a81
MF
252}
253
da844a81
MF
254#endif /* CONFIG_OF */
255
5a0015d6
CZ
256/*
257 * Initialize architecture. (Early stage)
258 */
259
260void __init init_arch(bp_tag_t *bp_start)
261{
5a0015d6
CZ
262 /* Parse boot parameters */
263
c4c4594b 264 if (bp_start)
da844a81
MF
265 parse_bootparam(bp_start);
266
267#ifdef CONFIG_OF
268 early_init_devtree(dtb_start);
269#endif
5a0015d6
CZ
270
271 if (sysmem.nr_banks == 0) {
9ba067f9
MF
272 add_sysmem_bank(PLATFORM_DEFAULT_MEM_START,
273 PLATFORM_DEFAULT_MEM_START +
274 PLATFORM_DEFAULT_MEM_SIZE);
5a0015d6
CZ
275 }
276
da844a81
MF
277#ifdef CONFIG_CMDLINE_BOOL
278 if (!command_line[0])
279 strlcpy(command_line, default_command_line, COMMAND_LINE_SIZE);
280#endif
281
5a0015d6
CZ
282 /* Early hook for platforms */
283
284 platform_init(bp_start);
285
286 /* Initialize MMU. */
287
288 init_mmu();
289}
290
291/*
292 * Initialize system. Setup memory and reserve regions.
293 */
294
295extern char _end;
296extern char _stext;
297extern char _WindowVectors_text_start;
298extern char _WindowVectors_text_end;
299extern char _DebugInterruptVector_literal_start;
300extern char _DebugInterruptVector_text_end;
301extern char _KernelExceptionVector_literal_start;
302extern char _KernelExceptionVector_text_end;
303extern char _UserExceptionVector_literal_start;
304extern char _UserExceptionVector_text_end;
305extern char _DoubleExceptionVector_literal_start;
306extern char _DoubleExceptionVector_text_end;
2d1c645c
MG
307#if XCHAL_EXCM_LEVEL >= 2
308extern char _Level2InterruptVector_text_start;
309extern char _Level2InterruptVector_text_end;
310#endif
311#if XCHAL_EXCM_LEVEL >= 3
312extern char _Level3InterruptVector_text_start;
313extern char _Level3InterruptVector_text_end;
314#endif
315#if XCHAL_EXCM_LEVEL >= 4
316extern char _Level4InterruptVector_text_start;
317extern char _Level4InterruptVector_text_end;
318#endif
319#if XCHAL_EXCM_LEVEL >= 5
320extern char _Level5InterruptVector_text_start;
321extern char _Level5InterruptVector_text_end;
322#endif
323#if XCHAL_EXCM_LEVEL >= 6
324extern char _Level6InterruptVector_text_start;
325extern char _Level6InterruptVector_text_end;
326#endif
ab45fb14
MF
327#ifdef CONFIG_SMP
328extern char _SecondaryResetVector_text_start;
329extern char _SecondaryResetVector_text_end;
330#endif
5a0015d6 331
00273125
MF
332
333#ifdef CONFIG_S32C1I_SELFTEST
334#if XCHAL_HAVE_S32C1I
335
336static int __initdata rcw_word, rcw_probe_pc, rcw_exc;
337
338/*
339 * Basic atomic compare-and-swap, that records PC of S32C1I for probing.
340 *
341 * If *v == cmp, set *v = set. Return previous *v.
342 */
343static inline int probed_compare_swap(int *v, int cmp, int set)
344{
345 int tmp;
346
347 __asm__ __volatile__(
348 " movi %1, 1f\n"
349 " s32i %1, %4, 0\n"
350 " wsr %2, scompare1\n"
351 "1: s32c1i %0, %3, 0\n"
352 : "=a" (set), "=&a" (tmp)
353 : "a" (cmp), "a" (v), "a" (&rcw_probe_pc), "0" (set)
354 : "memory"
355 );
356 return set;
357}
358
359/* Handle probed exception */
360
59970753
MF
361static void __init do_probed_exception(struct pt_regs *regs,
362 unsigned long exccause)
00273125
MF
363{
364 if (regs->pc == rcw_probe_pc) { /* exception on s32c1i ? */
365 regs->pc += 3; /* skip the s32c1i instruction */
366 rcw_exc = exccause;
367 } else {
368 do_unhandled(regs, exccause);
369 }
370}
371
372/* Simple test of S32C1I (soc bringup assist) */
373
59970753 374static int __init check_s32c1i(void)
00273125
MF
375{
376 int n, cause1, cause2;
377 void *handbus, *handdata, *handaddr; /* temporarily saved handlers */
378
379 rcw_probe_pc = 0;
380 handbus = trap_set_handler(EXCCAUSE_LOAD_STORE_ERROR,
381 do_probed_exception);
382 handdata = trap_set_handler(EXCCAUSE_LOAD_STORE_DATA_ERROR,
383 do_probed_exception);
384 handaddr = trap_set_handler(EXCCAUSE_LOAD_STORE_ADDR_ERROR,
385 do_probed_exception);
386
387 /* First try an S32C1I that does not store: */
388 rcw_exc = 0;
389 rcw_word = 1;
390 n = probed_compare_swap(&rcw_word, 0, 2);
391 cause1 = rcw_exc;
392
393 /* took exception? */
394 if (cause1 != 0) {
395 /* unclean exception? */
396 if (n != 2 || rcw_word != 1)
397 panic("S32C1I exception error");
398 } else if (rcw_word != 1 || n != 1) {
399 panic("S32C1I compare error");
400 }
401
402 /* Then an S32C1I that stores: */
403 rcw_exc = 0;
404 rcw_word = 0x1234567;
405 n = probed_compare_swap(&rcw_word, 0x1234567, 0xabcde);
406 cause2 = rcw_exc;
407
408 if (cause2 != 0) {
409 /* unclean exception? */
410 if (n != 0xabcde || rcw_word != 0x1234567)
411 panic("S32C1I exception error (b)");
412 } else if (rcw_word != 0xabcde || n != 0x1234567) {
413 panic("S32C1I store error");
414 }
415
416 /* Verify consistency of exceptions: */
417 if (cause1 || cause2) {
418 pr_warn("S32C1I took exception %d, %d\n", cause1, cause2);
419 /* If emulation of S32C1I upon bus error gets implemented,
420 we can get rid of this panic for single core (not SMP) */
421 panic("S32C1I exceptions not currently supported");
422 }
423 if (cause1 != cause2)
424 panic("inconsistent S32C1I exceptions");
425
426 trap_set_handler(EXCCAUSE_LOAD_STORE_ERROR, handbus);
427 trap_set_handler(EXCCAUSE_LOAD_STORE_DATA_ERROR, handdata);
428 trap_set_handler(EXCCAUSE_LOAD_STORE_ADDR_ERROR, handaddr);
59970753 429 return 0;
00273125
MF
430}
431
432#else /* XCHAL_HAVE_S32C1I */
433
434/* This condition should not occur with a commercially deployed processor.
435 Display reminder for early engr test or demo chips / FPGA bitstreams */
59970753 436static int __init check_s32c1i(void)
00273125
MF
437{
438 pr_warn("Processor configuration lacks atomic compare-and-swap support!\n");
59970753 439 return 0;
00273125
MF
440}
441
442#endif /* XCHAL_HAVE_S32C1I */
59970753 443early_initcall(check_s32c1i);
00273125
MF
444#endif /* CONFIG_S32C1I_SELFTEST */
445
446
5a0015d6
CZ
447void __init setup_arch(char **cmdline_p)
448{
da844a81 449 strlcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
5a0015d6
CZ
450 *cmdline_p = command_line;
451
452 /* Reserve some memory regions */
453
454#ifdef CONFIG_BLK_DEV_INITRD
455 if (initrd_start < initrd_end) {
456 initrd_is_mapped = mem_reserve(__pa(initrd_start),
62327918 457 __pa(initrd_end), 0) == 0;
5a0015d6 458 initrd_below_start_ok = 1;
c4c4594b 459 } else {
5a0015d6
CZ
460 initrd_start = 0;
461 }
462#endif
463
464 mem_reserve(__pa(&_stext),__pa(&_end), 1);
465
466 mem_reserve(__pa(&_WindowVectors_text_start),
467 __pa(&_WindowVectors_text_end), 0);
468
469 mem_reserve(__pa(&_DebugInterruptVector_literal_start),
470 __pa(&_DebugInterruptVector_text_end), 0);
471
472 mem_reserve(__pa(&_KernelExceptionVector_literal_start),
473 __pa(&_KernelExceptionVector_text_end), 0);
474
475 mem_reserve(__pa(&_UserExceptionVector_literal_start),
476 __pa(&_UserExceptionVector_text_end), 0);
477
478 mem_reserve(__pa(&_DoubleExceptionVector_literal_start),
479 __pa(&_DoubleExceptionVector_text_end), 0);
480
2d1c645c
MG
481#if XCHAL_EXCM_LEVEL >= 2
482 mem_reserve(__pa(&_Level2InterruptVector_text_start),
483 __pa(&_Level2InterruptVector_text_end), 0);
484#endif
485#if XCHAL_EXCM_LEVEL >= 3
486 mem_reserve(__pa(&_Level3InterruptVector_text_start),
487 __pa(&_Level3InterruptVector_text_end), 0);
488#endif
489#if XCHAL_EXCM_LEVEL >= 4
490 mem_reserve(__pa(&_Level4InterruptVector_text_start),
491 __pa(&_Level4InterruptVector_text_end), 0);
492#endif
493#if XCHAL_EXCM_LEVEL >= 5
494 mem_reserve(__pa(&_Level5InterruptVector_text_start),
495 __pa(&_Level5InterruptVector_text_end), 0);
496#endif
497#if XCHAL_EXCM_LEVEL >= 6
498 mem_reserve(__pa(&_Level6InterruptVector_text_start),
499 __pa(&_Level6InterruptVector_text_end), 0);
500#endif
501
ab45fb14
MF
502#ifdef CONFIG_SMP
503 mem_reserve(__pa(&_SecondaryResetVector_text_start),
504 __pa(&_SecondaryResetVector_text_end), 0);
505#endif
06bd2824 506 parse_early_param();
5a0015d6
CZ
507 bootmem_init();
508
3104021c 509 unflatten_and_copy_device_tree();
5a0015d6 510
da844a81 511 platform_setup(cmdline_p);
5a0015d6 512
f615136c
MF
513#ifdef CONFIG_SMP
514 smp_init_cpus();
515#endif
516
5a0015d6 517 paging_init();
e5083a63 518 zones_init();
5a0015d6
CZ
519
520#ifdef CONFIG_VT
521# if defined(CONFIG_VGA_CONSOLE)
522 conswitchp = &vga_con;
523# elif defined(CONFIG_DUMMY_CONSOLE)
524 conswitchp = &dummy_con;
525# endif
526#endif
527
288a60cf 528#ifdef CONFIG_PCI
5a0015d6
CZ
529 platform_pcibios_init();
530#endif
531}
532
f615136c
MF
533static DEFINE_PER_CPU(struct cpu, cpu_data);
534
535static int __init topology_init(void)
536{
537 int i;
538
539 for_each_possible_cpu(i) {
540 struct cpu *cpu = &per_cpu(cpu_data, i);
49b424fe 541 cpu->hotpluggable = !!i;
f615136c
MF
542 register_cpu(cpu, i);
543 }
544
545 return 0;
546}
547subsys_initcall(topology_init);
548
5a0015d6
CZ
549void machine_restart(char * cmd)
550{
551 platform_restart();
552}
553
554void machine_halt(void)
555{
556 platform_halt();
557 while (1);
558}
559
560void machine_power_off(void)
561{
562 platform_power_off();
563 while (1);
564}
565#ifdef CONFIG_PROC_FS
566
567/*
568 * Display some core information through /proc/cpuinfo.
569 */
570
571static int
572c_show(struct seq_file *f, void *slot)
573{
574 /* high-level stuff */
f615136c 575 seq_printf(f, "CPU count\t: %u\n"
62518994 576 "CPU list\t: %*pbl\n"
f615136c
MF
577 "vendor_id\t: Tensilica\n"
578 "model\t\t: Xtensa " XCHAL_HW_VERSION_NAME "\n"
579 "core ID\t\t: " XCHAL_CORE_ID "\n"
580 "build ID\t: 0x%x\n"
581 "byte order\t: %s\n"
582 "cpu MHz\t\t: %lu.%02lu\n"
583 "bogomips\t: %lu.%02lu\n",
584 num_online_cpus(),
62518994 585 cpumask_pr_args(cpu_online_mask),
f615136c
MF
586 XCHAL_BUILD_UNIQUE_ID,
587 XCHAL_HAVE_BE ? "big" : "little",
588 ccount_freq/1000000,
589 (ccount_freq/10000) % 100,
590 loops_per_jiffy/(500000/HZ),
591 (loops_per_jiffy/(5000/HZ)) % 100);
5a0015d6
CZ
592
593 seq_printf(f,"flags\t\t: "
594#if XCHAL_HAVE_NMI
595 "nmi "
596#endif
597#if XCHAL_HAVE_DEBUG
598 "debug "
599# if XCHAL_HAVE_OCD
600 "ocd "
601# endif
602#endif
603#if XCHAL_HAVE_DENSITY
604 "density "
605#endif
606#if XCHAL_HAVE_BOOLEANS
607 "boolean "
608#endif
609#if XCHAL_HAVE_LOOPS
610 "loop "
611#endif
612#if XCHAL_HAVE_NSA
613 "nsa "
614#endif
615#if XCHAL_HAVE_MINMAX
616 "minmax "
617#endif
618#if XCHAL_HAVE_SEXT
619 "sext "
620#endif
621#if XCHAL_HAVE_CLAMPS
622 "clamps "
623#endif
624#if XCHAL_HAVE_MAC16
625 "mac16 "
626#endif
627#if XCHAL_HAVE_MUL16
628 "mul16 "
629#endif
630#if XCHAL_HAVE_MUL32
631 "mul32 "
632#endif
633#if XCHAL_HAVE_MUL32_HIGH
634 "mul32h "
635#endif
636#if XCHAL_HAVE_FP
637 "fpu "
2f6ea6a7
MF
638#endif
639#if XCHAL_HAVE_S32C1I
640 "s32c1i "
5a0015d6
CZ
641#endif
642 "\n");
643
644 /* Registers. */
645 seq_printf(f,"physical aregs\t: %d\n"
646 "misc regs\t: %d\n"
647 "ibreak\t\t: %d\n"
648 "dbreak\t\t: %d\n",
649 XCHAL_NUM_AREGS,
650 XCHAL_NUM_MISC_REGS,
651 XCHAL_NUM_IBREAK,
652 XCHAL_NUM_DBREAK);
653
654
655 /* Interrupt. */
656 seq_printf(f,"num ints\t: %d\n"
657 "ext ints\t: %d\n"
658 "int levels\t: %d\n"
659 "timers\t\t: %d\n"
660 "debug level\t: %d\n",
661 XCHAL_NUM_INTERRUPTS,
662 XCHAL_NUM_EXTINTERRUPTS,
663 XCHAL_NUM_INTLEVELS,
664 XCHAL_NUM_TIMERS,
665 XCHAL_DEBUGLEVEL);
666
5a0015d6
CZ
667 /* Cache */
668 seq_printf(f,"icache line size: %d\n"
669 "icache ways\t: %d\n"
670 "icache size\t: %d\n"
671 "icache flags\t: "
672#if XCHAL_ICACHE_LINE_LOCKABLE
415217ef 673 "lock "
5a0015d6
CZ
674#endif
675 "\n"
676 "dcache line size: %d\n"
677 "dcache ways\t: %d\n"
678 "dcache size\t: %d\n"
679 "dcache flags\t: "
680#if XCHAL_DCACHE_IS_WRITEBACK
415217ef 681 "writeback "
5a0015d6
CZ
682#endif
683#if XCHAL_DCACHE_LINE_LOCKABLE
415217ef 684 "lock "
5a0015d6
CZ
685#endif
686 "\n",
687 XCHAL_ICACHE_LINESIZE,
688 XCHAL_ICACHE_WAYS,
689 XCHAL_ICACHE_SIZE,
690 XCHAL_DCACHE_LINESIZE,
691 XCHAL_DCACHE_WAYS,
692 XCHAL_DCACHE_SIZE);
693
5a0015d6
CZ
694 return 0;
695}
696
697/*
698 * We show only CPU #0 info.
699 */
700static void *
701c_start(struct seq_file *f, loff_t *pos)
702{
f615136c 703 return (*pos == 0) ? (void *)1 : NULL;
5a0015d6
CZ
704}
705
706static void *
707c_next(struct seq_file *f, void *v, loff_t *pos)
708{
709 return NULL;
710}
711
712static void
713c_stop(struct seq_file *f, void *v)
714{
715}
716
03a44825 717const struct seq_operations cpuinfo_op =
5a0015d6 718{
f615136c
MF
719 .start = c_start,
720 .next = c_next,
721 .stop = c_stop,
722 .show = c_show,
5a0015d6
CZ
723};
724
725#endif /* CONFIG_PROC_FS */