diff options
-rw-r--r-- | Documentation/arm/Booting | 33 | ||||
-rw-r--r-- | Documentation/devicetree/booting-without-of.txt | 48 | ||||
-rw-r--r-- | arch/arm/Kconfig | 7 | ||||
-rw-r--r-- | arch/arm/include/asm/mach/arch.h | 9 | ||||
-rw-r--r-- | arch/arm/include/asm/prom.h | 37 | ||||
-rw-r--r-- | arch/arm/include/asm/setup.h | 4 | ||||
-rw-r--r-- | arch/arm/kernel/Makefile | 1 | ||||
-rw-r--r-- | arch/arm/kernel/devtree.c | 145 | ||||
-rw-r--r-- | arch/arm/kernel/head-common.S | 24 | ||||
-rw-r--r-- | arch/arm/kernel/head.S | 8 | ||||
-rw-r--r-- | arch/arm/kernel/setup.c | 90 | ||||
-rw-r--r-- | arch/arm/mm/init.c | 11 | ||||
-rw-r--r-- | arch/microblaze/kernel/prom.c | 2 | ||||
-rw-r--r-- | arch/mips/include/asm/prom.h | 3 | ||||
-rw-r--r-- | arch/mips/kernel/prom.c | 3 | ||||
-rw-r--r-- | arch/powerpc/kernel/prom.c | 2 | ||||
-rw-r--r-- | drivers/of/fdt.c | 8 |
17 files changed, 375 insertions, 60 deletions
diff --git a/Documentation/arm/Booting b/Documentation/arm/Booting index 76850295af8f..4e686a2ed91e 100644 --- a/Documentation/arm/Booting +++ b/Documentation/arm/Booting | |||
@@ -65,13 +65,19 @@ looks at the connected hardware is beyond the scope of this document. | |||
65 | The boot loader must ultimately be able to provide a MACH_TYPE_xxx | 65 | The boot loader must ultimately be able to provide a MACH_TYPE_xxx |
66 | value to the kernel. (see linux/arch/arm/tools/mach-types). | 66 | value to the kernel. (see linux/arch/arm/tools/mach-types). |
67 | 67 | ||
68 | 68 | 4. Setup boot data | |
69 | 4. Setup the kernel tagged list | 69 | ------------------ |
70 | ------------------------------- | ||
71 | 70 | ||
72 | Existing boot loaders: OPTIONAL, HIGHLY RECOMMENDED | 71 | Existing boot loaders: OPTIONAL, HIGHLY RECOMMENDED |
73 | New boot loaders: MANDATORY | 72 | New boot loaders: MANDATORY |
74 | 73 | ||
74 | The boot loader must provide either a tagged list or a dtb image for | ||
75 | passing configuration data to the kernel. The physical address of the | ||
76 | boot data is passed to the kernel in register r2. | ||
77 | |||
78 | 4a. Setup the kernel tagged list | ||
79 | -------------------------------- | ||
80 | |||
75 | The boot loader must create and initialise the kernel tagged list. | 81 | The boot loader must create and initialise the kernel tagged list. |
76 | A valid tagged list starts with ATAG_CORE and ends with ATAG_NONE. | 82 | A valid tagged list starts with ATAG_CORE and ends with ATAG_NONE. |
77 | The ATAG_CORE tag may or may not be empty. An empty ATAG_CORE tag | 83 | The ATAG_CORE tag may or may not be empty. An empty ATAG_CORE tag |
@@ -101,6 +107,24 @@ The tagged list must be placed in a region of memory where neither | |||
101 | the kernel decompressor nor initrd 'bootp' program will overwrite | 107 | the kernel decompressor nor initrd 'bootp' program will overwrite |
102 | it. The recommended placement is in the first 16KiB of RAM. | 108 | it. The recommended placement is in the first 16KiB of RAM. |
103 | 109 | ||
110 | 4b. Setup the device tree | ||
111 | ------------------------- | ||
112 | |||
113 | The boot loader must load a device tree image (dtb) into system ram | ||
114 | at a 64bit aligned address and initialize it with the boot data. The | ||
115 | dtb format is documented in Documentation/devicetree/booting-without-of.txt. | ||
116 | The kernel will look for the dtb magic value of 0xd00dfeed at the dtb | ||
117 | physical address to determine if a dtb has been passed instead of a | ||
118 | tagged list. | ||
119 | |||
120 | The boot loader must pass at a minimum the size and location of the | ||
121 | system memory, and the root filesystem location. The dtb must be | ||
122 | placed in a region of memory where the kernel decompressor will not | ||
123 | overwrite it. The recommended placement is in the first 16KiB of RAM | ||
124 | with the caveat that it may not be located at physical address 0 since | ||
125 | the kernel interprets a value of 0 in r2 to mean neither a tagged list | ||
126 | nor a dtb were passed. | ||
127 | |||
104 | 5. Calling the kernel image | 128 | 5. Calling the kernel image |
105 | --------------------------- | 129 | --------------------------- |
106 | 130 | ||
@@ -125,7 +149,8 @@ In either case, the following conditions must be met: | |||
125 | - CPU register settings | 149 | - CPU register settings |
126 | r0 = 0, | 150 | r0 = 0, |
127 | r1 = machine type number discovered in (3) above. | 151 | r1 = machine type number discovered in (3) above. |
128 | r2 = physical address of tagged list in system RAM. | 152 | r2 = physical address of tagged list in system RAM, or |
153 | physical address of device tree block (dtb) in system RAM | ||
129 | 154 | ||
130 | - CPU mode | 155 | - CPU mode |
131 | All forms of interrupts must be disabled (IRQs and FIQs) | 156 | All forms of interrupts must be disabled (IRQs and FIQs) |
diff --git a/Documentation/devicetree/booting-without-of.txt b/Documentation/devicetree/booting-without-of.txt index 50619a0720a8..7c1329de0596 100644 --- a/Documentation/devicetree/booting-without-of.txt +++ b/Documentation/devicetree/booting-without-of.txt | |||
@@ -12,8 +12,9 @@ Table of Contents | |||
12 | ================= | 12 | ================= |
13 | 13 | ||
14 | I - Introduction | 14 | I - Introduction |
15 | 1) Entry point for arch/powerpc | 15 | 1) Entry point for arch/arm |
16 | 2) Entry point for arch/x86 | 16 | 2) Entry point for arch/powerpc |
17 | 3) Entry point for arch/x86 | ||
17 | 18 | ||
18 | II - The DT block format | 19 | II - The DT block format |
19 | 1) Header | 20 | 1) Header |
@@ -148,7 +149,46 @@ upgrades without significantly impacting the kernel code or cluttering | |||
148 | it with special cases. | 149 | it with special cases. |
149 | 150 | ||
150 | 151 | ||
151 | 1) Entry point for arch/powerpc | 152 | 1) Entry point for arch/arm |
153 | --------------------------- | ||
154 | |||
155 | There is one single entry point to the kernel, at the start | ||
156 | of the kernel image. That entry point supports two calling | ||
157 | conventions. A summary of the interface is described here. A full | ||
158 | description of the boot requirements is documented in | ||
159 | Documentation/arm/Booting | ||
160 | |||
161 | a) ATAGS interface. Minimal information is passed from firmware | ||
162 | to the kernel with a tagged list of predefined parameters. | ||
163 | |||
164 | r0 : 0 | ||
165 | |||
166 | r1 : Machine type number | ||
167 | |||
168 | r2 : Physical address of tagged list in system RAM | ||
169 | |||
170 | b) Entry with a flattened device-tree block. Firmware loads the | ||
171 | physical address of the flattened device tree block (dtb) into r2, | ||
172 | r1 is not used, but it is considered good practise to use a valid | ||
173 | machine number as described in Documentation/arm/Booting. | ||
174 | |||
175 | r0 : 0 | ||
176 | |||
177 | r1 : Valid machine type number. When using a device tree, | ||
178 | a single machine type number will often be assigned to | ||
179 | represent a class or family of SoCs. | ||
180 | |||
181 | r2 : physical pointer to the device-tree block | ||
182 | (defined in chapter II) in RAM. Device tree can be located | ||
183 | anywhere in system RAM, but it should be aligned on a 64 bit | ||
184 | boundary. | ||
185 | |||
186 | The kernel will differentiate between ATAGS and device tree booting by | ||
187 | reading the memory pointed to by r2 and looking for either the flattened | ||
188 | device tree block magic value (0xd00dfeed) or the ATAG_CORE value at | ||
189 | offset 0x4 from r2 (0x54410001). | ||
190 | |||
191 | 2) Entry point for arch/powerpc | ||
152 | ------------------------------- | 192 | ------------------------------- |
153 | 193 | ||
154 | There is one single entry point to the kernel, at the start | 194 | There is one single entry point to the kernel, at the start |
@@ -226,7 +266,7 @@ it with special cases. | |||
226 | cannot support both configurations with Book E and configurations | 266 | cannot support both configurations with Book E and configurations |
227 | with classic Powerpc architectures. | 267 | with classic Powerpc architectures. |
228 | 268 | ||
229 | 2) Entry point for arch/x86 | 269 | 3) Entry point for arch/x86 |
230 | ------------------------------- | 270 | ------------------------------- |
231 | 271 | ||
232 | There is one single 32bit entry point to the kernel at code32_start, | 272 | There is one single 32bit entry point to the kernel at code32_start, |
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 7275009686e6..3bc1a58cc7d8 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig | |||
@@ -1683,6 +1683,13 @@ endmenu | |||
1683 | 1683 | ||
1684 | menu "Boot options" | 1684 | menu "Boot options" |
1685 | 1685 | ||
1686 | config USE_OF | ||
1687 | bool "Flattened Device Tree support" | ||
1688 | select OF | ||
1689 | select OF_EARLY_FLATTREE | ||
1690 | help | ||
1691 | Include support for flattened device tree machine descriptions. | ||
1692 | |||
1686 | # Compressed boot loader in ROM. Yes, we really want to ask about | 1693 | # Compressed boot loader in ROM. Yes, we really want to ask about |
1687 | # TEXT and BSS so we preserve their values in the config files. | 1694 | # TEXT and BSS so we preserve their values in the config files. |
1688 | config ZBOOT_ROM_TEXT | 1695 | config ZBOOT_ROM_TEXT |
diff --git a/arch/arm/include/asm/mach/arch.h b/arch/arm/include/asm/mach/arch.h index bf13b814c1b8..946f4d778f71 100644 --- a/arch/arm/include/asm/mach/arch.h +++ b/arch/arm/include/asm/mach/arch.h | |||
@@ -18,6 +18,8 @@ struct machine_desc { | |||
18 | unsigned int nr; /* architecture number */ | 18 | unsigned int nr; /* architecture number */ |
19 | const char *name; /* architecture name */ | 19 | const char *name; /* architecture name */ |
20 | unsigned long boot_params; /* tagged list */ | 20 | unsigned long boot_params; /* tagged list */ |
21 | const char **dt_compat; /* array of device tree | ||
22 | * 'compatible' strings */ | ||
21 | 23 | ||
22 | unsigned int nr_irqs; /* number of IRQs */ | 24 | unsigned int nr_irqs; /* number of IRQs */ |
23 | 25 | ||
@@ -48,6 +50,13 @@ struct machine_desc { | |||
48 | extern struct machine_desc *machine_desc; | 50 | extern struct machine_desc *machine_desc; |
49 | 51 | ||
50 | /* | 52 | /* |
53 | * Machine type table - also only accessible during boot | ||
54 | */ | ||
55 | extern struct machine_desc __arch_info_begin[], __arch_info_end[]; | ||
56 | #define for_each_machine_desc(p) \ | ||
57 | for (p = __arch_info_begin; p < __arch_info_end; p++) | ||
58 | |||
59 | /* | ||
51 | * Set of macros to define architecture features. This is built into | 60 | * Set of macros to define architecture features. This is built into |
52 | * a table by the linker. | 61 | * a table by the linker. |
53 | */ | 62 | */ |
diff --git a/arch/arm/include/asm/prom.h b/arch/arm/include/asm/prom.h new file mode 100644 index 000000000000..11b8708fc4db --- /dev/null +++ b/arch/arm/include/asm/prom.h | |||
@@ -0,0 +1,37 @@ | |||
1 | /* | ||
2 | * arch/arm/include/asm/prom.h | ||
3 | * | ||
4 | * Copyright (C) 2009 Canonical Ltd. <jeremy.kerr@canonical.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | */ | ||
11 | #ifndef __ASMARM_PROM_H | ||
12 | #define __ASMARM_PROM_H | ||
13 | |||
14 | #ifdef CONFIG_OF | ||
15 | |||
16 | #include <asm/setup.h> | ||
17 | #include <asm/irq.h> | ||
18 | |||
19 | static inline void irq_dispose_mapping(unsigned int virq) | ||
20 | { | ||
21 | return; | ||
22 | } | ||
23 | |||
24 | extern struct machine_desc *setup_machine_fdt(unsigned int dt_phys); | ||
25 | extern void arm_dt_memblock_reserve(void); | ||
26 | |||
27 | #else /* CONFIG_OF */ | ||
28 | |||
29 | static inline struct machine_desc *setup_machine_fdt(unsigned int dt_phys) | ||
30 | { | ||
31 | return NULL; | ||
32 | } | ||
33 | |||
34 | static inline void arm_dt_memblock_reserve(void) { } | ||
35 | |||
36 | #endif /* CONFIG_OF */ | ||
37 | #endif /* ASMARM_PROM_H */ | ||
diff --git a/arch/arm/include/asm/setup.h b/arch/arm/include/asm/setup.h index 95176af3df8c..ee2ad8ae07af 100644 --- a/arch/arm/include/asm/setup.h +++ b/arch/arm/include/asm/setup.h | |||
@@ -217,6 +217,10 @@ extern struct meminfo meminfo; | |||
217 | #define bank_phys_end(bank) ((bank)->start + (bank)->size) | 217 | #define bank_phys_end(bank) ((bank)->start + (bank)->size) |
218 | #define bank_phys_size(bank) (bank)->size | 218 | #define bank_phys_size(bank) (bank)->size |
219 | 219 | ||
220 | extern int arm_add_memory(phys_addr_t start, unsigned long size); | ||
221 | extern void early_print(const char *str, ...); | ||
222 | extern void dump_machine_table(void); | ||
223 | |||
220 | #endif /* __KERNEL__ */ | 224 | #endif /* __KERNEL__ */ |
221 | 225 | ||
222 | #endif | 226 | #endif |
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile index 8d95446150a3..908c78cb1d1c 100644 --- a/arch/arm/kernel/Makefile +++ b/arch/arm/kernel/Makefile | |||
@@ -44,6 +44,7 @@ obj-$(CONFIG_ARM_THUMBEE) += thumbee.o | |||
44 | obj-$(CONFIG_KGDB) += kgdb.o | 44 | obj-$(CONFIG_KGDB) += kgdb.o |
45 | obj-$(CONFIG_ARM_UNWIND) += unwind.o | 45 | obj-$(CONFIG_ARM_UNWIND) += unwind.o |
46 | obj-$(CONFIG_HAVE_TCM) += tcm.o | 46 | obj-$(CONFIG_HAVE_TCM) += tcm.o |
47 | obj-$(CONFIG_OF) += devtree.o | ||
47 | obj-$(CONFIG_CRASH_DUMP) += crash_dump.o | 48 | obj-$(CONFIG_CRASH_DUMP) += crash_dump.o |
48 | obj-$(CONFIG_SWP_EMULATE) += swp_emulate.o | 49 | obj-$(CONFIG_SWP_EMULATE) += swp_emulate.o |
49 | CFLAGS_swp_emulate.o := -Wa,-march=armv7-a | 50 | CFLAGS_swp_emulate.o := -Wa,-march=armv7-a |
diff --git a/arch/arm/kernel/devtree.c b/arch/arm/kernel/devtree.c new file mode 100644 index 000000000000..a701e4226a6c --- /dev/null +++ b/arch/arm/kernel/devtree.c | |||
@@ -0,0 +1,145 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/kernel/devtree.c | ||
3 | * | ||
4 | * Copyright (C) 2009 Canonical Ltd. <jeremy.kerr@canonical.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #include <linux/init.h> | ||
12 | #include <linux/module.h> | ||
13 | #include <linux/errno.h> | ||
14 | #include <linux/types.h> | ||
15 | #include <linux/bootmem.h> | ||
16 | #include <linux/memblock.h> | ||
17 | #include <linux/of.h> | ||
18 | #include <linux/of_fdt.h> | ||
19 | #include <linux/of_irq.h> | ||
20 | #include <linux/of_platform.h> | ||
21 | |||
22 | #include <asm/setup.h> | ||
23 | #include <asm/page.h> | ||
24 | #include <asm/mach/arch.h> | ||
25 | #include <asm/mach-types.h> | ||
26 | |||
27 | void __init early_init_dt_add_memory_arch(u64 base, u64 size) | ||
28 | { | ||
29 | arm_add_memory(base, size); | ||
30 | } | ||
31 | |||
32 | void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align) | ||
33 | { | ||
34 | return alloc_bootmem_align(size, align); | ||
35 | } | ||
36 | |||
37 | void __init arm_dt_memblock_reserve(void) | ||
38 | { | ||
39 | u64 *reserve_map, base, size; | ||
40 | |||
41 | if (!initial_boot_params) | ||
42 | return; | ||
43 | |||
44 | /* Reserve the dtb region */ | ||
45 | memblock_reserve(virt_to_phys(initial_boot_params), | ||
46 | be32_to_cpu(initial_boot_params->totalsize)); | ||
47 | |||
48 | /* | ||
49 | * Process the reserve map. This will probably overlap the initrd | ||
50 | * and dtb locations which are already reserved, but overlaping | ||
51 | * doesn't hurt anything | ||
52 | */ | ||
53 | reserve_map = ((void*)initial_boot_params) + | ||
54 | be32_to_cpu(initial_boot_params->off_mem_rsvmap); | ||
55 | while (1) { | ||
56 | base = be64_to_cpup(reserve_map++); | ||
57 | size = be64_to_cpup(reserve_map++); | ||
58 | if (!size) | ||
59 | break; | ||
60 | memblock_reserve(base, size); | ||
61 | } | ||
62 | } | ||
63 | |||
64 | /** | ||
65 | * setup_machine_fdt - Machine setup when an dtb was passed to the kernel | ||
66 | * @dt_phys: physical address of dt blob | ||
67 | * | ||
68 | * If a dtb was passed to the kernel in r2, then use it to choose the | ||
69 | * correct machine_desc and to setup the system. | ||
70 | */ | ||
71 | struct machine_desc * __init setup_machine_fdt(unsigned int dt_phys) | ||
72 | { | ||
73 | struct boot_param_header *devtree; | ||
74 | struct machine_desc *mdesc, *mdesc_best = NULL; | ||
75 | unsigned int score, mdesc_score = ~1; | ||
76 | unsigned long dt_root; | ||
77 | const char *model; | ||
78 | |||
79 | devtree = phys_to_virt(dt_phys); | ||
80 | |||
81 | /* check device tree validity */ | ||
82 | if (be32_to_cpu(devtree->magic) != OF_DT_HEADER) | ||
83 | return NULL; | ||
84 | |||
85 | /* Search the mdescs for the 'best' compatible value match */ | ||
86 | initial_boot_params = devtree; | ||
87 | dt_root = of_get_flat_dt_root(); | ||
88 | for_each_machine_desc(mdesc) { | ||
89 | score = of_flat_dt_match(dt_root, mdesc->dt_compat); | ||
90 | if (score > 0 && score < mdesc_score) { | ||
91 | mdesc_best = mdesc; | ||
92 | mdesc_score = score; | ||
93 | } | ||
94 | } | ||
95 | if (!mdesc_best) { | ||
96 | const char *prop; | ||
97 | long size; | ||
98 | |||
99 | early_print("\nError: unrecognized/unsupported " | ||
100 | "device tree compatible list:\n[ "); | ||
101 | |||
102 | prop = of_get_flat_dt_prop(dt_root, "compatible", &size); | ||
103 | while (size > 0) { | ||
104 | early_print("'%s' ", prop); | ||
105 | size -= strlen(prop) + 1; | ||
106 | prop += strlen(prop) + 1; | ||
107 | } | ||
108 | early_print("]\n\n"); | ||
109 | |||
110 | dump_machine_table(); /* does not return */ | ||
111 | } | ||
112 | |||
113 | model = of_get_flat_dt_prop(dt_root, "model", NULL); | ||
114 | if (!model) | ||
115 | model = of_get_flat_dt_prop(dt_root, "compatible", NULL); | ||
116 | if (!model) | ||
117 | model = "<unknown>"; | ||
118 | pr_info("Machine: %s, model: %s\n", mdesc_best->name, model); | ||
119 | |||
120 | /* Retrieve various information from the /chosen node */ | ||
121 | of_scan_flat_dt(early_init_dt_scan_chosen, boot_command_line); | ||
122 | /* Initialize {size,address}-cells info */ | ||
123 | of_scan_flat_dt(early_init_dt_scan_root, NULL); | ||
124 | /* Setup memory, calling early_init_dt_add_memory_arch */ | ||
125 | of_scan_flat_dt(early_init_dt_scan_memory, NULL); | ||
126 | |||
127 | /* Change machine number to match the mdesc we're using */ | ||
128 | __machine_arch_type = mdesc_best->nr; | ||
129 | |||
130 | return mdesc_best; | ||
131 | } | ||
132 | |||
133 | /** | ||
134 | * irq_create_of_mapping - Hook to resolve OF irq specifier into a Linux irq# | ||
135 | * | ||
136 | * Currently the mapping mechanism is trivial; simple flat hwirq numbers are | ||
137 | * mapped 1:1 onto Linux irq numbers. Cascaded irq controllers are not | ||
138 | * supported. | ||
139 | */ | ||
140 | unsigned int irq_create_of_mapping(struct device_node *controller, | ||
141 | const u32 *intspec, unsigned int intsize) | ||
142 | { | ||
143 | return intspec[0]; | ||
144 | } | ||
145 | EXPORT_SYMBOL_GPL(irq_create_of_mapping); | ||
diff --git a/arch/arm/kernel/head-common.S b/arch/arm/kernel/head-common.S index c84b57d27d07..854bd22380d3 100644 --- a/arch/arm/kernel/head-common.S +++ b/arch/arm/kernel/head-common.S | |||
@@ -15,6 +15,12 @@ | |||
15 | #define ATAG_CORE_SIZE ((2*4 + 3*4) >> 2) | 15 | #define ATAG_CORE_SIZE ((2*4 + 3*4) >> 2) |
16 | #define ATAG_CORE_SIZE_EMPTY ((2*4) >> 2) | 16 | #define ATAG_CORE_SIZE_EMPTY ((2*4) >> 2) |
17 | 17 | ||
18 | #ifdef CONFIG_CPU_BIG_ENDIAN | ||
19 | #define OF_DT_MAGIC 0xd00dfeed | ||
20 | #else | ||
21 | #define OF_DT_MAGIC 0xedfe0dd0 /* 0xd00dfeed in big-endian */ | ||
22 | #endif | ||
23 | |||
18 | /* | 24 | /* |
19 | * Exception handling. Something went wrong and we can't proceed. We | 25 | * Exception handling. Something went wrong and we can't proceed. We |
20 | * ought to tell the user, but since we don't have any guarantee that | 26 | * ought to tell the user, but since we don't have any guarantee that |
@@ -28,20 +34,26 @@ | |||
28 | 34 | ||
29 | /* Determine validity of the r2 atags pointer. The heuristic requires | 35 | /* Determine validity of the r2 atags pointer. The heuristic requires |
30 | * that the pointer be aligned, in the first 16k of physical RAM and | 36 | * that the pointer be aligned, in the first 16k of physical RAM and |
31 | * that the ATAG_CORE marker is first and present. Future revisions | 37 | * that the ATAG_CORE marker is first and present. If CONFIG_OF_FLATTREE |
38 | * is selected, then it will also accept a dtb pointer. Future revisions | ||
32 | * of this function may be more lenient with the physical address and | 39 | * of this function may be more lenient with the physical address and |
33 | * may also be able to move the ATAGS block if necessary. | 40 | * may also be able to move the ATAGS block if necessary. |
34 | * | 41 | * |
35 | * Returns: | 42 | * Returns: |
36 | * r2 either valid atags pointer, or zero | 43 | * r2 either valid atags pointer, valid dtb pointer, or zero |
37 | * r5, r6 corrupted | 44 | * r5, r6 corrupted |
38 | */ | 45 | */ |
39 | __vet_atags: | 46 | __vet_atags: |
40 | tst r2, #0x3 @ aligned? | 47 | tst r2, #0x3 @ aligned? |
41 | bne 1f | 48 | bne 1f |
42 | 49 | ||
43 | ldr r5, [r2, #0] @ is first tag ATAG_CORE? | 50 | ldr r5, [r2, #0] |
44 | cmp r5, #ATAG_CORE_SIZE | 51 | #ifdef CONFIG_OF_FLATTREE |
52 | ldr r6, =OF_DT_MAGIC @ is it a DTB? | ||
53 | cmp r5, r6 | ||
54 | beq 2f | ||
55 | #endif | ||
56 | cmp r5, #ATAG_CORE_SIZE @ is first tag ATAG_CORE? | ||
45 | cmpne r5, #ATAG_CORE_SIZE_EMPTY | 57 | cmpne r5, #ATAG_CORE_SIZE_EMPTY |
46 | bne 1f | 58 | bne 1f |
47 | ldr r5, [r2, #4] | 59 | ldr r5, [r2, #4] |
@@ -49,7 +61,7 @@ __vet_atags: | |||
49 | cmp r5, r6 | 61 | cmp r5, r6 |
50 | bne 1f | 62 | bne 1f |
51 | 63 | ||
52 | mov pc, lr @ atag pointer is ok | 64 | 2: mov pc, lr @ atag/dtb pointer is ok |
53 | 65 | ||
54 | 1: mov r2, #0 | 66 | 1: mov r2, #0 |
55 | mov pc, lr | 67 | mov pc, lr |
@@ -61,7 +73,7 @@ ENDPROC(__vet_atags) | |||
61 | * | 73 | * |
62 | * r0 = cp#15 control register | 74 | * r0 = cp#15 control register |
63 | * r1 = machine ID | 75 | * r1 = machine ID |
64 | * r2 = atags pointer | 76 | * r2 = atags/dtb pointer |
65 | * r9 = processor ID | 77 | * r9 = processor ID |
66 | */ | 78 | */ |
67 | __INIT | 79 | __INIT |
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S index c9173cfbbc74..a5e5c5b9b48e 100644 --- a/arch/arm/kernel/head.S +++ b/arch/arm/kernel/head.S | |||
@@ -59,7 +59,7 @@ | |||
59 | * | 59 | * |
60 | * This is normally called from the decompressor code. The requirements | 60 | * This is normally called from the decompressor code. The requirements |
61 | * are: MMU = off, D-cache = off, I-cache = dont care, r0 = 0, | 61 | * are: MMU = off, D-cache = off, I-cache = dont care, r0 = 0, |
62 | * r1 = machine nr, r2 = atags pointer. | 62 | * r1 = machine nr, r2 = atags or dtb pointer. |
63 | * | 63 | * |
64 | * This code is mostly position independent, so if you link the kernel at | 64 | * This code is mostly position independent, so if you link the kernel at |
65 | * 0xc0008000, you call this at __pa(0xc0008000). | 65 | * 0xc0008000, you call this at __pa(0xc0008000). |
@@ -91,7 +91,7 @@ ENTRY(stext) | |||
91 | #endif | 91 | #endif |
92 | 92 | ||
93 | /* | 93 | /* |
94 | * r1 = machine no, r2 = atags, | 94 | * r1 = machine no, r2 = atags or dtb, |
95 | * r8 = phys_offset, r9 = cpuid, r10 = procinfo | 95 | * r8 = phys_offset, r9 = cpuid, r10 = procinfo |
96 | */ | 96 | */ |
97 | bl __vet_atags | 97 | bl __vet_atags |
@@ -339,7 +339,7 @@ __secondary_data: | |||
339 | * | 339 | * |
340 | * r0 = cp#15 control register | 340 | * r0 = cp#15 control register |
341 | * r1 = machine ID | 341 | * r1 = machine ID |
342 | * r2 = atags pointer | 342 | * r2 = atags or dtb pointer |
343 | * r4 = page table pointer | 343 | * r4 = page table pointer |
344 | * r9 = processor ID | 344 | * r9 = processor ID |
345 | * r13 = *virtual* address to jump to upon completion | 345 | * r13 = *virtual* address to jump to upon completion |
@@ -376,7 +376,7 @@ ENDPROC(__enable_mmu) | |||
376 | * | 376 | * |
377 | * r0 = cp#15 control register | 377 | * r0 = cp#15 control register |
378 | * r1 = machine ID | 378 | * r1 = machine ID |
379 | * r2 = atags pointer | 379 | * r2 = atags or dtb pointer |
380 | * r9 = processor ID | 380 | * r9 = processor ID |
381 | * r13 = *virtual* address to jump to upon completion | 381 | * r13 = *virtual* address to jump to upon completion |
382 | * | 382 | * |
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index 6dce209a623b..ed11fb08b05a 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/screen_info.h> | 20 | #include <linux/screen_info.h> |
21 | #include <linux/init.h> | 21 | #include <linux/init.h> |
22 | #include <linux/kexec.h> | 22 | #include <linux/kexec.h> |
23 | #include <linux/of_fdt.h> | ||
23 | #include <linux/crash_dump.h> | 24 | #include <linux/crash_dump.h> |
24 | #include <linux/root_dev.h> | 25 | #include <linux/root_dev.h> |
25 | #include <linux/cpu.h> | 26 | #include <linux/cpu.h> |
@@ -42,6 +43,7 @@ | |||
42 | #include <asm/cachetype.h> | 43 | #include <asm/cachetype.h> |
43 | #include <asm/tlbflush.h> | 44 | #include <asm/tlbflush.h> |
44 | 45 | ||
46 | #include <asm/prom.h> | ||
45 | #include <asm/mach/arch.h> | 47 | #include <asm/mach/arch.h> |
46 | #include <asm/mach/irq.h> | 48 | #include <asm/mach/irq.h> |
47 | #include <asm/mach/time.h> | 49 | #include <asm/mach/time.h> |
@@ -309,7 +311,7 @@ static void __init cacheid_init(void) | |||
309 | */ | 311 | */ |
310 | extern struct proc_info_list *lookup_processor_type(unsigned int); | 312 | extern struct proc_info_list *lookup_processor_type(unsigned int); |
311 | 313 | ||
312 | static void __init early_print(const char *str, ...) | 314 | void __init early_print(const char *str, ...) |
313 | { | 315 | { |
314 | extern void printascii(const char *); | 316 | extern void printascii(const char *); |
315 | char buf[256]; | 317 | char buf[256]; |
@@ -439,25 +441,12 @@ void cpu_init(void) | |||
439 | : "r14"); | 441 | : "r14"); |
440 | } | 442 | } |
441 | 443 | ||
442 | static struct machine_desc * __init setup_machine(unsigned int nr) | 444 | void __init dump_machine_table(void) |
443 | { | 445 | { |
444 | extern struct machine_desc __arch_info_begin[], __arch_info_end[]; | ||
445 | struct machine_desc *p; | 446 | struct machine_desc *p; |
446 | 447 | ||
447 | /* | 448 | early_print("Available machine support:\n\nID (hex)\tNAME\n"); |
448 | * locate machine in the list of supported machines. | 449 | for_each_machine_desc(p) |
449 | */ | ||
450 | for (p = __arch_info_begin; p < __arch_info_end; p++) | ||
451 | if (nr == p->nr) { | ||
452 | printk("Machine: %s\n", p->name); | ||
453 | return p; | ||
454 | } | ||
455 | |||
456 | early_print("\n" | ||
457 | "Error: unrecognized/unsupported machine ID (r1 = 0x%08x).\n\n" | ||
458 | "Available machine support:\n\nID (hex)\tNAME\n", nr); | ||
459 | |||
460 | for (p = __arch_info_begin; p < __arch_info_end; p++) | ||
461 | early_print("%08x\t%s\n", p->nr, p->name); | 450 | early_print("%08x\t%s\n", p->nr, p->name); |
462 | 451 | ||
463 | early_print("\nPlease check your kernel config and/or bootloader.\n"); | 452 | early_print("\nPlease check your kernel config and/or bootloader.\n"); |
@@ -466,7 +455,7 @@ static struct machine_desc * __init setup_machine(unsigned int nr) | |||
466 | /* can't use cpu_relax() here as it may require MMU setup */; | 455 | /* can't use cpu_relax() here as it may require MMU setup */; |
467 | } | 456 | } |
468 | 457 | ||
469 | static int __init arm_add_memory(phys_addr_t start, unsigned long size) | 458 | int __init arm_add_memory(phys_addr_t start, unsigned long size) |
470 | { | 459 | { |
471 | struct membank *bank = &meminfo.bank[meminfo.nr_banks]; | 460 | struct membank *bank = &meminfo.bank[meminfo.nr_banks]; |
472 | 461 | ||
@@ -801,23 +790,29 @@ static void __init squash_mem_tags(struct tag *tag) | |||
801 | tag->hdr.tag = ATAG_NONE; | 790 | tag->hdr.tag = ATAG_NONE; |
802 | } | 791 | } |
803 | 792 | ||
804 | void __init setup_arch(char **cmdline_p) | 793 | static struct machine_desc * __init setup_machine_tags(unsigned int nr) |
805 | { | 794 | { |
806 | struct tag *tags = (struct tag *)&init_tags; | 795 | struct tag *tags = (struct tag *)&init_tags; |
807 | struct machine_desc *mdesc; | 796 | struct machine_desc *mdesc = NULL, *p; |
808 | char *from = default_command_line; | 797 | char *from = default_command_line; |
809 | 798 | ||
810 | init_tags.mem.start = PHYS_OFFSET; | 799 | init_tags.mem.start = PHYS_OFFSET; |
811 | 800 | ||
812 | unwind_init(); | 801 | /* |
813 | 802 | * locate machine in the list of supported machines. | |
814 | setup_processor(); | 803 | */ |
815 | mdesc = setup_machine(machine_arch_type); | 804 | for_each_machine_desc(p) |
816 | machine_desc = mdesc; | 805 | if (nr == p->nr) { |
817 | machine_name = mdesc->name; | 806 | printk("Machine: %s\n", p->name); |
807 | mdesc = p; | ||
808 | break; | ||
809 | } | ||
818 | 810 | ||
819 | if (mdesc->soft_reboot) | 811 | if (!mdesc) { |
820 | reboot_setup("s"); | 812 | early_print("\nError: unrecognized/unsupported machine ID" |
813 | " (r1 = 0x%08x).\n\n", nr); | ||
814 | dump_machine_table(); /* does not return */ | ||
815 | } | ||
821 | 816 | ||
822 | if (__atags_pointer) | 817 | if (__atags_pointer) |
823 | tags = phys_to_virt(__atags_pointer); | 818 | tags = phys_to_virt(__atags_pointer); |
@@ -849,8 +844,17 @@ void __init setup_arch(char **cmdline_p) | |||
849 | if (tags->hdr.tag != ATAG_CORE) | 844 | if (tags->hdr.tag != ATAG_CORE) |
850 | convert_to_tag_list(tags); | 845 | convert_to_tag_list(tags); |
851 | #endif | 846 | #endif |
852 | if (tags->hdr.tag != ATAG_CORE) | 847 | |
848 | if (tags->hdr.tag != ATAG_CORE) { | ||
849 | #if defined(CONFIG_OF) | ||
850 | /* | ||
851 | * If CONFIG_OF is set, then assume this is a reasonably | ||
852 | * modern system that should pass boot parameters | ||
853 | */ | ||
854 | early_print("Warning: Neither atags nor dtb found\n"); | ||
855 | #endif | ||
853 | tags = (struct tag *)&init_tags; | 856 | tags = (struct tag *)&init_tags; |
857 | } | ||
854 | 858 | ||
855 | if (mdesc->fixup) | 859 | if (mdesc->fixup) |
856 | mdesc->fixup(mdesc, tags, &from, &meminfo); | 860 | mdesc->fixup(mdesc, tags, &from, &meminfo); |
@@ -862,14 +866,34 @@ void __init setup_arch(char **cmdline_p) | |||
862 | parse_tags(tags); | 866 | parse_tags(tags); |
863 | } | 867 | } |
864 | 868 | ||
869 | /* parse_early_param needs a boot_command_line */ | ||
870 | strlcpy(boot_command_line, from, COMMAND_LINE_SIZE); | ||
871 | |||
872 | return mdesc; | ||
873 | } | ||
874 | |||
875 | |||
876 | void __init setup_arch(char **cmdline_p) | ||
877 | { | ||
878 | struct machine_desc *mdesc; | ||
879 | |||
880 | unwind_init(); | ||
881 | |||
882 | setup_processor(); | ||
883 | mdesc = setup_machine_fdt(__atags_pointer); | ||
884 | if (!mdesc) | ||
885 | mdesc = setup_machine_tags(machine_arch_type); | ||
886 | machine_desc = mdesc; | ||
887 | machine_name = mdesc->name; | ||
888 | |||
889 | if (mdesc->soft_reboot) | ||
890 | reboot_setup("s"); | ||
891 | |||
865 | init_mm.start_code = (unsigned long) _text; | 892 | init_mm.start_code = (unsigned long) _text; |
866 | init_mm.end_code = (unsigned long) _etext; | 893 | init_mm.end_code = (unsigned long) _etext; |
867 | init_mm.end_data = (unsigned long) _edata; | 894 | init_mm.end_data = (unsigned long) _edata; |
868 | init_mm.brk = (unsigned long) _end; | 895 | init_mm.brk = (unsigned long) _end; |
869 | 896 | ||
870 | /* parse_early_param needs a boot_command_line */ | ||
871 | strlcpy(boot_command_line, from, COMMAND_LINE_SIZE); | ||
872 | |||
873 | /* populate cmd_line too for later use, preserving boot_command_line */ | 897 | /* populate cmd_line too for later use, preserving boot_command_line */ |
874 | strlcpy(cmd_line, boot_command_line, COMMAND_LINE_SIZE); | 898 | strlcpy(cmd_line, boot_command_line, COMMAND_LINE_SIZE); |
875 | *cmdline_p = cmd_line; | 899 | *cmdline_p = cmd_line; |
@@ -881,6 +905,8 @@ void __init setup_arch(char **cmdline_p) | |||
881 | paging_init(mdesc); | 905 | paging_init(mdesc); |
882 | request_standard_resources(mdesc); | 906 | request_standard_resources(mdesc); |
883 | 907 | ||
908 | unflatten_device_tree(); | ||
909 | |||
884 | #ifdef CONFIG_SMP | 910 | #ifdef CONFIG_SMP |
885 | if (is_smp()) | 911 | if (is_smp()) |
886 | smp_init_cpus(); | 912 | smp_init_cpus(); |
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index 76f82ae44efb..751767279b3e 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c | |||
@@ -15,12 +15,14 @@ | |||
15 | #include <linux/mman.h> | 15 | #include <linux/mman.h> |
16 | #include <linux/nodemask.h> | 16 | #include <linux/nodemask.h> |
17 | #include <linux/initrd.h> | 17 | #include <linux/initrd.h> |
18 | #include <linux/of_fdt.h> | ||
18 | #include <linux/highmem.h> | 19 | #include <linux/highmem.h> |
19 | #include <linux/gfp.h> | 20 | #include <linux/gfp.h> |
20 | #include <linux/memblock.h> | 21 | #include <linux/memblock.h> |
21 | #include <linux/sort.h> | 22 | #include <linux/sort.h> |
22 | 23 | ||
23 | #include <asm/mach-types.h> | 24 | #include <asm/mach-types.h> |
25 | #include <asm/prom.h> | ||
24 | #include <asm/sections.h> | 26 | #include <asm/sections.h> |
25 | #include <asm/setup.h> | 27 | #include <asm/setup.h> |
26 | #include <asm/sizes.h> | 28 | #include <asm/sizes.h> |
@@ -71,6 +73,14 @@ static int __init parse_tag_initrd2(const struct tag *tag) | |||
71 | 73 | ||
72 | __tagtable(ATAG_INITRD2, parse_tag_initrd2); | 74 | __tagtable(ATAG_INITRD2, parse_tag_initrd2); |
73 | 75 | ||
76 | #ifdef CONFIG_OF_FLATTREE | ||
77 | void __init early_init_dt_setup_initrd_arch(unsigned long start, unsigned long end) | ||
78 | { | ||
79 | phys_initrd_start = start; | ||
80 | phys_initrd_size = end - start; | ||
81 | } | ||
82 | #endif /* CONFIG_OF_FLATTREE */ | ||
83 | |||
74 | /* | 84 | /* |
75 | * This keeps memory configuration data used by a couple memory | 85 | * This keeps memory configuration data used by a couple memory |
76 | * initialization functions, as well as show_mem() for the skipping | 86 | * initialization functions, as well as show_mem() for the skipping |
@@ -334,6 +344,7 @@ void __init arm_memblock_init(struct meminfo *mi, struct machine_desc *mdesc) | |||
334 | #endif | 344 | #endif |
335 | 345 | ||
336 | arm_mm_memblock_reserve(); | 346 | arm_mm_memblock_reserve(); |
347 | arm_dt_memblock_reserve(); | ||
337 | 348 | ||
338 | /* reserve any platform specific memblock areas */ | 349 | /* reserve any platform specific memblock areas */ |
339 | if (mdesc->reserve) | 350 | if (mdesc->reserve) |
diff --git a/arch/microblaze/kernel/prom.c b/arch/microblaze/kernel/prom.c index 00ee90f08343..b15cc219b1d9 100644 --- a/arch/microblaze/kernel/prom.c +++ b/arch/microblaze/kernel/prom.c | |||
@@ -130,7 +130,7 @@ void __init early_init_devtree(void *params) | |||
130 | * device-tree, including the platform type, initrd location and | 130 | * device-tree, including the platform type, initrd location and |
131 | * size, TCE reserve, and more ... | 131 | * size, TCE reserve, and more ... |
132 | */ | 132 | */ |
133 | of_scan_flat_dt(early_init_dt_scan_chosen, NULL); | 133 | of_scan_flat_dt(early_init_dt_scan_chosen, cmd_line); |
134 | 134 | ||
135 | /* Scan memory nodes and rebuild MEMBLOCKs */ | 135 | /* Scan memory nodes and rebuild MEMBLOCKs */ |
136 | memblock_init(); | 136 | memblock_init(); |
diff --git a/arch/mips/include/asm/prom.h b/arch/mips/include/asm/prom.h index f29b862d9db3..857d9b7858ad 100644 --- a/arch/mips/include/asm/prom.h +++ b/arch/mips/include/asm/prom.h | |||
@@ -14,9 +14,6 @@ | |||
14 | #ifdef CONFIG_OF | 14 | #ifdef CONFIG_OF |
15 | #include <asm/bootinfo.h> | 15 | #include <asm/bootinfo.h> |
16 | 16 | ||
17 | /* which is compatible with the flattened device tree (FDT) */ | ||
18 | #define cmd_line arcs_cmdline | ||
19 | |||
20 | extern int early_init_dt_scan_memory_arch(unsigned long node, | 17 | extern int early_init_dt_scan_memory_arch(unsigned long node, |
21 | const char *uname, int depth, void *data); | 18 | const char *uname, int depth, void *data); |
22 | 19 | ||
diff --git a/arch/mips/kernel/prom.c b/arch/mips/kernel/prom.c index a19811e98a41..5b7eade41fa3 100644 --- a/arch/mips/kernel/prom.c +++ b/arch/mips/kernel/prom.c | |||
@@ -83,7 +83,8 @@ void __init early_init_devtree(void *params) | |||
83 | * device-tree, including the platform type, initrd location and | 83 | * device-tree, including the platform type, initrd location and |
84 | * size, and more ... | 84 | * size, and more ... |
85 | */ | 85 | */ |
86 | of_scan_flat_dt(early_init_dt_scan_chosen, NULL); | 86 | of_scan_flat_dt(early_init_dt_scan_chosen, arcs_cmdline); |
87 | |||
87 | 88 | ||
88 | /* Scan memory nodes */ | 89 | /* Scan memory nodes */ |
89 | of_scan_flat_dt(early_init_dt_scan_root, NULL); | 90 | of_scan_flat_dt(early_init_dt_scan_root, NULL); |
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 48aeb55faae9..f2c906b1d8d3 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c | |||
@@ -694,7 +694,7 @@ void __init early_init_devtree(void *params) | |||
694 | * device-tree, including the platform type, initrd location and | 694 | * device-tree, including the platform type, initrd location and |
695 | * size, TCE reserve, and more ... | 695 | * size, TCE reserve, and more ... |
696 | */ | 696 | */ |
697 | of_scan_flat_dt(early_init_dt_scan_chosen_ppc, NULL); | 697 | of_scan_flat_dt(early_init_dt_scan_chosen_ppc, cmd_line); |
698 | 698 | ||
699 | /* Scan memory nodes and rebuild MEMBLOCKs */ | 699 | /* Scan memory nodes and rebuild MEMBLOCKs */ |
700 | memblock_init(); | 700 | memblock_init(); |
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index 8b63a691a9ed..65200af29c52 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c | |||
@@ -670,7 +670,7 @@ int __init early_init_dt_scan_chosen(unsigned long node, const char *uname, | |||
670 | 670 | ||
671 | pr_debug("search \"chosen\", depth: %d, uname: %s\n", depth, uname); | 671 | pr_debug("search \"chosen\", depth: %d, uname: %s\n", depth, uname); |
672 | 672 | ||
673 | if (depth != 1 || | 673 | if (depth != 1 || !data || |
674 | (strcmp(uname, "chosen") != 0 && strcmp(uname, "chosen@0") != 0)) | 674 | (strcmp(uname, "chosen") != 0 && strcmp(uname, "chosen@0") != 0)) |
675 | return 0; | 675 | return 0; |
676 | 676 | ||
@@ -679,16 +679,16 @@ int __init early_init_dt_scan_chosen(unsigned long node, const char *uname, | |||
679 | /* Retrieve command line */ | 679 | /* Retrieve command line */ |
680 | p = of_get_flat_dt_prop(node, "bootargs", &l); | 680 | p = of_get_flat_dt_prop(node, "bootargs", &l); |
681 | if (p != NULL && l > 0) | 681 | if (p != NULL && l > 0) |
682 | strlcpy(cmd_line, p, min((int)l, COMMAND_LINE_SIZE)); | 682 | strlcpy(data, p, min((int)l, COMMAND_LINE_SIZE)); |
683 | 683 | ||
684 | #ifdef CONFIG_CMDLINE | 684 | #ifdef CONFIG_CMDLINE |
685 | #ifndef CONFIG_CMDLINE_FORCE | 685 | #ifndef CONFIG_CMDLINE_FORCE |
686 | if (p == NULL || l == 0 || (l == 1 && (*p) == 0)) | 686 | if (p == NULL || l == 0 || (l == 1 && (*p) == 0)) |
687 | #endif | 687 | #endif |
688 | strlcpy(cmd_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE); | 688 | strlcpy(data, CONFIG_CMDLINE, COMMAND_LINE_SIZE); |
689 | #endif /* CONFIG_CMDLINE */ | 689 | #endif /* CONFIG_CMDLINE */ |
690 | 690 | ||
691 | pr_debug("Command line is: %s\n", cmd_line); | 691 | pr_debug("Command line is: %s\n", (char*)data); |
692 | 692 | ||
693 | /* break now */ | 693 | /* break now */ |
694 | return 1; | 694 | return 1; |