diff options
Diffstat (limited to 'arch/sparc/kernel/prom_common.c')
-rw-r--r-- | arch/sparc/kernel/prom_common.c | 202 |
1 files changed, 28 insertions, 174 deletions
diff --git a/arch/sparc/kernel/prom_common.c b/arch/sparc/kernel/prom_common.c index 1f830da2ddf..ed25834328f 100644 --- a/arch/sparc/kernel/prom_common.c +++ b/arch/sparc/kernel/prom_common.c @@ -20,14 +20,13 @@ #include <linux/mutex.h> #include <linux/slab.h> #include <linux/of.h> +#include <linux/of_pdt.h> #include <asm/prom.h> #include <asm/oplib.h> #include <asm/leon.h> #include "prom.h" -void (*prom_build_more)(struct device_node *dp, struct device_node ***nextp); - struct device_node *of_console_device; EXPORT_SYMBOL(of_console_device); @@ -119,192 +118,47 @@ int of_find_in_proplist(const char *list, const char *match, int len) } EXPORT_SYMBOL(of_find_in_proplist); -unsigned int prom_unique_id; - -static struct property * __init build_one_prop(phandle node, char *prev, - char *special_name, - void *special_val, - int special_len) +/* + * SPARC32 and SPARC64's prom_nextprop() do things differently + * here, despite sharing the same interface. SPARC32 doesn't fill in 'buf', + * returning NULL on an error. SPARC64 fills in 'buf', but sets it to an + * empty string upon error. + */ +static int __init handle_nextprop_quirks(char *buf, const char *name) { - static struct property *tmp = NULL; - struct property *p; - const char *name; - - if (tmp) { - p = tmp; - memset(p, 0, sizeof(*p) + 32); - tmp = NULL; - } else { - p = prom_early_alloc(sizeof(struct property) + 32); - p->unique_id = prom_unique_id++; - } - - p->name = (char *) (p + 1); - if (special_name) { - strcpy(p->name, special_name); - p->length = special_len; - p->value = prom_early_alloc(special_len); - memcpy(p->value, special_val, special_len); - } else { - if (prev == NULL) { - name = prom_firstprop(node, p->name); - } else { - name = prom_nextprop(node, prev, p->name); - } + if (!name || strlen(name) == 0) + return -1; - if (!name || strlen(name) == 0) { - tmp = p; - return NULL; - } #ifdef CONFIG_SPARC32 - strcpy(p->name, name); + strcpy(buf, name); #endif - p->length = prom_getproplen(node, p->name); - if (p->length <= 0) { - p->length = 0; - } else { - int len; - - p->value = prom_early_alloc(p->length + 1); - len = prom_getproperty(node, p->name, p->value, - p->length); - if (len <= 0) - p->length = 0; - ((unsigned char *)p->value)[p->length] = '\0'; - } - } - return p; -} - -static struct property * __init build_prop_list(phandle node) -{ - struct property *head, *tail; - - head = tail = build_one_prop(node, NULL, - ".node", &node, sizeof(node)); - - tail->next = build_one_prop(node, NULL, NULL, NULL, 0); - tail = tail->next; - while(tail) { - tail->next = build_one_prop(node, tail->name, - NULL, NULL, 0); - tail = tail->next; - } - - return head; -} - -static char * __init get_one_property(phandle node, const char *name) -{ - char *buf = "<NULL>"; - int len; - - len = prom_getproplen(node, name); - if (len > 0) { - buf = prom_early_alloc(len); - len = prom_getproperty(node, name, buf, len); - } - - return buf; -} - -static struct device_node * __init prom_create_node(phandle node, - struct device_node *parent) -{ - struct device_node *dp; - - if (!node) - return NULL; - - dp = prom_early_alloc(sizeof(*dp)); - dp->unique_id = prom_unique_id++; - dp->parent = parent; - - kref_init(&dp->kref); - - dp->name = get_one_property(node, "name"); - dp->type = get_one_property(node, "device_type"); - dp->phandle = node; - - dp->properties = build_prop_list(node); - - irq_trans_init(dp); - - return dp; -} - -char * __init build_full_name(struct device_node *dp) -{ - int len, ourlen, plen; - char *n; - - plen = strlen(dp->parent->full_name); - ourlen = strlen(dp->path_component_name); - len = ourlen + plen + 2; - - n = prom_early_alloc(len); - strcpy(n, dp->parent->full_name); - if (!of_node_is_root(dp->parent)) { - strcpy(n + plen, "/"); - plen++; - } - strcpy(n + plen, dp->path_component_name); - - return n; + return 0; } -static struct device_node * __init prom_build_tree(struct device_node *parent, - phandle node, - struct device_node ***nextp) +static int __init prom_common_nextprop(phandle node, char *prev, char *buf) { - struct device_node *ret = NULL, *prev_sibling = NULL; - struct device_node *dp; - - while (1) { - dp = prom_create_node(node, parent); - if (!dp) - break; - - if (prev_sibling) - prev_sibling->sibling = dp; - - if (!ret) - ret = dp; - prev_sibling = dp; - - *(*nextp) = dp; - *nextp = &dp->allnext; - - dp->path_component_name = build_path_component(dp); - dp->full_name = build_full_name(dp); - - dp->child = prom_build_tree(dp, prom_getchild(node), nextp); - - if (prom_build_more) - prom_build_more(dp, nextp); - - node = prom_getsibling(node); - } + const char *name; - return ret; + buf[0] = '\0'; + name = prom_nextprop(node, prev, buf); + return handle_nextprop_quirks(buf, name); } unsigned int prom_early_allocated __initdata; +static struct of_pdt_ops prom_sparc_ops __initdata = { + .nextprop = prom_common_nextprop, + .getproplen = prom_getproplen, + .getproperty = prom_getproperty, + .getchild = prom_getchild, + .getsibling = prom_getsibling, +}; + void __init prom_build_devicetree(void) { - struct device_node **nextp; - - allnodes = prom_create_node(prom_root_node, NULL); - allnodes->path_component_name = ""; - allnodes->full_name = "/"; - - nextp = &allnodes->allnext; - allnodes->child = prom_build_tree(allnodes, - prom_getchild(allnodes->phandle), - &nextp); + of_pdt_build_devicetree(prom_root_node, &prom_sparc_ops); of_console_init(); - printk("PROM: Built device tree with %u bytes of memory.\n", - prom_early_allocated); + pr_info("PROM: Built device tree with %u bytes of memory.\n", + prom_early_allocated); } |