diff options
| -rw-r--r-- | arch/powerpc/boot/devtree.c | 47 | ||||
| -rw-r--r-- | arch/powerpc/boot/ops.h | 4 |
2 files changed, 35 insertions, 16 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 | } | ||
diff --git a/arch/powerpc/boot/ops.h b/arch/powerpc/boot/ops.h index 20e87199f6a4..73bd47a3a079 100644 --- a/arch/powerpc/boot/ops.h +++ b/arch/powerpc/boot/ops.h | |||
| @@ -82,8 +82,8 @@ int ns16550_console_init(void *devp, struct serial_console_data *scdp); | |||
| 82 | void *simple_alloc_init(char *base, unsigned long heap_size, | 82 | void *simple_alloc_init(char *base, unsigned long heap_size, |
| 83 | unsigned long granularity, unsigned long max_allocs); | 83 | unsigned long granularity, unsigned long max_allocs); |
| 84 | extern void flush_cache(void *, unsigned long); | 84 | extern void flush_cache(void *, unsigned long); |
| 85 | int dt_xlate_reg(void *node, int res, unsigned long *addr, | 85 | int dt_xlate_reg(void *node, int res, unsigned long *addr, unsigned long *size); |
| 86 | unsigned long *size); | 86 | int dt_xlate_addr(void *node, u32 *buf, int buflen, unsigned long *xlated_addr); |
| 87 | 87 | ||
| 88 | static inline void *finddevice(const char *name) | 88 | static inline void *finddevice(const char *name) |
| 89 | { | 89 | { |
