diff options
Diffstat (limited to 'arch/powerpc/boot/devtree.c')
-rw-r--r-- | arch/powerpc/boot/devtree.c | 99 |
1 files changed, 65 insertions, 34 deletions
diff --git a/arch/powerpc/boot/devtree.c b/arch/powerpc/boot/devtree.c index c9951550ed2c..e5dfe4497313 100644 --- a/arch/powerpc/boot/devtree.c +++ b/arch/powerpc/boot/devtree.c | |||
@@ -74,6 +74,8 @@ void dt_fixup_cpu_clocks(u32 cpu, u32 tb, u32 bus) | |||
74 | if (bus > 0) | 74 | if (bus > 0) |
75 | setprop_val(devp, "bus-frequency", bus); | 75 | setprop_val(devp, "bus-frequency", bus); |
76 | } | 76 | } |
77 | |||
78 | timebase_period_ns = 1000000000 / tb; | ||
77 | } | 79 | } |
78 | 80 | ||
79 | void dt_fixup_clock(const char *path, u32 freq) | 81 | void dt_fixup_clock(const char *path, u32 freq) |
@@ -86,34 +88,38 @@ void dt_fixup_clock(const char *path, u32 freq) | |||
86 | } | 88 | } |
87 | } | 89 | } |
88 | 90 | ||
91 | void dt_fixup_mac_address(u32 index, const u8 *addr) | ||
92 | { | ||
93 | void *devp = find_node_by_prop_value(NULL, "linux,network-index", | ||
94 | (void*)&index, sizeof(index)); | ||
95 | |||
96 | if (devp) { | ||
97 | printf("ENET%d: local-mac-address <-" | ||
98 | " %02x:%02x:%02x:%02x:%02x:%02x\n\r", index, | ||
99 | addr[0], addr[1], addr[2], | ||
100 | addr[3], addr[4], addr[5]); | ||
101 | |||
102 | setprop(devp, "local-mac-address", addr, 6); | ||
103 | } | ||
104 | } | ||
105 | |||
89 | void __dt_fixup_mac_addresses(u32 startindex, ...) | 106 | void __dt_fixup_mac_addresses(u32 startindex, ...) |
90 | { | 107 | { |
91 | va_list ap; | 108 | va_list ap; |
92 | u32 index = startindex; | 109 | u32 index = startindex; |
93 | void *devp; | ||
94 | const u8 *addr; | 110 | const u8 *addr; |
95 | 111 | ||
96 | va_start(ap, startindex); | 112 | va_start(ap, startindex); |
97 | while ((addr = va_arg(ap, const u8 *))) { | ||
98 | devp = find_node_by_prop_value(NULL, "linux,network-index", | ||
99 | (void*)&index, sizeof(index)); | ||
100 | |||
101 | printf("ENET%d: local-mac-address <-" | ||
102 | " %02x:%02x:%02x:%02x:%02x:%02x\n\r", index, | ||
103 | addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); | ||
104 | 113 | ||
105 | if (devp) | 114 | while ((addr = va_arg(ap, const u8 *))) |
106 | setprop(devp, "local-mac-address", addr, 6); | 115 | dt_fixup_mac_address(index++, addr); |
107 | 116 | ||
108 | index++; | ||
109 | } | ||
110 | va_end(ap); | 117 | va_end(ap); |
111 | } | 118 | } |
112 | 119 | ||
113 | #define MAX_ADDR_CELLS 4 | 120 | #define MAX_ADDR_CELLS 4 |
114 | #define MAX_RANGES 8 | ||
115 | 121 | ||
116 | static void get_reg_format(void *node, u32 *naddr, u32 *nsize) | 122 | void dt_get_reg_format(void *node, u32 *naddr, u32 *nsize) |
117 | { | 123 | { |
118 | if (getprop(node, "#address-cells", naddr, 4) != 4) | 124 | if (getprop(node, "#address-cells", naddr, 4) != 4) |
119 | *naddr = 2; | 125 | *naddr = 2; |
@@ -207,7 +213,7 @@ static int find_range(u32 *reg, u32 *ranges, int nregaddr, | |||
207 | * In particular, PCI is not supported. Also, only the beginning of the | 213 | * In particular, PCI is not supported. Also, only the beginning of the |
208 | * reg block is tracked; size is ignored except in ranges. | 214 | * reg block is tracked; size is ignored except in ranges. |
209 | */ | 215 | */ |
210 | static u32 dt_xlate_buf[MAX_ADDR_CELLS * MAX_RANGES * 3]; | 216 | static u32 prop_buf[MAX_PROP_LEN / 4]; |
211 | 217 | ||
212 | static int dt_xlate(void *node, int res, int reglen, unsigned long *addr, | 218 | static int dt_xlate(void *node, int res, int reglen, unsigned long *addr, |
213 | unsigned long *size) | 219 | unsigned long *size) |
@@ -216,14 +222,14 @@ static int dt_xlate(void *node, int res, int reglen, unsigned long *addr, | |||
216 | u32 this_addr[MAX_ADDR_CELLS]; | 222 | u32 this_addr[MAX_ADDR_CELLS]; |
217 | void *parent; | 223 | void *parent; |
218 | u64 ret_addr, ret_size; | 224 | u64 ret_addr, ret_size; |
219 | u32 naddr, nsize, prev_naddr; | 225 | u32 naddr, nsize, prev_naddr, prev_nsize; |
220 | int buflen, offset; | 226 | int buflen, offset; |
221 | 227 | ||
222 | parent = get_parent(node); | 228 | parent = get_parent(node); |
223 | if (!parent) | 229 | if (!parent) |
224 | return 0; | 230 | return 0; |
225 | 231 | ||
226 | get_reg_format(parent, &naddr, &nsize); | 232 | dt_get_reg_format(parent, &naddr, &nsize); |
227 | 233 | ||
228 | if (nsize > 2) | 234 | if (nsize > 2) |
229 | return 0; | 235 | return 0; |
@@ -231,41 +237,47 @@ static int dt_xlate(void *node, int res, int reglen, unsigned long *addr, | |||
231 | offset = (naddr + nsize) * res; | 237 | offset = (naddr + nsize) * res; |
232 | 238 | ||
233 | if (reglen < offset + naddr + nsize || | 239 | if (reglen < offset + naddr + nsize || |
234 | sizeof(dt_xlate_buf) < offset + naddr + nsize) | 240 | MAX_PROP_LEN < (offset + naddr + nsize) * 4) |
235 | return 0; | 241 | return 0; |
236 | 242 | ||
237 | copy_val(last_addr, dt_xlate_buf + offset, naddr); | 243 | copy_val(last_addr, prop_buf + offset, naddr); |
238 | 244 | ||
239 | ret_size = dt_xlate_buf[offset + naddr]; | 245 | ret_size = prop_buf[offset + naddr]; |
240 | if (nsize == 2) { | 246 | if (nsize == 2) { |
241 | ret_size <<= 32; | 247 | ret_size <<= 32; |
242 | ret_size |= dt_xlate_buf[offset + naddr + 1]; | 248 | ret_size |= prop_buf[offset + naddr + 1]; |
243 | } | 249 | } |
244 | 250 | ||
245 | while ((node = get_parent(node))) { | 251 | for (;;) { |
246 | prev_naddr = naddr; | 252 | prev_naddr = naddr; |
253 | prev_nsize = nsize; | ||
254 | node = parent; | ||
255 | |||
256 | parent = get_parent(node); | ||
257 | if (!parent) | ||
258 | break; | ||
247 | 259 | ||
248 | get_reg_format(node, &naddr, &nsize); | 260 | dt_get_reg_format(parent, &naddr, &nsize); |
249 | 261 | ||
250 | buflen = getprop(node, "ranges", dt_xlate_buf, | 262 | buflen = getprop(node, "ranges", prop_buf, |
251 | sizeof(dt_xlate_buf)); | 263 | sizeof(prop_buf)); |
252 | if (buflen < 0) | 264 | if (buflen == 0) |
253 | continue; | 265 | continue; |
254 | if (buflen > sizeof(dt_xlate_buf)) | 266 | if (buflen < 0 || buflen > sizeof(prop_buf)) |
255 | return 0; | 267 | return 0; |
256 | 268 | ||
257 | offset = find_range(last_addr, dt_xlate_buf, prev_naddr, | 269 | offset = find_range(last_addr, prop_buf, prev_naddr, |
258 | naddr, nsize, buflen / 4); | 270 | naddr, prev_nsize, buflen / 4); |
259 | 271 | ||
260 | if (offset < 0) | 272 | if (offset < 0) |
261 | return 0; | 273 | return 0; |
262 | 274 | ||
263 | copy_val(this_addr, dt_xlate_buf + offset, prev_naddr); | 275 | copy_val(this_addr, prop_buf + offset, prev_naddr); |
264 | 276 | ||
265 | if (!sub_reg(last_addr, this_addr)) | 277 | if (!sub_reg(last_addr, this_addr)) |
266 | return 0; | 278 | return 0; |
267 | 279 | ||
268 | copy_val(this_addr, dt_xlate_buf + offset + prev_naddr, naddr); | 280 | copy_val(this_addr, prop_buf + offset + prev_naddr, naddr); |
269 | 281 | ||
270 | if (!add_reg(last_addr, this_addr, naddr)) | 282 | if (!add_reg(last_addr, this_addr, naddr)) |
271 | return 0; | 283 | return 0; |
@@ -292,16 +304,35 @@ int dt_xlate_reg(void *node, int res, unsigned long *addr, unsigned long *size) | |||
292 | { | 304 | { |
293 | int reglen; | 305 | int reglen; |
294 | 306 | ||
295 | reglen = getprop(node, "reg", dt_xlate_buf, sizeof(dt_xlate_buf)) / 4; | 307 | reglen = getprop(node, "reg", prop_buf, sizeof(prop_buf)) / 4; |
296 | return dt_xlate(node, res, reglen, addr, size); | 308 | return dt_xlate(node, res, reglen, addr, size); |
297 | } | 309 | } |
298 | 310 | ||
299 | int dt_xlate_addr(void *node, u32 *buf, int buflen, unsigned long *xlated_addr) | 311 | int dt_xlate_addr(void *node, u32 *buf, int buflen, unsigned long *xlated_addr) |
300 | { | 312 | { |
301 | 313 | ||
302 | if (buflen > sizeof(dt_xlate_buf)) | 314 | if (buflen > sizeof(prop_buf)) |
303 | return 0; | 315 | return 0; |
304 | 316 | ||
305 | memcpy(dt_xlate_buf, buf, buflen); | 317 | memcpy(prop_buf, buf, buflen); |
306 | return dt_xlate(node, 0, buflen / 4, xlated_addr, NULL); | 318 | return dt_xlate(node, 0, buflen / 4, xlated_addr, NULL); |
307 | } | 319 | } |
320 | |||
321 | int dt_is_compatible(void *node, const char *compat) | ||
322 | { | ||
323 | char *buf = (char *)prop_buf; | ||
324 | int len, pos; | ||
325 | |||
326 | len = getprop(node, "compatible", buf, MAX_PROP_LEN); | ||
327 | if (len < 0) | ||
328 | return 0; | ||
329 | |||
330 | for (pos = 0; pos < len; pos++) { | ||
331 | if (!strcmp(buf + pos, compat)) | ||
332 | return 1; | ||
333 | |||
334 | pos += strnlen(&buf[pos], len - pos); | ||
335 | } | ||
336 | |||
337 | return 0; | ||
338 | } | ||