diff options
-rw-r--r-- | arch/x86/Kconfig | 6 | ||||
-rw-r--r-- | arch/x86/include/asm/irq.h | 3 | ||||
-rw-r--r-- | arch/x86/include/asm/olpc_ofw.h | 9 | ||||
-rw-r--r-- | arch/x86/include/asm/prom.h | 1 | ||||
-rw-r--r-- | arch/x86/kernel/irq.c | 10 | ||||
-rw-r--r-- | arch/x86/mm/init_32.c | 2 | ||||
-rw-r--r-- | arch/x86/platform/olpc/Makefile | 1 | ||||
-rw-r--r-- | arch/x86/platform/olpc/olpc_dt.c | 183 | ||||
-rw-r--r-- | arch/x86/platform/olpc/olpc_ofw.c | 5 |
9 files changed, 220 insertions, 0 deletions
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 6e15fa9455e0..36ed2e2c896b 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig | |||
@@ -2076,11 +2076,17 @@ config OLPC_OPENFIRMWARE | |||
2076 | bool "Support for OLPC's Open Firmware" | 2076 | bool "Support for OLPC's Open Firmware" |
2077 | depends on !X86_64 && !X86_PAE | 2077 | depends on !X86_64 && !X86_PAE |
2078 | default n | 2078 | default n |
2079 | select OF | ||
2079 | help | 2080 | help |
2080 | This option adds support for the implementation of Open Firmware | 2081 | This option adds support for the implementation of Open Firmware |
2081 | that is used on the OLPC XO-1 Children's Machine. | 2082 | that is used on the OLPC XO-1 Children's Machine. |
2082 | If unsure, say N here. | 2083 | If unsure, say N here. |
2083 | 2084 | ||
2085 | config OLPC_OPENFIRMWARE_DT | ||
2086 | bool | ||
2087 | default y if OLPC_OPENFIRMWARE && PROC_DEVICETREE | ||
2088 | select OF_PROMTREE | ||
2089 | |||
2084 | endif # X86_32 | 2090 | endif # X86_32 |
2085 | 2091 | ||
2086 | config AMD_NB | 2092 | config AMD_NB |
diff --git a/arch/x86/include/asm/irq.h b/arch/x86/include/asm/irq.h index ba870bb6dd8e..c704b38c57a2 100644 --- a/arch/x86/include/asm/irq.h +++ b/arch/x86/include/asm/irq.h | |||
@@ -10,6 +10,9 @@ | |||
10 | #include <asm/apicdef.h> | 10 | #include <asm/apicdef.h> |
11 | #include <asm/irq_vectors.h> | 11 | #include <asm/irq_vectors.h> |
12 | 12 | ||
13 | /* Even though we don't support this, supply it to appease OF */ | ||
14 | static inline void irq_dispose_mapping(unsigned int virq) { } | ||
15 | |||
13 | static inline int irq_canonicalize(int irq) | 16 | static inline int irq_canonicalize(int irq) |
14 | { | 17 | { |
15 | return ((irq == 2) ? 9 : irq); | 18 | return ((irq == 2) ? 9 : irq); |
diff --git a/arch/x86/include/asm/olpc_ofw.h b/arch/x86/include/asm/olpc_ofw.h index 2a8478140bb3..641988efe063 100644 --- a/arch/x86/include/asm/olpc_ofw.h +++ b/arch/x86/include/asm/olpc_ofw.h | |||
@@ -8,6 +8,8 @@ | |||
8 | 8 | ||
9 | #ifdef CONFIG_OLPC_OPENFIRMWARE | 9 | #ifdef CONFIG_OLPC_OPENFIRMWARE |
10 | 10 | ||
11 | extern bool olpc_ofw_is_installed(void); | ||
12 | |||
11 | /* run an OFW command by calling into the firmware */ | 13 | /* run an OFW command by calling into the firmware */ |
12 | #define olpc_ofw(name, args, res) \ | 14 | #define olpc_ofw(name, args, res) \ |
13 | __olpc_ofw((name), ARRAY_SIZE(args), args, ARRAY_SIZE(res), res) | 15 | __olpc_ofw((name), ARRAY_SIZE(args), args, ARRAY_SIZE(res), res) |
@@ -26,10 +28,17 @@ extern bool olpc_ofw_present(void); | |||
26 | 28 | ||
27 | #else /* !CONFIG_OLPC_OPENFIRMWARE */ | 29 | #else /* !CONFIG_OLPC_OPENFIRMWARE */ |
28 | 30 | ||
31 | static inline bool olpc_ofw_is_installed(void) { return false; } | ||
29 | static inline void olpc_ofw_detect(void) { } | 32 | static inline void olpc_ofw_detect(void) { } |
30 | static inline void setup_olpc_ofw_pgd(void) { } | 33 | static inline void setup_olpc_ofw_pgd(void) { } |
31 | static inline bool olpc_ofw_present(void) { return false; } | 34 | static inline bool olpc_ofw_present(void) { return false; } |
32 | 35 | ||
33 | #endif /* !CONFIG_OLPC_OPENFIRMWARE */ | 36 | #endif /* !CONFIG_OLPC_OPENFIRMWARE */ |
34 | 37 | ||
38 | #ifdef CONFIG_OLPC_OPENFIRMWARE_DT | ||
39 | extern void olpc_dt_build_devicetree(void); | ||
40 | #else | ||
41 | static inline void olpc_dt_build_devicetree(void) { } | ||
42 | #endif /* CONFIG_OLPC_OPENFIRMWARE_DT */ | ||
43 | |||
35 | #endif /* _ASM_X86_OLPC_OFW_H */ | 44 | #endif /* _ASM_X86_OLPC_OFW_H */ |
diff --git a/arch/x86/include/asm/prom.h b/arch/x86/include/asm/prom.h new file mode 100644 index 000000000000..b4ec95f07518 --- /dev/null +++ b/arch/x86/include/asm/prom.h | |||
@@ -0,0 +1 @@ | |||
/* dummy prom.h; here to make linux/of.h's #includes happy */ | |||
diff --git a/arch/x86/kernel/irq.c b/arch/x86/kernel/irq.c index 3a43caa3beb7..52945da52a94 100644 --- a/arch/x86/kernel/irq.c +++ b/arch/x86/kernel/irq.c | |||
@@ -4,6 +4,7 @@ | |||
4 | #include <linux/cpu.h> | 4 | #include <linux/cpu.h> |
5 | #include <linux/interrupt.h> | 5 | #include <linux/interrupt.h> |
6 | #include <linux/kernel_stat.h> | 6 | #include <linux/kernel_stat.h> |
7 | #include <linux/of.h> | ||
7 | #include <linux/seq_file.h> | 8 | #include <linux/seq_file.h> |
8 | #include <linux/smp.h> | 9 | #include <linux/smp.h> |
9 | #include <linux/ftrace.h> | 10 | #include <linux/ftrace.h> |
@@ -275,6 +276,15 @@ void smp_x86_platform_ipi(struct pt_regs *regs) | |||
275 | 276 | ||
276 | EXPORT_SYMBOL_GPL(vector_used_by_percpu_irq); | 277 | EXPORT_SYMBOL_GPL(vector_used_by_percpu_irq); |
277 | 278 | ||
279 | #ifdef CONFIG_OF | ||
280 | unsigned int irq_create_of_mapping(struct device_node *controller, | ||
281 | const u32 *intspec, unsigned int intsize) | ||
282 | { | ||
283 | return intspec[0]; | ||
284 | } | ||
285 | EXPORT_SYMBOL_GPL(irq_create_of_mapping); | ||
286 | #endif | ||
287 | |||
278 | #ifdef CONFIG_HOTPLUG_CPU | 288 | #ifdef CONFIG_HOTPLUG_CPU |
279 | /* A cpu has been removed from cpu_online_mask. Reset irq affinities. */ | 289 | /* A cpu has been removed from cpu_online_mask. Reset irq affinities. */ |
280 | void fixup_irqs(void) | 290 | void fixup_irqs(void) |
diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c index f89b5bb4e93f..c821074b7f0b 100644 --- a/arch/x86/mm/init_32.c +++ b/arch/x86/mm/init_32.c | |||
@@ -45,6 +45,7 @@ | |||
45 | #include <asm/bugs.h> | 45 | #include <asm/bugs.h> |
46 | #include <asm/tlb.h> | 46 | #include <asm/tlb.h> |
47 | #include <asm/tlbflush.h> | 47 | #include <asm/tlbflush.h> |
48 | #include <asm/olpc_ofw.h> | ||
48 | #include <asm/pgalloc.h> | 49 | #include <asm/pgalloc.h> |
49 | #include <asm/sections.h> | 50 | #include <asm/sections.h> |
50 | #include <asm/paravirt.h> | 51 | #include <asm/paravirt.h> |
@@ -715,6 +716,7 @@ void __init paging_init(void) | |||
715 | /* | 716 | /* |
716 | * NOTE: at this point the bootmem allocator is fully available. | 717 | * NOTE: at this point the bootmem allocator is fully available. |
717 | */ | 718 | */ |
719 | olpc_dt_build_devicetree(); | ||
718 | sparse_init(); | 720 | sparse_init(); |
719 | zone_sizes_init(); | 721 | zone_sizes_init(); |
720 | } | 722 | } |
diff --git a/arch/x86/platform/olpc/Makefile b/arch/x86/platform/olpc/Makefile index c31b8fcb5a86..e797428b163b 100644 --- a/arch/x86/platform/olpc/Makefile +++ b/arch/x86/platform/olpc/Makefile | |||
@@ -1,3 +1,4 @@ | |||
1 | obj-$(CONFIG_OLPC) += olpc.o | 1 | obj-$(CONFIG_OLPC) += olpc.o |
2 | obj-$(CONFIG_OLPC_XO1) += olpc-xo1.o | 2 | obj-$(CONFIG_OLPC_XO1) += olpc-xo1.o |
3 | obj-$(CONFIG_OLPC_OPENFIRMWARE) += olpc_ofw.o | 3 | obj-$(CONFIG_OLPC_OPENFIRMWARE) += olpc_ofw.o |
4 | obj-$(CONFIG_OLPC_OPENFIRMWARE_DT) += olpc_dt.o | ||
diff --git a/arch/x86/platform/olpc/olpc_dt.c b/arch/x86/platform/olpc/olpc_dt.c new file mode 100644 index 000000000000..dab874647530 --- /dev/null +++ b/arch/x86/platform/olpc/olpc_dt.c | |||
@@ -0,0 +1,183 @@ | |||
1 | /* | ||
2 | * OLPC-specific OFW device tree support code. | ||
3 | * | ||
4 | * Paul Mackerras August 1996. | ||
5 | * Copyright (C) 1996-2005 Paul Mackerras. | ||
6 | * | ||
7 | * Adapted for 64bit PowerPC by Dave Engebretsen and Peter Bergner. | ||
8 | * {engebret|bergner}@us.ibm.com | ||
9 | * | ||
10 | * Adapted for sparc by David S. Miller davem@davemloft.net | ||
11 | * Adapted for x86/OLPC by Andres Salomon <dilinger@queued.net> | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or | ||
14 | * modify it under the terms of the GNU General Public License | ||
15 | * as published by the Free Software Foundation; either version | ||
16 | * 2 of the License, or (at your option) any later version. | ||
17 | */ | ||
18 | |||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/bootmem.h> | ||
21 | #include <linux/of.h> | ||
22 | #include <linux/of_pdt.h> | ||
23 | #include <asm/olpc_ofw.h> | ||
24 | |||
25 | static phandle __init olpc_dt_getsibling(phandle node) | ||
26 | { | ||
27 | const void *args[] = { (void *)node }; | ||
28 | void *res[] = { &node }; | ||
29 | |||
30 | if ((s32)node == -1) | ||
31 | return 0; | ||
32 | |||
33 | if (olpc_ofw("peer", args, res) || (s32)node == -1) | ||
34 | return 0; | ||
35 | |||
36 | return node; | ||
37 | } | ||
38 | |||
39 | static phandle __init olpc_dt_getchild(phandle node) | ||
40 | { | ||
41 | const void *args[] = { (void *)node }; | ||
42 | void *res[] = { &node }; | ||
43 | |||
44 | if ((s32)node == -1) | ||
45 | return 0; | ||
46 | |||
47 | if (olpc_ofw("child", args, res) || (s32)node == -1) { | ||
48 | pr_err("PROM: %s: fetching child failed!\n", __func__); | ||
49 | return 0; | ||
50 | } | ||
51 | |||
52 | return node; | ||
53 | } | ||
54 | |||
55 | static int __init olpc_dt_getproplen(phandle node, const char *prop) | ||
56 | { | ||
57 | const void *args[] = { (void *)node, prop }; | ||
58 | int len; | ||
59 | void *res[] = { &len }; | ||
60 | |||
61 | if ((s32)node == -1) | ||
62 | return -1; | ||
63 | |||
64 | if (olpc_ofw("getproplen", args, res)) { | ||
65 | pr_err("PROM: %s: getproplen failed!\n", __func__); | ||
66 | return -1; | ||
67 | } | ||
68 | |||
69 | return len; | ||
70 | } | ||
71 | |||
72 | static int __init olpc_dt_getproperty(phandle node, const char *prop, | ||
73 | char *buf, int bufsize) | ||
74 | { | ||
75 | int plen; | ||
76 | |||
77 | plen = olpc_dt_getproplen(node, prop); | ||
78 | if (plen > bufsize || plen < 1) { | ||
79 | return -1; | ||
80 | } else { | ||
81 | const void *args[] = { (void *)node, prop, buf, (void *)plen }; | ||
82 | void *res[] = { &plen }; | ||
83 | |||
84 | if (olpc_ofw("getprop", args, res)) { | ||
85 | pr_err("PROM: %s: getprop failed!\n", __func__); | ||
86 | return -1; | ||
87 | } | ||
88 | } | ||
89 | |||
90 | return plen; | ||
91 | } | ||
92 | |||
93 | static int __init olpc_dt_nextprop(phandle node, char *prev, char *buf) | ||
94 | { | ||
95 | const void *args[] = { (void *)node, prev, buf }; | ||
96 | int success; | ||
97 | void *res[] = { &success }; | ||
98 | |||
99 | buf[0] = '\0'; | ||
100 | |||
101 | if ((s32)node == -1) | ||
102 | return -1; | ||
103 | |||
104 | if (olpc_ofw("nextprop", args, res) || success != 1) | ||
105 | return -1; | ||
106 | |||
107 | return 0; | ||
108 | } | ||
109 | |||
110 | static int __init olpc_dt_pkg2path(phandle node, char *buf, | ||
111 | const int buflen, int *len) | ||
112 | { | ||
113 | const void *args[] = { (void *)node, buf, (void *)buflen }; | ||
114 | void *res[] = { len }; | ||
115 | |||
116 | if ((s32)node == -1) | ||
117 | return -1; | ||
118 | |||
119 | if (olpc_ofw("package-to-path", args, res) || *len < 1) | ||
120 | return -1; | ||
121 | |||
122 | return 0; | ||
123 | } | ||
124 | |||
125 | static unsigned int prom_early_allocated __initdata; | ||
126 | |||
127 | void * __init prom_early_alloc(unsigned long size) | ||
128 | { | ||
129 | static u8 *mem; | ||
130 | static size_t free_mem; | ||
131 | void *res; | ||
132 | |||
133 | if (free_mem < size) { | ||
134 | const size_t chunk_size = max(PAGE_SIZE, size); | ||
135 | |||
136 | /* | ||
137 | * To mimimize the number of allocations, grab at least | ||
138 | * PAGE_SIZE of memory (that's an arbitrary choice that's | ||
139 | * fast enough on the platforms we care about while minimizing | ||
140 | * wasted bootmem) and hand off chunks of it to callers. | ||
141 | */ | ||
142 | res = alloc_bootmem(chunk_size); | ||
143 | if (!res) | ||
144 | return NULL; | ||
145 | prom_early_allocated += chunk_size; | ||
146 | memset(res, 0, chunk_size); | ||
147 | free_mem = chunk_size; | ||
148 | mem = res; | ||
149 | } | ||
150 | |||
151 | /* allocate from the local cache */ | ||
152 | free_mem -= size; | ||
153 | res = mem; | ||
154 | mem += size; | ||
155 | return res; | ||
156 | } | ||
157 | |||
158 | static struct of_pdt_ops prom_olpc_ops __initdata = { | ||
159 | .nextprop = olpc_dt_nextprop, | ||
160 | .getproplen = olpc_dt_getproplen, | ||
161 | .getproperty = olpc_dt_getproperty, | ||
162 | .getchild = olpc_dt_getchild, | ||
163 | .getsibling = olpc_dt_getsibling, | ||
164 | .pkg2path = olpc_dt_pkg2path, | ||
165 | }; | ||
166 | |||
167 | void __init olpc_dt_build_devicetree(void) | ||
168 | { | ||
169 | phandle root; | ||
170 | |||
171 | if (!olpc_ofw_is_installed()) | ||
172 | return; | ||
173 | |||
174 | root = olpc_dt_getsibling(0); | ||
175 | if (!root) { | ||
176 | pr_err("PROM: unable to get root node from OFW!\n"); | ||
177 | return; | ||
178 | } | ||
179 | of_pdt_build_devicetree(root, &prom_olpc_ops); | ||
180 | |||
181 | pr_info("PROM DT: Built device tree with %u bytes of memory.\n", | ||
182 | prom_early_allocated); | ||
183 | } | ||
diff --git a/arch/x86/platform/olpc/olpc_ofw.c b/arch/x86/platform/olpc/olpc_ofw.c index 787320464379..e7604f62870d 100644 --- a/arch/x86/platform/olpc/olpc_ofw.c +++ b/arch/x86/platform/olpc/olpc_ofw.c | |||
@@ -110,3 +110,8 @@ void __init olpc_ofw_detect(void) | |||
110 | (unsigned long)olpc_ofw_cif, (-start) >> 20); | 110 | (unsigned long)olpc_ofw_cif, (-start) >> 20); |
111 | reserve_top_address(-start); | 111 | reserve_top_address(-start); |
112 | } | 112 | } |
113 | |||
114 | bool __init olpc_ofw_is_installed(void) | ||
115 | { | ||
116 | return olpc_ofw_cif != NULL; | ||
117 | } | ||