Skip to content

Commit c10d1e2

Browse files
dilingerH. Peter Anvin
authored andcommitted
x86, olpc: Add OLPC device-tree support
Make use of PROC_DEVICETREE to export the tree, and sparc's PROMTREE code to call into OLPC's Open Firmware to build the tree. v5: fix buglet with root node check (introduced in v4) v4: address some minor style issues pointed out by Grant, and explicitly cast negative phandle checks to s32. v3: rename olpc_prom to olpc_dt - rework Kconfig entries - drop devtree build hook from proc, instead adding a call to x86's paging_init (similarly to how sparc64 does it) - switch allocation from using slab to alloc_bootmem. this allows the DT to be built earlier during boot (during setup_arch); the downside is that there are some 1200 bootmem reservations that are done during boot. Not ideal.. - add a helper olpc_ofw_is_installed function to test for the existence and successful detection of OLPC's OFW. Signed-off-by: Andres Salomon <[email protected]> LKML-Reference: <[email protected]> Signed-off-by: H. Peter Anvin <[email protected]>
1 parent 4722d19 commit c10d1e2

File tree

7 files changed

+189
-0
lines changed

7 files changed

+189
-0
lines changed

arch/x86/Kconfig

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2049,11 +2049,17 @@ config OLPC_OPENFIRMWARE
20492049
bool "Support for OLPC's Open Firmware"
20502050
depends on !X86_64 && !X86_PAE
20512051
default n
2052+
select OF
20522053
help
20532054
This option adds support for the implementation of Open Firmware
20542055
that is used on the OLPC XO-1 Children's Machine.
20552056
If unsure, say N here.
20562057

2058+
config OLPC_OPENFIRMWARE_DT
2059+
bool
2060+
default y if OLPC_OPENFIRMWARE && PROC_DEVICETREE
2061+
select OF_PROMTREE
2062+
20572063
endif # X86_32
20582064

20592065
config AMD_NB

arch/x86/include/asm/olpc_ofw.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88

99
#ifdef CONFIG_OLPC_OPENFIRMWARE
1010

11+
extern bool olpc_ofw_is_installed(void);
12+
1113
/* run an OFW command by calling into the firmware */
1214
#define olpc_ofw(name, args, res) \
1315
__olpc_ofw((name), ARRAY_SIZE(args), args, ARRAY_SIZE(res), res)
@@ -26,10 +28,17 @@ extern bool olpc_ofw_present(void);
2628

2729
#else /* !CONFIG_OLPC_OPENFIRMWARE */
2830

31+
static inline bool olpc_ofw_is_installed(void) { return false; }
2932
static inline void olpc_ofw_detect(void) { }
3033
static inline void setup_olpc_ofw_pgd(void) { }
3134
static inline bool olpc_ofw_present(void) { return false; }
3235

3336
#endif /* !CONFIG_OLPC_OPENFIRMWARE */
3437

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+
3544
#endif /* _ASM_X86_OLPC_OFW_H */

arch/x86/include/asm/prom.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/* dummy prom.h; here to make linux/of.h's #includes happy */

arch/x86/mm/init_32.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
#include <asm/bugs.h>
4646
#include <asm/tlb.h>
4747
#include <asm/tlbflush.h>
48+
#include <asm/olpc_ofw.h>
4849
#include <asm/pgalloc.h>
4950
#include <asm/sections.h>
5051
#include <asm/paravirt.h>
@@ -715,6 +716,7 @@ void __init paging_init(void)
715716
/*
716717
* NOTE: at this point the bootmem allocator is fully available.
717718
*/
719+
olpc_dt_build_devicetree();
718720
sparse_init();
719721
zone_sizes_init();
720722
}

arch/x86/platform/olpc/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
obj-$(CONFIG_OLPC) += olpc.o
22
obj-$(CONFIG_OLPC_XO1) += olpc-xo1.o
33
obj-$(CONFIG_OLPC_OPENFIRMWARE) += olpc_ofw.o
4+
obj-$(CONFIG_OLPC_OPENFIRMWARE_DT) += olpc_dt.o

arch/x86/platform/olpc/olpc_dt.c

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
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 [email protected]
11+
* Adapted for x86/OLPC by Andres Salomon <[email protected]>
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+
void *res;
130+
131+
res = alloc_bootmem(size);
132+
if (res)
133+
memset(res, 0, size);
134+
135+
prom_early_allocated += size;
136+
137+
return res;
138+
}
139+
140+
static struct of_pdt_ops prom_olpc_ops __initdata = {
141+
.nextprop = olpc_dt_nextprop,
142+
.getproplen = olpc_dt_getproplen,
143+
.getproperty = olpc_dt_getproperty,
144+
.getchild = olpc_dt_getchild,
145+
.getsibling = olpc_dt_getsibling,
146+
.pkg2path = olpc_dt_pkg2path,
147+
};
148+
149+
void __init olpc_dt_build_devicetree(void)
150+
{
151+
phandle root;
152+
153+
if (!olpc_ofw_is_installed())
154+
return;
155+
156+
root = olpc_dt_getsibling(0);
157+
if (!root) {
158+
pr_err("PROM: unable to get root node from OFW!\n");
159+
return;
160+
}
161+
of_pdt_build_devicetree(root, &prom_olpc_ops);
162+
163+
pr_info("PROM DT: Built device tree with %u bytes of memory.\n",
164+
prom_early_allocated);
165+
}

arch/x86/platform/olpc/olpc_ofw.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,3 +110,8 @@ void __init olpc_ofw_detect(void)
110110
(unsigned long)olpc_ofw_cif, (-start) >> 20);
111111
reserve_top_address(-start);
112112
}
113+
114+
bool __init olpc_ofw_is_installed(void)
115+
{
116+
return olpc_ofw_cif != NULL;
117+
}

0 commit comments

Comments
 (0)