diff options
Diffstat (limited to 'arch/xtensa/kernel/setup.c')
-rw-r--r-- | arch/xtensa/kernel/setup.c | 131 |
1 files changed, 94 insertions, 37 deletions
diff --git a/arch/xtensa/kernel/setup.c b/arch/xtensa/kernel/setup.c index 6e2b6638122d..7d12af1317f1 100644 --- a/arch/xtensa/kernel/setup.c +++ b/arch/xtensa/kernel/setup.c | |||
@@ -21,6 +21,8 @@ | |||
21 | #include <linux/screen_info.h> | 21 | #include <linux/screen_info.h> |
22 | #include <linux/bootmem.h> | 22 | #include <linux/bootmem.h> |
23 | #include <linux/kernel.h> | 23 | #include <linux/kernel.h> |
24 | #include <linux/percpu.h> | ||
25 | #include <linux/cpu.h> | ||
24 | #include <linux/of_fdt.h> | 26 | #include <linux/of_fdt.h> |
25 | #include <linux/of_platform.h> | 27 | #include <linux/of_platform.h> |
26 | 28 | ||
@@ -37,6 +39,7 @@ | |||
37 | #endif | 39 | #endif |
38 | 40 | ||
39 | #include <asm/bootparam.h> | 41 | #include <asm/bootparam.h> |
42 | #include <asm/mmu_context.h> | ||
40 | #include <asm/pgtable.h> | 43 | #include <asm/pgtable.h> |
41 | #include <asm/processor.h> | 44 | #include <asm/processor.h> |
42 | #include <asm/timex.h> | 45 | #include <asm/timex.h> |
@@ -45,6 +48,7 @@ | |||
45 | #include <asm/setup.h> | 48 | #include <asm/setup.h> |
46 | #include <asm/param.h> | 49 | #include <asm/param.h> |
47 | #include <asm/traps.h> | 50 | #include <asm/traps.h> |
51 | #include <asm/smp.h> | ||
48 | 52 | ||
49 | #include <platform/hardware.h> | 53 | #include <platform/hardware.h> |
50 | 54 | ||
@@ -85,12 +89,6 @@ static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE; | |||
85 | 89 | ||
86 | sysmem_info_t __initdata sysmem; | 90 | sysmem_info_t __initdata sysmem; |
87 | 91 | ||
88 | #ifdef CONFIG_MMU | ||
89 | extern void init_mmu(void); | ||
90 | #else | ||
91 | static inline void init_mmu(void) { } | ||
92 | #endif | ||
93 | |||
94 | extern int mem_reserve(unsigned long, unsigned long, int); | 92 | extern int mem_reserve(unsigned long, unsigned long, int); |
95 | extern void bootmem_init(void); | 93 | extern void bootmem_init(void); |
96 | extern void zones_init(void); | 94 | extern void zones_init(void); |
@@ -214,6 +212,42 @@ static int __init parse_bootparam(const bp_tag_t* tag) | |||
214 | #ifdef CONFIG_OF | 212 | #ifdef CONFIG_OF |
215 | bool __initdata dt_memory_scan = false; | 213 | bool __initdata dt_memory_scan = false; |
216 | 214 | ||
215 | #if XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY | ||
216 | unsigned long xtensa_kio_paddr = XCHAL_KIO_DEFAULT_PADDR; | ||
217 | EXPORT_SYMBOL(xtensa_kio_paddr); | ||
218 | |||
219 | static int __init xtensa_dt_io_area(unsigned long node, const char *uname, | ||
220 | int depth, void *data) | ||
221 | { | ||
222 | const __be32 *ranges; | ||
223 | unsigned long len; | ||
224 | |||
225 | if (depth > 1) | ||
226 | return 0; | ||
227 | |||
228 | if (!of_flat_dt_is_compatible(node, "simple-bus")) | ||
229 | return 0; | ||
230 | |||
231 | ranges = of_get_flat_dt_prop(node, "ranges", &len); | ||
232 | if (!ranges) | ||
233 | return 1; | ||
234 | if (len == 0) | ||
235 | return 1; | ||
236 | |||
237 | xtensa_kio_paddr = of_read_ulong(ranges+1, 1); | ||
238 | /* round down to nearest 256MB boundary */ | ||
239 | xtensa_kio_paddr &= 0xf0000000; | ||
240 | |||
241 | return 1; | ||
242 | } | ||
243 | #else | ||
244 | static int __init xtensa_dt_io_area(unsigned long node, const char *uname, | ||
245 | int depth, void *data) | ||
246 | { | ||
247 | return 1; | ||
248 | } | ||
249 | #endif | ||
250 | |||
217 | void __init early_init_dt_add_memory_arch(u64 base, u64 size) | 251 | void __init early_init_dt_add_memory_arch(u64 base, u64 size) |
218 | { | 252 | { |
219 | if (!dt_memory_scan) | 253 | if (!dt_memory_scan) |
@@ -234,6 +268,7 @@ void __init early_init_devtree(void *params) | |||
234 | dt_memory_scan = true; | 268 | dt_memory_scan = true; |
235 | 269 | ||
236 | early_init_dt_scan(params); | 270 | early_init_dt_scan(params); |
271 | of_scan_flat_dt(xtensa_dt_io_area, NULL); | ||
237 | 272 | ||
238 | if (!command_line[0]) | 273 | if (!command_line[0]) |
239 | strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE); | 274 | strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE); |
@@ -241,7 +276,7 @@ void __init early_init_devtree(void *params) | |||
241 | 276 | ||
242 | static int __init xtensa_device_probe(void) | 277 | static int __init xtensa_device_probe(void) |
243 | { | 278 | { |
244 | of_platform_populate(NULL, NULL, NULL, NULL); | 279 | of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); |
245 | return 0; | 280 | return 0; |
246 | } | 281 | } |
247 | 282 | ||
@@ -354,7 +389,8 @@ static inline int probed_compare_swap(int *v, int cmp, int set) | |||
354 | 389 | ||
355 | /* Handle probed exception */ | 390 | /* Handle probed exception */ |
356 | 391 | ||
357 | void __init do_probed_exception(struct pt_regs *regs, unsigned long exccause) | 392 | static void __init do_probed_exception(struct pt_regs *regs, |
393 | unsigned long exccause) | ||
358 | { | 394 | { |
359 | if (regs->pc == rcw_probe_pc) { /* exception on s32c1i ? */ | 395 | if (regs->pc == rcw_probe_pc) { /* exception on s32c1i ? */ |
360 | regs->pc += 3; /* skip the s32c1i instruction */ | 396 | regs->pc += 3; /* skip the s32c1i instruction */ |
@@ -366,7 +402,7 @@ void __init do_probed_exception(struct pt_regs *regs, unsigned long exccause) | |||
366 | 402 | ||
367 | /* Simple test of S32C1I (soc bringup assist) */ | 403 | /* Simple test of S32C1I (soc bringup assist) */ |
368 | 404 | ||
369 | void __init check_s32c1i(void) | 405 | static int __init check_s32c1i(void) |
370 | { | 406 | { |
371 | int n, cause1, cause2; | 407 | int n, cause1, cause2; |
372 | void *handbus, *handdata, *handaddr; /* temporarily saved handlers */ | 408 | void *handbus, *handdata, *handaddr; /* temporarily saved handlers */ |
@@ -421,24 +457,21 @@ void __init check_s32c1i(void) | |||
421 | trap_set_handler(EXCCAUSE_LOAD_STORE_ERROR, handbus); | 457 | trap_set_handler(EXCCAUSE_LOAD_STORE_ERROR, handbus); |
422 | trap_set_handler(EXCCAUSE_LOAD_STORE_DATA_ERROR, handdata); | 458 | trap_set_handler(EXCCAUSE_LOAD_STORE_DATA_ERROR, handdata); |
423 | trap_set_handler(EXCCAUSE_LOAD_STORE_ADDR_ERROR, handaddr); | 459 | trap_set_handler(EXCCAUSE_LOAD_STORE_ADDR_ERROR, handaddr); |
460 | return 0; | ||
424 | } | 461 | } |
425 | 462 | ||
426 | #else /* XCHAL_HAVE_S32C1I */ | 463 | #else /* XCHAL_HAVE_S32C1I */ |
427 | 464 | ||
428 | /* This condition should not occur with a commercially deployed processor. | 465 | /* This condition should not occur with a commercially deployed processor. |
429 | Display reminder for early engr test or demo chips / FPGA bitstreams */ | 466 | Display reminder for early engr test or demo chips / FPGA bitstreams */ |
430 | void __init check_s32c1i(void) | 467 | static int __init check_s32c1i(void) |
431 | { | 468 | { |
432 | pr_warn("Processor configuration lacks atomic compare-and-swap support!\n"); | 469 | pr_warn("Processor configuration lacks atomic compare-and-swap support!\n"); |
470 | return 0; | ||
433 | } | 471 | } |
434 | 472 | ||
435 | #endif /* XCHAL_HAVE_S32C1I */ | 473 | #endif /* XCHAL_HAVE_S32C1I */ |
436 | #else /* CONFIG_S32C1I_SELFTEST */ | 474 | early_initcall(check_s32c1i); |
437 | |||
438 | void __init check_s32c1i(void) | ||
439 | { | ||
440 | } | ||
441 | |||
442 | #endif /* CONFIG_S32C1I_SELFTEST */ | 475 | #endif /* CONFIG_S32C1I_SELFTEST */ |
443 | 476 | ||
444 | 477 | ||
@@ -447,8 +480,6 @@ void __init setup_arch(char **cmdline_p) | |||
447 | strlcpy(boot_command_line, command_line, COMMAND_LINE_SIZE); | 480 | strlcpy(boot_command_line, command_line, COMMAND_LINE_SIZE); |
448 | *cmdline_p = command_line; | 481 | *cmdline_p = command_line; |
449 | 482 | ||
450 | check_s32c1i(); | ||
451 | |||
452 | /* Reserve some memory regions */ | 483 | /* Reserve some memory regions */ |
453 | 484 | ||
454 | #ifdef CONFIG_BLK_DEV_INITRD | 485 | #ifdef CONFIG_BLK_DEV_INITRD |
@@ -505,6 +536,10 @@ void __init setup_arch(char **cmdline_p) | |||
505 | 536 | ||
506 | platform_setup(cmdline_p); | 537 | platform_setup(cmdline_p); |
507 | 538 | ||
539 | #ifdef CONFIG_SMP | ||
540 | smp_init_cpus(); | ||
541 | #endif | ||
542 | |||
508 | paging_init(); | 543 | paging_init(); |
509 | zones_init(); | 544 | zones_init(); |
510 | 545 | ||
@@ -521,6 +556,22 @@ void __init setup_arch(char **cmdline_p) | |||
521 | #endif | 556 | #endif |
522 | } | 557 | } |
523 | 558 | ||
559 | static DEFINE_PER_CPU(struct cpu, cpu_data); | ||
560 | |||
561 | static int __init topology_init(void) | ||
562 | { | ||
563 | int i; | ||
564 | |||
565 | for_each_possible_cpu(i) { | ||
566 | struct cpu *cpu = &per_cpu(cpu_data, i); | ||
567 | cpu->hotpluggable = !!i; | ||
568 | register_cpu(cpu, i); | ||
569 | } | ||
570 | |||
571 | return 0; | ||
572 | } | ||
573 | subsys_initcall(topology_init); | ||
574 | |||
524 | void machine_restart(char * cmd) | 575 | void machine_restart(char * cmd) |
525 | { | 576 | { |
526 | platform_restart(); | 577 | platform_restart(); |
@@ -546,21 +597,27 @@ void machine_power_off(void) | |||
546 | static int | 597 | static int |
547 | c_show(struct seq_file *f, void *slot) | 598 | c_show(struct seq_file *f, void *slot) |
548 | { | 599 | { |
600 | char buf[NR_CPUS * 5]; | ||
601 | |||
602 | cpulist_scnprintf(buf, sizeof(buf), cpu_online_mask); | ||
549 | /* high-level stuff */ | 603 | /* high-level stuff */ |
550 | seq_printf(f,"processor\t: 0\n" | 604 | seq_printf(f, "CPU count\t: %u\n" |
551 | "vendor_id\t: Tensilica\n" | 605 | "CPU list\t: %s\n" |
552 | "model\t\t: Xtensa " XCHAL_HW_VERSION_NAME "\n" | 606 | "vendor_id\t: Tensilica\n" |
553 | "core ID\t\t: " XCHAL_CORE_ID "\n" | 607 | "model\t\t: Xtensa " XCHAL_HW_VERSION_NAME "\n" |
554 | "build ID\t: 0x%x\n" | 608 | "core ID\t\t: " XCHAL_CORE_ID "\n" |
555 | "byte order\t: %s\n" | 609 | "build ID\t: 0x%x\n" |
556 | "cpu MHz\t\t: %lu.%02lu\n" | 610 | "byte order\t: %s\n" |
557 | "bogomips\t: %lu.%02lu\n", | 611 | "cpu MHz\t\t: %lu.%02lu\n" |
558 | XCHAL_BUILD_UNIQUE_ID, | 612 | "bogomips\t: %lu.%02lu\n", |
559 | XCHAL_HAVE_BE ? "big" : "little", | 613 | num_online_cpus(), |
560 | ccount_freq/1000000, | 614 | buf, |
561 | (ccount_freq/10000) % 100, | 615 | XCHAL_BUILD_UNIQUE_ID, |
562 | loops_per_jiffy/(500000/HZ), | 616 | XCHAL_HAVE_BE ? "big" : "little", |
563 | (loops_per_jiffy/(5000/HZ)) % 100); | 617 | ccount_freq/1000000, |
618 | (ccount_freq/10000) % 100, | ||
619 | loops_per_jiffy/(500000/HZ), | ||
620 | (loops_per_jiffy/(5000/HZ)) % 100); | ||
564 | 621 | ||
565 | seq_printf(f,"flags\t\t: " | 622 | seq_printf(f,"flags\t\t: " |
566 | #if XCHAL_HAVE_NMI | 623 | #if XCHAL_HAVE_NMI |
@@ -672,7 +729,7 @@ c_show(struct seq_file *f, void *slot) | |||
672 | static void * | 729 | static void * |
673 | c_start(struct seq_file *f, loff_t *pos) | 730 | c_start(struct seq_file *f, loff_t *pos) |
674 | { | 731 | { |
675 | return (void *) ((*pos == 0) ? (void *)1 : NULL); | 732 | return (*pos == 0) ? (void *)1 : NULL; |
676 | } | 733 | } |
677 | 734 | ||
678 | static void * | 735 | static void * |
@@ -688,10 +745,10 @@ c_stop(struct seq_file *f, void *v) | |||
688 | 745 | ||
689 | const struct seq_operations cpuinfo_op = | 746 | const struct seq_operations cpuinfo_op = |
690 | { | 747 | { |
691 | start: c_start, | 748 | .start = c_start, |
692 | next: c_next, | 749 | .next = c_next, |
693 | stop: c_stop, | 750 | .stop = c_stop, |
694 | show: c_show | 751 | .show = c_show, |
695 | }; | 752 | }; |
696 | 753 | ||
697 | #endif /* CONFIG_PROC_FS */ | 754 | #endif /* CONFIG_PROC_FS */ |