1 /* prom_common.c: OF device tree support common code. 2 * 3 * Paul Mackerras August 1996. 4 * Copyright (C) 1996-2005 Paul Mackerras. 5 * 6 * Adapted for 64bit PowerPC by Dave Engebretsen and Peter Bergner. 7 * {engebret|bergner}@us.ibm.com 8 * 9 * Adapted for sparc by David S. Miller davem@davemloft.net 10 * 11 * This program is free software; you can redistribute it and/or 12 * modify it under the terms of the GNU General Public License 13 * as published by the Free Software Foundation; either version 14 * 2 of the License, or (at your option) any later version. 15 */ 16 17 #include <linux/kernel.h> 18 #include <linux/module.h> 19 #include <linux/errno.h> 20 #include <linux/mutex.h> 21 #include <linux/slab.h> 22 #include <linux/of.h> 23 #include <asm/prom.h> 24 #include <asm/oplib.h> 25 #include <asm/leon.h> 26 27 #include "prom.h" 28 29 void (*prom_build_more)(struct device_node *dp, struct device_node ***nextp); 30 31 struct device_node *of_console_device; 32 EXPORT_SYMBOL(of_console_device); 33 34 char *of_console_path; 35 EXPORT_SYMBOL(of_console_path); 36 37 char *of_console_options; 38 EXPORT_SYMBOL(of_console_options); 39 40 int of_getintprop_default(struct device_node *np, const char *name, int def) 41 { 42 struct property *prop; 43 int len; 44 45 prop = of_find_property(np, name, &len); 46 if (!prop || len != 4) 47 return def; 48 49 return *(int *) prop->value; 50 } 51 EXPORT_SYMBOL(of_getintprop_default); 52 53 DEFINE_MUTEX(of_set_property_mutex); 54 EXPORT_SYMBOL(of_set_property_mutex); 55 56 int of_set_property(struct device_node *dp, const char *name, void *val, int len) 57 { 58 struct property **prevp; 59 void *new_val; 60 int err; 61 62 new_val = kmalloc(len, GFP_KERNEL); 63 if (!new_val) 64 return -ENOMEM; 65 66 memcpy(new_val, val, len); 67 68 err = -ENODEV; 69 70 mutex_lock(&of_set_property_mutex); 71 write_lock(&devtree_lock); 72 prevp = &dp->properties; 73 while (*prevp) { 74 struct property *prop = *prevp; 75 76 if (!strcasecmp(prop->name, name)) { 77 void *old_val = prop->value; 78 int ret; 79 80 ret = prom_setprop(dp->phandle, name, val, len); 81 82 err = -EINVAL; 83 if (ret >= 0) { 84 prop->value = new_val; 85 prop->length = len; 86 87 if (OF_IS_DYNAMIC(prop)) 88 kfree(old_val); 89 90 OF_MARK_DYNAMIC(prop); 91 92 err = 0; 93 } 94 break; 95 } 96 prevp = &(*prevp)->next; 97 } 98 write_unlock(&devtree_lock); 99 mutex_unlock(&of_set_property_mutex); 100 101 /* XXX Upate procfs if necessary... */ 102 103 return err; 104 } 105 EXPORT_SYMBOL(of_set_property); 106 107 int of_find_in_proplist(const char *list, const char *match, int len) 108 { 109 while (len > 0) { 110 int l; 111 112 if (!strcmp(list, match)) 113 return 1; 114 l = strlen(list) + 1; 115 list += l; 116 len -= l; 117 } 118 return 0; 119 } 120 EXPORT_SYMBOL(of_find_in_proplist); 121 122 unsigned int prom_unique_id; 123 124 static struct property * __init build_one_prop(phandle node, char *prev, 125 char *special_name, 126 void *special_val, 127 int special_len) 128 { 129 static struct property *tmp = NULL; 130 struct property *p; 131 const char *name; 132 133 if (tmp) { 134 p = tmp; 135 memset(p, 0, sizeof(*p) + 32); 136 tmp = NULL; 137 } else { 138 p = prom_early_alloc(sizeof(struct property) + 32); 139 p->unique_id = prom_unique_id++; 140 } 141 142 p->name = (char *) (p + 1); 143 if (special_name) { 144 strcpy(p->name, special_name); 145 p->length = special_len; 146 p->value = prom_early_alloc(special_len); 147 memcpy(p->value, special_val, special_len); 148 } else { 149 if (prev == NULL) { 150 name = prom_firstprop(node, p->name); 151 } else { 152 name = prom_nextprop(node, prev, p->name); 153 } 154 155 if (!name || strlen(name) == 0) { 156 tmp = p; 157 return NULL; 158 } 159 #ifdef CONFIG_SPARC32 160 strcpy(p->name, name); 161 #endif 162 p->length = prom_getproplen(node, p->name); 163 if (p->length <= 0) { 164 p->length = 0; 165 } else { 166 int len; 167 168 p->value = prom_early_alloc(p->length + 1); 169 len = prom_getproperty(node, p->name, p->value, 170 p->length); 171 if (len <= 0) 172 p->length = 0; 173 ((unsigned char *)p->value)[p->length] = '\0'; 174 } 175 } 176 return p; 177 } 178 179 static struct property * __init build_prop_list(phandle node) 180 { 181 struct property *head, *tail; 182 183 head = tail = build_one_prop(node, NULL, 184 ".node", &node, sizeof(node)); 185 186 tail->next = build_one_prop(node, NULL, NULL, NULL, 0); 187 tail = tail->next; 188 while(tail) { 189 tail->next = build_one_prop(node, tail->name, 190 NULL, NULL, 0); 191 tail = tail->next; 192 } 193 194 return head; 195 } 196 197 static char * __init get_one_property(phandle node, const char *name) 198 { 199 char *buf = "<NULL>"; 200 int len; 201 202 len = prom_getproplen(node, name); 203 if (len > 0) { 204 buf = prom_early_alloc(len); 205 len = prom_getproperty(node, name, buf, len); 206 } 207 208 return buf; 209 } 210 211 static struct device_node * __init prom_create_node(phandle node, 212 struct device_node *parent) 213 { 214 struct device_node *dp; 215 216 if (!node) 217 return NULL; 218 219 dp = prom_early_alloc(sizeof(*dp)); 220 dp->unique_id = prom_unique_id++; 221 dp->parent = parent; 222 223 kref_init(&dp->kref); 224 225 dp->name = get_one_property(node, "name"); 226 dp->type = get_one_property(node, "device_type"); 227 dp->phandle = node; 228 229 dp->properties = build_prop_list(node); 230 231 irq_trans_init(dp); 232 233 return dp; 234 } 235 236 char * __init build_full_name(struct device_node *dp) 237 { 238 int len, ourlen, plen; 239 char *n; 240 241 plen = strlen(dp->parent->full_name); 242 ourlen = strlen(dp->path_component_name); 243 len = ourlen + plen + 2; 244 245 n = prom_early_alloc(len); 246 strcpy(n, dp->parent->full_name); 247 if (!of_node_is_root(dp->parent)) { 248 strcpy(n + plen, "/"); 249 plen++; 250 } 251 strcpy(n + plen, dp->path_component_name); 252 253 return n; 254 } 255 256 static struct device_node * __init prom_build_tree(struct device_node *parent, 257 phandle node, 258 struct device_node ***nextp) 259 { 260 struct device_node *ret = NULL, *prev_sibling = NULL; 261 struct device_node *dp; 262 263 while (1) { 264 dp = prom_create_node(node, parent); 265 if (!dp) 266 break; 267 268 if (prev_sibling) 269 prev_sibling->sibling = dp; 270 271 if (!ret) 272 ret = dp; 273 prev_sibling = dp; 274 275 *(*nextp) = dp; 276 *nextp = &dp->allnext; 277 278 dp->path_component_name = build_path_component(dp); 279 dp->full_name = build_full_name(dp); 280 281 dp->child = prom_build_tree(dp, prom_getchild(node), nextp); 282 283 if (prom_build_more) 284 prom_build_more(dp, nextp); 285 286 node = prom_getsibling(node); 287 } 288 289 return ret; 290 } 291 292 unsigned int prom_early_allocated __initdata; 293 294 void __init prom_build_devicetree(void) 295 { 296 struct device_node **nextp; 297 298 allnodes = prom_create_node(prom_root_node, NULL); 299 allnodes->path_component_name = ""; 300 allnodes->full_name = "/"; 301 302 nextp = &allnodes->allnext; 303 allnodes->child = prom_build_tree(allnodes, 304 prom_getchild(allnodes->phandle), 305 &nextp); 306 of_console_init(); 307 308 printk("PROM: Built device tree with %u bytes of memory.\n", 309 prom_early_allocated); 310 } 311