diff options
Diffstat (limited to 'arch/powerpc/boot/devtree.c')
-rw-r--r-- | arch/powerpc/boot/devtree.c | 47 |
1 files changed, 33 insertions, 14 deletions
diff --git a/arch/powerpc/boot/devtree.c b/arch/powerpc/boot/devtree.c index ac4b5ee92d58..c9951550ed2c 100644 --- a/arch/powerpc/boot/devtree.c +++ b/arch/powerpc/boot/devtree.c | |||
@@ -207,12 +207,13 @@ static int find_range(u32 *reg, u32 *ranges, int nregaddr, | |||
207 | * In particular, PCI is not supported. Also, only the beginning of the | 207 | * In particular, PCI is not supported. Also, only the beginning of the |
208 | * reg block is tracked; size is ignored except in ranges. | 208 | * reg block is tracked; size is ignored except in ranges. |
209 | */ | 209 | */ |
210 | int dt_xlate_reg(void *node, int res, unsigned long *addr, | 210 | static u32 dt_xlate_buf[MAX_ADDR_CELLS * MAX_RANGES * 3]; |
211 | unsigned long *size) | 211 | |
212 | static int dt_xlate(void *node, int res, int reglen, unsigned long *addr, | ||
213 | unsigned long *size) | ||
212 | { | 214 | { |
213 | u32 last_addr[MAX_ADDR_CELLS]; | 215 | u32 last_addr[MAX_ADDR_CELLS]; |
214 | u32 this_addr[MAX_ADDR_CELLS]; | 216 | u32 this_addr[MAX_ADDR_CELLS]; |
215 | u32 buf[MAX_ADDR_CELLS * MAX_RANGES * 3]; | ||
216 | void *parent; | 217 | void *parent; |
217 | u64 ret_addr, ret_size; | 218 | u64 ret_addr, ret_size; |
218 | u32 naddr, nsize, prev_naddr; | 219 | u32 naddr, nsize, prev_naddr; |
@@ -227,19 +228,18 @@ int dt_xlate_reg(void *node, int res, unsigned long *addr, | |||
227 | if (nsize > 2) | 228 | if (nsize > 2) |
228 | return 0; | 229 | return 0; |
229 | 230 | ||
230 | buflen = getprop(node, "reg", buf, sizeof(buf)) / 4; | ||
231 | offset = (naddr + nsize) * res; | 231 | offset = (naddr + nsize) * res; |
232 | 232 | ||
233 | if (buflen < offset + naddr + nsize || | 233 | if (reglen < offset + naddr + nsize || |
234 | sizeof(buf) < offset + naddr + nsize) | 234 | sizeof(dt_xlate_buf) < offset + naddr + nsize) |
235 | return 0; | 235 | return 0; |
236 | 236 | ||
237 | copy_val(last_addr, buf + offset, naddr); | 237 | copy_val(last_addr, dt_xlate_buf + offset, naddr); |
238 | 238 | ||
239 | ret_size = buf[offset + naddr]; | 239 | ret_size = dt_xlate_buf[offset + naddr]; |
240 | if (nsize == 2) { | 240 | if (nsize == 2) { |
241 | ret_size <<= 32; | 241 | ret_size <<= 32; |
242 | ret_size |= buf[offset + naddr + 1]; | 242 | ret_size |= dt_xlate_buf[offset + naddr + 1]; |
243 | } | 243 | } |
244 | 244 | ||
245 | while ((node = get_parent(node))) { | 245 | while ((node = get_parent(node))) { |
@@ -247,24 +247,25 @@ int dt_xlate_reg(void *node, int res, unsigned long *addr, | |||
247 | 247 | ||
248 | get_reg_format(node, &naddr, &nsize); | 248 | get_reg_format(node, &naddr, &nsize); |
249 | 249 | ||
250 | buflen = getprop(node, "ranges", buf, sizeof(buf)); | 250 | buflen = getprop(node, "ranges", dt_xlate_buf, |
251 | sizeof(dt_xlate_buf)); | ||
251 | if (buflen < 0) | 252 | if (buflen < 0) |
252 | continue; | 253 | continue; |
253 | if (buflen > sizeof(buf)) | 254 | if (buflen > sizeof(dt_xlate_buf)) |
254 | return 0; | 255 | return 0; |
255 | 256 | ||
256 | offset = find_range(last_addr, buf, prev_naddr, | 257 | offset = find_range(last_addr, dt_xlate_buf, prev_naddr, |
257 | naddr, nsize, buflen / 4); | 258 | naddr, nsize, buflen / 4); |
258 | 259 | ||
259 | if (offset < 0) | 260 | if (offset < 0) |
260 | return 0; | 261 | return 0; |
261 | 262 | ||
262 | copy_val(this_addr, buf + offset, prev_naddr); | 263 | copy_val(this_addr, dt_xlate_buf + offset, prev_naddr); |
263 | 264 | ||
264 | if (!sub_reg(last_addr, this_addr)) | 265 | if (!sub_reg(last_addr, this_addr)) |
265 | return 0; | 266 | return 0; |
266 | 267 | ||
267 | copy_val(this_addr, buf + offset + prev_naddr, naddr); | 268 | copy_val(this_addr, dt_xlate_buf + offset + prev_naddr, naddr); |
268 | 269 | ||
269 | if (!add_reg(last_addr, this_addr, naddr)) | 270 | if (!add_reg(last_addr, this_addr, naddr)) |
270 | return 0; | 271 | return 0; |
@@ -286,3 +287,21 @@ int dt_xlate_reg(void *node, int res, unsigned long *addr, | |||
286 | 287 | ||
287 | return 1; | 288 | return 1; |
288 | } | 289 | } |
290 | |||
291 | int dt_xlate_reg(void *node, int res, unsigned long *addr, unsigned long *size) | ||
292 | { | ||
293 | int reglen; | ||
294 | |||
295 | reglen = getprop(node, "reg", dt_xlate_buf, sizeof(dt_xlate_buf)) / 4; | ||
296 | return dt_xlate(node, res, reglen, addr, size); | ||
297 | } | ||
298 | |||
299 | int dt_xlate_addr(void *node, u32 *buf, int buflen, unsigned long *xlated_addr) | ||
300 | { | ||
301 | |||
302 | if (buflen > sizeof(dt_xlate_buf)) | ||
303 | return 0; | ||
304 | |||
305 | memcpy(dt_xlate_buf, buf, buflen); | ||
306 | return dt_xlate(node, 0, buflen / 4, xlated_addr, NULL); | ||
307 | } | ||