diff options
Diffstat (limited to 'arch/arc/kernel')
-rw-r--r-- | arch/arc/kernel/devtree.c | 47 | ||||
-rw-r--r-- | arch/arc/kernel/irq.c | 7 | ||||
-rw-r--r-- | arch/arc/kernel/setup.c | 28 | ||||
-rw-r--r-- | arch/arc/kernel/smp.c | 3 | ||||
-rw-r--r-- | arch/arc/kernel/time.c | 4 | ||||
-rw-r--r-- | arch/arc/kernel/vmlinux.lds.S | 6 |
6 files changed, 84 insertions, 11 deletions
diff --git a/arch/arc/kernel/devtree.c b/arch/arc/kernel/devtree.c index c8166dc..a7d98b3 100644 --- a/arch/arc/kernel/devtree.c +++ b/arch/arc/kernel/devtree.c @@ -16,6 +16,7 @@ #include <linux/of_fdt.h> #include <asm/prom.h> #include <asm/clk.h> +#include <asm/mach_desc.h> /* called from unflatten_device_tree() to bootstrap devicetree itself */ void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align) @@ -30,27 +31,57 @@ void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align) * If a dtb was passed to the kernel, then use it to choose the correct * machine_desc and to setup the system. */ -int __init setup_machine_fdt(void *dt) +struct machine_desc * __init setup_machine_fdt(void *dt) { struct boot_param_header *devtree = dt; + struct machine_desc *mdesc = NULL, *mdesc_best = NULL; + unsigned int score, mdesc_score = ~1; unsigned long dt_root; - char *model, *compat; + const char *model, *compat; void *clk; char manufacturer[16]; unsigned long len; /* check device tree validity */ if (be32_to_cpu(devtree->magic) != OF_DT_HEADER) - return 1; + return NULL; - /* Search the mdescs for the 'best' compatible value match */ initial_boot_params = devtree; dt_root = of_get_flat_dt_root(); + /* + * The kernel could be multi-platform enabled, thus could have many + * "baked-in" machine descriptors. Search thru all for the best + * "compatible" string match. + */ + for_each_machine_desc(mdesc) { + score = of_flat_dt_match(dt_root, mdesc->dt_compat); + if (score > 0 && score < mdesc_score) { + mdesc_best = mdesc; + mdesc_score = score; + } + } + if (!mdesc_best) { + const char *prop; + long size; + + pr_err("\n unrecognized device tree list:\n[ "); + + prop = of_get_flat_dt_prop(dt_root, "compatible", &size); + if (prop) { + while (size > 0) { + printk("'%s' ", prop); + size -= strlen(prop) + 1; + prop += strlen(prop) + 1; + } + } + printk("]\n\n"); + + machine_halt(); + } + /* compat = "<manufacturer>,<model>" */ - compat = of_get_flat_dt_prop(dt_root, "compatible", NULL); - if (!compat) - compat = "<unknown>"; + compat = mdesc_best->dt_compat[0]; model = strchr(compat, ','); if (model) @@ -73,5 +104,5 @@ int __init setup_machine_fdt(void *dt) if (clk) arc_set_core_freq(of_read_ulong(clk, len/4)); - return 0; + return mdesc_best; } diff --git a/arch/arc/kernel/irq.c b/arch/arc/kernel/irq.c index df7da2b..11981688 100644 --- a/arch/arc/kernel/irq.c +++ b/arch/arc/kernel/irq.c @@ -13,6 +13,7 @@ #include <linux/irqdomain.h> #include <asm/sections.h> #include <asm/irq.h> +#include <asm/mach_desc.h> /* * Early Hardware specific Interrupt setup @@ -125,9 +126,15 @@ void __init init_IRQ(void) init_onchip_IRQ(); plat_init_IRQ(); + /* Any external intc can be setup here */ + if (machine_desc->init_irq) + machine_desc->init_irq(); + #ifdef CONFIG_SMP /* Master CPU can initialize it's side of IPI */ arc_platform_smp_init_cpu(); + if (machine_desc->init_smp) + machine_desc->init_smp(smp_processor_id()); #endif } diff --git a/arch/arc/kernel/setup.c b/arch/arc/kernel/setup.c index 6cc361c..20273b8 100644 --- a/arch/arc/kernel/setup.c +++ b/arch/arc/kernel/setup.c @@ -25,12 +25,14 @@ #include <asm/prom.h> #include <asm/unwind.h> #include <asm/clk.h> +#include <asm/mach_desc.h> #define FIX_PTR(x) __asm__ __volatile__(";" : "+r"(x)) int running_on_hw = 1; /* vs. on ISS */ char __initdata command_line[COMMAND_LINE_SIZE]; +struct machine_desc *machine_desc __initdata; struct task_struct *_current_task[NR_CPUS]; /* For stack switching */ @@ -323,8 +325,6 @@ void __init __attribute__((weak)) arc_platform_early_init(void) void __init setup_arch(char **cmdline_p) { - int rc; - #ifdef CONFIG_CMDLINE_UBOOT /* Make sure that a whitespace is inserted before */ strlcat(command_line, " ", sizeof(command_line)); @@ -339,13 +339,17 @@ void __init setup_arch(char **cmdline_p) strlcpy(boot_command_line, command_line, COMMAND_LINE_SIZE); *cmdline_p = command_line; - rc = setup_machine_fdt(__dtb_start); + machine_desc = setup_machine_fdt(__dtb_start); + if (!machine_desc) + panic("Embedded DT invalid\n"); /* To force early parsing of things like mem=xxx */ parse_early_param(); /* Platform/board specific: e.g. early console registration */ arc_platform_early_init(); + if (machine_desc->init_early) + machine_desc->init_early(); setup_processor(); @@ -372,6 +376,24 @@ void __init setup_arch(char **cmdline_p) arc_unwind_setup(); } +static int __init customize_machine(void) +{ + /* Add platform devices */ + if (machine_desc->init_machine) + machine_desc->init_machine(); + + return 0; +} +arch_initcall(customize_machine); + +static int __init init_late_machine(void) +{ + if (machine_desc->init_late) + machine_desc->init_late(); + + return 0; +} +late_initcall(init_late_machine); /* * Get CPU information for use by the procfs. */ diff --git a/arch/arc/kernel/smp.c b/arch/arc/kernel/smp.c index 1f762ad..ea15f07 100644 --- a/arch/arc/kernel/smp.c +++ b/arch/arc/kernel/smp.c @@ -32,6 +32,7 @@ #include <linux/reboot.h> #include <asm/processor.h> #include <asm/setup.h> +#include <asm/mach_desc.h> arch_spinlock_t smp_atomic_ops_lock = __ARCH_SPIN_LOCK_UNLOCKED; arch_spinlock_t smp_bitops_lock = __ARCH_SPIN_LOCK_UNLOCKED; @@ -127,6 +128,8 @@ void __cpuinit start_kernel_secondary(void) pr_info("## CPU%u LIVE ##: Executing Code...\n", cpu); arc_platform_smp_init_cpu(); + if (machine_desc->init_smp) + machine_desc->init_smp(smp_processor_id()); arc_local_timer_setup(cpu); diff --git a/arch/arc/kernel/time.c b/arch/arc/kernel/time.c index 05dba11..0ce0e6f 100644 --- a/arch/arc/kernel/time.c +++ b/arch/arc/kernel/time.c @@ -43,6 +43,7 @@ #include <asm/irq.h> #include <asm/arcregs.h> #include <asm/clk.h> +#include <asm/mach_desc.h> #define ARC_TIMER_MAX 0xFFFFFFFF @@ -258,6 +259,9 @@ void __init time_init(void) /* sets up the periodic event timer */ arc_local_timer_setup(smp_processor_id()); + + if (machine_desc->init_time) + machine_desc->init_time(); } #ifdef CONFIG_ARC_HAS_RTSC diff --git a/arch/arc/kernel/vmlinux.lds.S b/arch/arc/kernel/vmlinux.lds.S index 8d3b0d4..622d8b6 100644 --- a/arch/arc/kernel/vmlinux.lds.S +++ b/arch/arc/kernel/vmlinux.lds.S @@ -75,6 +75,12 @@ SECTIONS SECURITY_INITCALL } + .init.arch.info : { + __arch_info_begin = .; + *(.arch.info.init) + __arch_info_end = .; + } + PERCPU_SECTION(L1_CACHE_BYTES) /* |