diff options
Diffstat (limited to 'arch/sparc/kernel/prom.c')
-rw-r--r-- | arch/sparc/kernel/prom.c | 320 |
1 files changed, 149 insertions, 171 deletions
diff --git a/arch/sparc/kernel/prom.c b/arch/sparc/kernel/prom.c index eed140b3c73..cd4fb79aa3a 100644 --- a/arch/sparc/kernel/prom.c +++ b/arch/sparc/kernel/prom.c @@ -25,73 +25,9 @@ #include <asm/prom.h> #include <asm/oplib.h> -static struct device_node *allnodes; +extern struct device_node *allnodes; /* temporary while merging */ -/* use when traversing tree through the allnext, child, sibling, - * or parent members of struct device_node. - */ -static DEFINE_RWLOCK(devtree_lock); - -int of_device_is_compatible(const struct device_node *device, - const char *compat) -{ - const char* cp; - int cplen, l; - - cp = of_get_property(device, "compatible", &cplen); - if (cp == NULL) - return 0; - while (cplen > 0) { - if (strncmp(cp, compat, strlen(compat)) == 0) - return 1; - l = strlen(cp) + 1; - cp += l; - cplen -= l; - } - - return 0; -} -EXPORT_SYMBOL(of_device_is_compatible); - -struct device_node *of_get_parent(const struct device_node *node) -{ - struct device_node *np; - - if (!node) - return NULL; - - np = node->parent; - - return np; -} -EXPORT_SYMBOL(of_get_parent); - -struct device_node *of_get_next_child(const struct device_node *node, - struct device_node *prev) -{ - struct device_node *next; - - next = prev ? prev->sibling : node->child; - for (; next != 0; next = next->sibling) { - break; - } - - return next; -} -EXPORT_SYMBOL(of_get_next_child); - -struct device_node *of_find_node_by_path(const char *path) -{ - struct device_node *np = allnodes; - - for (; np != 0; np = np->allnext) { - if (np->full_name != 0 && strcmp(np->full_name, path) == 0) - break; - } - - return np; -} -EXPORT_SYMBOL(of_find_node_by_path); +extern rwlock_t devtree_lock; /* temporary while merging */ struct device_node *of_find_node_by_phandle(phandle handle) { @@ -105,81 +41,6 @@ struct device_node *of_find_node_by_phandle(phandle handle) } EXPORT_SYMBOL(of_find_node_by_phandle); -struct device_node *of_find_node_by_name(struct device_node *from, - const char *name) -{ - struct device_node *np; - - np = from ? from->allnext : allnodes; - for (; np != NULL; np = np->allnext) - if (np->name != NULL && strcmp(np->name, name) == 0) - break; - - return np; -} -EXPORT_SYMBOL(of_find_node_by_name); - -struct device_node *of_find_node_by_type(struct device_node *from, - const char *type) -{ - struct device_node *np; - - np = from ? from->allnext : allnodes; - for (; np != 0; np = np->allnext) - if (np->type != 0 && strcmp(np->type, type) == 0) - break; - - return np; -} -EXPORT_SYMBOL(of_find_node_by_type); - -struct device_node *of_find_compatible_node(struct device_node *from, - const char *type, const char *compatible) -{ - struct device_node *np; - - np = from ? from->allnext : allnodes; - for (; np != 0; np = np->allnext) { - if (type != NULL - && !(np->type != 0 && strcmp(np->type, type) == 0)) - continue; - if (of_device_is_compatible(np, compatible)) - break; - } - - return np; -} -EXPORT_SYMBOL(of_find_compatible_node); - -struct property *of_find_property(const struct device_node *np, - const char *name, - int *lenp) -{ - struct property *pp; - - for (pp = np->properties; pp != 0; pp = pp->next) { - if (strcasecmp(pp->name, name) == 0) { - if (lenp != 0) - *lenp = pp->length; - break; - } - } - return pp; -} -EXPORT_SYMBOL(of_find_property); - -/* - * Find a property with a given name for a given node - * and return the value. - */ -const void *of_get_property(const struct device_node *np, const char *name, - int *lenp) -{ - struct property *pp = of_find_property(np,name,lenp); - return pp ? pp->value : NULL; -} -EXPORT_SYMBOL(of_get_property); - int of_getintprop_default(struct device_node *np, const char *name, int def) { struct property *prop; @@ -193,36 +54,6 @@ int of_getintprop_default(struct device_node *np, const char *name, int def) } EXPORT_SYMBOL(of_getintprop_default); -int of_n_addr_cells(struct device_node *np) -{ - const int* ip; - do { - if (np->parent) - np = np->parent; - ip = of_get_property(np, "#address-cells", NULL); - if (ip != NULL) - return *ip; - } while (np->parent); - /* No #address-cells property for the root node, default to 2 */ - return 2; -} -EXPORT_SYMBOL(of_n_addr_cells); - -int of_n_size_cells(struct device_node *np) -{ - const int* ip; - do { - if (np->parent) - np = np->parent; - ip = of_get_property(np, "#size-cells", NULL); - if (ip != NULL) - return *ip; - } while (np->parent); - /* No #size-cells property for the root node, default to 1 */ - return 1; -} -EXPORT_SYMBOL(of_n_size_cells); - int of_set_property(struct device_node *dp, const char *name, void *val, int len) { struct property **prevp; @@ -271,6 +102,21 @@ int of_set_property(struct device_node *dp, const char *name, void *val, int len } EXPORT_SYMBOL(of_set_property); +int of_find_in_proplist(const char *list, const char *match, int len) +{ + while (len > 0) { + int l; + + if (!strcmp(list, match)) + return 1; + l = strlen(list) + 1; + list += l; + len -= l; + } + return 0; +} +EXPORT_SYMBOL(of_find_in_proplist); + static unsigned int prom_early_allocated; static void * __init prom_early_alloc(unsigned long size) @@ -566,6 +412,136 @@ static struct device_node * __init build_tree(struct device_node *parent, phandl return dp; } +struct device_node *of_console_device; +EXPORT_SYMBOL(of_console_device); + +char *of_console_path; +EXPORT_SYMBOL(of_console_path); + +char *of_console_options; +EXPORT_SYMBOL(of_console_options); + +extern void restore_current(void); + +static void __init of_console_init(void) +{ + char *msg = "OF stdout device is: %s\n"; + struct device_node *dp; + unsigned long flags; + const char *type; + phandle node; + int skip, tmp, fd; + + of_console_path = prom_early_alloc(256); + + switch (prom_vers) { + case PROM_V0: + case PROM_SUN4: + skip = 0; + switch (*romvec->pv_stdout) { + case PROMDEV_SCREEN: + type = "display"; + break; + + case PROMDEV_TTYB: + skip = 1; + /* FALLTHRU */ + + case PROMDEV_TTYA: + type = "serial"; + break; + + default: + prom_printf("Invalid PROM_V0 stdout value %u\n", + *romvec->pv_stdout); + prom_halt(); + } + + tmp = skip; + for_each_node_by_type(dp, type) { + if (!tmp--) + break; + } + if (!dp) { + prom_printf("Cannot find PROM_V0 console node.\n"); + prom_halt(); + } + of_console_device = dp; + + strcpy(of_console_path, dp->full_name); + if (!strcmp(type, "serial")) { + strcat(of_console_path, + (skip ? ":b" : ":a")); + } + break; + + default: + case PROM_V2: + case PROM_V3: + fd = *romvec->pv_v2bootargs.fd_stdout; + + spin_lock_irqsave(&prom_lock, flags); + node = (*romvec->pv_v2devops.v2_inst2pkg)(fd); + restore_current(); + spin_unlock_irqrestore(&prom_lock, flags); + + if (!node) { + prom_printf("Cannot resolve stdout node from " + "instance %08x.\n", fd); + prom_halt(); + } + dp = of_find_node_by_phandle(node); + type = of_get_property(dp, "device_type", NULL); + + if (!type) { + prom_printf("Console stdout lacks " + "device_type property.\n"); + prom_halt(); + } + + if (strcmp(type, "display") && strcmp(type, "serial")) { + prom_printf("Console device_type is neither display " + "nor serial.\n"); + prom_halt(); + } + + of_console_device = dp; + + if (prom_vers == PROM_V2) { + strcpy(of_console_path, dp->full_name); + switch (*romvec->pv_stdout) { + case PROMDEV_TTYA: + strcat(of_console_path, ":a"); + break; + case PROMDEV_TTYB: + strcat(of_console_path, ":b"); + break; + } + } else { + const char *path; + + dp = of_find_node_by_path("/"); + path = of_get_property(dp, "stdout-path", NULL); + if (!path) { + prom_printf("No stdout-path in root node.\n"); + prom_halt(); + } + strcpy(of_console_path, path); + } + break; + } + + of_console_options = strrchr(of_console_path, ':'); + if (of_console_options) { + of_console_options++; + if (*of_console_options == '\0') + of_console_options = NULL; + } + + prom_printf(msg, of_console_path); + printk(msg, of_console_path); +} + void __init prom_build_devicetree(void) { struct device_node **nextp; @@ -578,6 +554,8 @@ void __init prom_build_devicetree(void) allnodes->child = build_tree(allnodes, prom_getchild(allnodes->node), &nextp); + of_console_init(); + printk("PROM: Built device tree with %u bytes of memory.\n", prom_early_allocated); } |