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