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 c8166dc02c38..a7d98b30358b 100644 --- a/arch/arc/kernel/devtree.c +++ b/arch/arc/kernel/devtree.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/of_fdt.h> | 16 | #include <linux/of_fdt.h> |
17 | #include <asm/prom.h> | 17 | #include <asm/prom.h> |
18 | #include <asm/clk.h> | 18 | #include <asm/clk.h> |
19 | #include <asm/mach_desc.h> | ||
19 | 20 | ||
20 | /* called from unflatten_device_tree() to bootstrap devicetree itself */ | 21 | /* called from unflatten_device_tree() to bootstrap devicetree itself */ |
21 | void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align) | 22 | 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) | |||
30 | * If a dtb was passed to the kernel, then use it to choose the correct | 31 | * If a dtb was passed to the kernel, then use it to choose the correct |
31 | * machine_desc and to setup the system. | 32 | * machine_desc and to setup the system. |
32 | */ | 33 | */ |
33 | int __init setup_machine_fdt(void *dt) | 34 | struct machine_desc * __init setup_machine_fdt(void *dt) |
34 | { | 35 | { |
35 | struct boot_param_header *devtree = dt; | 36 | struct boot_param_header *devtree = dt; |
37 | struct machine_desc *mdesc = NULL, *mdesc_best = NULL; | ||
38 | unsigned int score, mdesc_score = ~1; | ||
36 | unsigned long dt_root; | 39 | unsigned long dt_root; |
37 | char *model, *compat; | 40 | const char *model, *compat; |
38 | void *clk; | 41 | void *clk; |
39 | char manufacturer[16]; | 42 | char manufacturer[16]; |
40 | unsigned long len; | 43 | unsigned long len; |
41 | 44 | ||
42 | /* check device tree validity */ | 45 | /* check device tree validity */ |
43 | if (be32_to_cpu(devtree->magic) != OF_DT_HEADER) | 46 | if (be32_to_cpu(devtree->magic) != OF_DT_HEADER) |
44 | return 1; | 47 | return NULL; |
45 | 48 | ||
46 | /* Search the mdescs for the 'best' compatible value match */ | ||
47 | initial_boot_params = devtree; | 49 | initial_boot_params = devtree; |
48 | dt_root = of_get_flat_dt_root(); | 50 | dt_root = of_get_flat_dt_root(); |
49 | 51 | ||
52 | /* | ||
53 | * The kernel could be multi-platform enabled, thus could have many | ||
54 | * "baked-in" machine descriptors. Search thru all for the best | ||
55 | * "compatible" string match. | ||
56 | */ | ||
57 | for_each_machine_desc(mdesc) { | ||
58 | score = of_flat_dt_match(dt_root, mdesc->dt_compat); | ||
59 | if (score > 0 && score < mdesc_score) { | ||
60 | mdesc_best = mdesc; | ||
61 | mdesc_score = score; | ||
62 | } | ||
63 | } | ||
64 | if (!mdesc_best) { | ||
65 | const char *prop; | ||
66 | long size; | ||
67 | |||
68 | pr_err("\n unrecognized device tree list:\n[ "); | ||
69 | |||
70 | prop = of_get_flat_dt_prop(dt_root, "compatible", &size); | ||
71 | if (prop) { | ||
72 | while (size > 0) { | ||
73 | printk("'%s' ", prop); | ||
74 | size -= strlen(prop) + 1; | ||
75 | prop += strlen(prop) + 1; | ||
76 | } | ||
77 | } | ||
78 | printk("]\n\n"); | ||
79 | |||
80 | machine_halt(); | ||
81 | } | ||
82 | |||
50 | /* compat = "<manufacturer>,<model>" */ | 83 | /* compat = "<manufacturer>,<model>" */ |
51 | compat = of_get_flat_dt_prop(dt_root, "compatible", NULL); | 84 | compat = mdesc_best->dt_compat[0]; |
52 | if (!compat) | ||
53 | compat = "<unknown>"; | ||
54 | 85 | ||
55 | model = strchr(compat, ','); | 86 | model = strchr(compat, ','); |
56 | if (model) | 87 | if (model) |
@@ -73,5 +104,5 @@ int __init setup_machine_fdt(void *dt) | |||
73 | if (clk) | 104 | if (clk) |
74 | arc_set_core_freq(of_read_ulong(clk, len/4)); | 105 | arc_set_core_freq(of_read_ulong(clk, len/4)); |
75 | 106 | ||
76 | return 0; | 107 | return mdesc_best; |
77 | } | 108 | } |
diff --git a/arch/arc/kernel/irq.c b/arch/arc/kernel/irq.c index df7da2b5a5bd..1198168850e8 100644 --- a/arch/arc/kernel/irq.c +++ b/arch/arc/kernel/irq.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/irqdomain.h> | 13 | #include <linux/irqdomain.h> |
14 | #include <asm/sections.h> | 14 | #include <asm/sections.h> |
15 | #include <asm/irq.h> | 15 | #include <asm/irq.h> |
16 | #include <asm/mach_desc.h> | ||
16 | 17 | ||
17 | /* | 18 | /* |
18 | * Early Hardware specific Interrupt setup | 19 | * Early Hardware specific Interrupt setup |
@@ -125,9 +126,15 @@ void __init init_IRQ(void) | |||
125 | init_onchip_IRQ(); | 126 | init_onchip_IRQ(); |
126 | plat_init_IRQ(); | 127 | plat_init_IRQ(); |
127 | 128 | ||
129 | /* Any external intc can be setup here */ | ||
130 | if (machine_desc->init_irq) | ||
131 | machine_desc->init_irq(); | ||
132 | |||
128 | #ifdef CONFIG_SMP | 133 | #ifdef CONFIG_SMP |
129 | /* Master CPU can initialize it's side of IPI */ | 134 | /* Master CPU can initialize it's side of IPI */ |
130 | arc_platform_smp_init_cpu(); | 135 | arc_platform_smp_init_cpu(); |
136 | if (machine_desc->init_smp) | ||
137 | machine_desc->init_smp(smp_processor_id()); | ||
131 | #endif | 138 | #endif |
132 | } | 139 | } |
133 | 140 | ||
diff --git a/arch/arc/kernel/setup.c b/arch/arc/kernel/setup.c index 6cc361c6751a..20273b89e545 100644 --- a/arch/arc/kernel/setup.c +++ b/arch/arc/kernel/setup.c | |||
@@ -25,12 +25,14 @@ | |||
25 | #include <asm/prom.h> | 25 | #include <asm/prom.h> |
26 | #include <asm/unwind.h> | 26 | #include <asm/unwind.h> |
27 | #include <asm/clk.h> | 27 | #include <asm/clk.h> |
28 | #include <asm/mach_desc.h> | ||
28 | 29 | ||
29 | #define FIX_PTR(x) __asm__ __volatile__(";" : "+r"(x)) | 30 | #define FIX_PTR(x) __asm__ __volatile__(";" : "+r"(x)) |
30 | 31 | ||
31 | int running_on_hw = 1; /* vs. on ISS */ | 32 | int running_on_hw = 1; /* vs. on ISS */ |
32 | 33 | ||
33 | char __initdata command_line[COMMAND_LINE_SIZE]; | 34 | char __initdata command_line[COMMAND_LINE_SIZE]; |
35 | struct machine_desc *machine_desc __initdata; | ||
34 | 36 | ||
35 | struct task_struct *_current_task[NR_CPUS]; /* For stack switching */ | 37 | struct task_struct *_current_task[NR_CPUS]; /* For stack switching */ |
36 | 38 | ||
@@ -323,8 +325,6 @@ void __init __attribute__((weak)) arc_platform_early_init(void) | |||
323 | 325 | ||
324 | void __init setup_arch(char **cmdline_p) | 326 | void __init setup_arch(char **cmdline_p) |
325 | { | 327 | { |
326 | int rc; | ||
327 | |||
328 | #ifdef CONFIG_CMDLINE_UBOOT | 328 | #ifdef CONFIG_CMDLINE_UBOOT |
329 | /* Make sure that a whitespace is inserted before */ | 329 | /* Make sure that a whitespace is inserted before */ |
330 | strlcat(command_line, " ", sizeof(command_line)); | 330 | strlcat(command_line, " ", sizeof(command_line)); |
@@ -339,13 +339,17 @@ void __init setup_arch(char **cmdline_p) | |||
339 | strlcpy(boot_command_line, command_line, COMMAND_LINE_SIZE); | 339 | strlcpy(boot_command_line, command_line, COMMAND_LINE_SIZE); |
340 | *cmdline_p = command_line; | 340 | *cmdline_p = command_line; |
341 | 341 | ||
342 | rc = setup_machine_fdt(__dtb_start); | 342 | machine_desc = setup_machine_fdt(__dtb_start); |
343 | if (!machine_desc) | ||
344 | panic("Embedded DT invalid\n"); | ||
343 | 345 | ||
344 | /* To force early parsing of things like mem=xxx */ | 346 | /* To force early parsing of things like mem=xxx */ |
345 | parse_early_param(); | 347 | parse_early_param(); |
346 | 348 | ||
347 | /* Platform/board specific: e.g. early console registration */ | 349 | /* Platform/board specific: e.g. early console registration */ |
348 | arc_platform_early_init(); | 350 | arc_platform_early_init(); |
351 | if (machine_desc->init_early) | ||
352 | machine_desc->init_early(); | ||
349 | 353 | ||
350 | setup_processor(); | 354 | setup_processor(); |
351 | 355 | ||
@@ -372,6 +376,24 @@ void __init setup_arch(char **cmdline_p) | |||
372 | arc_unwind_setup(); | 376 | arc_unwind_setup(); |
373 | } | 377 | } |
374 | 378 | ||
379 | static int __init customize_machine(void) | ||
380 | { | ||
381 | /* Add platform devices */ | ||
382 | if (machine_desc->init_machine) | ||
383 | machine_desc->init_machine(); | ||
384 | |||
385 | return 0; | ||
386 | } | ||
387 | arch_initcall(customize_machine); | ||
388 | |||
389 | static int __init init_late_machine(void) | ||
390 | { | ||
391 | if (machine_desc->init_late) | ||
392 | machine_desc->init_late(); | ||
393 | |||
394 | return 0; | ||
395 | } | ||
396 | late_initcall(init_late_machine); | ||
375 | /* | 397 | /* |
376 | * Get CPU information for use by the procfs. | 398 | * Get CPU information for use by the procfs. |
377 | */ | 399 | */ |
diff --git a/arch/arc/kernel/smp.c b/arch/arc/kernel/smp.c index 1f762ad6969b..ea15f073452f 100644 --- a/arch/arc/kernel/smp.c +++ b/arch/arc/kernel/smp.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <linux/reboot.h> | 32 | #include <linux/reboot.h> |
33 | #include <asm/processor.h> | 33 | #include <asm/processor.h> |
34 | #include <asm/setup.h> | 34 | #include <asm/setup.h> |
35 | #include <asm/mach_desc.h> | ||
35 | 36 | ||
36 | arch_spinlock_t smp_atomic_ops_lock = __ARCH_SPIN_LOCK_UNLOCKED; | 37 | arch_spinlock_t smp_atomic_ops_lock = __ARCH_SPIN_LOCK_UNLOCKED; |
37 | arch_spinlock_t smp_bitops_lock = __ARCH_SPIN_LOCK_UNLOCKED; | 38 | arch_spinlock_t smp_bitops_lock = __ARCH_SPIN_LOCK_UNLOCKED; |
@@ -127,6 +128,8 @@ void __cpuinit start_kernel_secondary(void) | |||
127 | pr_info("## CPU%u LIVE ##: Executing Code...\n", cpu); | 128 | pr_info("## CPU%u LIVE ##: Executing Code...\n", cpu); |
128 | 129 | ||
129 | arc_platform_smp_init_cpu(); | 130 | arc_platform_smp_init_cpu(); |
131 | if (machine_desc->init_smp) | ||
132 | machine_desc->init_smp(smp_processor_id()); | ||
130 | 133 | ||
131 | arc_local_timer_setup(cpu); | 134 | arc_local_timer_setup(cpu); |
132 | 135 | ||
diff --git a/arch/arc/kernel/time.c b/arch/arc/kernel/time.c index 05dba11fdb2d..0ce0e6f76eb0 100644 --- a/arch/arc/kernel/time.c +++ b/arch/arc/kernel/time.c | |||
@@ -43,6 +43,7 @@ | |||
43 | #include <asm/irq.h> | 43 | #include <asm/irq.h> |
44 | #include <asm/arcregs.h> | 44 | #include <asm/arcregs.h> |
45 | #include <asm/clk.h> | 45 | #include <asm/clk.h> |
46 | #include <asm/mach_desc.h> | ||
46 | 47 | ||
47 | #define ARC_TIMER_MAX 0xFFFFFFFF | 48 | #define ARC_TIMER_MAX 0xFFFFFFFF |
48 | 49 | ||
@@ -258,6 +259,9 @@ void __init time_init(void) | |||
258 | 259 | ||
259 | /* sets up the periodic event timer */ | 260 | /* sets up the periodic event timer */ |
260 | arc_local_timer_setup(smp_processor_id()); | 261 | arc_local_timer_setup(smp_processor_id()); |
262 | |||
263 | if (machine_desc->init_time) | ||
264 | machine_desc->init_time(); | ||
261 | } | 265 | } |
262 | 266 | ||
263 | #ifdef CONFIG_ARC_HAS_RTSC | 267 | #ifdef CONFIG_ARC_HAS_RTSC |
diff --git a/arch/arc/kernel/vmlinux.lds.S b/arch/arc/kernel/vmlinux.lds.S index 8d3b0d447498..622d8b665a68 100644 --- a/arch/arc/kernel/vmlinux.lds.S +++ b/arch/arc/kernel/vmlinux.lds.S | |||
@@ -75,6 +75,12 @@ SECTIONS | |||
75 | SECURITY_INITCALL | 75 | SECURITY_INITCALL |
76 | } | 76 | } |
77 | 77 | ||
78 | .init.arch.info : { | ||
79 | __arch_info_begin = .; | ||
80 | *(.arch.info.init) | ||
81 | __arch_info_end = .; | ||
82 | } | ||
83 | |||
78 | PERCPU_SECTION(L1_CACHE_BYTES) | 84 | PERCPU_SECTION(L1_CACHE_BYTES) |
79 | 85 | ||
80 | /* | 86 | /* |