1 /* pdt.c: OF PROM device tree support 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 * Adapted for multiple architectures by Andres Salomon <dilinger@queued.net> 11 * 12 * This program is free software; you can redistribute it and/or 13 * modify it under the terms of the GNU General Public License 14 * as published by the Free Software Foundation; either version 15 * 2 of the License, or (at your option) any later version. 16 */ 17 18 #include <linux/kernel.h> 19 #include <linux/module.h> 20 #include <linux/errno.h> 21 #include <linux/mutex.h> 22 #include <linux/slab.h> 23 #include <linux/of.h> 24 #include <linux/of_pdt.h> 25 26 static struct of_pdt_ops *of_pdt_prom_ops __initdata; 27 28 void __initdata (*of_pdt_build_more)(struct device_node *dp, 29 struct device_node ***nextp); 30 31 #if defined(CONFIG_SPARC) 32 unsigned int of_pdt_unique_id __initdata; 33 34 #define of_pdt_incr_unique_id(p) do { \ 35 (p)->unique_id = of_pdt_unique_id++; \ 36 } while (0) 37 38 static char * __init of_pdt_build_full_name(struct device_node *dp) 39 { 40 int len, ourlen, plen; 41 char *n; 42 43 dp->path_component_name = build_path_component(dp); 44 45 plen = strlen(dp->parent->full_name); 46 ourlen = strlen(dp->path_component_name); 47 len = ourlen + plen + 2; 48 49 n = prom_early_alloc(len); 50 strcpy(n, dp->parent->full_name); 51 if (!of_node_is_root(dp->parent)) { 52 strcpy(n + plen, "/"); 53 plen++; 54 } 55 strcpy(n + plen, dp->path_component_name); 56 57 return n; 58 } 59 60 #else /* CONFIG_SPARC */ 61 62 static inline void of_pdt_incr_unique_id(void *p) { } 63 static inline void irq_trans_init(struct device_node *dp) { } 64 65 static char * __init of_pdt_build_full_name(struct device_node *dp) 66 { 67 static int failsafe_id = 0; /* for generating unique names on failure */ 68 char *buf; 69 int len; 70 71 if (of_pdt_prom_ops->pkg2path(dp->phandle, NULL, 0, &len)) 72 goto failsafe; 73 74 buf = prom_early_alloc(len + 1); 75 if (of_pdt_prom_ops->pkg2path(dp->phandle, buf, len, &len)) 76 goto failsafe; 77 return buf; 78 79 failsafe: 80 buf = prom_early_alloc(strlen(dp->parent->full_name) + 81 strlen(dp->name) + 16); 82 sprintf(buf, "%s/%s@unknown%i", 83 of_node_is_root(dp->parent) ? "" : dp->parent->full_name, 84 dp->name, failsafe_id++); 85 pr_err("%s: pkg2path failed; assigning %s\n", __func__, buf); 86 return buf; 87 } 88 89 #endif /* !CONFIG_SPARC */ 90 91 static struct property * __init of_pdt_build_one_prop(phandle node, char *prev, 92 char *special_name, 93 void *special_val, 94 int special_len) 95 { 96 static struct property *tmp = NULL; 97 struct property *p; 98 int err; 99 100 if (tmp) { 101 p = tmp; 102 memset(p, 0, sizeof(*p) + 32); 103 tmp = NULL; 104 } else { 105 p = prom_early_alloc(sizeof(struct property) + 32); 106 of_pdt_incr_unique_id(p); 107 } 108 109 p->name = (char *) (p + 1); 110 if (special_name) { 111 strcpy(p->name, special_name); 112 p->length = special_len; 113 p->value = prom_early_alloc(special_len); 114 memcpy(p->value, special_val, special_len); 115 } else { 116 err = of_pdt_prom_ops->nextprop(node, prev, p->name); 117 if (err) { 118 tmp = p; 119 return NULL; 120 } 121 p->length = of_pdt_prom_ops->getproplen(node, p->name); 122 if (p->length <= 0) { 123 p->length = 0; 124 } else { 125 int len; 126 127 p->value = prom_early_alloc(p->length + 1); 128 len = of_pdt_prom_ops->getproperty(node, p->name, 129 p->value, p->length); 130 if (len <= 0) 131 p->length = 0; 132 ((unsigned char *)p->value)[p->length] = '\0'; 133 } 134 } 135 return p; 136 } 137 138 static struct property * __init of_pdt_build_prop_list(phandle node) 139 { 140 struct property *head, *tail; 141 142 head = tail = of_pdt_build_one_prop(node, NULL, 143 ".node", &node, sizeof(node)); 144 145 tail->next = of_pdt_build_one_prop(node, NULL, NULL, NULL, 0); 146 tail = tail->next; 147 while(tail) { 148 tail->next = of_pdt_build_one_prop(node, tail->name, 149 NULL, NULL, 0); 150 tail = tail->next; 151 } 152 153 return head; 154 } 155 156 static char * __init of_pdt_get_one_property(phandle node, const char *name) 157 { 158 char *buf = "<NULL>"; 159 int len; 160 161 len = of_pdt_prom_ops->getproplen(node, name); 162 if (len > 0) { 163 buf = prom_early_alloc(len); 164 len = of_pdt_prom_ops->getproperty(node, name, buf, len); 165 } 166 167 return buf; 168 } 169 170 static struct device_node * __init of_pdt_create_node(phandle node, 171 struct device_node *parent) 172 { 173 struct device_node *dp; 174 175 if (!node) 176 return NULL; 177 178 dp = prom_early_alloc(sizeof(*dp)); 179 of_pdt_incr_unique_id(dp); 180 dp->parent = parent; 181 182 kref_init(&dp->kref); 183 184 dp->name = of_pdt_get_one_property(node, "name"); 185 dp->type = of_pdt_get_one_property(node, "device_type"); 186 dp->phandle = node; 187 188 dp->properties = of_pdt_build_prop_list(node); 189 190 irq_trans_init(dp); 191 192 return dp; 193 } 194 195 static struct device_node * __init of_pdt_build_tree(struct device_node *parent, 196 phandle node, 197 struct device_node ***nextp) 198 { 199 struct device_node *ret = NULL, *prev_sibling = NULL; 200 struct device_node *dp; 201 202 while (1) { 203 dp = of_pdt_create_node(node, parent); 204 if (!dp) 205 break; 206 207 if (prev_sibling) 208 prev_sibling->sibling = dp; 209 210 if (!ret) 211 ret = dp; 212 prev_sibling = dp; 213 214 *(*nextp) = dp; 215 *nextp = &dp->allnext; 216 217 dp->full_name = of_pdt_build_full_name(dp); 218 219 dp->child = of_pdt_build_tree(dp, 220 of_pdt_prom_ops->getchild(node), nextp); 221 222 if (of_pdt_build_more) 223 of_pdt_build_more(dp, nextp); 224 225 node = of_pdt_prom_ops->getsibling(node); 226 } 227 228 return ret; 229 } 230 231 static void * __init kernel_tree_alloc(u64 size, u64 align) 232 { 233 return prom_early_alloc(size); 234 } 235 236 void __init of_pdt_build_devicetree(phandle root_node, struct of_pdt_ops *ops) 237 { 238 struct device_node **nextp; 239 240 BUG_ON(!ops); 241 of_pdt_prom_ops = ops; 242 243 of_allnodes = of_pdt_create_node(root_node, NULL); 244 #if defined(CONFIG_SPARC) 245 of_allnodes->path_component_name = ""; 246 #endif 247 of_allnodes->full_name = "/"; 248 249 nextp = &of_allnodes->allnext; 250 of_allnodes->child = of_pdt_build_tree(of_allnodes, 251 of_pdt_prom_ops->getchild(of_allnodes->phandle), &nextp); 252 253 /* Get pointer to "/chosen" and "/aliases" nodes for use everywhere */ 254 of_alias_scan(kernel_tree_alloc); 255 } 256