d61c8468abea40b5783fde6fe4b5b6e577b17ddf
[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 #include <linux/of_platform.h>
30
31 #if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE)
32 # include <linux/console.h>
33 #endif
34
35 #ifdef CONFIG_RTC
36 # include <linux/timex.h>
37 #endif
38
39 #ifdef CONFIG_PROC_FS
40 # include <linux/seq_file.h>
41 #endif
42
43 #include <asm/bootparam.h>
44 #include <asm/mmu_context.h>
45 #include <asm/pgtable.h>
46 #include <asm/processor.h>
47 #include <asm/timex.h>
48 #include <asm/platform.h>
49 #include <asm/page.h>
50 #include <asm/setup.h>
51 #include <asm/param.h>
52 #include <asm/traps.h>
53 #include <asm/smp.h>
54 #include <asm/sysmem.h>
55
56 #include <platform/hardware.h>
57
58 #if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE)
59 struct screen_info screen_info = { 0, 24, 0, 0, 0, 80, 0, 0, 0, 24, 1, 16};
60 #endif
61
62 #ifdef CONFIG_BLK_DEV_FD
63 extern struct fd_ops no_fd_ops;
64 struct fd_ops *fd_ops;
65 #endif
66
67 extern struct rtc_ops no_rtc_ops;
68 struct rtc_ops *rtc_ops;
69
70 #ifdef CONFIG_BLK_DEV_INITRD
71 extern unsigned long initrd_start;
72 extern unsigned long initrd_end;
73 int initrd_is_mapped = 0;
74 extern int initrd_below_start_ok;
75 #endif
76
77 #ifdef CONFIG_OF
78 void *dtb_start = __dtb_start;
79 #endif
80
81 unsigned char aux_device_present;
82 extern unsigned long loops_per_jiffy;
83
84 /* Command line specified as configuration option. */
85
86 static char __initdata command_line[COMMAND_LINE_SIZE];
87
88 #ifdef CONFIG_CMDLINE_BOOL
89 static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
90 #endif
91
92 /*
93  * Boot parameter parsing.
94  *
95  * The Xtensa port uses a list of variable-sized tags to pass data to
96  * the kernel. The first tag must be a BP_TAG_FIRST tag for the list
97  * to be recognised. The list is terminated with a zero-sized
98  * BP_TAG_LAST tag.
99  */
100
101 typedef struct tagtable {
102         u32 tag;
103         int (*parse)(const bp_tag_t*);
104 } tagtable_t;
105
106 #define __tagtable(tag, fn) static tagtable_t __tagtable_##fn           \
107         __attribute__((used, section(".taglist"))) = { tag, fn }
108
109 /* parse current tag */
110
111 static int __init parse_tag_mem(const bp_tag_t *tag)
112 {
113         struct bp_meminfo *mi = (struct bp_meminfo *)(tag->data);
114
115         if (mi->type != MEMORY_TYPE_CONVENTIONAL)
116                 return -1;
117
118         return memblock_add(mi->start, mi->end - mi->start);
119 }
120
121 __tagtable(BP_TAG_MEMORY, parse_tag_mem);
122
123 #ifdef CONFIG_BLK_DEV_INITRD
124
125 static int __init parse_tag_initrd(const bp_tag_t* tag)
126 {
127         struct bp_meminfo *mi = (struct bp_meminfo *)(tag->data);
128
129         initrd_start = (unsigned long)__va(mi->start);
130         initrd_end = (unsigned long)__va(mi->end);
131
132         return 0;
133 }
134
135 __tagtable(BP_TAG_INITRD, parse_tag_initrd);
136
137 #ifdef CONFIG_OF
138
139 static int __init parse_tag_fdt(const bp_tag_t *tag)
140 {
141         dtb_start = __va(tag->data[0]);
142         return 0;
143 }
144
145 __tagtable(BP_TAG_FDT, parse_tag_fdt);
146
147 #endif /* CONFIG_OF */
148
149 #endif /* CONFIG_BLK_DEV_INITRD */
150
151 static int __init parse_tag_cmdline(const bp_tag_t* tag)
152 {
153         strlcpy(command_line, (char *)(tag->data), COMMAND_LINE_SIZE);
154         return 0;
155 }
156
157 __tagtable(BP_TAG_COMMAND_LINE, parse_tag_cmdline);
158
159 static int __init parse_bootparam(const bp_tag_t* tag)
160 {
161         extern tagtable_t __tagtable_begin, __tagtable_end;
162         tagtable_t *t;
163
164         /* Boot parameters must start with a BP_TAG_FIRST tag. */
165
166         if (tag->id != BP_TAG_FIRST) {
167                 printk(KERN_WARNING "Invalid boot parameters!\n");
168                 return 0;
169         }
170
171         tag = (bp_tag_t*)((unsigned long)tag + sizeof(bp_tag_t) + tag->size);
172
173         /* Parse all tags. */
174
175         while (tag != NULL && tag->id != BP_TAG_LAST) {
176                 for (t = &__tagtable_begin; t < &__tagtable_end; t++) {
177                         if (tag->id == t->tag) {
178                                 t->parse(tag);
179                                 break;
180                         }
181                 }
182                 if (t == &__tagtable_end)
183                         printk(KERN_WARNING "Ignoring tag "
184                                "0x%08x\n", tag->id);
185                 tag = (bp_tag_t*)((unsigned long)(tag + 1) + tag->size);
186         }
187
188         return 0;
189 }
190
191 #ifdef CONFIG_OF
192
193 #if !XCHAL_HAVE_PTP_MMU || XCHAL_HAVE_SPANNING_WAY
194 unsigned long xtensa_kio_paddr = XCHAL_KIO_DEFAULT_PADDR;
195 EXPORT_SYMBOL(xtensa_kio_paddr);
196
197 static int __init xtensa_dt_io_area(unsigned long node, const char *uname,
198                 int depth, void *data)
199 {
200         const __be32 *ranges;
201         int len;
202
203         if (depth > 1)
204                 return 0;
205
206         if (!of_flat_dt_is_compatible(node, "simple-bus"))
207                 return 0;
208
209         ranges = of_get_flat_dt_prop(node, "ranges", &len);
210         if (!ranges)
211                 return 1;
212         if (len == 0)
213                 return 1;
214
215         xtensa_kio_paddr = of_read_ulong(ranges+1, 1);
216         /* round down to nearest 256MB boundary */
217         xtensa_kio_paddr &= 0xf0000000;
218
219         return 1;
220 }
221 #else
222 static int __init xtensa_dt_io_area(unsigned long node, const char *uname,
223                 int depth, void *data)
224 {
225         return 1;
226 }
227 #endif
228
229 void __init early_init_dt_add_memory_arch(u64 base, u64 size)
230 {
231         size &= PAGE_MASK;
232         memblock_add(base, size);
233 }
234
235 void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align)
236 {
237         return __alloc_bootmem(size, align, 0);
238 }
239
240 void __init early_init_devtree(void *params)
241 {
242         early_init_dt_scan(params);
243         of_scan_flat_dt(xtensa_dt_io_area, NULL);
244
245         if (!command_line[0])
246                 strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE);
247 }
248
249 static int __init xtensa_device_probe(void)
250 {
251         of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
252         return 0;
253 }
254
255 device_initcall(xtensa_device_probe);
256
257 #endif /* CONFIG_OF */
258
259 /*
260  * Initialize architecture. (Early stage)
261  */
262
263 void __init init_arch(bp_tag_t *bp_start)
264 {
265         /* Parse boot parameters */
266
267         if (bp_start)
268                 parse_bootparam(bp_start);
269
270 #ifdef CONFIG_OF
271         early_init_devtree(dtb_start);
272 #endif
273
274 #ifdef CONFIG_CMDLINE_BOOL
275         if (!command_line[0])
276                 strlcpy(command_line, default_command_line, COMMAND_LINE_SIZE);
277 #endif
278
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
292 extern char _end;
293 extern char _stext;
294 extern char _WindowVectors_text_start;
295 extern char _WindowVectors_text_end;
296 extern char _DebugInterruptVector_literal_start;
297 extern char _DebugInterruptVector_text_end;
298 extern char _KernelExceptionVector_literal_start;
299 extern char _KernelExceptionVector_text_end;
300 extern char _UserExceptionVector_literal_start;
301 extern char _UserExceptionVector_text_end;
302 extern char _DoubleExceptionVector_literal_start;
303 extern char _DoubleExceptionVector_text_end;
304 #if XCHAL_EXCM_LEVEL >= 2
305 extern char _Level2InterruptVector_text_start;
306 extern char _Level2InterruptVector_text_end;
307 #endif
308 #if XCHAL_EXCM_LEVEL >= 3
309 extern char _Level3InterruptVector_text_start;
310 extern char _Level3InterruptVector_text_end;
311 #endif
312 #if XCHAL_EXCM_LEVEL >= 4
313 extern char _Level4InterruptVector_text_start;
314 extern char _Level4InterruptVector_text_end;
315 #endif
316 #if XCHAL_EXCM_LEVEL >= 5
317 extern char _Level5InterruptVector_text_start;
318 extern char _Level5InterruptVector_text_end;
319 #endif
320 #if XCHAL_EXCM_LEVEL >= 6
321 extern char _Level6InterruptVector_text_start;
322 extern char _Level6InterruptVector_text_end;
323 #endif
324 #ifdef CONFIG_SMP
325 extern char _SecondaryResetVector_text_start;
326 extern char _SecondaryResetVector_text_end;
327 #endif
328
329
330 #ifdef CONFIG_S32C1I_SELFTEST
331 #if XCHAL_HAVE_S32C1I
332
333 static 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  */
340 static 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
358 static void __init do_probed_exception(struct pt_regs *regs,
359                 unsigned long exccause)
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
371 static int __init check_s32c1i(void)
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);
426         return 0;
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 */
433 static int __init check_s32c1i(void)
434 {
435         pr_warn("Processor configuration lacks atomic compare-and-swap support!\n");
436         return 0;
437 }
438
439 #endif /* XCHAL_HAVE_S32C1I */
440 early_initcall(check_s32c1i);
441 #endif /* CONFIG_S32C1I_SELFTEST */
442
443 static inline int mem_reserve(unsigned long start, unsigned long end)
444 {
445         return memblock_reserve(start, end - start);
446 }
447
448 void __init setup_arch(char **cmdline_p)
449 {
450         strlcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
451         *cmdline_p = command_line;
452
453         /* Reserve some memory regions */
454
455 #ifdef CONFIG_BLK_DEV_INITRD
456         if (initrd_start < initrd_end) {
457                 initrd_is_mapped = mem_reserve(__pa(initrd_start),
458                                                __pa(initrd_end)) == 0;
459                 initrd_below_start_ok = 1;
460         } else {
461                 initrd_start = 0;
462         }
463 #endif
464
465         mem_reserve(__pa(&_stext), __pa(&_end));
466
467         mem_reserve(__pa(&_WindowVectors_text_start),
468                     __pa(&_WindowVectors_text_end));
469
470         mem_reserve(__pa(&_DebugInterruptVector_literal_start),
471                     __pa(&_DebugInterruptVector_text_end));
472
473         mem_reserve(__pa(&_KernelExceptionVector_literal_start),
474                     __pa(&_KernelExceptionVector_text_end));
475
476         mem_reserve(__pa(&_UserExceptionVector_literal_start),
477                     __pa(&_UserExceptionVector_text_end));
478
479         mem_reserve(__pa(&_DoubleExceptionVector_literal_start),
480                     __pa(&_DoubleExceptionVector_text_end));
481
482 #if XCHAL_EXCM_LEVEL >= 2
483         mem_reserve(__pa(&_Level2InterruptVector_text_start),
484                     __pa(&_Level2InterruptVector_text_end));
485 #endif
486 #if XCHAL_EXCM_LEVEL >= 3
487         mem_reserve(__pa(&_Level3InterruptVector_text_start),
488                     __pa(&_Level3InterruptVector_text_end));
489 #endif
490 #if XCHAL_EXCM_LEVEL >= 4
491         mem_reserve(__pa(&_Level4InterruptVector_text_start),
492                     __pa(&_Level4InterruptVector_text_end));
493 #endif
494 #if XCHAL_EXCM_LEVEL >= 5
495         mem_reserve(__pa(&_Level5InterruptVector_text_start),
496                     __pa(&_Level5InterruptVector_text_end));
497 #endif
498 #if XCHAL_EXCM_LEVEL >= 6
499         mem_reserve(__pa(&_Level6InterruptVector_text_start),
500                     __pa(&_Level6InterruptVector_text_end));
501 #endif
502
503 #ifdef CONFIG_SMP
504         mem_reserve(__pa(&_SecondaryResetVector_text_start),
505                     __pa(&_SecondaryResetVector_text_end));
506 #endif
507         parse_early_param();
508         bootmem_init();
509
510         unflatten_and_copy_device_tree();
511
512         platform_setup(cmdline_p);
513
514 #ifdef CONFIG_SMP
515         smp_init_cpus();
516 #endif
517
518         paging_init();
519         zones_init();
520
521 #ifdef CONFIG_VT
522 # if defined(CONFIG_VGA_CONSOLE)
523         conswitchp = &vga_con;
524 # elif defined(CONFIG_DUMMY_CONSOLE)
525         conswitchp = &dummy_con;
526 # endif
527 #endif
528
529 #ifdef CONFIG_PCI
530         platform_pcibios_init();
531 #endif
532 }
533
534 static DEFINE_PER_CPU(struct cpu, cpu_data);
535
536 static int __init topology_init(void)
537 {
538         int i;
539
540         for_each_possible_cpu(i) {
541                 struct cpu *cpu = &per_cpu(cpu_data, i);
542                 cpu->hotpluggable = !!i;
543                 register_cpu(cpu, i);
544         }
545
546         return 0;
547 }
548 subsys_initcall(topology_init);
549
550 void cpu_reset(void)
551 {
552 #if XCHAL_HAVE_PTP_MMU
553         local_irq_disable();
554         /*
555          * We have full MMU: all autoload ways, ways 7, 8 and 9 of DTLB must
556          * be flushed.
557          * Way 4 is not currently used by linux.
558          * Ways 5 and 6 shall not be touched on MMUv2 as they are hardwired.
559          * Way 5 shall be flushed and way 6 shall be set to identity mapping
560          * on MMUv3.
561          */
562         local_flush_tlb_all();
563         invalidate_page_directory();
564 #if XCHAL_HAVE_SPANNING_WAY
565         /* MMU v3 */
566         {
567                 unsigned long vaddr = (unsigned long)cpu_reset;
568                 unsigned long paddr = __pa(vaddr);
569                 unsigned long tmpaddr = vaddr + SZ_512M;
570                 unsigned long tmp0, tmp1, tmp2, tmp3;
571
572                 /*
573                  * Find a place for the temporary mapping. It must not be
574                  * in the same 512MB region with vaddr or paddr, otherwise
575                  * there may be multihit exception either on entry to the
576                  * temporary mapping, or on entry to the identity mapping.
577                  * (512MB is the biggest page size supported by TLB.)
578                  */
579                 while (((tmpaddr ^ paddr) & -SZ_512M) == 0)
580                         tmpaddr += SZ_512M;
581
582                 /* Invalidate mapping in the selected temporary area */
583                 if (itlb_probe(tmpaddr) & 0x8)
584                         invalidate_itlb_entry(itlb_probe(tmpaddr));
585                 if (itlb_probe(tmpaddr + PAGE_SIZE) & 0x8)
586                         invalidate_itlb_entry(itlb_probe(tmpaddr + PAGE_SIZE));
587
588                 /*
589                  * Map two consecutive pages starting at the physical address
590                  * of this function to the temporary mapping area.
591                  */
592                 write_itlb_entry(__pte((paddr & PAGE_MASK) |
593                                        _PAGE_HW_VALID |
594                                        _PAGE_HW_EXEC |
595                                        _PAGE_CA_BYPASS),
596                                  tmpaddr & PAGE_MASK);
597                 write_itlb_entry(__pte(((paddr & PAGE_MASK) + PAGE_SIZE) |
598                                        _PAGE_HW_VALID |
599                                        _PAGE_HW_EXEC |
600                                        _PAGE_CA_BYPASS),
601                                  (tmpaddr & PAGE_MASK) + PAGE_SIZE);
602
603                 /* Reinitialize TLB */
604                 __asm__ __volatile__ ("movi     %0, 1f\n\t"
605                                       "movi     %3, 2f\n\t"
606                                       "add      %0, %0, %4\n\t"
607                                       "add      %3, %3, %5\n\t"
608                                       "jx       %0\n"
609                                       /*
610                                        * No literal, data or stack access
611                                        * below this point
612                                        */
613                                       "1:\n\t"
614                                       /* Initialize *tlbcfg */
615                                       "movi     %0, 0\n\t"
616                                       "wsr      %0, itlbcfg\n\t"
617                                       "wsr      %0, dtlbcfg\n\t"
618                                       /* Invalidate TLB way 5 */
619                                       "movi     %0, 4\n\t"
620                                       "movi     %1, 5\n"
621                                       "1:\n\t"
622                                       "iitlb    %1\n\t"
623                                       "idtlb    %1\n\t"
624                                       "add      %1, %1, %6\n\t"
625                                       "addi     %0, %0, -1\n\t"
626                                       "bnez     %0, 1b\n\t"
627                                       /* Initialize TLB way 6 */
628                                       "movi     %0, 7\n\t"
629                                       "addi     %1, %9, 3\n\t"
630                                       "addi     %2, %9, 6\n"
631                                       "1:\n\t"
632                                       "witlb    %1, %2\n\t"
633                                       "wdtlb    %1, %2\n\t"
634                                       "add      %1, %1, %7\n\t"
635                                       "add      %2, %2, %7\n\t"
636                                       "addi     %0, %0, -1\n\t"
637                                       "bnez     %0, 1b\n\t"
638                                       /* Jump to identity mapping */
639                                       "jx       %3\n"
640                                       "2:\n\t"
641                                       /* Complete way 6 initialization */
642                                       "witlb    %1, %2\n\t"
643                                       "wdtlb    %1, %2\n\t"
644                                       /* Invalidate temporary mapping */
645                                       "sub      %0, %9, %7\n\t"
646                                       "iitlb    %0\n\t"
647                                       "add      %0, %0, %8\n\t"
648                                       "iitlb    %0"
649                                       : "=&a"(tmp0), "=&a"(tmp1), "=&a"(tmp2),
650                                         "=&a"(tmp3)
651                                       : "a"(tmpaddr - vaddr),
652                                         "a"(paddr - vaddr),
653                                         "a"(SZ_128M), "a"(SZ_512M),
654                                         "a"(PAGE_SIZE),
655                                         "a"((tmpaddr + SZ_512M) & PAGE_MASK)
656                                       : "memory");
657         }
658 #endif
659 #endif
660         __asm__ __volatile__ ("movi     a2, 0\n\t"
661                               "wsr      a2, icountlevel\n\t"
662                               "movi     a2, 0\n\t"
663                               "wsr      a2, icount\n\t"
664 #if XCHAL_NUM_IBREAK > 0
665                               "wsr      a2, ibreakenable\n\t"
666 #endif
667 #if XCHAL_HAVE_LOOPS
668                               "wsr      a2, lcount\n\t"
669 #endif
670                               "movi     a2, 0x1f\n\t"
671                               "wsr      a2, ps\n\t"
672                               "isync\n\t"
673                               "jx       %0\n\t"
674                               :
675                               : "a" (XCHAL_RESET_VECTOR_VADDR)
676                               : "a2");
677         for (;;)
678                 ;
679 }
680
681 void machine_restart(char * cmd)
682 {
683         platform_restart();
684 }
685
686 void machine_halt(void)
687 {
688         platform_halt();
689         while (1);
690 }
691
692 void machine_power_off(void)
693 {
694         platform_power_off();
695         while (1);
696 }
697 #ifdef CONFIG_PROC_FS
698
699 /*
700  * Display some core information through /proc/cpuinfo.
701  */
702
703 static int
704 c_show(struct seq_file *f, void *slot)
705 {
706         /* high-level stuff */
707         seq_printf(f, "CPU count\t: %u\n"
708                       "CPU list\t: %*pbl\n"
709                       "vendor_id\t: Tensilica\n"
710                       "model\t\t: Xtensa " XCHAL_HW_VERSION_NAME "\n"
711                       "core ID\t\t: " XCHAL_CORE_ID "\n"
712                       "build ID\t: 0x%x\n"
713                       "byte order\t: %s\n"
714                       "cpu MHz\t\t: %lu.%02lu\n"
715                       "bogomips\t: %lu.%02lu\n",
716                       num_online_cpus(),
717                       cpumask_pr_args(cpu_online_mask),
718                       XCHAL_BUILD_UNIQUE_ID,
719                       XCHAL_HAVE_BE ?  "big" : "little",
720                       ccount_freq/1000000,
721                       (ccount_freq/10000) % 100,
722                       loops_per_jiffy/(500000/HZ),
723                       (loops_per_jiffy/(5000/HZ)) % 100);
724
725         seq_printf(f,"flags\t\t: "
726 #if XCHAL_HAVE_NMI
727                      "nmi "
728 #endif
729 #if XCHAL_HAVE_DEBUG
730                      "debug "
731 # if XCHAL_HAVE_OCD
732                      "ocd "
733 # endif
734 #endif
735 #if XCHAL_HAVE_DENSITY
736                      "density "
737 #endif
738 #if XCHAL_HAVE_BOOLEANS
739                      "boolean "
740 #endif
741 #if XCHAL_HAVE_LOOPS
742                      "loop "
743 #endif
744 #if XCHAL_HAVE_NSA
745                      "nsa "
746 #endif
747 #if XCHAL_HAVE_MINMAX
748                      "minmax "
749 #endif
750 #if XCHAL_HAVE_SEXT
751                      "sext "
752 #endif
753 #if XCHAL_HAVE_CLAMPS
754                      "clamps "
755 #endif
756 #if XCHAL_HAVE_MAC16
757                      "mac16 "
758 #endif
759 #if XCHAL_HAVE_MUL16
760                      "mul16 "
761 #endif
762 #if XCHAL_HAVE_MUL32
763                      "mul32 "
764 #endif
765 #if XCHAL_HAVE_MUL32_HIGH
766                      "mul32h "
767 #endif
768 #if XCHAL_HAVE_FP
769                      "fpu "
770 #endif
771 #if XCHAL_HAVE_S32C1I
772                      "s32c1i "
773 #endif
774                      "\n");
775
776         /* Registers. */
777         seq_printf(f,"physical aregs\t: %d\n"
778                      "misc regs\t: %d\n"
779                      "ibreak\t\t: %d\n"
780                      "dbreak\t\t: %d\n",
781                      XCHAL_NUM_AREGS,
782                      XCHAL_NUM_MISC_REGS,
783                      XCHAL_NUM_IBREAK,
784                      XCHAL_NUM_DBREAK);
785
786
787         /* Interrupt. */
788         seq_printf(f,"num ints\t: %d\n"
789                      "ext ints\t: %d\n"
790                      "int levels\t: %d\n"
791                      "timers\t\t: %d\n"
792                      "debug level\t: %d\n",
793                      XCHAL_NUM_INTERRUPTS,
794                      XCHAL_NUM_EXTINTERRUPTS,
795                      XCHAL_NUM_INTLEVELS,
796                      XCHAL_NUM_TIMERS,
797                      XCHAL_DEBUGLEVEL);
798
799         /* Cache */
800         seq_printf(f,"icache line size: %d\n"
801                      "icache ways\t: %d\n"
802                      "icache size\t: %d\n"
803                      "icache flags\t: "
804 #if XCHAL_ICACHE_LINE_LOCKABLE
805                      "lock "
806 #endif
807                      "\n"
808                      "dcache line size: %d\n"
809                      "dcache ways\t: %d\n"
810                      "dcache size\t: %d\n"
811                      "dcache flags\t: "
812 #if XCHAL_DCACHE_IS_WRITEBACK
813                      "writeback "
814 #endif
815 #if XCHAL_DCACHE_LINE_LOCKABLE
816                      "lock "
817 #endif
818                      "\n",
819                      XCHAL_ICACHE_LINESIZE,
820                      XCHAL_ICACHE_WAYS,
821                      XCHAL_ICACHE_SIZE,
822                      XCHAL_DCACHE_LINESIZE,
823                      XCHAL_DCACHE_WAYS,
824                      XCHAL_DCACHE_SIZE);
825
826         return 0;
827 }
828
829 /*
830  * We show only CPU #0 info.
831  */
832 static void *
833 c_start(struct seq_file *f, loff_t *pos)
834 {
835         return (*pos == 0) ? (void *)1 : NULL;
836 }
837
838 static void *
839 c_next(struct seq_file *f, void *v, loff_t *pos)
840 {
841         return NULL;
842 }
843
844 static void
845 c_stop(struct seq_file *f, void *v)
846 {
847 }
848
849 const struct seq_operations cpuinfo_op =
850 {
851         .start  = c_start,
852         .next   = c_next,
853         .stop   = c_stop,
854         .show   = c_show,
855 };
856
857 #endif /* CONFIG_PROC_FS */