aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/boot/devtree.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/boot/devtree.c')
-rw-r--r--arch/powerpc/boot/devtree.c47
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 */
210int dt_xlate_reg(void *node, int res, unsigned long *addr, 210static u32 dt_xlate_buf[MAX_ADDR_CELLS * MAX_RANGES * 3];
211 unsigned long *size) 211
212static 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
291int 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
299int 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}