diff options
Diffstat (limited to 'arch/xtensa/kernel/setup.c')
| -rw-r--r-- | arch/xtensa/kernel/setup.c | 235 |
1 files changed, 121 insertions, 114 deletions
diff --git a/arch/xtensa/kernel/setup.c b/arch/xtensa/kernel/setup.c index 946fb8d06c8..06370ccea9e 100644 --- a/arch/xtensa/kernel/setup.c +++ b/arch/xtensa/kernel/setup.c @@ -21,11 +21,11 @@ #include <linux/screen_info.h> #include <linux/bootmem.h> #include <linux/kernel.h> - -#ifdef CONFIG_OF +#include <linux/percpu.h> +#include <linux/clk-provider.h> +#include <linux/cpu.h> #include <linux/of_fdt.h> #include <linux/of_platform.h> -#endif #if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE) # include <linux/console.h> @@ -40,6 +40,7 @@ #endif #include <asm/bootparam.h> +#include <asm/mmu_context.h> #include <asm/pgtable.h> #include <asm/processor.h> #include <asm/timex.h> @@ -48,6 +49,8 @@ #include <asm/setup.h> #include <asm/param.h> #include <asm/traps.h> +#include <asm/smp.h> +#include <asm/sysmem.h> #include <platform/hardware.h> @@ -64,14 +67,13 @@ extern struct rtc_ops no_rtc_ops; struct rtc_ops *rtc_ops; #ifdef CONFIG_BLK_DEV_INITRD -extern void *initrd_start; -extern void *initrd_end; +extern unsigned long initrd_start; +extern unsigned long initrd_end; int initrd_is_mapped = 0; extern int initrd_below_start_ok; #endif #ifdef CONFIG_OF -extern u32 __dtb_start[]; void *dtb_start = __dtb_start; #endif @@ -86,18 +88,6 @@ static char __initdata command_line[COMMAND_LINE_SIZE]; static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE; #endif -sysmem_info_t __initdata sysmem; - -#ifdef CONFIG_MMU -extern void init_mmu(void); -#else -static inline void init_mmu(void) { } -#endif - -extern int mem_reserve(unsigned long, unsigned long, int); -extern void bootmem_init(void); -extern void zones_init(void); - /* * Boot parameter parsing. * @@ -117,31 +107,14 @@ typedef struct tagtable { /* parse current tag */ -static int __init add_sysmem_bank(unsigned long type, unsigned long start, - unsigned long end) -{ - if (sysmem.nr_banks >= SYSMEM_BANKS_MAX) { - printk(KERN_WARNING - "Ignoring memory bank 0x%08lx size %ldKB\n", - start, end - start); - return -EINVAL; - } - sysmem.bank[sysmem.nr_banks].type = type; - sysmem.bank[sysmem.nr_banks].start = PAGE_ALIGN(start); - sysmem.bank[sysmem.nr_banks].end = end & PAGE_MASK; - sysmem.nr_banks++; - - return 0; -} - static int __init parse_tag_mem(const bp_tag_t *tag) { - meminfo_t *mi = (meminfo_t *)(tag->data); + struct bp_meminfo *mi = (struct bp_meminfo *)(tag->data); if (mi->type != MEMORY_TYPE_CONVENTIONAL) return -1; - return add_sysmem_bank(mi->type, mi->start, mi->end); + return add_sysmem_bank(mi->start, mi->end); } __tagtable(BP_TAG_MEMORY, parse_tag_mem); @@ -150,10 +123,10 @@ __tagtable(BP_TAG_MEMORY, parse_tag_mem); static int __init parse_tag_initrd(const bp_tag_t* tag) { - meminfo_t* mi; - mi = (meminfo_t*)(tag->data); - initrd_start = __va(mi->start); - initrd_end = __va(mi->end); + struct bp_meminfo *mi = (struct bp_meminfo *)(tag->data); + + initrd_start = (unsigned long)__va(mi->start); + initrd_end = (unsigned long)__va(mi->end); return 0; } @@ -170,13 +143,6 @@ static int __init parse_tag_fdt(const bp_tag_t *tag) __tagtable(BP_TAG_FDT, parse_tag_fdt); -void __init early_init_dt_setup_initrd_arch(u64 start, u64 end) -{ - initrd_start = (void *)__va(start); - initrd_end = (void *)__va(end); - initrd_below_start_ok = 1; -} - #endif /* CONFIG_OF */ #endif /* CONFIG_BLK_DEV_INITRD */ @@ -222,11 +188,51 @@ static int __init parse_bootparam(const bp_tag_t* tag) } #ifdef CONFIG_OF +bool __initdata dt_memory_scan = false; + +#if XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY +unsigned long xtensa_kio_paddr = XCHAL_KIO_DEFAULT_PADDR; +EXPORT_SYMBOL(xtensa_kio_paddr); + +static int __init xtensa_dt_io_area(unsigned long node, const char *uname, + int depth, void *data) +{ + const __be32 *ranges; + int len; + + if (depth > 1) + return 0; + + if (!of_flat_dt_is_compatible(node, "simple-bus")) + return 0; + + ranges = of_get_flat_dt_prop(node, "ranges", &len); + if (!ranges) + return 1; + if (len == 0) + return 1; + + xtensa_kio_paddr = of_read_ulong(ranges+1, 1); + /* round down to nearest 256MB boundary */ + xtensa_kio_paddr &= 0xf0000000; + + return 1; +} +#else +static int __init xtensa_dt_io_area(unsigned long node, const char *uname, + int depth, void *data) +{ + return 1; +} +#endif void __init early_init_dt_add_memory_arch(u64 base, u64 size) { + if (!dt_memory_scan) + return; + size &= PAGE_MASK; - add_sysmem_bank(MEMORY_TYPE_CONVENTIONAL, base, base + size); + add_sysmem_bank(base, base + size); } void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align) @@ -236,36 +242,20 @@ void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align) void __init early_init_devtree(void *params) { - /* Setup flat device-tree pointer */ - initial_boot_params = params; - - /* Retrieve various informations from the /chosen node of the - * device-tree, including the platform type, initrd location and - * size, TCE reserve, and more ... - */ - if (!command_line[0]) - of_scan_flat_dt(early_init_dt_scan_chosen, command_line); - - /* Scan memory nodes and rebuild MEMBLOCKs */ - of_scan_flat_dt(early_init_dt_scan_root, NULL); if (sysmem.nr_banks == 0) - of_scan_flat_dt(early_init_dt_scan_memory, NULL); -} + dt_memory_scan = true; -static void __init copy_devtree(void) -{ - void *alloc = early_init_dt_alloc_memory_arch( - be32_to_cpu(initial_boot_params->totalsize), 8); - if (alloc) { - memcpy(alloc, initial_boot_params, - be32_to_cpu(initial_boot_params->totalsize)); - initial_boot_params = alloc; - } + early_init_dt_scan(params); + of_scan_flat_dt(xtensa_dt_io_area, NULL); + + if (!command_line[0]) + strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE); } static int __init xtensa_device_probe(void) { - of_platform_populate(NULL, NULL, NULL, NULL); + of_clk_init(NULL); + of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); return 0; } @@ -279,8 +269,6 @@ device_initcall(xtensa_device_probe); void __init init_arch(bp_tag_t *bp_start) { - sysmem.nr_banks = 0; - /* Parse boot parameters */ if (bp_start) @@ -291,10 +279,9 @@ void __init init_arch(bp_tag_t *bp_start) #endif if (sysmem.nr_banks == 0) { - sysmem.nr_banks = 1; - sysmem.bank[0].start = PLATFORM_DEFAULT_MEM_START; - sysmem.bank[0].end = PLATFORM_DEFAULT_MEM_START - + PLATFORM_DEFAULT_MEM_SIZE; + add_sysmem_bank(PLATFORM_DEFAULT_MEM_START, + PLATFORM_DEFAULT_MEM_START + + PLATFORM_DEFAULT_MEM_SIZE); } #ifdef CONFIG_CMDLINE_BOOL @@ -378,7 +365,8 @@ static inline int probed_compare_swap(int *v, int cmp, int set) /* Handle probed exception */ -void __init do_probed_exception(struct pt_regs *regs, unsigned long exccause) +static void __init do_probed_exception(struct pt_regs *regs, + unsigned long exccause) { if (regs->pc == rcw_probe_pc) { /* exception on s32c1i ? */ regs->pc += 3; /* skip the s32c1i instruction */ @@ -390,7 +378,7 @@ void __init do_probed_exception(struct pt_regs *regs, unsigned long exccause) /* Simple test of S32C1I (soc bringup assist) */ -void __init check_s32c1i(void) +static int __init check_s32c1i(void) { int n, cause1, cause2; void *handbus, *handdata, *handaddr; /* temporarily saved handlers */ @@ -445,24 +433,21 @@ void __init check_s32c1i(void) trap_set_handler(EXCCAUSE_LOAD_STORE_ERROR, handbus); trap_set_handler(EXCCAUSE_LOAD_STORE_DATA_ERROR, handdata); trap_set_handler(EXCCAUSE_LOAD_STORE_ADDR_ERROR, handaddr); + return 0; } #else /* XCHAL_HAVE_S32C1I */ /* This condition should not occur with a commercially deployed processor. Display reminder for early engr test or demo chips / FPGA bitstreams */ -void __init check_s32c1i(void) +static int __init check_s32c1i(void) { pr_warn("Processor configuration lacks atomic compare-and-swap support!\n"); + return 0; } #endif /* XCHAL_HAVE_S32C1I */ -#else /* CONFIG_S32C1I_SELFTEST */ - -void __init check_s32c1i(void) -{ -} - +early_initcall(check_s32c1i); #endif /* CONFIG_S32C1I_SELFTEST */ @@ -471,14 +456,12 @@ void __init setup_arch(char **cmdline_p) strlcpy(boot_command_line, command_line, COMMAND_LINE_SIZE); *cmdline_p = command_line; - check_s32c1i(); - /* Reserve some memory regions */ #ifdef CONFIG_BLK_DEV_INITRD if (initrd_start < initrd_end) { initrd_is_mapped = mem_reserve(__pa(initrd_start), - __pa(initrd_end), 0); + __pa(initrd_end), 0) == 0; initrd_below_start_ok = 1; } else { initrd_start = 0; @@ -523,15 +506,17 @@ void __init setup_arch(char **cmdline_p) __pa(&_Level6InterruptVector_text_end), 0); #endif + parse_early_param(); bootmem_init(); -#ifdef CONFIG_OF - copy_devtree(); - unflatten_device_tree(); -#endif + unflatten_and_copy_device_tree(); platform_setup(cmdline_p); +#ifdef CONFIG_SMP + smp_init_cpus(); +#endif + paging_init(); zones_init(); @@ -548,6 +533,22 @@ void __init setup_arch(char **cmdline_p) #endif } +static DEFINE_PER_CPU(struct cpu, cpu_data); + +static int __init topology_init(void) +{ + int i; + + for_each_possible_cpu(i) { + struct cpu *cpu = &per_cpu(cpu_data, i); + cpu->hotpluggable = !!i; + register_cpu(cpu, i); + } + + return 0; +} +subsys_initcall(topology_init); + void machine_restart(char * cmd) { platform_restart(); @@ -573,21 +574,27 @@ void machine_power_off(void) static int c_show(struct seq_file *f, void *slot) { + char buf[NR_CPUS * 5]; + + cpulist_scnprintf(buf, sizeof(buf), cpu_online_mask); /* high-level stuff */ - seq_printf(f,"processor\t: 0\n" - "vendor_id\t: Tensilica\n" - "model\t\t: Xtensa " XCHAL_HW_VERSION_NAME "\n" - "core ID\t\t: " XCHAL_CORE_ID "\n" - "build ID\t: 0x%x\n" - "byte order\t: %s\n" - "cpu MHz\t\t: %lu.%02lu\n" - "bogomips\t: %lu.%02lu\n", - XCHAL_BUILD_UNIQUE_ID, - XCHAL_HAVE_BE ? "big" : "little", - ccount_freq/1000000, - (ccount_freq/10000) % 100, - loops_per_jiffy/(500000/HZ), - (loops_per_jiffy/(5000/HZ)) % 100); + seq_printf(f, "CPU count\t: %u\n" + "CPU list\t: %s\n" + "vendor_id\t: Tensilica\n" + "model\t\t: Xtensa " XCHAL_HW_VERSION_NAME "\n" + "core ID\t\t: " XCHAL_CORE_ID "\n" + "build ID\t: 0x%x\n" + "byte order\t: %s\n" + "cpu MHz\t\t: %lu.%02lu\n" + "bogomips\t: %lu.%02lu\n", + num_online_cpus(), + buf, + XCHAL_BUILD_UNIQUE_ID, + XCHAL_HAVE_BE ? "big" : "little", + ccount_freq/1000000, + (ccount_freq/10000) % 100, + loops_per_jiffy/(500000/HZ), + (loops_per_jiffy/(5000/HZ)) % 100); seq_printf(f,"flags\t\t: " #if XCHAL_HAVE_NMI @@ -699,7 +706,7 @@ c_show(struct seq_file *f, void *slot) static void * c_start(struct seq_file *f, loff_t *pos) { - return (void *) ((*pos == 0) ? (void *)1 : NULL); + return (*pos == 0) ? (void *)1 : NULL; } static void * @@ -715,10 +722,10 @@ c_stop(struct seq_file *f, void *v) const struct seq_operations cpuinfo_op = { - start: c_start, - next: c_next, - stop: c_stop, - show: c_show + .start = c_start, + .next = c_next, + .stop = c_stop, + .show = c_show, }; #endif /* CONFIG_PROC_FS */ |
