diff options
| -rw-r--r-- | arch/sparc/kernel/prom_common.c | 36 | ||||
| -rw-r--r-- | drivers/of/pdt.c | 40 | ||||
| -rw-r--r-- | include/linux/of_pdt.h | 20 |
3 files changed, 72 insertions, 24 deletions
diff --git a/arch/sparc/kernel/prom_common.c b/arch/sparc/kernel/prom_common.c index fe84d56b7c5a..ed25834328f4 100644 --- a/arch/sparc/kernel/prom_common.c +++ b/arch/sparc/kernel/prom_common.c | |||
| @@ -118,11 +118,45 @@ int of_find_in_proplist(const char *list, const char *match, int len) | |||
| 118 | } | 118 | } |
| 119 | EXPORT_SYMBOL(of_find_in_proplist); | 119 | EXPORT_SYMBOL(of_find_in_proplist); |
| 120 | 120 | ||
| 121 | /* | ||
| 122 | * SPARC32 and SPARC64's prom_nextprop() do things differently | ||
| 123 | * here, despite sharing the same interface. SPARC32 doesn't fill in 'buf', | ||
| 124 | * returning NULL on an error. SPARC64 fills in 'buf', but sets it to an | ||
| 125 | * empty string upon error. | ||
| 126 | */ | ||
| 127 | static int __init handle_nextprop_quirks(char *buf, const char *name) | ||
| 128 | { | ||
| 129 | if (!name || strlen(name) == 0) | ||
| 130 | return -1; | ||
| 131 | |||
| 132 | #ifdef CONFIG_SPARC32 | ||
| 133 | strcpy(buf, name); | ||
| 134 | #endif | ||
| 135 | return 0; | ||
| 136 | } | ||
| 137 | |||
| 138 | static int __init prom_common_nextprop(phandle node, char *prev, char *buf) | ||
| 139 | { | ||
| 140 | const char *name; | ||
| 141 | |||
| 142 | buf[0] = '\0'; | ||
| 143 | name = prom_nextprop(node, prev, buf); | ||
| 144 | return handle_nextprop_quirks(buf, name); | ||
| 145 | } | ||
| 146 | |||
| 121 | unsigned int prom_early_allocated __initdata; | 147 | unsigned int prom_early_allocated __initdata; |
| 122 | 148 | ||
| 149 | static struct of_pdt_ops prom_sparc_ops __initdata = { | ||
| 150 | .nextprop = prom_common_nextprop, | ||
| 151 | .getproplen = prom_getproplen, | ||
| 152 | .getproperty = prom_getproperty, | ||
| 153 | .getchild = prom_getchild, | ||
| 154 | .getsibling = prom_getsibling, | ||
| 155 | }; | ||
| 156 | |||
| 123 | void __init prom_build_devicetree(void) | 157 | void __init prom_build_devicetree(void) |
| 124 | { | 158 | { |
| 125 | of_pdt_build_devicetree(prom_root_node); | 159 | of_pdt_build_devicetree(prom_root_node, &prom_sparc_ops); |
| 126 | of_console_init(); | 160 | of_console_init(); |
| 127 | 161 | ||
| 128 | pr_info("PROM: Built device tree with %u bytes of memory.\n", | 162 | pr_info("PROM: Built device tree with %u bytes of memory.\n", |
diff --git a/drivers/of/pdt.c b/drivers/of/pdt.c index 2fdb1b478d6f..fd02fc1dd891 100644 --- a/drivers/of/pdt.c +++ b/drivers/of/pdt.c | |||
| @@ -23,7 +23,8 @@ | |||
| 23 | #include <linux/of.h> | 23 | #include <linux/of.h> |
| 24 | #include <linux/of_pdt.h> | 24 | #include <linux/of_pdt.h> |
| 25 | #include <asm/prom.h> | 25 | #include <asm/prom.h> |
| 26 | #include <asm/oplib.h> | 26 | |
| 27 | static struct of_pdt_ops *of_pdt_prom_ops __initdata; | ||
| 27 | 28 | ||
| 28 | void __initdata (*prom_build_more)(struct device_node *dp, | 29 | void __initdata (*prom_build_more)(struct device_node *dp, |
| 29 | struct device_node ***nextp); | 30 | struct device_node ***nextp); |
| @@ -59,7 +60,7 @@ static struct property * __init build_one_prop(phandle node, char *prev, | |||
| 59 | { | 60 | { |
| 60 | static struct property *tmp = NULL; | 61 | static struct property *tmp = NULL; |
| 61 | struct property *p; | 62 | struct property *p; |
| 62 | const char *name; | 63 | int err; |
| 63 | 64 | ||
| 64 | if (tmp) { | 65 | if (tmp) { |
| 65 | p = tmp; | 66 | p = tmp; |
| @@ -77,28 +78,20 @@ static struct property * __init build_one_prop(phandle node, char *prev, | |||
| 77 | p->value = prom_early_alloc(special_len); | 78 | p->value = prom_early_alloc(special_len); |
| 78 | memcpy(p->value, special_val, special_len); | 79 | memcpy(p->value, special_val, special_len); |
| 79 | } else { | 80 | } else { |
| 80 | if (prev == NULL) { | 81 | err = of_pdt_prom_ops->nextprop(node, prev, p->name); |
| 81 | name = prom_firstprop(node, p->name); | 82 | if (err) { |
| 82 | } else { | ||
| 83 | name = prom_nextprop(node, prev, p->name); | ||
| 84 | } | ||
| 85 | |||
| 86 | if (!name || strlen(name) == 0) { | ||
| 87 | tmp = p; | 83 | tmp = p; |
| 88 | return NULL; | 84 | return NULL; |
| 89 | } | 85 | } |
| 90 | #ifdef CONFIG_SPARC32 | 86 | p->length = of_pdt_prom_ops->getproplen(node, p->name); |
| 91 | strcpy(p->name, name); | ||
| 92 | #endif | ||
| 93 | p->length = prom_getproplen(node, p->name); | ||
| 94 | if (p->length <= 0) { | 87 | if (p->length <= 0) { |
| 95 | p->length = 0; | 88 | p->length = 0; |
| 96 | } else { | 89 | } else { |
| 97 | int len; | 90 | int len; |
| 98 | 91 | ||
| 99 | p->value = prom_early_alloc(p->length + 1); | 92 | p->value = prom_early_alloc(p->length + 1); |
| 100 | len = prom_getproperty(node, p->name, p->value, | 93 | len = of_pdt_prom_ops->getproperty(node, p->name, |
| 101 | p->length); | 94 | p->value, p->length); |
| 102 | if (len <= 0) | 95 | if (len <= 0) |
| 103 | p->length = 0; | 96 | p->length = 0; |
| 104 | ((unsigned char *)p->value)[p->length] = '\0'; | 97 | ((unsigned char *)p->value)[p->length] = '\0'; |
| @@ -130,10 +123,10 @@ static char * __init get_one_property(phandle node, const char *name) | |||
| 130 | char *buf = "<NULL>"; | 123 | char *buf = "<NULL>"; |
| 131 | int len; | 124 | int len; |
| 132 | 125 | ||
| 133 | len = prom_getproplen(node, name); | 126 | len = of_pdt_prom_ops->getproplen(node, name); |
| 134 | if (len > 0) { | 127 | if (len > 0) { |
| 135 | buf = prom_early_alloc(len); | 128 | buf = prom_early_alloc(len); |
| 136 | len = prom_getproperty(node, name, buf, len); | 129 | len = of_pdt_prom_ops->getproperty(node, name, buf, len); |
| 137 | } | 130 | } |
| 138 | 131 | ||
| 139 | return buf; | 132 | return buf; |
| @@ -211,21 +204,25 @@ static struct device_node * __init prom_build_tree(struct device_node *parent, | |||
| 211 | #endif | 204 | #endif |
| 212 | dp->full_name = build_full_name(dp); | 205 | dp->full_name = build_full_name(dp); |
| 213 | 206 | ||
| 214 | dp->child = prom_build_tree(dp, prom_getchild(node), nextp); | 207 | dp->child = prom_build_tree(dp, |
| 208 | of_pdt_prom_ops->getchild(node), nextp); | ||
| 215 | 209 | ||
| 216 | if (prom_build_more) | 210 | if (prom_build_more) |
| 217 | prom_build_more(dp, nextp); | 211 | prom_build_more(dp, nextp); |
| 218 | 212 | ||
| 219 | node = prom_getsibling(node); | 213 | node = of_pdt_prom_ops->getsibling(node); |
| 220 | } | 214 | } |
| 221 | 215 | ||
| 222 | return ret; | 216 | return ret; |
| 223 | } | 217 | } |
| 224 | 218 | ||
| 225 | void __init of_pdt_build_devicetree(phandle root_node) | 219 | void __init of_pdt_build_devicetree(phandle root_node, struct of_pdt_ops *ops) |
| 226 | { | 220 | { |
| 227 | struct device_node **nextp; | 221 | struct device_node **nextp; |
| 228 | 222 | ||
| 223 | BUG_ON(!ops); | ||
| 224 | of_pdt_prom_ops = ops; | ||
| 225 | |||
| 229 | allnodes = prom_create_node(root_node, NULL); | 226 | allnodes = prom_create_node(root_node, NULL); |
| 230 | #if defined(CONFIG_SPARC) | 227 | #if defined(CONFIG_SPARC) |
| 231 | allnodes->path_component_name = ""; | 228 | allnodes->path_component_name = ""; |
| @@ -234,6 +231,5 @@ void __init of_pdt_build_devicetree(phandle root_node) | |||
| 234 | 231 | ||
| 235 | nextp = &allnodes->allnext; | 232 | nextp = &allnodes->allnext; |
| 236 | allnodes->child = prom_build_tree(allnodes, | 233 | allnodes->child = prom_build_tree(allnodes, |
| 237 | prom_getchild(allnodes->phandle), | 234 | of_pdt_prom_ops->getchild(allnodes->phandle), &nextp); |
| 238 | &nextp); | ||
| 239 | } | 235 | } |
diff --git a/include/linux/of_pdt.h b/include/linux/of_pdt.h index c0a8774e45d0..303c5ffae9b4 100644 --- a/include/linux/of_pdt.h +++ b/include/linux/of_pdt.h | |||
| @@ -13,10 +13,28 @@ | |||
| 13 | #ifndef _LINUX_OF_PDT_H | 13 | #ifndef _LINUX_OF_PDT_H |
| 14 | #define _LINUX_OF_PDT_H | 14 | #define _LINUX_OF_PDT_H |
| 15 | 15 | ||
| 16 | /* overridable operations for calling into the PROM */ | ||
| 17 | struct of_pdt_ops { | ||
| 18 | /* | ||
| 19 | * buf should be 32 bytes; return 0 on success. | ||
| 20 | * If prev is NULL, the first property will be returned. | ||
| 21 | */ | ||
| 22 | int (*nextprop)(phandle node, char *prev, char *buf); | ||
| 23 | |||
| 24 | /* for both functions, return proplen on success; -1 on error */ | ||
| 25 | int (*getproplen)(phandle node, const char *prop); | ||
| 26 | int (*getproperty)(phandle node, const char *prop, char *buf, | ||
| 27 | int bufsize); | ||
| 28 | |||
| 29 | /* phandles are 0 if no child or sibling exists */ | ||
| 30 | phandle (*getchild)(phandle parent); | ||
| 31 | phandle (*getsibling)(phandle node); | ||
| 32 | }; | ||
| 33 | |||
| 16 | extern void *prom_early_alloc(unsigned long size); | 34 | extern void *prom_early_alloc(unsigned long size); |
| 17 | 35 | ||
| 18 | /* for building the device tree */ | 36 | /* for building the device tree */ |
| 19 | extern void of_pdt_build_devicetree(phandle root_node); | 37 | extern void of_pdt_build_devicetree(phandle root_node, struct of_pdt_ops *ops); |
| 20 | 38 | ||
| 21 | extern void (*prom_build_more)(struct device_node *dp, | 39 | extern void (*prom_build_more)(struct device_node *dp, |
| 22 | struct device_node ***nextp); | 40 | struct device_node ***nextp); |
