aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/boot
diff options
context:
space:
mode:
authorScott Wood <scottwood@freescale.com>2007-08-20 13:39:48 -0400
committerPaul Mackerras <paulus@samba.org>2007-08-22 01:21:48 -0400
commita73ac50c4787b1b28d5c94bb18c60352f5dd7d6f (patch)
tree8c78ad293d3ee4bb43543e25df348b729832a02c /arch/powerpc/boot
parent0602801c22ea1767cd0298b11da140bd5cb764d2 (diff)
[POWERPC] bootwrapper: Add dt_is_compatible()
This can be used rather than doing a simple strcmp, which will fail to handle multiple compatible entries. Signed-off-by: Scott Wood <scottwood@freescale.com> Acked-by: David Gibson <david@gibson.dropbear.id.au> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/boot')
-rw-r--r--arch/powerpc/boot/devtree.c48
-rw-r--r--arch/powerpc/boot/ops.h1
2 files changed, 34 insertions, 15 deletions
diff --git a/arch/powerpc/boot/devtree.c b/arch/powerpc/boot/devtree.c
index 129e6d9b8d43..3a18bfe0fdf7 100644
--- a/arch/powerpc/boot/devtree.c
+++ b/arch/powerpc/boot/devtree.c
@@ -113,7 +113,6 @@ void __dt_fixup_mac_addresses(u32 startindex, ...)
113} 113}
114 114
115#define MAX_ADDR_CELLS 4 115#define MAX_ADDR_CELLS 4
116#define MAX_RANGES 8
117 116
118static void get_reg_format(void *node, u32 *naddr, u32 *nsize) 117static void get_reg_format(void *node, u32 *naddr, u32 *nsize)
119{ 118{
@@ -209,7 +208,7 @@ static int find_range(u32 *reg, u32 *ranges, int nregaddr,
209 * In particular, PCI is not supported. Also, only the beginning of the 208 * In particular, PCI is not supported. Also, only the beginning of the
210 * reg block is tracked; size is ignored except in ranges. 209 * reg block is tracked; size is ignored except in ranges.
211 */ 210 */
212static u32 dt_xlate_buf[MAX_ADDR_CELLS * MAX_RANGES * 3]; 211static u32 prop_buf[MAX_PROP_LEN / 4];
213 212
214static int dt_xlate(void *node, int res, int reglen, unsigned long *addr, 213static int dt_xlate(void *node, int res, int reglen, unsigned long *addr,
215 unsigned long *size) 214 unsigned long *size)
@@ -233,15 +232,15 @@ static int dt_xlate(void *node, int res, int reglen, unsigned long *addr,
233 offset = (naddr + nsize) * res; 232 offset = (naddr + nsize) * res;
234 233
235 if (reglen < offset + naddr + nsize || 234 if (reglen < offset + naddr + nsize ||
236 sizeof(dt_xlate_buf) < (offset + naddr + nsize) * 4) 235 MAX_PROP_LEN < (offset + naddr + nsize) * 4)
237 return 0; 236 return 0;
238 237
239 copy_val(last_addr, dt_xlate_buf + offset, naddr); 238 copy_val(last_addr, prop_buf + offset, naddr);
240 239
241 ret_size = dt_xlate_buf[offset + naddr]; 240 ret_size = prop_buf[offset + naddr];
242 if (nsize == 2) { 241 if (nsize == 2) {
243 ret_size <<= 32; 242 ret_size <<= 32;
244 ret_size |= dt_xlate_buf[offset + naddr + 1]; 243 ret_size |= prop_buf[offset + naddr + 1];
245 } 244 }
246 245
247 for (;;) { 246 for (;;) {
@@ -255,25 +254,25 @@ static int dt_xlate(void *node, int res, int reglen, unsigned long *addr,
255 254
256 get_reg_format(parent, &naddr, &nsize); 255 get_reg_format(parent, &naddr, &nsize);
257 256
258 buflen = getprop(node, "ranges", dt_xlate_buf, 257 buflen = getprop(node, "ranges", prop_buf,
259 sizeof(dt_xlate_buf)); 258 sizeof(prop_buf));
260 if (buflen == 0) 259 if (buflen == 0)
261 continue; 260 continue;
262 if (buflen < 0 || buflen > sizeof(dt_xlate_buf)) 261 if (buflen < 0 || buflen > sizeof(prop_buf))
263 return 0; 262 return 0;
264 263
265 offset = find_range(last_addr, dt_xlate_buf, prev_naddr, 264 offset = find_range(last_addr, prop_buf, prev_naddr,
266 naddr, prev_nsize, buflen / 4); 265 naddr, prev_nsize, buflen / 4);
267 266
268 if (offset < 0) 267 if (offset < 0)
269 return 0; 268 return 0;
270 269
271 copy_val(this_addr, dt_xlate_buf + offset, prev_naddr); 270 copy_val(this_addr, prop_buf + offset, prev_naddr);
272 271
273 if (!sub_reg(last_addr, this_addr)) 272 if (!sub_reg(last_addr, this_addr))
274 return 0; 273 return 0;
275 274
276 copy_val(this_addr, dt_xlate_buf + offset + prev_naddr, naddr); 275 copy_val(this_addr, prop_buf + offset + prev_naddr, naddr);
277 276
278 if (!add_reg(last_addr, this_addr, naddr)) 277 if (!add_reg(last_addr, this_addr, naddr))
279 return 0; 278 return 0;
@@ -300,16 +299,35 @@ int dt_xlate_reg(void *node, int res, unsigned long *addr, unsigned long *size)
300{ 299{
301 int reglen; 300 int reglen;
302 301
303 reglen = getprop(node, "reg", dt_xlate_buf, sizeof(dt_xlate_buf)) / 4; 302 reglen = getprop(node, "reg", prop_buf, sizeof(prop_buf)) / 4;
304 return dt_xlate(node, res, reglen, addr, size); 303 return dt_xlate(node, res, reglen, addr, size);
305} 304}
306 305
307int dt_xlate_addr(void *node, u32 *buf, int buflen, unsigned long *xlated_addr) 306int dt_xlate_addr(void *node, u32 *buf, int buflen, unsigned long *xlated_addr)
308{ 307{
309 308
310 if (buflen > sizeof(dt_xlate_buf)) 309 if (buflen > sizeof(prop_buf))
311 return 0; 310 return 0;
312 311
313 memcpy(dt_xlate_buf, buf, buflen); 312 memcpy(prop_buf, buf, buflen);
314 return dt_xlate(node, 0, buflen / 4, xlated_addr, NULL); 313 return dt_xlate(node, 0, buflen / 4, xlated_addr, NULL);
315} 314}
315
316int dt_is_compatible(void *node, const char *compat)
317{
318 char *buf = (char *)prop_buf;
319 int len, pos;
320
321 len = getprop(node, "compatible", buf, MAX_PROP_LEN);
322 if (len < 0)
323 return 0;
324
325 for (pos = 0; pos < len; pos++) {
326 if (!strcmp(buf + pos, compat))
327 return 1;
328
329 pos += strnlen(&buf[pos], len - pos);
330 }
331
332 return 0;
333}
diff --git a/arch/powerpc/boot/ops.h b/arch/powerpc/boot/ops.h
index aebd6edc9a90..a10bf5a153d5 100644
--- a/arch/powerpc/boot/ops.h
+++ b/arch/powerpc/boot/ops.h
@@ -87,6 +87,7 @@ void *simple_alloc_init(char *base, unsigned long heap_size,
87extern void flush_cache(void *, unsigned long); 87extern void flush_cache(void *, unsigned long);
88int dt_xlate_reg(void *node, int res, unsigned long *addr, unsigned long *size); 88int dt_xlate_reg(void *node, int res, unsigned long *addr, unsigned long *size);
89int dt_xlate_addr(void *node, u32 *buf, int buflen, unsigned long *xlated_addr); 89int dt_xlate_addr(void *node, u32 *buf, int buflen, unsigned long *xlated_addr);
90int dt_is_compatible(void *node, const char *compat);
90 91
91static inline void *finddevice(const char *name) 92static inline void *finddevice(const char *name)
92{ 93{