aboutsummaryrefslogtreecommitdiffstats
path: root/arch/microblaze/kernel/prom.c
diff options
context:
space:
mode:
authorGrant Likely <grant.likely@secretlab.ca>2009-11-23 22:07:00 -0500
committerGrant Likely <grant.likely@secretlab.ca>2009-11-23 22:07:00 -0500
commitbbd33931a08362f78266a4016211a35947b91041 (patch)
tree6cc38aa6f43c8db7737915ee854e42e1e4f71533 /arch/microblaze/kernel/prom.c
parent00e38efd90f27518ec96b37b1c7773e3ac529966 (diff)
of/flattree: Merge unflatten_dt_node
Merge common code between PowerPC and MicroBlaze Signed-off-by: Grant Likely <grant.likely@secretlab.ca> Reviewed-by: Wolfram Sang <w.sang@pengutronix.de> Tested-by: Michal Simek <monstr@monstr.eu>
Diffstat (limited to 'arch/microblaze/kernel/prom.c')
-rw-r--r--arch/microblaze/kernel/prom.c195
1 files changed, 0 insertions, 195 deletions
diff --git a/arch/microblaze/kernel/prom.c b/arch/microblaze/kernel/prom.c
index eb27bd3a39b4..021770abfbd7 100644
--- a/arch/microblaze/kernel/prom.c
+++ b/arch/microblaze/kernel/prom.c
@@ -50,201 +50,6 @@ typedef u32 cell_t;
50/* export that to outside world */ 50/* export that to outside world */
51struct device_node *of_chosen; 51struct device_node *of_chosen;
52 52
53static void *__init unflatten_dt_alloc(unsigned long *mem, unsigned long size,
54 unsigned long align)
55{
56 void *res;
57
58 *mem = _ALIGN(*mem, align);
59 res = (void *)*mem;
60 *mem += size;
61
62 return res;
63}
64
65static unsigned long __init unflatten_dt_node(unsigned long mem,
66 unsigned long *p,
67 struct device_node *dad,
68 struct device_node ***allnextpp,
69 unsigned long fpsize)
70{
71 struct device_node *np;
72 struct property *pp, **prev_pp = NULL;
73 char *pathp;
74 u32 tag;
75 unsigned int l, allocl;
76 int has_name = 0;
77 int new_format = 0;
78
79 tag = *((u32 *)(*p));
80 if (tag != OF_DT_BEGIN_NODE) {
81 printk("Weird tag at start of node: %x\n", tag);
82 return mem;
83 }
84 *p += 4;
85 pathp = (char *)*p;
86 l = allocl = strlen(pathp) + 1;
87 *p = _ALIGN(*p + l, 4);
88
89 /* version 0x10 has a more compact unit name here instead of the full
90 * path. we accumulate the full path size using "fpsize", we'll rebuild
91 * it later. We detect this because the first character of the name is
92 * not '/'.
93 */
94 if ((*pathp) != '/') {
95 new_format = 1;
96 if (fpsize == 0) {
97 /* root node: special case. fpsize accounts for path
98 * plus terminating zero. root node only has '/', so
99 * fpsize should be 2, but we want to avoid the first
100 * level nodes to have two '/' so we use fpsize 1 here
101 */
102 fpsize = 1;
103 allocl = 2;
104 } else {
105 /* account for '/' and path size minus terminal 0
106 * already in 'l'
107 */
108 fpsize += l;
109 allocl = fpsize;
110 }
111 }
112
113 np = unflatten_dt_alloc(&mem, sizeof(struct device_node) + allocl,
114 __alignof__(struct device_node));
115 if (allnextpp) {
116 memset(np, 0, sizeof(*np));
117 np->full_name = ((char *)np) + sizeof(struct device_node);
118 if (new_format) {
119 char *p2 = np->full_name;
120 /* rebuild full path for new format */
121 if (dad && dad->parent) {
122 strcpy(p2, dad->full_name);
123#ifdef DEBUG
124 if ((strlen(p2) + l + 1) != allocl) {
125 pr_debug("%s: p: %d, l: %d, a: %d\n",
126 pathp, (int)strlen(p2),
127 l, allocl);
128 }
129#endif
130 p2 += strlen(p2);
131 }
132 *(p2++) = '/';
133 memcpy(p2, pathp, l);
134 } else
135 memcpy(np->full_name, pathp, l);
136 prev_pp = &np->properties;
137 **allnextpp = np;
138 *allnextpp = &np->allnext;
139 if (dad != NULL) {
140 np->parent = dad;
141 /* we temporarily use the next field as `last_child'*/
142 if (dad->next == NULL)
143 dad->child = np;
144 else
145 dad->next->sibling = np;
146 dad->next = np;
147 }
148 kref_init(&np->kref);
149 }
150 while (1) {
151 u32 sz, noff;
152 char *pname;
153
154 tag = *((u32 *)(*p));
155 if (tag == OF_DT_NOP) {
156 *p += 4;
157 continue;
158 }
159 if (tag != OF_DT_PROP)
160 break;
161 *p += 4;
162 sz = *((u32 *)(*p));
163 noff = *((u32 *)((*p) + 4));
164 *p += 8;
165 if (initial_boot_params->version < 0x10)
166 *p = _ALIGN(*p, sz >= 8 ? 8 : 4);
167
168 pname = find_flat_dt_string(noff);
169 if (pname == NULL) {
170 printk(KERN_INFO
171 "Can't find property name in list !\n");
172 break;
173 }
174 if (strcmp(pname, "name") == 0)
175 has_name = 1;
176 l = strlen(pname) + 1;
177 pp = unflatten_dt_alloc(&mem, sizeof(struct property),
178 __alignof__(struct property));
179 if (allnextpp) {
180 if (strcmp(pname, "linux,phandle") == 0) {
181 np->node = *((u32 *)*p);
182 if (np->linux_phandle == 0)
183 np->linux_phandle = np->node;
184 }
185 if (strcmp(pname, "ibm,phandle") == 0)
186 np->linux_phandle = *((u32 *)*p);
187 pp->name = pname;
188 pp->length = sz;
189 pp->value = (void *)*p;
190 *prev_pp = pp;
191 prev_pp = &pp->next;
192 }
193 *p = _ALIGN((*p) + sz, 4);
194 }
195 /* with version 0x10 we may not have the name property, recreate
196 * it here from the unit name if absent
197 */
198 if (!has_name) {
199 char *p1 = pathp, *ps = pathp, *pa = NULL;
200 int sz;
201
202 while (*p1) {
203 if ((*p1) == '@')
204 pa = p1;
205 if ((*p1) == '/')
206 ps = p1 + 1;
207 p1++;
208 }
209 if (pa < ps)
210 pa = p1;
211 sz = (pa - ps) + 1;
212 pp = unflatten_dt_alloc(&mem, sizeof(struct property) + sz,
213 __alignof__(struct property));
214 if (allnextpp) {
215 pp->name = "name";
216 pp->length = sz;
217 pp->value = pp + 1;
218 *prev_pp = pp;
219 prev_pp = &pp->next;
220 memcpy(pp->value, ps, sz - 1);
221 ((char *)pp->value)[sz - 1] = 0;
222 pr_debug("fixed up name for %s -> %s\n", pathp,
223 (char *)pp->value);
224 }
225 }
226 if (allnextpp) {
227 *prev_pp = NULL;
228 np->name = of_get_property(np, "name", NULL);
229 np->type = of_get_property(np, "device_type", NULL);
230
231 if (!np->name)
232 np->name = "<NULL>";
233 if (!np->type)
234 np->type = "<NULL>";
235 }
236 while (tag == OF_DT_BEGIN_NODE) {
237 mem = unflatten_dt_node(mem, p, np, allnextpp, fpsize);
238 tag = *((u32 *)(*p));
239 }
240 if (tag != OF_DT_END_NODE) {
241 printk(KERN_INFO "Weird tag at end of node: %x\n", tag);
242 return mem;
243 }
244 *p += 4;
245 return mem;
246}
247
248/** 53/**
249 * unflattens the device-tree passed by the firmware, creating the 54 * unflattens the device-tree passed by the firmware, creating the
250 * tree of struct device_node. It also fills the "name" and "type" 55 * tree of struct device_node. It also fills the "name" and "type"