From e169cfbef46d62e042614ffafa8880eed1d894bb Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Mon, 23 Nov 2009 14:53:09 -0700 Subject: of/flattree: merge find_flat_dt_string and initial_boot_params Merge common code between Microblaze and PowerPC. Signed-off-by: Grant Likely Reviewed-by: Wolfram Sang Tested-by: Michal Simek --- drivers/of/fdt.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 drivers/of/fdt.c (limited to 'drivers/of/fdt.c') diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c new file mode 100644 index 000000000000..9faa9a5cbdf0 --- /dev/null +++ b/drivers/of/fdt.c @@ -0,0 +1,21 @@ +/* + * Functions for working with the Flattened Device Tree data format + * + * Copyright 2009 Benjamin Herrenschmidt, IBM Corp + * benh@kernel.crashing.org + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +#include +#include + +struct boot_param_header *initial_boot_params; + +char *find_flat_dt_string(u32 offset) +{ + return ((char *)initial_boot_params) + + initial_boot_params->off_dt_strings + offset; +} -- cgit v1.2.3 From c8cb7a59842c0b512b44f6f818cdb0b5a3ddc89e Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Mon, 23 Nov 2009 18:54:23 -0700 Subject: of/flattree: merge of_scan_flat_dt Merge common code between PowerPC and Microblaze Signed-off-by: Grant Likely Reviewed-by: Wolfram Sang Tested-by: Michal Simek --- arch/microblaze/kernel/prom.c | 61 ----------------------------------------- arch/powerpc/kernel/prom.c | 61 ----------------------------------------- drivers/of/fdt.c | 64 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 64 insertions(+), 122 deletions(-) (limited to 'drivers/of/fdt.c') diff --git a/arch/microblaze/kernel/prom.c b/arch/microblaze/kernel/prom.c index 06d620ab4168..0db8ee64ffe6 100644 --- a/arch/microblaze/kernel/prom.c +++ b/arch/microblaze/kernel/prom.c @@ -50,67 +50,6 @@ typedef u32 cell_t; /* export that to outside world */ struct device_node *of_chosen; -/** - * This function is used to scan the flattened device-tree, it is - * used to extract the memory informations at boot before we can - * unflatten the tree - */ -int __init of_scan_flat_dt(int (*it)(unsigned long node, - const char *uname, int depth, - void *data), - void *data) -{ - unsigned long p = ((unsigned long)initial_boot_params) + - initial_boot_params->off_dt_struct; - int rc = 0; - int depth = -1; - - do { - u32 tag = *((u32 *)p); - char *pathp; - - p += 4; - if (tag == OF_DT_END_NODE) { - depth--; - continue; - } - if (tag == OF_DT_NOP) - continue; - if (tag == OF_DT_END) - break; - if (tag == OF_DT_PROP) { - u32 sz = *((u32 *)p); - p += 8; - if (initial_boot_params->version < 0x10) - p = _ALIGN(p, sz >= 8 ? 8 : 4); - p += sz; - p = _ALIGN(p, 4); - continue; - } - if (tag != OF_DT_BEGIN_NODE) { - printk(KERN_WARNING "Invalid tag %x scanning flattened" - " device tree !\n", tag); - return -EINVAL; - } - depth++; - pathp = (char *)p; - p = _ALIGN(p + strlen(pathp) + 1, 4); - if ((*pathp) == '/') { - char *lp, *np; - for (lp = NULL, np = pathp; *np; np++) - if ((*np) == '/') - lp = np+1; - if (lp != NULL) - pathp = lp; - } - rc = it(p, pathp, depth, data); - if (rc != 0) - break; - } while (1); - - return rc; -} - unsigned long __init of_get_flat_dt_root(void) { unsigned long p = ((unsigned long)initial_boot_params) + diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index fccf7e49bb28..14a07b9e00d1 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -80,67 +80,6 @@ extern rwlock_t devtree_lock; /* temporary while merging */ /* export that to outside world */ struct device_node *of_chosen; -/** - * This function is used to scan the flattened device-tree, it is - * used to extract the memory informations at boot before we can - * unflatten the tree - */ -int __init of_scan_flat_dt(int (*it)(unsigned long node, - const char *uname, int depth, - void *data), - void *data) -{ - unsigned long p = ((unsigned long)initial_boot_params) + - initial_boot_params->off_dt_struct; - int rc = 0; - int depth = -1; - - do { - u32 tag = *((u32 *)p); - char *pathp; - - p += 4; - if (tag == OF_DT_END_NODE) { - depth --; - continue; - } - if (tag == OF_DT_NOP) - continue; - if (tag == OF_DT_END) - break; - if (tag == OF_DT_PROP) { - u32 sz = *((u32 *)p); - p += 8; - if (initial_boot_params->version < 0x10) - p = _ALIGN(p, sz >= 8 ? 8 : 4); - p += sz; - p = _ALIGN(p, 4); - continue; - } - if (tag != OF_DT_BEGIN_NODE) { - printk(KERN_WARNING "Invalid tag %x scanning flattened" - " device tree !\n", tag); - return -EINVAL; - } - depth++; - pathp = (char *)p; - p = _ALIGN(p + strlen(pathp) + 1, 4); - if ((*pathp) == '/') { - char *lp, *np; - for (lp = NULL, np = pathp; *np; np++) - if ((*np) == '/') - lp = np+1; - if (lp != NULL) - pathp = lp; - } - rc = it(p, pathp, depth, data); - if (rc != 0) - break; - } while(1); - - return rc; -} - unsigned long __init of_get_flat_dt_root(void) { unsigned long p = ((unsigned long)initial_boot_params) + diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index 9faa9a5cbdf0..dd9057cb7aa7 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -19,3 +19,67 @@ char *find_flat_dt_string(u32 offset) return ((char *)initial_boot_params) + initial_boot_params->off_dt_strings + offset; } + +/** + * of_scan_flat_dt - scan flattened tree blob and call callback on each. + * @it: callback function + * @data: context data pointer + * + * This function is used to scan the flattened device-tree, it is + * used to extract the memory information at boot before we can + * unflatten the tree + */ +int __init of_scan_flat_dt(int (*it)(unsigned long node, + const char *uname, int depth, + void *data), + void *data) +{ + unsigned long p = ((unsigned long)initial_boot_params) + + initial_boot_params->off_dt_struct; + int rc = 0; + int depth = -1; + + do { + u32 tag = *((u32 *)p); + char *pathp; + + p += 4; + if (tag == OF_DT_END_NODE) { + depth--; + continue; + } + if (tag == OF_DT_NOP) + continue; + if (tag == OF_DT_END) + break; + if (tag == OF_DT_PROP) { + u32 sz = *((u32 *)p); + p += 8; + if (initial_boot_params->version < 0x10) + p = _ALIGN(p, sz >= 8 ? 8 : 4); + p += sz; + p = _ALIGN(p, 4); + continue; + } + if (tag != OF_DT_BEGIN_NODE) { + pr_err("Invalid tag %x in flat device tree!\n", tag); + return -EINVAL; + } + depth++; + pathp = (char *)p; + p = _ALIGN(p + strlen(pathp) + 1, 4); + if ((*pathp) == '/') { + char *lp, *np; + for (lp = NULL, np = pathp; *np; np++) + if ((*np) == '/') + lp = np+1; + if (lp != NULL) + pathp = lp; + } + rc = it(p, pathp, depth, data); + if (rc != 0) + break; + } while (1); + + return rc; +} -- cgit v1.2.3 From 819d2819303654c6829d572e698e2d0021c08599 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Mon, 23 Nov 2009 19:44:23 -0700 Subject: of/flattree: merge of_get_flat_dt_root Merge common code between PowerPC and MicroBlaze Signed-off-by: Grant Likely Reviewed-by: Wolfram Sang Tested-by: Michal Simek --- arch/microblaze/kernel/prom.c | 12 ------------ arch/powerpc/kernel/prom.c | 12 ------------ drivers/of/fdt.c | 16 ++++++++++++++++ 3 files changed, 16 insertions(+), 24 deletions(-) (limited to 'drivers/of/fdt.c') diff --git a/arch/microblaze/kernel/prom.c b/arch/microblaze/kernel/prom.c index 0db8ee64ffe6..7eb6f8bdb81a 100644 --- a/arch/microblaze/kernel/prom.c +++ b/arch/microblaze/kernel/prom.c @@ -50,18 +50,6 @@ typedef u32 cell_t; /* export that to outside world */ struct device_node *of_chosen; -unsigned long __init of_get_flat_dt_root(void) -{ - unsigned long p = ((unsigned long)initial_boot_params) + - initial_boot_params->off_dt_struct; - - while (*((u32 *)p) == OF_DT_NOP) - p += 4; - BUG_ON(*((u32 *)p) != OF_DT_BEGIN_NODE); - p += 4; - return _ALIGN(p + strlen((char *)p) + 1, 4); -} - /** * This function can be used within scan_flattened_dt callback to get * access to properties diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 14a07b9e00d1..b5d5f85e9c2c 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -80,18 +80,6 @@ extern rwlock_t devtree_lock; /* temporary while merging */ /* export that to outside world */ struct device_node *of_chosen; -unsigned long __init of_get_flat_dt_root(void) -{ - unsigned long p = ((unsigned long)initial_boot_params) + - initial_boot_params->off_dt_struct; - - while(*((u32 *)p) == OF_DT_NOP) - p += 4; - BUG_ON (*((u32 *)p) != OF_DT_BEGIN_NODE); - p += 4; - return _ALIGN(p + strlen((char *)p) + 1, 4); -} - /** * This function can be used within scan_flattened_dt callback to get * access to properties diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index dd9057cb7aa7..f41d739aa2f7 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -83,3 +83,19 @@ int __init of_scan_flat_dt(int (*it)(unsigned long node, return rc; } + +/** + * of_get_flat_dt_root - find the root node in the flat blob + */ +unsigned long __init of_get_flat_dt_root(void) +{ + unsigned long p = ((unsigned long)initial_boot_params) + + initial_boot_params->off_dt_struct; + + while (*((u32 *)p) == OF_DT_NOP) + p += 4; + BUG_ON(*((u32 *)p) != OF_DT_BEGIN_NODE); + p += 4; + return _ALIGN(p + strlen((char *)p) + 1, 4); +} + -- cgit v1.2.3 From ca900cfa2944448bdb76e1246f282e59bc65f472 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Mon, 23 Nov 2009 20:06:59 -0700 Subject: of/flattree: merge of_get_flat_dt_prop Merge common code between PowerPC and Microblaze Signed-off-by: Grant Likely Reviewed-by: Wolfram Sang Tested-by: Michal Simek --- arch/microblaze/kernel/prom.c | 42 ------------------------------------------ arch/powerpc/kernel/prom.c | 42 ------------------------------------------ drivers/of/fdt.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 43 insertions(+), 84 deletions(-) (limited to 'drivers/of/fdt.c') diff --git a/arch/microblaze/kernel/prom.c b/arch/microblaze/kernel/prom.c index 7eb6f8bdb81a..d75c6253c0de 100644 --- a/arch/microblaze/kernel/prom.c +++ b/arch/microblaze/kernel/prom.c @@ -50,48 +50,6 @@ typedef u32 cell_t; /* export that to outside world */ struct device_node *of_chosen; -/** - * This function can be used within scan_flattened_dt callback to get - * access to properties - */ -void *__init of_get_flat_dt_prop(unsigned long node, const char *name, - unsigned long *size) -{ - unsigned long p = node; - - do { - u32 tag = *((u32 *)p); - u32 sz, noff; - const char *nstr; - - p += 4; - if (tag == OF_DT_NOP) - continue; - if (tag != OF_DT_PROP) - return NULL; - - sz = *((u32 *)p); - noff = *((u32 *)(p + 4)); - p += 8; - if (initial_boot_params->version < 0x10) - p = _ALIGN(p, sz >= 8 ? 8 : 4); - - nstr = find_flat_dt_string(noff); - if (nstr == NULL) { - printk(KERN_WARNING "Can't find property index" - " name !\n"); - return NULL; - } - if (strcmp(name, nstr) == 0) { - if (size) - *size = sz; - return (void *)p; - } - p += sz; - p = _ALIGN(p, 4); - } while (1); -} - int __init of_flat_dt_is_compatible(unsigned long node, const char *compat) { const char *cp; diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index b5d5f85e9c2c..cd0a2bfc978b 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -80,48 +80,6 @@ extern rwlock_t devtree_lock; /* temporary while merging */ /* export that to outside world */ struct device_node *of_chosen; -/** - * This function can be used within scan_flattened_dt callback to get - * access to properties - */ -void* __init of_get_flat_dt_prop(unsigned long node, const char *name, - unsigned long *size) -{ - unsigned long p = node; - - do { - u32 tag = *((u32 *)p); - u32 sz, noff; - const char *nstr; - - p += 4; - if (tag == OF_DT_NOP) - continue; - if (tag != OF_DT_PROP) - return NULL; - - sz = *((u32 *)p); - noff = *((u32 *)(p + 4)); - p += 8; - if (initial_boot_params->version < 0x10) - p = _ALIGN(p, sz >= 8 ? 8 : 4); - - nstr = find_flat_dt_string(noff); - if (nstr == NULL) { - printk(KERN_WARNING "Can't find property index" - " name !\n"); - return NULL; - } - if (strcmp(name, nstr) == 0) { - if (size) - *size = sz; - return (void *)p; - } - p += sz; - p = _ALIGN(p, 4); - } while(1); -} - int __init of_flat_dt_is_compatible(unsigned long node, const char *compat) { const char* cp; diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index f41d739aa2f7..b17a9086cbfc 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -99,3 +99,46 @@ unsigned long __init of_get_flat_dt_root(void) return _ALIGN(p + strlen((char *)p) + 1, 4); } +/** + * of_get_flat_dt_prop - Given a node in the flat blob, return the property ptr + * + * This function can be used within scan_flattened_dt callback to get + * access to properties + */ +void *__init of_get_flat_dt_prop(unsigned long node, const char *name, + unsigned long *size) +{ + unsigned long p = node; + + do { + u32 tag = *((u32 *)p); + u32 sz, noff; + const char *nstr; + + p += 4; + if (tag == OF_DT_NOP) + continue; + if (tag != OF_DT_PROP) + return NULL; + + sz = *((u32 *)p); + noff = *((u32 *)(p + 4)); + p += 8; + if (initial_boot_params->version < 0x10) + p = _ALIGN(p, sz >= 8 ? 8 : 4); + + nstr = find_flat_dt_string(noff); + if (nstr == NULL) { + pr_warning("Can't find property index name !\n"); + return NULL; + } + if (strcmp(name, nstr) == 0) { + if (size) + *size = sz; + return (void *)p; + } + p += sz; + p = _ALIGN(p, 4); + } while (1); +} + -- cgit v1.2.3 From 00e38efd90f27518ec96b37b1c7773e3ac529966 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Mon, 23 Nov 2009 20:07:00 -0700 Subject: of/flattree: Merge of_flat_dt_is_compatible Merge common code between PowerPC and Microblaze Signed-off-by: Grant Likely Reviewed-by: Wolfram Sang Tested-by: Michal Simek --- arch/microblaze/kernel/prom.c | 19 ------------------- arch/powerpc/kernel/prom.c | 19 ------------------- drivers/of/fdt.c | 24 ++++++++++++++++++++++++ 3 files changed, 24 insertions(+), 38 deletions(-) (limited to 'drivers/of/fdt.c') diff --git a/arch/microblaze/kernel/prom.c b/arch/microblaze/kernel/prom.c index d75c6253c0de..eb27bd3a39b4 100644 --- a/arch/microblaze/kernel/prom.c +++ b/arch/microblaze/kernel/prom.c @@ -50,25 +50,6 @@ typedef u32 cell_t; /* export that to outside world */ struct device_node *of_chosen; -int __init of_flat_dt_is_compatible(unsigned long node, const char *compat) -{ - const char *cp; - unsigned long cplen, l; - - cp = of_get_flat_dt_prop(node, "compatible", &cplen); - if (cp == NULL) - return 0; - while (cplen > 0) { - if (strncasecmp(cp, compat, strlen(compat)) == 0) - return 1; - l = strlen(cp) + 1; - cp += l; - cplen -= l; - } - - return 0; -} - static void *__init unflatten_dt_alloc(unsigned long *mem, unsigned long size, unsigned long align) { diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index cd0a2bfc978b..413e608863dd 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -80,25 +80,6 @@ extern rwlock_t devtree_lock; /* temporary while merging */ /* export that to outside world */ struct device_node *of_chosen; -int __init of_flat_dt_is_compatible(unsigned long node, const char *compat) -{ - const char* cp; - unsigned long cplen, l; - - cp = of_get_flat_dt_prop(node, "compatible", &cplen); - if (cp == NULL) - return 0; - while (cplen > 0) { - if (strncasecmp(cp, compat, strlen(compat)) == 0) - return 1; - l = strlen(cp) + 1; - cp += l; - cplen -= l; - } - - return 0; -} - static void *__init unflatten_dt_alloc(unsigned long *mem, unsigned long size, unsigned long align) { diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index b17a9086cbfc..5cdd958db9af 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -142,3 +142,27 @@ void *__init of_get_flat_dt_prop(unsigned long node, const char *name, } while (1); } +/** + * of_flat_dt_is_compatible - Return true if given node has compat in compatible list + * @node: node to test + * @compat: compatible string to compare with compatible list. + */ +int __init of_flat_dt_is_compatible(unsigned long node, const char *compat) +{ + const char *cp; + unsigned long cplen, l; + + cp = of_get_flat_dt_prop(node, "compatible", &cplen); + if (cp == NULL) + return 0; + while (cplen > 0) { + if (strncasecmp(cp, compat, strlen(compat)) == 0) + return 1; + l = strlen(cp) + 1; + cp += l; + cplen -= l; + } + + return 0; +} + -- cgit v1.2.3 From bbd33931a08362f78266a4016211a35947b91041 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Mon, 23 Nov 2009 20:07:00 -0700 Subject: of/flattree: Merge unflatten_dt_node Merge common code between PowerPC and MicroBlaze Signed-off-by: Grant Likely Reviewed-by: Wolfram Sang Tested-by: Michal Simek --- arch/microblaze/kernel/prom.c | 195 ---------------------------------------- arch/powerpc/kernel/prom.c | 194 ---------------------------------------- drivers/of/fdt.c | 200 ++++++++++++++++++++++++++++++++++++++++++ include/linux/of_fdt.h | 4 + 4 files changed, 204 insertions(+), 389 deletions(-) (limited to 'drivers/of/fdt.c') diff --git a/arch/microblaze/kernel/prom.c b/arch/microblaze/kernel/prom.c index eb27bd3a39b4..021770abfbd7 100644 --- a/arch/microblaze/kernel/prom.c +++ b/arch/microblaze/kernel/prom.c @@ -50,201 +50,6 @@ typedef u32 cell_t; /* export that to outside world */ struct device_node *of_chosen; -static void *__init unflatten_dt_alloc(unsigned long *mem, unsigned long size, - unsigned long align) -{ - void *res; - - *mem = _ALIGN(*mem, align); - res = (void *)*mem; - *mem += size; - - return res; -} - -static unsigned long __init unflatten_dt_node(unsigned long mem, - unsigned long *p, - struct device_node *dad, - struct device_node ***allnextpp, - unsigned long fpsize) -{ - struct device_node *np; - struct property *pp, **prev_pp = NULL; - char *pathp; - u32 tag; - unsigned int l, allocl; - int has_name = 0; - int new_format = 0; - - tag = *((u32 *)(*p)); - if (tag != OF_DT_BEGIN_NODE) { - printk("Weird tag at start of node: %x\n", tag); - return mem; - } - *p += 4; - pathp = (char *)*p; - l = allocl = strlen(pathp) + 1; - *p = _ALIGN(*p + l, 4); - - /* version 0x10 has a more compact unit name here instead of the full - * path. we accumulate the full path size using "fpsize", we'll rebuild - * it later. We detect this because the first character of the name is - * not '/'. - */ - if ((*pathp) != '/') { - new_format = 1; - if (fpsize == 0) { - /* root node: special case. fpsize accounts for path - * plus terminating zero. root node only has '/', so - * fpsize should be 2, but we want to avoid the first - * level nodes to have two '/' so we use fpsize 1 here - */ - fpsize = 1; - allocl = 2; - } else { - /* account for '/' and path size minus terminal 0 - * already in 'l' - */ - fpsize += l; - allocl = fpsize; - } - } - - np = unflatten_dt_alloc(&mem, sizeof(struct device_node) + allocl, - __alignof__(struct device_node)); - if (allnextpp) { - memset(np, 0, sizeof(*np)); - np->full_name = ((char *)np) + sizeof(struct device_node); - if (new_format) { - char *p2 = np->full_name; - /* rebuild full path for new format */ - if (dad && dad->parent) { - strcpy(p2, dad->full_name); -#ifdef DEBUG - if ((strlen(p2) + l + 1) != allocl) { - pr_debug("%s: p: %d, l: %d, a: %d\n", - pathp, (int)strlen(p2), - l, allocl); - } -#endif - p2 += strlen(p2); - } - *(p2++) = '/'; - memcpy(p2, pathp, l); - } else - memcpy(np->full_name, pathp, l); - prev_pp = &np->properties; - **allnextpp = np; - *allnextpp = &np->allnext; - if (dad != NULL) { - np->parent = dad; - /* we temporarily use the next field as `last_child'*/ - if (dad->next == NULL) - dad->child = np; - else - dad->next->sibling = np; - dad->next = np; - } - kref_init(&np->kref); - } - while (1) { - u32 sz, noff; - char *pname; - - tag = *((u32 *)(*p)); - if (tag == OF_DT_NOP) { - *p += 4; - continue; - } - if (tag != OF_DT_PROP) - break; - *p += 4; - sz = *((u32 *)(*p)); - noff = *((u32 *)((*p) + 4)); - *p += 8; - if (initial_boot_params->version < 0x10) - *p = _ALIGN(*p, sz >= 8 ? 8 : 4); - - pname = find_flat_dt_string(noff); - if (pname == NULL) { - printk(KERN_INFO - "Can't find property name in list !\n"); - break; - } - if (strcmp(pname, "name") == 0) - has_name = 1; - l = strlen(pname) + 1; - pp = unflatten_dt_alloc(&mem, sizeof(struct property), - __alignof__(struct property)); - if (allnextpp) { - if (strcmp(pname, "linux,phandle") == 0) { - np->node = *((u32 *)*p); - if (np->linux_phandle == 0) - np->linux_phandle = np->node; - } - if (strcmp(pname, "ibm,phandle") == 0) - np->linux_phandle = *((u32 *)*p); - pp->name = pname; - pp->length = sz; - pp->value = (void *)*p; - *prev_pp = pp; - prev_pp = &pp->next; - } - *p = _ALIGN((*p) + sz, 4); - } - /* with version 0x10 we may not have the name property, recreate - * it here from the unit name if absent - */ - if (!has_name) { - char *p1 = pathp, *ps = pathp, *pa = NULL; - int sz; - - while (*p1) { - if ((*p1) == '@') - pa = p1; - if ((*p1) == '/') - ps = p1 + 1; - p1++; - } - if (pa < ps) - pa = p1; - sz = (pa - ps) + 1; - pp = unflatten_dt_alloc(&mem, sizeof(struct property) + sz, - __alignof__(struct property)); - if (allnextpp) { - pp->name = "name"; - pp->length = sz; - pp->value = pp + 1; - *prev_pp = pp; - prev_pp = &pp->next; - memcpy(pp->value, ps, sz - 1); - ((char *)pp->value)[sz - 1] = 0; - pr_debug("fixed up name for %s -> %s\n", pathp, - (char *)pp->value); - } - } - if (allnextpp) { - *prev_pp = NULL; - np->name = of_get_property(np, "name", NULL); - np->type = of_get_property(np, "device_type", NULL); - - if (!np->name) - np->name = ""; - if (!np->type) - np->type = ""; - } - while (tag == OF_DT_BEGIN_NODE) { - mem = unflatten_dt_node(mem, p, np, allnextpp, fpsize); - tag = *((u32 *)(*p)); - } - if (tag != OF_DT_END_NODE) { - printk(KERN_INFO "Weird tag at end of node: %x\n", tag); - return mem; - } - *p += 4; - return mem; -} - /** * unflattens the device-tree passed by the firmware, creating the * tree of struct device_node. It also fills the "name" and "type" diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 413e608863dd..a102a0a33ed1 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -80,200 +80,6 @@ extern rwlock_t devtree_lock; /* temporary while merging */ /* export that to outside world */ struct device_node *of_chosen; -static void *__init unflatten_dt_alloc(unsigned long *mem, unsigned long size, - unsigned long align) -{ - void *res; - - *mem = _ALIGN(*mem, align); - res = (void *)*mem; - *mem += size; - - return res; -} - -static unsigned long __init unflatten_dt_node(unsigned long mem, - unsigned long *p, - struct device_node *dad, - struct device_node ***allnextpp, - unsigned long fpsize) -{ - struct device_node *np; - struct property *pp, **prev_pp = NULL; - char *pathp; - u32 tag; - unsigned int l, allocl; - int has_name = 0; - int new_format = 0; - - tag = *((u32 *)(*p)); - if (tag != OF_DT_BEGIN_NODE) { - printk("Weird tag at start of node: %x\n", tag); - return mem; - } - *p += 4; - pathp = (char *)*p; - l = allocl = strlen(pathp) + 1; - *p = _ALIGN(*p + l, 4); - - /* version 0x10 has a more compact unit name here instead of the full - * path. we accumulate the full path size using "fpsize", we'll rebuild - * it later. We detect this because the first character of the name is - * not '/'. - */ - if ((*pathp) != '/') { - new_format = 1; - if (fpsize == 0) { - /* root node: special case. fpsize accounts for path - * plus terminating zero. root node only has '/', so - * fpsize should be 2, but we want to avoid the first - * level nodes to have two '/' so we use fpsize 1 here - */ - fpsize = 1; - allocl = 2; - } else { - /* account for '/' and path size minus terminal 0 - * already in 'l' - */ - fpsize += l; - allocl = fpsize; - } - } - - - np = unflatten_dt_alloc(&mem, sizeof(struct device_node) + allocl, - __alignof__(struct device_node)); - if (allnextpp) { - memset(np, 0, sizeof(*np)); - np->full_name = ((char*)np) + sizeof(struct device_node); - if (new_format) { - char *p = np->full_name; - /* rebuild full path for new format */ - if (dad && dad->parent) { - strcpy(p, dad->full_name); -#ifdef DEBUG - if ((strlen(p) + l + 1) != allocl) { - DBG("%s: p: %d, l: %d, a: %d\n", - pathp, (int)strlen(p), l, allocl); - } -#endif - p += strlen(p); - } - *(p++) = '/'; - memcpy(p, pathp, l); - } else - memcpy(np->full_name, pathp, l); - prev_pp = &np->properties; - **allnextpp = np; - *allnextpp = &np->allnext; - if (dad != NULL) { - np->parent = dad; - /* we temporarily use the next field as `last_child'*/ - if (dad->next == 0) - dad->child = np; - else - dad->next->sibling = np; - dad->next = np; - } - kref_init(&np->kref); - } - while(1) { - u32 sz, noff; - char *pname; - - tag = *((u32 *)(*p)); - if (tag == OF_DT_NOP) { - *p += 4; - continue; - } - if (tag != OF_DT_PROP) - break; - *p += 4; - sz = *((u32 *)(*p)); - noff = *((u32 *)((*p) + 4)); - *p += 8; - if (initial_boot_params->version < 0x10) - *p = _ALIGN(*p, sz >= 8 ? 8 : 4); - - pname = find_flat_dt_string(noff); - if (pname == NULL) { - printk("Can't find property name in list !\n"); - break; - } - if (strcmp(pname, "name") == 0) - has_name = 1; - l = strlen(pname) + 1; - pp = unflatten_dt_alloc(&mem, sizeof(struct property), - __alignof__(struct property)); - if (allnextpp) { - if (strcmp(pname, "linux,phandle") == 0) { - np->node = *((u32 *)*p); - if (np->linux_phandle == 0) - np->linux_phandle = np->node; - } - if (strcmp(pname, "ibm,phandle") == 0) - np->linux_phandle = *((u32 *)*p); - pp->name = pname; - pp->length = sz; - pp->value = (void *)*p; - *prev_pp = pp; - prev_pp = &pp->next; - } - *p = _ALIGN((*p) + sz, 4); - } - /* with version 0x10 we may not have the name property, recreate - * it here from the unit name if absent - */ - if (!has_name) { - char *p = pathp, *ps = pathp, *pa = NULL; - int sz; - - while (*p) { - if ((*p) == '@') - pa = p; - if ((*p) == '/') - ps = p + 1; - p++; - } - if (pa < ps) - pa = p; - sz = (pa - ps) + 1; - pp = unflatten_dt_alloc(&mem, sizeof(struct property) + sz, - __alignof__(struct property)); - if (allnextpp) { - pp->name = "name"; - pp->length = sz; - pp->value = pp + 1; - *prev_pp = pp; - prev_pp = &pp->next; - memcpy(pp->value, ps, sz - 1); - ((char *)pp->value)[sz - 1] = 0; - DBG("fixed up name for %s -> %s\n", pathp, - (char *)pp->value); - } - } - if (allnextpp) { - *prev_pp = NULL; - np->name = of_get_property(np, "name", NULL); - np->type = of_get_property(np, "device_type", NULL); - - if (!np->name) - np->name = ""; - if (!np->type) - np->type = ""; - } - while (tag == OF_DT_BEGIN_NODE) { - mem = unflatten_dt_node(mem, p, np, allnextpp, fpsize); - tag = *((u32 *)(*p)); - } - if (tag != OF_DT_END_NODE) { - printk("Weird tag at end of node: %x\n", tag); - return mem; - } - *p += 4; - return mem; -} - static int __init early_parse_mem(char *p) { if (!p) diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index 5cdd958db9af..6852ecf6d1e1 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -166,3 +166,203 @@ int __init of_flat_dt_is_compatible(unsigned long node, const char *compat) return 0; } +static void *__init unflatten_dt_alloc(unsigned long *mem, unsigned long size, + unsigned long align) +{ + void *res; + + *mem = _ALIGN(*mem, align); + res = (void *)*mem; + *mem += size; + + return res; +} + +/** + * unflatten_dt_node - Alloc and populate a device_node from the flat tree + * @p: pointer to node in flat tree + * @dad: Parent struct device_node + * @allnextpp: pointer to ->allnext from last allocated device_node + * @fpsize: Size of the node path up at the current depth. + */ +unsigned long __init unflatten_dt_node(unsigned long mem, + unsigned long *p, + struct device_node *dad, + struct device_node ***allnextpp, + unsigned long fpsize) +{ + struct device_node *np; + struct property *pp, **prev_pp = NULL; + char *pathp; + u32 tag; + unsigned int l, allocl; + int has_name = 0; + int new_format = 0; + + tag = *((u32 *)(*p)); + if (tag != OF_DT_BEGIN_NODE) { + pr_err("Weird tag at start of node: %x\n", tag); + return mem; + } + *p += 4; + pathp = (char *)*p; + l = allocl = strlen(pathp) + 1; + *p = _ALIGN(*p + l, 4); + + /* version 0x10 has a more compact unit name here instead of the full + * path. we accumulate the full path size using "fpsize", we'll rebuild + * it later. We detect this because the first character of the name is + * not '/'. + */ + if ((*pathp) != '/') { + new_format = 1; + if (fpsize == 0) { + /* root node: special case. fpsize accounts for path + * plus terminating zero. root node only has '/', so + * fpsize should be 2, but we want to avoid the first + * level nodes to have two '/' so we use fpsize 1 here + */ + fpsize = 1; + allocl = 2; + } else { + /* account for '/' and path size minus terminal 0 + * already in 'l' + */ + fpsize += l; + allocl = fpsize; + } + } + + np = unflatten_dt_alloc(&mem, sizeof(struct device_node) + allocl, + __alignof__(struct device_node)); + if (allnextpp) { + memset(np, 0, sizeof(*np)); + np->full_name = ((char *)np) + sizeof(struct device_node); + if (new_format) { + char *fn = np->full_name; + /* rebuild full path for new format */ + if (dad && dad->parent) { + strcpy(fn, dad->full_name); +#ifdef DEBUG + if ((strlen(fn) + l + 1) != allocl) { + pr_debug("%s: p: %d, l: %d, a: %d\n", + pathp, (int)strlen(fn), + l, allocl); + } +#endif + fn += strlen(fn); + } + *(fn++) = '/'; + memcpy(fn, pathp, l); + } else + memcpy(np->full_name, pathp, l); + prev_pp = &np->properties; + **allnextpp = np; + *allnextpp = &np->allnext; + if (dad != NULL) { + np->parent = dad; + /* we temporarily use the next field as `last_child'*/ + if (dad->next == NULL) + dad->child = np; + else + dad->next->sibling = np; + dad->next = np; + } + kref_init(&np->kref); + } + while (1) { + u32 sz, noff; + char *pname; + + tag = *((u32 *)(*p)); + if (tag == OF_DT_NOP) { + *p += 4; + continue; + } + if (tag != OF_DT_PROP) + break; + *p += 4; + sz = *((u32 *)(*p)); + noff = *((u32 *)((*p) + 4)); + *p += 8; + if (initial_boot_params->version < 0x10) + *p = _ALIGN(*p, sz >= 8 ? 8 : 4); + + pname = find_flat_dt_string(noff); + if (pname == NULL) { + pr_info("Can't find property name in list !\n"); + break; + } + if (strcmp(pname, "name") == 0) + has_name = 1; + l = strlen(pname) + 1; + pp = unflatten_dt_alloc(&mem, sizeof(struct property), + __alignof__(struct property)); + if (allnextpp) { + if (strcmp(pname, "linux,phandle") == 0) { + np->node = *((u32 *)*p); + if (np->linux_phandle == 0) + np->linux_phandle = np->node; + } + if (strcmp(pname, "ibm,phandle") == 0) + np->linux_phandle = *((u32 *)*p); + pp->name = pname; + pp->length = sz; + pp->value = (void *)*p; + *prev_pp = pp; + prev_pp = &pp->next; + } + *p = _ALIGN((*p) + sz, 4); + } + /* with version 0x10 we may not have the name property, recreate + * it here from the unit name if absent + */ + if (!has_name) { + char *p1 = pathp, *ps = pathp, *pa = NULL; + int sz; + + while (*p1) { + if ((*p1) == '@') + pa = p1; + if ((*p1) == '/') + ps = p1 + 1; + p1++; + } + if (pa < ps) + pa = p1; + sz = (pa - ps) + 1; + pp = unflatten_dt_alloc(&mem, sizeof(struct property) + sz, + __alignof__(struct property)); + if (allnextpp) { + pp->name = "name"; + pp->length = sz; + pp->value = pp + 1; + *prev_pp = pp; + prev_pp = &pp->next; + memcpy(pp->value, ps, sz - 1); + ((char *)pp->value)[sz - 1] = 0; + pr_debug("fixed up name for %s -> %s\n", pathp, + (char *)pp->value); + } + } + if (allnextpp) { + *prev_pp = NULL; + np->name = of_get_property(np, "name", NULL); + np->type = of_get_property(np, "device_type", NULL); + + if (!np->name) + np->name = ""; + if (!np->type) + np->type = ""; + } + while (tag == OF_DT_BEGIN_NODE) { + mem = unflatten_dt_node(mem, p, np, allnextpp, fpsize); + tag = *((u32 *)(*p)); + } + if (tag != OF_DT_END_NODE) { + pr_err("Weird tag at end of node: %x\n", tag); + return mem; + } + *p += 4; + return mem; +} diff --git a/include/linux/of_fdt.h b/include/linux/of_fdt.h index 81231e04e8f3..ace9068e07e8 100644 --- a/include/linux/of_fdt.h +++ b/include/linux/of_fdt.h @@ -69,6 +69,10 @@ extern void *of_get_flat_dt_prop(unsigned long node, const char *name, unsigned long *size); extern int of_flat_dt_is_compatible(unsigned long node, const char *name); extern unsigned long of_get_flat_dt_root(void); +extern unsigned long unflatten_dt_node(unsigned long mem, unsigned long *p, + struct device_node *dad, + struct device_node ***allnextpp, + unsigned long fpsize); /* Other Prototypes */ extern void finish_device_tree(void); -- cgit v1.2.3 From 41f880091c15b039ffcc8b3d831656b81517a6d3 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Mon, 23 Nov 2009 20:07:01 -0700 Subject: of/flattree: Merge unflatten_device_tree Merge common code between PowerPC and MicroBlaze Signed-off-by: Grant Likely Reviewed-by: Wolfram Sang Tested-by: Michal Simek --- arch/microblaze/include/asm/prom.h | 1 - arch/microblaze/kernel/prom.c | 49 ----------------------------------- arch/powerpc/kernel/prom.c | 50 ------------------------------------ drivers/of/fdt.c | 52 ++++++++++++++++++++++++++++++++++++++ include/linux/of.h | 3 +++ include/linux/of_fdt.h | 4 --- 6 files changed, 55 insertions(+), 104 deletions(-) (limited to 'drivers/of/fdt.c') diff --git a/arch/microblaze/include/asm/prom.h b/arch/microblaze/include/asm/prom.h index ef3ec1d6ceb3..07d1063f9aae 100644 --- a/arch/microblaze/include/asm/prom.h +++ b/arch/microblaze/include/asm/prom.h @@ -37,7 +37,6 @@ extern struct device_node *of_chosen; #define HAVE_ARCH_DEVTREE_FIXUPS -extern struct device_node *allnodes; /* temporary while merging */ extern rwlock_t devtree_lock; /* temporary while merging */ /* For updating the device tree at runtime */ diff --git a/arch/microblaze/kernel/prom.c b/arch/microblaze/kernel/prom.c index 021770abfbd7..901d538c15ef 100644 --- a/arch/microblaze/kernel/prom.c +++ b/arch/microblaze/kernel/prom.c @@ -50,55 +50,6 @@ typedef u32 cell_t; /* export that to outside world */ struct device_node *of_chosen; -/** - * unflattens the device-tree passed by the firmware, creating the - * tree of struct device_node. It also fills the "name" and "type" - * pointers of the nodes so the normal device-tree walking functions - * can be used (this used to be done by finish_device_tree) - */ -void __init unflatten_device_tree(void) -{ - unsigned long start, mem, size; - struct device_node **allnextp = &allnodes; - - pr_debug(" -> unflatten_device_tree()\n"); - - /* First pass, scan for size */ - start = ((unsigned long)initial_boot_params) + - initial_boot_params->off_dt_struct; - size = unflatten_dt_node(0, &start, NULL, NULL, 0); - size = (size | 3) + 1; - - pr_debug(" size is %lx, allocating...\n", size); - - /* Allocate memory for the expanded device tree */ - mem = lmb_alloc(size + 4, __alignof__(struct device_node)); - mem = (unsigned long) __va(mem); - - ((u32 *)mem)[size / 4] = 0xdeadbeef; - - pr_debug(" unflattening %lx...\n", mem); - - /* Second pass, do actual unflattening */ - start = ((unsigned long)initial_boot_params) + - initial_boot_params->off_dt_struct; - unflatten_dt_node(mem, &start, NULL, &allnextp, 0); - if (*((u32 *)start) != OF_DT_END) - printk(KERN_WARNING "Weird tag at end of tree: %08x\n", - *((u32 *)start)); - if (((u32 *)mem)[size / 4] != 0xdeadbeef) - printk(KERN_WARNING "End of tree marker overwritten: %08x\n", - ((u32 *)mem)[size / 4]); - *allnextp = NULL; - - /* Get pointer to OF "/chosen" node for use everywhere */ - of_chosen = of_find_node_by_path("/chosen"); - if (of_chosen == NULL) - of_chosen = of_find_node_by_path("/chosen@0"); - - pr_debug(" <- unflatten_device_tree()\n"); -} - #define early_init_dt_scan_drconf_memory(node) 0 static int __init early_init_dt_scan_cpus(unsigned long node, diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index a102a0a33ed1..1280f3484ad3 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -73,8 +73,6 @@ unsigned long tce_alloc_start, tce_alloc_end; typedef u32 cell_t; -extern struct device_node *allnodes; /* temporary while merging */ - extern rwlock_t devtree_lock; /* temporary while merging */ /* export that to outside world */ @@ -119,54 +117,6 @@ static void __init move_device_tree(void) DBG("<- move_device_tree\n"); } -/** - * unflattens the device-tree passed by the firmware, creating the - * tree of struct device_node. It also fills the "name" and "type" - * pointers of the nodes so the normal device-tree walking functions - * can be used (this used to be done by finish_device_tree) - */ -void __init unflatten_device_tree(void) -{ - unsigned long start, mem, size; - struct device_node **allnextp = &allnodes; - - DBG(" -> unflatten_device_tree()\n"); - - /* First pass, scan for size */ - start = ((unsigned long)initial_boot_params) + - initial_boot_params->off_dt_struct; - size = unflatten_dt_node(0, &start, NULL, NULL, 0); - size = (size | 3) + 1; - - DBG(" size is %lx, allocating...\n", size); - - /* Allocate memory for the expanded device tree */ - mem = lmb_alloc(size + 4, __alignof__(struct device_node)); - mem = (unsigned long) __va(mem); - - ((u32 *)mem)[size / 4] = 0xdeadbeef; - - DBG(" unflattening %lx...\n", mem); - - /* Second pass, do actual unflattening */ - start = ((unsigned long)initial_boot_params) + - initial_boot_params->off_dt_struct; - unflatten_dt_node(mem, &start, NULL, &allnextp, 0); - if (*((u32 *)start) != OF_DT_END) - printk(KERN_WARNING "Weird tag at end of tree: %08x\n", *((u32 *)start)); - if (((u32 *)mem)[size / 4] != 0xdeadbeef) - printk(KERN_WARNING "End of tree marker overwritten: %08x\n", - ((u32 *)mem)[size / 4] ); - *allnextp = NULL; - - /* Get pointer to OF "/chosen" node for use everywhere */ - of_chosen = of_find_node_by_path("/chosen"); - if (of_chosen == NULL) - of_chosen = of_find_node_by_path("/chosen@0"); - - DBG(" <- unflatten_device_tree()\n"); -} - /* * ibm,pa-features is a per-cpu property that contains a string of * attribute descriptors, each of which has a 2 byte header plus up diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index 6852ecf6d1e1..43d236cbc17b 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -9,6 +9,8 @@ * version 2 as published by the Free Software Foundation. */ +#include +#include #include #include @@ -366,3 +368,53 @@ unsigned long __init unflatten_dt_node(unsigned long mem, *p += 4; return mem; } + +/** + * unflatten_device_tree - create tree of device_nodes from flat blob + * + * unflattens the device-tree passed by the firmware, creating the + * tree of struct device_node. It also fills the "name" and "type" + * pointers of the nodes so the normal device-tree walking functions + * can be used. + */ +void __init unflatten_device_tree(void) +{ + unsigned long start, mem, size; + struct device_node **allnextp = &allnodes; + + pr_debug(" -> unflatten_device_tree()\n"); + + /* First pass, scan for size */ + start = ((unsigned long)initial_boot_params) + + initial_boot_params->off_dt_struct; + size = unflatten_dt_node(0, &start, NULL, NULL, 0); + size = (size | 3) + 1; + + pr_debug(" size is %lx, allocating...\n", size); + + /* Allocate memory for the expanded device tree */ + mem = lmb_alloc(size + 4, __alignof__(struct device_node)); + mem = (unsigned long) __va(mem); + + ((u32 *)mem)[size / 4] = 0xdeadbeef; + + pr_debug(" unflattening %lx...\n", mem); + + /* Second pass, do actual unflattening */ + start = ((unsigned long)initial_boot_params) + + initial_boot_params->off_dt_struct; + unflatten_dt_node(mem, &start, NULL, &allnextp, 0); + if (*((u32 *)start) != OF_DT_END) + pr_warning("Weird tag at end of tree: %08x\n", *((u32 *)start)); + if (((u32 *)mem)[size / 4] != 0xdeadbeef) + pr_warning("End of tree marker overwritten: %08x\n", + ((u32 *)mem)[size / 4]); + *allnextp = NULL; + + /* Get pointer to OF "/chosen" node for use everywhere */ + of_chosen = of_find_node_by_path("/chosen"); + if (of_chosen == NULL) + of_chosen = of_find_node_by_path("/chosen@0"); + + pr_debug(" <- unflatten_device_tree()\n"); +} diff --git a/include/linux/of.h b/include/linux/of.h index e7facd8fbce8..bec215792c4f 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -63,6 +63,9 @@ struct device_node { #endif }; +/* Pointer for first entry in chain of all nodes. */ +extern struct device_node *allnodes; + static inline int of_node_check_flag(struct device_node *n, unsigned long flag) { return test_bit(flag, &n->_flags); diff --git a/include/linux/of_fdt.h b/include/linux/of_fdt.h index ace9068e07e8..81231e04e8f3 100644 --- a/include/linux/of_fdt.h +++ b/include/linux/of_fdt.h @@ -69,10 +69,6 @@ extern void *of_get_flat_dt_prop(unsigned long node, const char *name, unsigned long *size); extern int of_flat_dt_is_compatible(unsigned long node, const char *name); extern unsigned long of_get_flat_dt_root(void); -extern unsigned long unflatten_dt_node(unsigned long mem, unsigned long *p, - struct device_node *dad, - struct device_node ***allnextpp, - unsigned long fpsize); /* Other Prototypes */ extern void finish_device_tree(void); -- cgit v1.2.3 From f7b3a8355ba6cad251297844a0bdd08898ea36e0 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Tue, 24 Nov 2009 03:26:58 -0700 Subject: of/flattree: Merge early_init_dt_check_for_initrd() Merge common code between PowerPC and Microblaze Signed-off-by: Grant Likely Tested-by: Wolfram Sang Acked-by: Benjamin Herrenschmidt --- arch/microblaze/kernel/prom.c | 32 -------------------------------- arch/powerpc/kernel/prom.c | 30 ------------------------------ drivers/of/fdt.c | 37 +++++++++++++++++++++++++++++++++++++ include/linux/of_fdt.h | 1 + 4 files changed, 38 insertions(+), 62 deletions(-) (limited to 'drivers/of/fdt.c') diff --git a/arch/microblaze/kernel/prom.c b/arch/microblaze/kernel/prom.c index a38e3733a09c..7959495b1d00 100644 --- a/arch/microblaze/kernel/prom.c +++ b/arch/microblaze/kernel/prom.c @@ -113,38 +113,6 @@ static int __init early_init_dt_scan_cpus(unsigned long node, return 0; } -#ifdef CONFIG_BLK_DEV_INITRD -static void __init early_init_dt_check_for_initrd(unsigned long node) -{ - unsigned long l; - u32 *prop; - - pr_debug("Looking for initrd properties... "); - - prop = of_get_flat_dt_prop(node, "linux,initrd-start", &l); - if (prop) { - initrd_start = (unsigned long) - __va((u32)of_read_ulong(prop, l/4)); - - prop = of_get_flat_dt_prop(node, "linux,initrd-end", &l); - if (prop) { - initrd_end = (unsigned long) - __va((u32)of_read_ulong(prop, 1/4)); - initrd_below_start_ok = 1; - } else { - initrd_start = 0; - } - } - - pr_debug("initrd_start=0x%lx initrd_end=0x%lx\n", - initrd_start, initrd_end); -} -#else -static inline void early_init_dt_check_for_initrd(unsigned long node) -{ -} -#endif /* CONFIG_BLK_DEV_INITRD */ - static int __init early_init_dt_scan_chosen(unsigned long node, const char *uname, int depth, void *data) { diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 7f8856655144..1ecd6c6ecabd 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -373,36 +373,6 @@ static int __init early_init_dt_scan_cpus(unsigned long node, return 0; } -#ifdef CONFIG_BLK_DEV_INITRD -static void __init early_init_dt_check_for_initrd(unsigned long node) -{ - unsigned long l; - u32 *prop; - - DBG("Looking for initrd properties... "); - - prop = of_get_flat_dt_prop(node, "linux,initrd-start", &l); - if (prop) { - initrd_start = (unsigned long)__va(of_read_ulong(prop, l/4)); - - prop = of_get_flat_dt_prop(node, "linux,initrd-end", &l); - if (prop) { - initrd_end = (unsigned long) - __va(of_read_ulong(prop, l/4)); - initrd_below_start_ok = 1; - } else { - initrd_start = 0; - } - } - - DBG("initrd_start=0x%lx initrd_end=0x%lx\n", initrd_start, initrd_end); -} -#else -static inline void early_init_dt_check_for_initrd(unsigned long node) -{ -} -#endif /* CONFIG_BLK_DEV_INITRD */ - static int __init early_init_dt_scan_chosen(unsigned long node, const char *uname, int depth, void *data) { diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index 43d236cbc17b..6ad98e85dc93 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -11,6 +11,7 @@ #include #include +#include #include #include @@ -369,6 +370,42 @@ unsigned long __init unflatten_dt_node(unsigned long mem, return mem; } +#ifdef CONFIG_BLK_DEV_INITRD +/** + * early_init_dt_check_for_initrd - Decode initrd location from flat tree + * @node: reference to node containing initrd location ('chosen') + */ +void __init early_init_dt_check_for_initrd(unsigned long node) +{ + unsigned long len; + u32 *prop; + + pr_debug("Looking for initrd properties... "); + + prop = of_get_flat_dt_prop(node, "linux,initrd-start", &len); + if (prop) { + initrd_start = (unsigned long) + __va(of_read_ulong(prop, len/4)); + + prop = of_get_flat_dt_prop(node, "linux,initrd-end", &len); + if (prop) { + initrd_end = (unsigned long) + __va(of_read_ulong(prop, len/4)); + initrd_below_start_ok = 1; + } else { + initrd_start = 0; + } + } + + pr_debug("initrd_start=0x%lx initrd_end=0x%lx\n", + initrd_start, initrd_end); +} +#else +inline void early_init_dt_check_for_initrd(unsigned long node) +{ +} +#endif /* CONFIG_BLK_DEV_INITRD */ + /** * unflatten_device_tree - create tree of device_nodes from flat blob * diff --git a/include/linux/of_fdt.h b/include/linux/of_fdt.h index 81231e04e8f3..ec2db8278c3f 100644 --- a/include/linux/of_fdt.h +++ b/include/linux/of_fdt.h @@ -69,6 +69,7 @@ extern void *of_get_flat_dt_prop(unsigned long node, const char *name, unsigned long *size); extern int of_flat_dt_is_compatible(unsigned long node, const char *name); extern unsigned long of_get_flat_dt_root(void); +extern void early_init_dt_check_for_initrd(unsigned long node); /* Other Prototypes */ extern void finish_device_tree(void); -- cgit v1.2.3 From f00abd94918c9780f9d2d961fc0e419c11457922 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Tue, 24 Nov 2009 03:27:10 -0700 Subject: of/flattree: Merge earlyinit_dt_scan_root() Merge common code between PowerPC and Microblaze Signed-off-by: Grant Likely Acked-by: Benjamin Herrenschmidt Tested-by: Wolfram Sang --- arch/microblaze/kernel/prom.c | 23 ----------------------- arch/powerpc/kernel/prom.c | 24 ------------------------ drivers/of/fdt.c | 26 ++++++++++++++++++++++++++ include/linux/of_fdt.h | 6 ++++++ 4 files changed, 32 insertions(+), 47 deletions(-) (limited to 'drivers/of/fdt.c') diff --git a/arch/microblaze/kernel/prom.c b/arch/microblaze/kernel/prom.c index 7959495b1d00..189179a9b554 100644 --- a/arch/microblaze/kernel/prom.c +++ b/arch/microblaze/kernel/prom.c @@ -42,9 +42,6 @@ #include #include -static int __initdata dt_root_addr_cells; -static int __initdata dt_root_size_cells; - typedef u32 cell_t; /* export that to outside world */ @@ -158,26 +155,6 @@ static int __init early_init_dt_scan_chosen(unsigned long node, return 1; } -static int __init early_init_dt_scan_root(unsigned long node, - const char *uname, int depth, void *data) -{ - u32 *prop; - - if (depth != 0) - return 0; - - prop = of_get_flat_dt_prop(node, "#size-cells", NULL); - dt_root_size_cells = (prop == NULL) ? 1 : *prop; - pr_debug("dt_root_size_cells = %x\n", dt_root_size_cells); - - prop = of_get_flat_dt_prop(node, "#address-cells", NULL); - dt_root_addr_cells = (prop == NULL) ? 2 : *prop; - pr_debug("dt_root_addr_cells = %x\n", dt_root_addr_cells); - - /* break now */ - return 1; -} - static u64 __init dt_mem_next_cell(int s, cell_t **cellp) { cell_t *p = *cellp; diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 1ecd6c6ecabd..78f65a4d8b03 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -61,10 +61,6 @@ #define DBG(fmt...) #endif - -static int __initdata dt_root_addr_cells; -static int __initdata dt_root_size_cells; - #ifdef CONFIG_PPC64 int __initdata iommu_is_off; int __initdata iommu_force_on; @@ -436,26 +432,6 @@ static int __init early_init_dt_scan_chosen(unsigned long node, return 1; } -static int __init early_init_dt_scan_root(unsigned long node, - const char *uname, int depth, void *data) -{ - u32 *prop; - - if (depth != 0) - return 0; - - prop = of_get_flat_dt_prop(node, "#size-cells", NULL); - dt_root_size_cells = (prop == NULL) ? 1 : *prop; - DBG("dt_root_size_cells = %x\n", dt_root_size_cells); - - prop = of_get_flat_dt_prop(node, "#address-cells", NULL); - dt_root_addr_cells = (prop == NULL) ? 2 : *prop; - DBG("dt_root_addr_cells = %x\n", dt_root_addr_cells); - - /* break now */ - return 1; -} - static u64 __init dt_mem_next_cell(int s, cell_t **cellp) { cell_t *p = *cellp; diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index 6ad98e85dc93..be200be47269 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -15,6 +15,9 @@ #include #include +int __initdata dt_root_addr_cells; +int __initdata dt_root_size_cells; + struct boot_param_header *initial_boot_params; char *find_flat_dt_string(u32 offset) @@ -406,6 +409,29 @@ inline void early_init_dt_check_for_initrd(unsigned long node) } #endif /* CONFIG_BLK_DEV_INITRD */ +/** + * early_init_dt_scan_root - fetch the top level address and size cells + */ +int __init early_init_dt_scan_root(unsigned long node, const char *uname, + int depth, void *data) +{ + u32 *prop; + + if (depth != 0) + return 0; + + prop = of_get_flat_dt_prop(node, "#size-cells", NULL); + dt_root_size_cells = (prop == NULL) ? 1 : *prop; + pr_debug("dt_root_size_cells = %x\n", dt_root_size_cells); + + prop = of_get_flat_dt_prop(node, "#address-cells", NULL); + dt_root_addr_cells = (prop == NULL) ? 2 : *prop; + pr_debug("dt_root_addr_cells = %x\n", dt_root_addr_cells); + + /* break now */ + return 1; +} + /** * unflatten_device_tree - create tree of device_nodes from flat blob * diff --git a/include/linux/of_fdt.h b/include/linux/of_fdt.h index ec2db8278c3f..828c3cdaea78 100644 --- a/include/linux/of_fdt.h +++ b/include/linux/of_fdt.h @@ -58,6 +58,8 @@ struct boot_param_header { }; /* TBD: Temporary export of fdt globals - remove when code fully merged */ +extern int __initdata dt_root_addr_cells; +extern int __initdata dt_root_size_cells; extern struct boot_param_header *initial_boot_params; /* For scanning the flat device-tree at boot time */ @@ -71,6 +73,10 @@ extern int of_flat_dt_is_compatible(unsigned long node, const char *name); extern unsigned long of_get_flat_dt_root(void); extern void early_init_dt_check_for_initrd(unsigned long node); +/* Early flat tree scan hooks */ +extern int early_init_dt_scan_root(unsigned long node, const char *uname, + int depth, void *data); + /* Other Prototypes */ extern void finish_device_tree(void); extern void unflatten_device_tree(void); -- cgit v1.2.3 From 83f7a06eb479e2aeb83536e77a2cb14cc2285e32 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Tue, 24 Nov 2009 03:37:56 -0700 Subject: of/flattree: merge dt_mem_next_cell Merge common code between PowerPC and Microblaze Signed-off-by: Grant Likely Acked-by: Benjamin Herrenschmidt Tested-by: Wolfram Sang --- arch/microblaze/kernel/prom.c | 8 -------- arch/powerpc/kernel/prom.c | 8 -------- drivers/of/fdt.c | 8 ++++++++ include/linux/of_fdt.h | 1 + 4 files changed, 9 insertions(+), 16 deletions(-) (limited to 'drivers/of/fdt.c') diff --git a/arch/microblaze/kernel/prom.c b/arch/microblaze/kernel/prom.c index 189179a9b554..e0f4c34ed0f2 100644 --- a/arch/microblaze/kernel/prom.c +++ b/arch/microblaze/kernel/prom.c @@ -155,14 +155,6 @@ static int __init early_init_dt_scan_chosen(unsigned long node, return 1; } -static u64 __init dt_mem_next_cell(int s, cell_t **cellp) -{ - cell_t *p = *cellp; - - *cellp = p + s; - return of_read_number(p, s); -} - static int __init early_init_dt_scan_memory(unsigned long node, const char *uname, int depth, void *data) { diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 78f65a4d8b03..048e3a3e9876 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -432,14 +432,6 @@ static int __init early_init_dt_scan_chosen(unsigned long node, return 1; } -static u64 __init dt_mem_next_cell(int s, cell_t **cellp) -{ - cell_t *p = *cellp; - - *cellp = p + s; - return of_read_number(p, s); -} - #ifdef CONFIG_PPC_PSERIES /* * Interpret the ibm,dynamic-memory property in the diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index be200be47269..ebce509b0886 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -432,6 +432,14 @@ int __init early_init_dt_scan_root(unsigned long node, const char *uname, return 1; } +u64 __init dt_mem_next_cell(int s, u32 **cellp) +{ + u32 *p = *cellp; + + *cellp = p + s; + return of_read_number(p, s); +} + /** * unflatten_device_tree - create tree of device_nodes from flat blob * diff --git a/include/linux/of_fdt.h b/include/linux/of_fdt.h index 828c3cdaea78..d1a37e56031e 100644 --- a/include/linux/of_fdt.h +++ b/include/linux/of_fdt.h @@ -72,6 +72,7 @@ extern void *of_get_flat_dt_prop(unsigned long node, const char *name, extern int of_flat_dt_is_compatible(unsigned long node, const char *name); extern unsigned long of_get_flat_dt_root(void); extern void early_init_dt_check_for_initrd(unsigned long node); +extern u64 dt_mem_next_cell(int s, u32 **cellp); /* Early flat tree scan hooks */ extern int early_init_dt_scan_root(unsigned long node, const char *uname, -- cgit v1.2.3 From 86e032213424958b45564d0cc96b3316641a49d3 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Thu, 10 Dec 2009 23:42:21 -0700 Subject: of/flattree: merge early_init_dt_scan_chosen() Merge common code between PowerPC and Microblaze. This patch splits the arch-specific stuff out into a new function, early_init_dt_scan_chosen_arch(). Signed-off-by: Grant Likely Tested-by: Wolfram Sang Acked-by: Benjamin Herrenschmidt --- arch/microblaze/kernel/prom.c | 44 ++--------------------------------------- arch/powerpc/kernel/prom.c | 46 ++++++++++--------------------------------- drivers/of/fdt.c | 38 +++++++++++++++++++++++++++++++++++ include/linux/of_fdt.h | 3 +++ 4 files changed, 53 insertions(+), 78 deletions(-) (limited to 'drivers/of/fdt.c') diff --git a/arch/microblaze/kernel/prom.c b/arch/microblaze/kernel/prom.c index 50d8b09d5e3f..5505bcffd7dd 100644 --- a/arch/microblaze/kernel/prom.c +++ b/arch/microblaze/kernel/prom.c @@ -108,49 +108,9 @@ static int __init early_init_dt_scan_cpus(unsigned long node, return 0; } -static int __init early_init_dt_scan_chosen(unsigned long node, - const char *uname, int depth, void *data) +void __init early_init_dt_scan_chosen_arch(unsigned long node) { - unsigned long l; - char *p; - - pr_debug("search \"chosen\", depth: %d, uname: %s\n", depth, uname); - - if (depth != 1 || - (strcmp(uname, "chosen") != 0 && - strcmp(uname, "chosen@0") != 0)) - return 0; - -#ifdef CONFIG_KEXEC - lprop = (u64 *)of_get_flat_dt_prop(node, - "linux,crashkernel-base", NULL); - if (lprop) - crashk_res.start = *lprop; - - lprop = (u64 *)of_get_flat_dt_prop(node, - "linux,crashkernel-size", NULL); - if (lprop) - crashk_res.end = crashk_res.start + *lprop - 1; -#endif - - early_init_dt_check_for_initrd(node); - - /* Retreive command line */ - p = of_get_flat_dt_prop(node, "bootargs", &l); - if (p != NULL && l > 0) - strlcpy(cmd_line, p, min((int)l, COMMAND_LINE_SIZE)); - -#ifdef CONFIG_CMDLINE -#ifndef CONFIG_CMDLINE_FORCE - if (p == NULL || l == 0 || (l == 1 && (*p) == 0)) -#endif - strlcpy(cmd_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE); -#endif /* CONFIG_CMDLINE */ - - pr_debug("Command line is: %s\n", cmd_line); - - /* break now */ - return 1; + /* No Microblaze specific code here */ } static int __init early_init_dt_scan_memory(unsigned long node, diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 4e3181cded44..877fad9b3745 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -367,18 +367,9 @@ static int __init early_init_dt_scan_cpus(unsigned long node, return 0; } -static int __init early_init_dt_scan_chosen(unsigned long node, - const char *uname, int depth, void *data) +void __init early_init_dt_scan_chosen_arch(unsigned long node) { unsigned long *lprop; - unsigned long l; - char *p; - - DBG("search \"chosen\", depth: %d, uname: %s\n", depth, uname); - - if (depth != 1 || - (strcmp(uname, "chosen") != 0 && strcmp(uname, "chosen@0") != 0)) - return 0; #ifdef CONFIG_PPC64 /* check if iommu is forced on or off */ @@ -389,17 +380,17 @@ static int __init early_init_dt_scan_chosen(unsigned long node, #endif /* mem=x on the command line is the preferred mechanism */ - lprop = of_get_flat_dt_prop(node, "linux,memory-limit", NULL); - if (lprop) - memory_limit = *lprop; + lprop = of_get_flat_dt_prop(node, "linux,memory-limit", NULL); + if (lprop) + memory_limit = *lprop; #ifdef CONFIG_PPC64 - lprop = of_get_flat_dt_prop(node, "linux,tce-alloc-start", NULL); - if (lprop) - tce_alloc_start = *lprop; - lprop = of_get_flat_dt_prop(node, "linux,tce-alloc-end", NULL); - if (lprop) - tce_alloc_end = *lprop; + lprop = of_get_flat_dt_prop(node, "linux,tce-alloc-start", NULL); + if (lprop) + tce_alloc_start = *lprop; + lprop = of_get_flat_dt_prop(node, "linux,tce-alloc-end", NULL); + if (lprop) + tce_alloc_end = *lprop; #endif #ifdef CONFIG_KEXEC @@ -411,23 +402,6 @@ static int __init early_init_dt_scan_chosen(unsigned long node, if (lprop) crashk_res.end = crashk_res.start + *lprop - 1; #endif - - early_init_dt_check_for_initrd(node); - - /* Retreive command line */ - p = of_get_flat_dt_prop(node, "bootargs", &l); - if (p != NULL && l > 0) - strlcpy(cmd_line, p, min((int)l, COMMAND_LINE_SIZE)); - -#ifdef CONFIG_CMDLINE - if (p == NULL || l == 0 || (l == 1 && (*p) == 0)) - strlcpy(cmd_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE); -#endif /* CONFIG_CMDLINE */ - - DBG("Command line is: %s\n", cmd_line); - - /* break now */ - return 1; } #ifdef CONFIG_PPC_PSERIES diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index ebce509b0886..616a4767a950 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -15,6 +15,10 @@ #include #include +#ifdef CONFIG_PPC +#include +#endif /* CONFIG_PPC */ + int __initdata dt_root_addr_cells; int __initdata dt_root_size_cells; @@ -440,6 +444,40 @@ u64 __init dt_mem_next_cell(int s, u32 **cellp) return of_read_number(p, s); } +int __init early_init_dt_scan_chosen(unsigned long node, const char *uname, + int depth, void *data) +{ + unsigned long l; + char *p; + + pr_debug("search \"chosen\", depth: %d, uname: %s\n", depth, uname); + + if (depth != 1 || + (strcmp(uname, "chosen") != 0 && strcmp(uname, "chosen@0") != 0)) + return 0; + + early_init_dt_check_for_initrd(node); + + /* Retreive command line */ + p = of_get_flat_dt_prop(node, "bootargs", &l); + if (p != NULL && l > 0) + strlcpy(cmd_line, p, min((int)l, COMMAND_LINE_SIZE)); + +#ifdef CONFIG_CMDLINE +#ifndef CONFIG_CMDLINE_FORCE + if (p == NULL || l == 0 || (l == 1 && (*p) == 0)) +#endif + strlcpy(cmd_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE); +#endif /* CONFIG_CMDLINE */ + + early_init_dt_scan_chosen_arch(node); + + pr_debug("Command line is: %s\n", cmd_line); + + /* break now */ + return 1; +} + /** * unflatten_device_tree - create tree of device_nodes from flat blob * diff --git a/include/linux/of_fdt.h b/include/linux/of_fdt.h index d1a37e56031e..8118d4559dd5 100644 --- a/include/linux/of_fdt.h +++ b/include/linux/of_fdt.h @@ -71,6 +71,9 @@ extern void *of_get_flat_dt_prop(unsigned long node, const char *name, unsigned long *size); extern int of_flat_dt_is_compatible(unsigned long node, const char *name); extern unsigned long of_get_flat_dt_root(void); +extern void early_init_dt_scan_chosen_arch(unsigned long node); +extern int early_init_dt_scan_chosen(unsigned long node, const char *uname, + int depth, void *data); extern void early_init_dt_check_for_initrd(unsigned long node); extern u64 dt_mem_next_cell(int s, u32 **cellp); -- cgit v1.2.3 From 6016a363f6b56b46b24655bcfc0499b715851cf3 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Thu, 28 Jan 2010 14:06:53 -0700 Subject: of: unify phandle name in struct device_node In struct device_node, the phandle is named 'linux_phandle' for PowerPC and MicroBlaze, and 'node' for SPARC. There is no good reason for the difference, it is just an artifact of the code diverging over a couple of years. This patch renames both to simply .phandle. Note: the .node also existed in PowerPC/MicroBlaze, but the only user seems to be arch/powerpc/platforms/powermac/pfunc_core.c. It doesn't look like the assignment between .linux_phandle and .node is significantly different enough to warrant the separate code paths unless ibm,phandle properties actually appear in Apple device trees. I think it is safe to eliminate the old .node property and use phandle everywhere. Signed-off-by: Grant Likely Acked-by: David S. Miller Tested-by: Wolfram Sang Acked-by: Benjamin Herrenschmidt --- arch/microblaze/kernel/of_platform.c | 2 +- arch/microblaze/kernel/prom.c | 2 +- arch/powerpc/kernel/of_platform.c | 2 +- arch/powerpc/kernel/prom.c | 6 +++--- arch/powerpc/platforms/cell/spu_manage.c | 6 +++--- arch/powerpc/platforms/powermac/pfunc_core.c | 2 +- arch/sparc/kernel/devices.c | 2 +- arch/sparc/kernel/of_device_32.c | 2 +- arch/sparc/kernel/of_device_64.c | 2 +- arch/sparc/kernel/prom_common.c | 8 ++++---- arch/sparc/kernel/smp_64.c | 2 +- drivers/of/fdt.c | 7 +++---- drivers/sbus/char/openprom.c | 10 +++++----- drivers/video/aty/atyfb_base.c | 2 +- include/linux/of.h | 5 +---- sound/aoa/fabrics/layout.c | 2 +- 16 files changed, 29 insertions(+), 33 deletions(-) (limited to 'drivers/of/fdt.c') diff --git a/arch/microblaze/kernel/of_platform.c b/arch/microblaze/kernel/of_platform.c index acf4574d0f18..1c6d684996d7 100644 --- a/arch/microblaze/kernel/of_platform.c +++ b/arch/microblaze/kernel/of_platform.c @@ -185,7 +185,7 @@ EXPORT_SYMBOL(of_find_device_by_node); static int of_dev_phandle_match(struct device *dev, void *data) { phandle *ph = data; - return to_of_device(dev)->node->linux_phandle == *ph; + return to_of_device(dev)->node->phandle == *ph; } struct of_device *of_find_device_by_phandle(phandle ph) diff --git a/arch/microblaze/kernel/prom.c b/arch/microblaze/kernel/prom.c index 46407e643926..6eff83a71218 100644 --- a/arch/microblaze/kernel/prom.c +++ b/arch/microblaze/kernel/prom.c @@ -342,7 +342,7 @@ struct device_node *of_find_node_by_phandle(phandle handle) read_lock(&devtree_lock); for (np = allnodes; np != NULL; np = np->allnext) - if (np->linux_phandle == handle) + if (np->phandle == handle) break; of_node_get(np); read_unlock(&devtree_lock); diff --git a/arch/powerpc/kernel/of_platform.c b/arch/powerpc/kernel/of_platform.c index 1a4fc0d11a03..666d08db319e 100644 --- a/arch/powerpc/kernel/of_platform.c +++ b/arch/powerpc/kernel/of_platform.c @@ -214,7 +214,7 @@ EXPORT_SYMBOL(of_find_device_by_node); static int of_dev_phandle_match(struct device *dev, void *data) { phandle *ph = data; - return to_of_device(dev)->node->linux_phandle == *ph; + return to_of_device(dev)->node->phandle == *ph; } struct of_device *of_find_device_by_phandle(phandle ph) diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index deccd91d7e81..1ed2ec2ea05b 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -778,7 +778,7 @@ struct device_node *of_find_node_by_phandle(phandle handle) read_lock(&devtree_lock); for (np = allnodes; np != 0; np = np->allnext) - if (np->linux_phandle == handle) + if (np->phandle == handle) break; of_node_get(np); read_unlock(&devtree_lock); @@ -907,9 +907,9 @@ static int of_finish_dynamic_node(struct device_node *node) if (machine_is(powermac)) return -ENODEV; - /* fix up new node's linux_phandle field */ + /* fix up new node's phandle field */ if ((ibm_phandle = of_get_property(node, "ibm,phandle", NULL))) - node->linux_phandle = *ibm_phandle; + node->phandle = *ibm_phandle; out: of_node_put(parent); diff --git a/arch/powerpc/platforms/cell/spu_manage.c b/arch/powerpc/platforms/cell/spu_manage.c index 4c506c1463cd..891f18e337a2 100644 --- a/arch/powerpc/platforms/cell/spu_manage.c +++ b/arch/powerpc/platforms/cell/spu_manage.c @@ -457,7 +457,7 @@ neighbour_spu(int cbe, struct device_node *target, struct device_node *avoid) continue; vic_handles = of_get_property(spu_dn, "vicinity", &lenp); for (i=0; i < (lenp / sizeof(phandle)); i++) { - if (vic_handles[i] == target->linux_phandle) + if (vic_handles[i] == target->phandle) return spu; } } @@ -499,7 +499,7 @@ static void init_affinity_node(int cbe) if (strcmp(name, "spe") == 0) { spu = devnode_spu(cbe, vic_dn); - avoid_ph = last_spu_dn->linux_phandle; + avoid_ph = last_spu_dn->phandle; } else { /* * "mic-tm" and "bif0" nodes do not have @@ -514,7 +514,7 @@ static void init_affinity_node(int cbe) last_spu->has_mem_affinity = 1; spu->has_mem_affinity = 1; } - avoid_ph = vic_dn->linux_phandle; + avoid_ph = vic_dn->phandle; } list_add_tail(&spu->aff_list, &last_spu->aff_list); diff --git a/arch/powerpc/platforms/powermac/pfunc_core.c b/arch/powerpc/platforms/powermac/pfunc_core.c index 96d5ce50364e..ede49e78a8da 100644 --- a/arch/powerpc/platforms/powermac/pfunc_core.c +++ b/arch/powerpc/platforms/powermac/pfunc_core.c @@ -842,7 +842,7 @@ struct pmf_function *__pmf_find_function(struct device_node *target, list_for_each_entry(func, &dev->functions, link) { if (name && strcmp(name, func->name)) continue; - if (func->phandle && target->node != func->phandle) + if (func->phandle && target->phandle != func->phandle) continue; if ((func->flags & flags) == 0) continue; diff --git a/arch/sparc/kernel/devices.c b/arch/sparc/kernel/devices.c index b171ae8de90d..b062de9424a4 100644 --- a/arch/sparc/kernel/devices.c +++ b/arch/sparc/kernel/devices.c @@ -59,7 +59,7 @@ static int __cpu_find_by(int (*compare)(int, int, void *), void *compare_arg, cur_inst = 0; for_each_node_by_type(dp, "cpu") { - int err = check_cpu_node(dp->node, &cur_inst, + int err = check_cpu_node(dp->phandle, &cur_inst, compare, compare_arg, prom_node, mid); if (!err) { diff --git a/arch/sparc/kernel/of_device_32.c b/arch/sparc/kernel/of_device_32.c index 4c26eb59e742..09138d403c7f 100644 --- a/arch/sparc/kernel/of_device_32.c +++ b/arch/sparc/kernel/of_device_32.c @@ -433,7 +433,7 @@ build_resources: if (!parent) dev_set_name(&op->dev, "root"); else - dev_set_name(&op->dev, "%08x", dp->node); + dev_set_name(&op->dev, "%08x", dp->phandle); if (of_device_register(op)) { printk("%s: Could not register of device.\n", diff --git a/arch/sparc/kernel/of_device_64.c b/arch/sparc/kernel/of_device_64.c index 881947e59e95..036f18ae59a6 100644 --- a/arch/sparc/kernel/of_device_64.c +++ b/arch/sparc/kernel/of_device_64.c @@ -666,7 +666,7 @@ static struct of_device * __init scan_one_device(struct device_node *dp, if (!parent) dev_set_name(&op->dev, "root"); else - dev_set_name(&op->dev, "%08x", dp->node); + dev_set_name(&op->dev, "%08x", dp->phandle); if (of_device_register(op)) { printk("%s: Could not register of device.\n", diff --git a/arch/sparc/kernel/prom_common.c b/arch/sparc/kernel/prom_common.c index d80a65d9e893..5832e13dfeeb 100644 --- a/arch/sparc/kernel/prom_common.c +++ b/arch/sparc/kernel/prom_common.c @@ -42,7 +42,7 @@ struct device_node *of_find_node_by_phandle(phandle handle) struct device_node *np; for (np = allnodes; np; np = np->allnext) - if (np->node == handle) + if (np->phandle == handle) break; return np; @@ -89,7 +89,7 @@ int of_set_property(struct device_node *dp, const char *name, void *val, int len void *old_val = prop->value; int ret; - ret = prom_setprop(dp->node, name, val, len); + ret = prom_setprop(dp->phandle, name, val, len); err = -EINVAL; if (ret >= 0) { @@ -236,7 +236,7 @@ static struct device_node * __init prom_create_node(phandle node, dp->name = get_one_property(node, "name"); dp->type = get_one_property(node, "device_type"); - dp->node = node; + dp->phandle = node; dp->properties = build_prop_list(node); @@ -313,7 +313,7 @@ void __init prom_build_devicetree(void) nextp = &allnodes->allnext; allnodes->child = prom_build_tree(allnodes, - prom_getchild(allnodes->node), + prom_getchild(allnodes->phandle), &nextp); of_console_init(); diff --git a/arch/sparc/kernel/smp_64.c b/arch/sparc/kernel/smp_64.c index aa36223497b9..eb14844a0021 100644 --- a/arch/sparc/kernel/smp_64.c +++ b/arch/sparc/kernel/smp_64.c @@ -370,7 +370,7 @@ static int __cpuinit smp_boot_one_cpu(unsigned int cpu) } else { struct device_node *dp = of_find_node_by_cpuid(cpu); - prom_startcpu(dp->node, entry, cookie); + prom_startcpu(dp->phandle, entry, cookie); } for (timeout = 0; timeout < 50000; timeout++) { diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index 616a4767a950..7f8861121a31 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -310,12 +310,11 @@ unsigned long __init unflatten_dt_node(unsigned long mem, __alignof__(struct property)); if (allnextpp) { if (strcmp(pname, "linux,phandle") == 0) { - np->node = *((u32 *)*p); - if (np->linux_phandle == 0) - np->linux_phandle = np->node; + if (np->phandle == 0) + np->phandle = *((u32 *)*p); } if (strcmp(pname, "ibm,phandle") == 0) - np->linux_phandle = *((u32 *)*p); + np->phandle = *((u32 *)*p); pp->name = pname; pp->length = sz; pp->value = (void *)*p; diff --git a/drivers/sbus/char/openprom.c b/drivers/sbus/char/openprom.c index 75ac19b1192f..fc2f676e984d 100644 --- a/drivers/sbus/char/openprom.c +++ b/drivers/sbus/char/openprom.c @@ -233,7 +233,7 @@ static int opromnext(void __user *argp, unsigned int cmd, struct device_node *dp ph = 0; if (dp) - ph = dp->node; + ph = dp->phandle; data->current_node = dp; *((int *) op->oprom_array) = ph; @@ -256,7 +256,7 @@ static int oprompci2node(void __user *argp, struct device_node *dp, struct openp dp = pci_device_to_OF_node(pdev); data->current_node = dp; - *((int *)op->oprom_array) = dp->node; + *((int *)op->oprom_array) = dp->phandle; op->oprom_size = sizeof(int); err = copyout(argp, op, bufsize + sizeof(int)); @@ -273,7 +273,7 @@ static int oprompath2node(void __user *argp, struct device_node *dp, struct open dp = of_find_node_by_path(op->oprom_array); if (dp) - ph = dp->node; + ph = dp->phandle; data->current_node = dp; *((int *)op->oprom_array) = ph; op->oprom_size = sizeof(int); @@ -540,7 +540,7 @@ static int opiocgetnext(unsigned int cmd, void __user *argp) } } if (dp) - nd = dp->node; + nd = dp->phandle; if (copy_to_user(argp, &nd, sizeof(phandle))) return -EFAULT; @@ -570,7 +570,7 @@ static int openprom_bsd_ioctl(struct inode * inode, struct file * file, case OPIOCGETOPTNODE: BUILD_BUG_ON(sizeof(phandle) != sizeof(int)); - if (copy_to_user(argp, &options_node->node, sizeof(phandle))) + if (copy_to_user(argp, &options_node->phandle, sizeof(phandle))) return -EFAULT; return 0; diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c index 913b4a47ae52..bb20987d58af 100644 --- a/drivers/video/aty/atyfb_base.c +++ b/drivers/video/aty/atyfb_base.c @@ -3104,7 +3104,7 @@ static int __devinit atyfb_setup_sparc(struct pci_dev *pdev, } dp = pci_device_to_OF_node(pdev); - if (node == dp->node) { + if (node == dp->phandle) { struct fb_var_screeninfo *var = &default_var; unsigned int N, P, Q, M, T, R; u32 v_total, h_total; diff --git a/include/linux/of.h b/include/linux/of.h index d4c014a35ea5..dbabf86e0b7a 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -39,10 +39,7 @@ struct of_irq_controller; struct device_node { const char *name; const char *type; - phandle node; -#if !defined(CONFIG_SPARC) - phandle linux_phandle; -#endif + phandle phandle; char *full_name; struct property *properties; diff --git a/sound/aoa/fabrics/layout.c b/sound/aoa/fabrics/layout.c index 586965f9605f..7a437da05646 100644 --- a/sound/aoa/fabrics/layout.c +++ b/sound/aoa/fabrics/layout.c @@ -768,7 +768,7 @@ static int check_codec(struct aoa_codec *codec, "required property %s not present\n", propname); return -ENODEV; } - if (*ref != codec->node->linux_phandle) { + if (*ref != codec->node->phandle) { printk(KERN_INFO "snd-aoa-fabric-layout: " "%s doesn't match!\n", propname); return -ENODEV; -- cgit v1.2.3 From 51975db0b7333cf389b64b5040c2a910341d241a Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Mon, 1 Feb 2010 21:34:14 -0700 Subject: of/flattree: merge early_init_dt_scan_memory() common code Merge common code between PowerPC and Microblaze architectures. Signed-off-by: Grant Likely Acked-by: Michal Simek --- arch/microblaze/kernel/prom.c | 51 ++------------------------------ arch/powerpc/kernel/prom.c | 69 +++++++++++-------------------------------- drivers/of/fdt.c | 50 +++++++++++++++++++++++++++++++ include/linux/of_fdt.h | 3 ++ 4 files changed, 73 insertions(+), 100 deletions(-) (limited to 'drivers/of/fdt.c') diff --git a/arch/microblaze/kernel/prom.c b/arch/microblaze/kernel/prom.c index f7bd0ee8d481..459c32e4a5fe 100644 --- a/arch/microblaze/kernel/prom.c +++ b/arch/microblaze/kernel/prom.c @@ -45,61 +45,14 @@ /* export that to outside world */ struct device_node *of_chosen; -#define early_init_dt_scan_drconf_memory(node) 0 - void __init early_init_dt_scan_chosen_arch(unsigned long node) { /* No Microblaze specific code here */ } -static int __init early_init_dt_scan_memory(unsigned long node, - const char *uname, int depth, void *data) +void __init early_init_dt_add_memory_arch(u64 base, u64 size) { - char *type = of_get_flat_dt_prop(node, "device_type", NULL); - __be32 *reg, *endp; - unsigned long l; - - /* Look for the ibm,dynamic-reconfiguration-memory node */ -/* if (depth == 1 && - strcmp(uname, "ibm,dynamic-reconfiguration-memory") == 0) - return early_init_dt_scan_drconf_memory(node); -*/ - /* We are scanning "memory" nodes only */ - if (type == NULL) { - /* - * The longtrail doesn't have a device_type on the - * /memory node, so look for the node called /memory@0. - */ - if (depth != 1 || strcmp(uname, "memory@0") != 0) - return 0; - } else if (strcmp(type, "memory") != 0) - return 0; - - reg = (__be32 *)of_get_flat_dt_prop(node, "linux,usable-memory", &l); - if (reg == NULL) - reg = (__be32 *)of_get_flat_dt_prop(node, "reg", &l); - if (reg == NULL) - return 0; - - endp = reg + (l / sizeof(__be32)); - - pr_debug("memory scan node %s, reg size %ld, data: %x %x %x %x,\n", - uname, l, reg[0], reg[1], reg[2], reg[3]); - - while ((endp - reg) >= (dt_root_addr_cells + dt_root_size_cells)) { - u64 base, size; - - base = dt_mem_next_cell(dt_root_addr_cells, ®); - size = dt_mem_next_cell(dt_root_size_cells, ®); - - if (size == 0) - continue; - pr_debug(" - %llx , %llx\n", (unsigned long long)base, - (unsigned long long)size); - - lmb_add(base, size); - } - return 0; + lmb_add(base, size); } #ifdef CONFIG_EARLY_PRINTK diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 28be19ab0f18..e0f368ff8d12 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -483,64 +483,31 @@ static int __init early_init_dt_scan_drconf_memory(unsigned long node) #define early_init_dt_scan_drconf_memory(node) 0 #endif /* CONFIG_PPC_PSERIES */ -static int __init early_init_dt_scan_memory(unsigned long node, - const char *uname, int depth, void *data) +static int __init early_init_dt_scan_memory_ppc(unsigned long node, + const char *uname, + int depth, void *data) { - char *type = of_get_flat_dt_prop(node, "device_type", NULL); - __be32 *reg, *endp; - unsigned long l; - - /* Look for the ibm,dynamic-reconfiguration-memory node */ if (depth == 1 && strcmp(uname, "ibm,dynamic-reconfiguration-memory") == 0) return early_init_dt_scan_drconf_memory(node); + + return early_init_dt_scan_memory(node, uname, depth, data); +} - /* We are scanning "memory" nodes only */ - if (type == NULL) { - /* - * The longtrail doesn't have a device_type on the - * /memory node, so look for the node called /memory@0. - */ - if (depth != 1 || strcmp(uname, "memory@0") != 0) - return 0; - } else if (strcmp(type, "memory") != 0) - return 0; - - reg = of_get_flat_dt_prop(node, "linux,usable-memory", &l); - if (reg == NULL) - reg = of_get_flat_dt_prop(node, "reg", &l); - if (reg == NULL) - return 0; - - endp = reg + (l / sizeof(__be32)); - - DBG("memory scan node %s, reg size %ld, data: %x %x %x %x,\n", - uname, l, reg[0], reg[1], reg[2], reg[3]); - - while ((endp - reg) >= (dt_root_addr_cells + dt_root_size_cells)) { - u64 base, size; - - base = dt_mem_next_cell(dt_root_addr_cells, ®); - size = dt_mem_next_cell(dt_root_size_cells, ®); - - if (size == 0) - continue; - DBG(" - %llx , %llx\n", (unsigned long long)base, - (unsigned long long)size); -#ifdef CONFIG_PPC64 - if (iommu_is_off) { - if (base >= 0x80000000ul) - continue; - if ((base + size) > 0x80000000ul) - size = 0x80000000ul - base; - } +void __init early_init_dt_add_memory_arch(u64 base, u64 size) +{ +#if defined(CONFIG_PPC64) + if (iommu_is_off) { + if (base >= 0x80000000ul) + return; + if ((base + size) > 0x80000000ul) + size = 0x80000000ul - base; + } #endif - lmb_add(base, size); - memstart_addr = min((u64)memstart_addr, base); - } + lmb_add(base, size); - return 0; + memstart_addr = min((u64)memstart_addr, base); } static void __init early_reserve_mem(void) @@ -706,7 +673,7 @@ void __init early_init_devtree(void *params) /* Scan memory nodes and rebuild LMBs */ lmb_init(); of_scan_flat_dt(early_init_dt_scan_root, NULL); - of_scan_flat_dt(early_init_dt_scan_memory, NULL); + of_scan_flat_dt(early_init_dt_scan_memory_ppc, NULL); /* Save command line for /proc/cmdline and then parse parameters */ strlcpy(boot_command_line, cmd_line, COMMAND_LINE_SIZE); diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index 7f8861121a31..f84152d112b0 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -15,6 +15,7 @@ #include #include + #ifdef CONFIG_PPC #include #endif /* CONFIG_PPC */ @@ -443,6 +444,55 @@ u64 __init dt_mem_next_cell(int s, u32 **cellp) return of_read_number(p, s); } +/** + * early_init_dt_scan_memory - Look for an parse memory nodes + */ +int __init early_init_dt_scan_memory(unsigned long node, const char *uname, + int depth, void *data) +{ + char *type = of_get_flat_dt_prop(node, "device_type", NULL); + __be32 *reg, *endp; + unsigned long l; + + /* We are scanning "memory" nodes only */ + if (type == NULL) { + /* + * The longtrail doesn't have a device_type on the + * /memory node, so look for the node called /memory@0. + */ + if (depth != 1 || strcmp(uname, "memory@0") != 0) + return 0; + } else if (strcmp(type, "memory") != 0) + return 0; + + reg = of_get_flat_dt_prop(node, "linux,usable-memory", &l); + if (reg == NULL) + reg = of_get_flat_dt_prop(node, "reg", &l); + if (reg == NULL) + return 0; + + endp = reg + (l / sizeof(__be32)); + + pr_debug("memory scan node %s, reg size %ld, data: %x %x %x %x,\n", + uname, l, reg[0], reg[1], reg[2], reg[3]); + + while ((endp - reg) >= (dt_root_addr_cells + dt_root_size_cells)) { + u64 base, size; + + base = dt_mem_next_cell(dt_root_addr_cells, ®); + size = dt_mem_next_cell(dt_root_size_cells, ®); + + if (size == 0) + continue; + pr_debug(" - %llx , %llx\n", (unsigned long long)base, + (unsigned long long)size); + + early_init_dt_add_memory_arch(base, size); + } + + return 0; +} + int __init early_init_dt_scan_chosen(unsigned long node, const char *uname, int depth, void *data) { diff --git a/include/linux/of_fdt.h b/include/linux/of_fdt.h index fbf29610616d..bf26bd5df9f1 100644 --- a/include/linux/of_fdt.h +++ b/include/linux/of_fdt.h @@ -75,6 +75,9 @@ extern void early_init_dt_scan_chosen_arch(unsigned long node); extern int early_init_dt_scan_chosen(unsigned long node, const char *uname, int depth, void *data); extern void early_init_dt_check_for_initrd(unsigned long node); +extern int early_init_dt_scan_memory(unsigned long node, const char *uname, + int depth, void *data); +extern void early_init_dt_add_memory_arch(u64 base, u64 size); extern u64 dt_mem_next_cell(int s, u32 **cellp); /* Early flat tree scan hooks */ -- cgit v1.2.3 From 1406bc2f57787797d1f6a3675c019a7093769275 Mon Sep 17 00:00:00 2001 From: Jeremy Kerr Date: Sat, 30 Jan 2010 01:31:21 -0700 Subject: of/flattree: use callback to setup initrd from /chosen At present, the fdt code sets the kernel-wide initrd_start and initrd_end variables when parsing /chosen. On ARM, we only set these once the bootmem has been reserved. This change adds an arch hook to setup the initrd from the device tree: void early_init_dt_setup_initrd_arch(unsigned long start, unsigned long end); The arch-specific code can then setup the initrd however it likes. Compiled on powerpc, with CONFIG_BLK_DEV_INITRD=y and =n. Signed-off-by: Jeremy Kerr Signed-off-by: Grant Likely --- arch/microblaze/kernel/prom.c | 10 ++++++++++ arch/powerpc/kernel/prom.c | 10 ++++++++++ drivers/of/fdt.c | 27 +++++++++++---------------- include/linux/of_fdt.h | 10 ++++++++++ 4 files changed, 41 insertions(+), 16 deletions(-) (limited to 'drivers/of/fdt.c') diff --git a/arch/microblaze/kernel/prom.c b/arch/microblaze/kernel/prom.c index 459c32e4a5fe..050b7993c51c 100644 --- a/arch/microblaze/kernel/prom.c +++ b/arch/microblaze/kernel/prom.c @@ -118,6 +118,16 @@ void __init early_init_devtree(void *params) pr_debug(" <- early_init_devtree()\n"); } +#ifdef CONFIG_BLK_DEV_INITRD +void __init early_init_dt_setup_initrd_arch(unsigned long start, + unsigned long end) +{ + initrd_start = (unsigned long)__va(start); + initrd_end = (unsigned long)__va(end); + initrd_below_start_ok = 1; +} +#endif + /******* * * New implementation of the OF "find" APIs, return a refcounted diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index e0f368ff8d12..40fce1c2f33b 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -510,6 +510,16 @@ void __init early_init_dt_add_memory_arch(u64 base, u64 size) memstart_addr = min((u64)memstart_addr, base); } +#ifdef CONFIG_BLK_DEV_INITRD +void __init early_init_dt_setup_initrd_arch(unsigned long start, + unsigned long end) +{ + initrd_start = (unsigned long)__va(start); + initrd_end = (unsigned long)__va(end); + initrd_below_start_ok = 1; +} +#endif + static void __init early_reserve_mem(void) { u64 base, size; diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index f84152d112b0..9290ca5aa892 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -384,28 +384,23 @@ unsigned long __init unflatten_dt_node(unsigned long mem, */ void __init early_init_dt_check_for_initrd(unsigned long node) { - unsigned long len; + unsigned long start, end, len; u32 *prop; pr_debug("Looking for initrd properties... "); prop = of_get_flat_dt_prop(node, "linux,initrd-start", &len); - if (prop) { - initrd_start = (unsigned long) - __va(of_read_ulong(prop, len/4)); - - prop = of_get_flat_dt_prop(node, "linux,initrd-end", &len); - if (prop) { - initrd_end = (unsigned long) - __va(of_read_ulong(prop, len/4)); - initrd_below_start_ok = 1; - } else { - initrd_start = 0; - } - } + if (!prop) + return; + start = of_read_ulong(prop, len/4); + + prop = of_get_flat_dt_prop(node, "linux,initrd-end", &len); + if (!prop) + return; + end = of_read_ulong(prop, len/4); - pr_debug("initrd_start=0x%lx initrd_end=0x%lx\n", - initrd_start, initrd_end); + early_init_dt_setup_initrd_arch(start, end); + pr_debug("initrd_start=0x%lx initrd_end=0x%lx\n", start, end); } #else inline void early_init_dt_check_for_initrd(unsigned long node) diff --git a/include/linux/of_fdt.h b/include/linux/of_fdt.h index bf26bd5df9f1..f32f0fc5314a 100644 --- a/include/linux/of_fdt.h +++ b/include/linux/of_fdt.h @@ -80,6 +80,16 @@ extern int early_init_dt_scan_memory(unsigned long node, const char *uname, extern void early_init_dt_add_memory_arch(u64 base, u64 size); extern u64 dt_mem_next_cell(int s, u32 **cellp); +/* + * If BLK_DEV_INITRD, the fdt early init code will call this function, + * to be provided by the arch code. start and end are specified as + * physical addresses. + */ +#ifdef CONFIG_BLK_DEV_INITRD +extern void early_init_dt_setup_initrd_arch(unsigned long start, + unsigned long end); +#endif + /* Early flat tree scan hooks */ extern int early_init_dt_scan_root(unsigned long node, const char *uname, int depth, void *data); -- cgit v1.2.3 From 36b9d3070d653af5807cef74ff129721d9047107 Mon Sep 17 00:00:00 2001 From: Jeremy Kerr Date: Mon, 1 Feb 2010 21:34:14 -0700 Subject: of/flattree: use OF_ROOT_NODE_{SIZE,ADDR}_CELLS DEFAULT for fdt parsing At present we're using hard-coded values for defaults when parsing the FDT. This change uses the #defines instead. Signed-off-by: Jeremy Kerr Signed-off-by: Grant Likely --- drivers/of/fdt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/of/fdt.c') diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index 9290ca5aa892..56fbd6e3122a 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -420,11 +420,11 @@ int __init early_init_dt_scan_root(unsigned long node, const char *uname, return 0; prop = of_get_flat_dt_prop(node, "#size-cells", NULL); - dt_root_size_cells = (prop == NULL) ? 1 : *prop; + dt_root_size_cells = prop ? *prop : OF_ROOT_NODE_SIZE_CELLS_DEFAULT; pr_debug("dt_root_size_cells = %x\n", dt_root_size_cells); prop = of_get_flat_dt_prop(node, "#address-cells", NULL); - dt_root_addr_cells = (prop == NULL) ? 2 : *prop; + dt_root_addr_cells = prop ? *prop : OF_ROOT_NODE_ADDR_CELLS_DEFAULT; pr_debug("dt_root_addr_cells = %x\n", dt_root_addr_cells); /* break now */ -- cgit v1.2.3 From 2e89e685a8fd0e8334de967739d11e2e28c1a4dd Mon Sep 17 00:00:00 2001 From: Jeremy Kerr Date: Sat, 30 Jan 2010 01:41:49 -0700 Subject: of: use __be32 for cell value accessors Currently, we're using u32 for cell values, and hence assuming host-endian device trees. As we'd like to support little-endian platforms, use a __be32 for cell values, and convert in the cell accessors. Signed-off-by: Jeremy Kerr Signed-off-by: Grant Likely --- drivers/of/fdt.c | 4 ++-- include/linux/of.h | 8 +++++--- include/linux/of_fdt.h | 2 +- 3 files changed, 8 insertions(+), 6 deletions(-) (limited to 'drivers/of/fdt.c') diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index 56fbd6e3122a..968a86af5301 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -431,9 +431,9 @@ int __init early_init_dt_scan_root(unsigned long node, const char *uname, return 1; } -u64 __init dt_mem_next_cell(int s, u32 **cellp) +u64 __init dt_mem_next_cell(int s, __be32 **cellp) { - u32 *p = *cellp; + __be32 *p = *cellp; *cellp = p + s; return of_read_number(p, s); diff --git a/include/linux/of.h b/include/linux/of.h index fd47c81d7a25..fa5571b6e219 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -20,6 +20,8 @@ #include #include +#include + typedef u32 phandle; typedef u32 ihandle; @@ -95,16 +97,16 @@ extern void of_node_put(struct device_node *node); */ /* Helper to read a big number; size is in cells (not bytes) */ -static inline u64 of_read_number(const u32 *cell, int size) +static inline u64 of_read_number(const __be32 *cell, int size) { u64 r = 0; while (size--) - r = (r << 32) | *(cell++); + r = (r << 32) | be32_to_cpu(*(cell++)); return r; } /* Like of_read_number, but we want an unsigned long result */ -static inline unsigned long of_read_ulong(const u32 *cell, int size) +static inline unsigned long of_read_ulong(const __be32 *cell, int size) { /* toss away upper bits if unsigned long is smaller than u64 */ return of_read_number(cell, size); diff --git a/include/linux/of_fdt.h b/include/linux/of_fdt.h index f32f0fc5314a..6a35d91a53a6 100644 --- a/include/linux/of_fdt.h +++ b/include/linux/of_fdt.h @@ -78,7 +78,7 @@ extern void early_init_dt_check_for_initrd(unsigned long node); extern int early_init_dt_scan_memory(unsigned long node, const char *uname, int depth, void *data); extern void early_init_dt_add_memory_arch(u64 base, u64 size); -extern u64 dt_mem_next_cell(int s, u32 **cellp); +extern u64 dt_mem_next_cell(int s, __be32 **cellp); /* * If BLK_DEV_INITRD, the fdt early init code will call this function, -- cgit v1.2.3 From 337148812f97368a8ec4a69f1691e4c5ce3af494 Mon Sep 17 00:00:00 2001 From: Jeremy Kerr Date: Sat, 30 Jan 2010 01:45:26 -0700 Subject: of: assume big-endian properties, adding conversions where necessary Properties in the device tree are specified as big-endian. At present, the only platforms to support device trees are also big-endian, so we've been acessing the properties as raw values. We'd like to add device tree support to little-endian platforms too, so add endian conversion to the sites where we access property values in the common of code. Compiled on powerpc (ppc44x_defconfig & ppc64_defconfig) and arm (fdt support only for now). Signed-off-by: Jeremy Kerr Signed-off-by: Grant Likely --- drivers/of/base.c | 12 ++++++------ drivers/of/fdt.c | 45 +++++++++++++++++++++++++-------------------- drivers/of/gpio.c | 13 +++++++------ drivers/of/of_i2c.c | 4 ++-- drivers/of/of_mdio.c | 8 ++++---- drivers/of/of_spi.c | 6 +++--- 6 files changed, 47 insertions(+), 41 deletions(-) (limited to 'drivers/of/fdt.c') diff --git a/drivers/of/base.c b/drivers/of/base.c index 524645ab42a4..873479a21c80 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -38,7 +38,7 @@ int of_n_addr_cells(struct device_node *np) np = np->parent; ip = of_get_property(np, "#address-cells", NULL); if (ip) - return *ip; + return be32_to_cpup(ip); } while (np->parent); /* No #address-cells property for the root node */ return OF_ROOT_NODE_ADDR_CELLS_DEFAULT; @@ -54,7 +54,7 @@ int of_n_size_cells(struct device_node *np) np = np->parent; ip = of_get_property(np, "#size-cells", NULL); if (ip) - return *ip; + return be32_to_cpup(ip); } while (np->parent); /* No #size-cells property for the root node */ return OF_ROOT_NODE_SIZE_CELLS_DEFAULT; @@ -696,8 +696,8 @@ int of_parse_phandles_with_args(struct device_node *np, const char *list_name, const void **out_args) { int ret = -EINVAL; - const u32 *list; - const u32 *list_end; + const __be32 *list; + const __be32 *list_end; int size; int cur_index = 0; struct device_node *node = NULL; @@ -711,7 +711,7 @@ int of_parse_phandles_with_args(struct device_node *np, const char *list_name, list_end = list + size / sizeof(*list); while (list < list_end) { - const u32 *cells; + const __be32 *cells; const phandle *phandle; phandle = list++; @@ -735,7 +735,7 @@ int of_parse_phandles_with_args(struct device_node *np, const char *list_name, goto err1; } - list += *cells; + list += be32_to_cpup(cells); if (list > list_end) { pr_debug("%s: insufficient arguments length\n", np->full_name); diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index 968a86af5301..5c5f03ef7f06 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -51,7 +51,7 @@ int __init of_scan_flat_dt(int (*it)(unsigned long node, int depth = -1; do { - u32 tag = *((u32 *)p); + u32 tag = be32_to_cpup((__be32 *)p); char *pathp; p += 4; @@ -64,7 +64,7 @@ int __init of_scan_flat_dt(int (*it)(unsigned long node, if (tag == OF_DT_END) break; if (tag == OF_DT_PROP) { - u32 sz = *((u32 *)p); + u32 sz = be32_to_cpup((__be32 *)p); p += 8; if (initial_boot_params->version < 0x10) p = _ALIGN(p, sz >= 8 ? 8 : 4); @@ -103,9 +103,9 @@ unsigned long __init of_get_flat_dt_root(void) unsigned long p = ((unsigned long)initial_boot_params) + initial_boot_params->off_dt_struct; - while (*((u32 *)p) == OF_DT_NOP) + while (be32_to_cpup((__be32 *)p) == OF_DT_NOP) p += 4; - BUG_ON(*((u32 *)p) != OF_DT_BEGIN_NODE); + BUG_ON(be32_to_cpup((__be32 *)p) != OF_DT_BEGIN_NODE); p += 4; return _ALIGN(p + strlen((char *)p) + 1, 4); } @@ -122,7 +122,7 @@ void *__init of_get_flat_dt_prop(unsigned long node, const char *name, unsigned long p = node; do { - u32 tag = *((u32 *)p); + u32 tag = be32_to_cpup((__be32 *)p); u32 sz, noff; const char *nstr; @@ -132,8 +132,8 @@ void *__init of_get_flat_dt_prop(unsigned long node, const char *name, if (tag != OF_DT_PROP) return NULL; - sz = *((u32 *)p); - noff = *((u32 *)(p + 4)); + sz = be32_to_cpup((__be32 *)p); + noff = be32_to_cpup((__be32 *)(p + 4)); p += 8; if (initial_boot_params->version < 0x10) p = _ALIGN(p, sz >= 8 ? 8 : 4); @@ -210,7 +210,7 @@ unsigned long __init unflatten_dt_node(unsigned long mem, int has_name = 0; int new_format = 0; - tag = *((u32 *)(*p)); + tag = be32_to_cpup((__be32 *)(*p)); if (tag != OF_DT_BEGIN_NODE) { pr_err("Weird tag at start of node: %x\n", tag); return mem; @@ -285,7 +285,7 @@ unsigned long __init unflatten_dt_node(unsigned long mem, u32 sz, noff; char *pname; - tag = *((u32 *)(*p)); + tag = be32_to_cpup((__be32 *)(*p)); if (tag == OF_DT_NOP) { *p += 4; continue; @@ -293,8 +293,8 @@ unsigned long __init unflatten_dt_node(unsigned long mem, if (tag != OF_DT_PROP) break; *p += 4; - sz = *((u32 *)(*p)); - noff = *((u32 *)((*p) + 4)); + sz = be32_to_cpup((__be32 *)(*p)); + noff = be32_to_cpup((__be32 *)((*p) + 4)); *p += 8; if (initial_boot_params->version < 0x10) *p = _ALIGN(*p, sz >= 8 ? 8 : 4); @@ -367,7 +367,7 @@ unsigned long __init unflatten_dt_node(unsigned long mem, } while (tag == OF_DT_BEGIN_NODE) { mem = unflatten_dt_node(mem, p, np, allnextpp, fpsize); - tag = *((u32 *)(*p)); + tag = be32_to_cpup((__be32 *)(*p)); } if (tag != OF_DT_END_NODE) { pr_err("Weird tag at end of node: %x\n", tag); @@ -385,7 +385,7 @@ unsigned long __init unflatten_dt_node(unsigned long mem, void __init early_init_dt_check_for_initrd(unsigned long node) { unsigned long start, end, len; - u32 *prop; + __be32 *prop; pr_debug("Looking for initrd properties... "); @@ -414,17 +414,22 @@ inline void early_init_dt_check_for_initrd(unsigned long node) int __init early_init_dt_scan_root(unsigned long node, const char *uname, int depth, void *data) { - u32 *prop; + __be32 *prop; if (depth != 0) return 0; + dt_root_size_cells = OF_ROOT_NODE_SIZE_CELLS_DEFAULT; + dt_root_addr_cells = OF_ROOT_NODE_ADDR_CELLS_DEFAULT; + prop = of_get_flat_dt_prop(node, "#size-cells", NULL); - dt_root_size_cells = prop ? *prop : OF_ROOT_NODE_SIZE_CELLS_DEFAULT; + if (prop) + dt_root_size_cells = be32_to_cpup(prop); pr_debug("dt_root_size_cells = %x\n", dt_root_size_cells); prop = of_get_flat_dt_prop(node, "#address-cells", NULL); - dt_root_addr_cells = prop ? *prop : OF_ROOT_NODE_ADDR_CELLS_DEFAULT; + if (prop) + dt_root_addr_cells = be32_to_cpup(prop); pr_debug("dt_root_addr_cells = %x\n", dt_root_addr_cells); /* break now */ @@ -549,7 +554,7 @@ void __init unflatten_device_tree(void) mem = lmb_alloc(size + 4, __alignof__(struct device_node)); mem = (unsigned long) __va(mem); - ((u32 *)mem)[size / 4] = 0xdeadbeef; + ((__be32 *)mem)[size / 4] = cpu_to_be32(0xdeadbeef); pr_debug(" unflattening %lx...\n", mem); @@ -557,11 +562,11 @@ void __init unflatten_device_tree(void) start = ((unsigned long)initial_boot_params) + initial_boot_params->off_dt_struct; unflatten_dt_node(mem, &start, NULL, &allnextp, 0); - if (*((u32 *)start) != OF_DT_END) + if (be32_to_cpup((__be32 *)start) != OF_DT_END) pr_warning("Weird tag at end of tree: %08x\n", *((u32 *)start)); - if (((u32 *)mem)[size / 4] != 0xdeadbeef) + if (be32_to_cpu(((__be32 *)mem)[size / 4]) != 0xdeadbeef) pr_warning("End of tree marker overwritten: %08x\n", - ((u32 *)mem)[size / 4]); + be32_to_cpu(((__be32 *)mem)[size / 4])); *allnextp = NULL; /* Get pointer to OF "/chosen" node for use everywhere */ diff --git a/drivers/of/gpio.c b/drivers/of/gpio.c index 6eea601a9204..24c3606217f8 100644 --- a/drivers/of/gpio.c +++ b/drivers/of/gpio.c @@ -36,7 +36,7 @@ int of_get_gpio_flags(struct device_node *np, int index, struct of_gpio_chip *of_gc = NULL; int size; const void *gpio_spec; - const u32 *gpio_cells; + const __be32 *gpio_cells; ret = of_parse_phandles_with_args(np, "gpios", "#gpio-cells", index, &gc, &gpio_spec); @@ -55,7 +55,7 @@ int of_get_gpio_flags(struct device_node *np, int index, gpio_cells = of_get_property(gc, "#gpio-cells", &size); if (!gpio_cells || size != sizeof(*gpio_cells) || - *gpio_cells != of_gc->gpio_cells) { + be32_to_cpup(gpio_cells) != of_gc->gpio_cells) { pr_debug("%s: wrong #gpio-cells for %s\n", np->full_name, gc->full_name); ret = -EINVAL; @@ -127,7 +127,8 @@ EXPORT_SYMBOL(of_gpio_count); int of_gpio_simple_xlate(struct of_gpio_chip *of_gc, struct device_node *np, const void *gpio_spec, enum of_gpio_flags *flags) { - const u32 *gpio = gpio_spec; + const __be32 *gpio = gpio_spec; + const u32 n = be32_to_cpup(gpio); /* * We're discouraging gpio_cells < 2, since that way you'll have to @@ -140,13 +141,13 @@ int of_gpio_simple_xlate(struct of_gpio_chip *of_gc, struct device_node *np, return -EINVAL; } - if (*gpio > of_gc->gc.ngpio) + if (n > of_gc->gc.ngpio) return -EINVAL; if (flags) - *flags = gpio[1]; + *flags = be32_to_cpu(gpio[1]); - return *gpio; + return n; } EXPORT_SYMBOL(of_gpio_simple_xlate); diff --git a/drivers/of/of_i2c.c b/drivers/of/of_i2c.c index fa65a2b2ae2e..a3a708e590d0 100644 --- a/drivers/of/of_i2c.c +++ b/drivers/of/of_i2c.c @@ -25,7 +25,7 @@ void of_register_i2c_devices(struct i2c_adapter *adap, for_each_child_of_node(adap_node, node) { struct i2c_board_info info = {}; struct dev_archdata dev_ad = {}; - const u32 *addr; + const __be32 *addr; int len; if (of_modalias_node(node, info.type, sizeof(info.type)) < 0) @@ -40,7 +40,7 @@ void of_register_i2c_devices(struct i2c_adapter *adap, info.irq = irq_of_parse_and_map(node, 0); - info.addr = *addr; + info.addr = be32_to_cpup(addr); dev_archdata_set_node(&dev_ad, node); info.archdata = &dev_ad; diff --git a/drivers/of/of_mdio.c b/drivers/of/of_mdio.c index 4b22ba568b19..18ecae4a4375 100644 --- a/drivers/of/of_mdio.c +++ b/drivers/of/of_mdio.c @@ -51,7 +51,7 @@ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np) /* Loop over the child nodes and register a phy_device for each one */ for_each_child_of_node(np, child) { - const u32 *addr; + const __be32 *addr; int len; /* A PHY must have a reg property in the range [0-31] */ @@ -68,7 +68,7 @@ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np) mdio->irq[*addr] = PHY_POLL; } - phy = get_phy_device(mdio, *addr); + phy = get_phy_device(mdio, be32_to_cpup(addr)); if (!phy) { dev_err(&mdio->dev, "error probing PHY at address %i\n", *addr); @@ -160,7 +160,7 @@ struct phy_device *of_phy_connect_fixed_link(struct net_device *dev, struct device_node *net_np; char bus_id[MII_BUS_ID_SIZE + 3]; struct phy_device *phy; - const u32 *phy_id; + const __be32 *phy_id; int sz; if (!dev->dev.parent) @@ -174,7 +174,7 @@ struct phy_device *of_phy_connect_fixed_link(struct net_device *dev, if (!phy_id || sz < sizeof(*phy_id)) return NULL; - sprintf(bus_id, PHY_ID_FMT, "0", phy_id[0]); + sprintf(bus_id, PHY_ID_FMT, "0", be32_to_cpu(phy_id[0])); phy = phy_connect(dev, bus_id, hndlr, 0, iface); return IS_ERR(phy) ? NULL : phy; diff --git a/drivers/of/of_spi.c b/drivers/of/of_spi.c index bed0ed6dcdc1..f65f48b98448 100644 --- a/drivers/of/of_spi.c +++ b/drivers/of/of_spi.c @@ -23,7 +23,7 @@ void of_register_spi_devices(struct spi_master *master, struct device_node *np) { struct spi_device *spi; struct device_node *nc; - const u32 *prop; + const __be32 *prop; int rc; int len; @@ -54,7 +54,7 @@ void of_register_spi_devices(struct spi_master *master, struct device_node *np) spi_dev_put(spi); continue; } - spi->chip_select = *prop; + spi->chip_select = be32_to_cpup(prop); /* Mode (clock phase/polarity/etc.) */ if (of_find_property(nc, "spi-cpha", NULL)) @@ -72,7 +72,7 @@ void of_register_spi_devices(struct spi_master *master, struct device_node *np) spi_dev_put(spi); continue; } - spi->max_speed_hz = *prop; + spi->max_speed_hz = be32_to_cpup(prop); /* IRQ */ spi->irq = irq_of_parse_and_map(nc, 0); -- cgit v1.2.3 From 087f79c48c090a2c0cd9ee45231d63290d2036d2 Mon Sep 17 00:00:00 2001 From: Jeremy Kerr Date: Sat, 30 Jan 2010 04:14:19 -0700 Subject: of/flattree: endian-convert members of boot_param_header The boot_param_header has big-endian fields, so change the types to __be32, and perform endian conversion when we access them. Signed-off-by: Jeremy Kerr Signed-off-by: Grant Likely --- arch/powerpc/kernel/prom.c | 2 +- drivers/of/fdt.c | 16 ++++++++-------- include/linux/of_fdt.h | 20 ++++++++++---------- 3 files changed, 19 insertions(+), 19 deletions(-) (limited to 'drivers/of/fdt.c') diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 40fce1c2f33b..43c78d74ddcb 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -98,7 +98,7 @@ static void __init move_device_tree(void) DBG("-> move_device_tree\n"); start = __pa(initial_boot_params); - size = initial_boot_params->totalsize; + size = be32_to_cpu(initial_boot_params->totalsize); if ((memory_limit && (start + size) > memory_limit) || overlaps_crashkernel(start, size)) { diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index 5c5f03ef7f06..18d282fefe58 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -28,7 +28,7 @@ struct boot_param_header *initial_boot_params; char *find_flat_dt_string(u32 offset) { return ((char *)initial_boot_params) + - initial_boot_params->off_dt_strings + offset; + be32_to_cpu(initial_boot_params->off_dt_strings) + offset; } /** @@ -46,7 +46,7 @@ int __init of_scan_flat_dt(int (*it)(unsigned long node, void *data) { unsigned long p = ((unsigned long)initial_boot_params) + - initial_boot_params->off_dt_struct; + be32_to_cpu(initial_boot_params->off_dt_struct); int rc = 0; int depth = -1; @@ -66,7 +66,7 @@ int __init of_scan_flat_dt(int (*it)(unsigned long node, if (tag == OF_DT_PROP) { u32 sz = be32_to_cpup((__be32 *)p); p += 8; - if (initial_boot_params->version < 0x10) + if (be32_to_cpu(initial_boot_params->version) < 0x10) p = _ALIGN(p, sz >= 8 ? 8 : 4); p += sz; p = _ALIGN(p, 4); @@ -101,7 +101,7 @@ int __init of_scan_flat_dt(int (*it)(unsigned long node, unsigned long __init of_get_flat_dt_root(void) { unsigned long p = ((unsigned long)initial_boot_params) + - initial_boot_params->off_dt_struct; + be32_to_cpu(initial_boot_params->off_dt_struct); while (be32_to_cpup((__be32 *)p) == OF_DT_NOP) p += 4; @@ -135,7 +135,7 @@ void *__init of_get_flat_dt_prop(unsigned long node, const char *name, sz = be32_to_cpup((__be32 *)p); noff = be32_to_cpup((__be32 *)(p + 4)); p += 8; - if (initial_boot_params->version < 0x10) + if (be32_to_cpu(initial_boot_params->version) < 0x10) p = _ALIGN(p, sz >= 8 ? 8 : 4); nstr = find_flat_dt_string(noff); @@ -296,7 +296,7 @@ unsigned long __init unflatten_dt_node(unsigned long mem, sz = be32_to_cpup((__be32 *)(*p)); noff = be32_to_cpup((__be32 *)((*p) + 4)); *p += 8; - if (initial_boot_params->version < 0x10) + if (be32_to_cpu(initial_boot_params->version) < 0x10) *p = _ALIGN(*p, sz >= 8 ? 8 : 4); pname = find_flat_dt_string(noff); @@ -544,7 +544,7 @@ void __init unflatten_device_tree(void) /* First pass, scan for size */ start = ((unsigned long)initial_boot_params) + - initial_boot_params->off_dt_struct; + be32_to_cpu(initial_boot_params->off_dt_struct); size = unflatten_dt_node(0, &start, NULL, NULL, 0); size = (size | 3) + 1; @@ -560,7 +560,7 @@ void __init unflatten_device_tree(void) /* Second pass, do actual unflattening */ start = ((unsigned long)initial_boot_params) + - initial_boot_params->off_dt_struct; + be32_to_cpu(initial_boot_params->off_dt_struct); unflatten_dt_node(mem, &start, NULL, &allnextp, 0); if (be32_to_cpup((__be32 *)start) != OF_DT_END) pr_warning("Weird tag at end of tree: %08x\n", *((u32 *)start)); diff --git a/include/linux/of_fdt.h b/include/linux/of_fdt.h index 6a35d91a53a6..0007187ab59b 100644 --- a/include/linux/of_fdt.h +++ b/include/linux/of_fdt.h @@ -42,19 +42,19 @@ * ends when size is 0 */ struct boot_param_header { - u32 magic; /* magic word OF_DT_HEADER */ - u32 totalsize; /* total size of DT block */ - u32 off_dt_struct; /* offset to structure */ - u32 off_dt_strings; /* offset to strings */ - u32 off_mem_rsvmap; /* offset to memory reserve map */ - u32 version; /* format version */ - u32 last_comp_version; /* last compatible version */ + __be32 magic; /* magic word OF_DT_HEADER */ + __be32 totalsize; /* total size of DT block */ + __be32 off_dt_struct; /* offset to structure */ + __be32 off_dt_strings; /* offset to strings */ + __be32 off_mem_rsvmap; /* offset to memory reserve map */ + __be32 version; /* format version */ + __be32 last_comp_version; /* last compatible version */ /* version 2 fields below */ - u32 boot_cpuid_phys; /* Physical CPU id we're booting on */ + __be32 boot_cpuid_phys; /* Physical CPU id we're booting on */ /* version 3 fields below */ - u32 dt_strings_size; /* size of the DT strings block */ + __be32 dt_strings_size; /* size of the DT strings block */ /* version 17 fields below */ - u32 dt_struct_size; /* size of the DT structure block */ + __be32 dt_struct_size; /* size of the DT structure block */ }; /* TBD: Temporary export of fdt globals - remove when code fully merged */ -- cgit v1.2.3 From 04b954a673dd02f585a2769c4945a43880faa989 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 1 Feb 2010 21:34:15 -0700 Subject: of/flattree: Make the kernel accept ePAPR style phandle information Currently when processing flattened device trees, the kernel expects the phandle in a property called "linux,phandle". The ePAPR spec - not being Linux specific - instead requires phandles to be encoded in a property named simply "phandle". This patch makes the kernel accept either form when unflattening the device tree. Signed-off-by: David Gibson Signed-off-by: Grant Likely --- drivers/of/fdt.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'drivers/of/fdt.c') diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index 18d282fefe58..b51f797d9d9d 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -310,10 +310,19 @@ unsigned long __init unflatten_dt_node(unsigned long mem, pp = unflatten_dt_alloc(&mem, sizeof(struct property), __alignof__(struct property)); if (allnextpp) { - if (strcmp(pname, "linux,phandle") == 0) { + /* We accept flattened tree phandles either in + * ePAPR-style "phandle" properties, or the + * legacy "linux,phandle" properties. If both + * appear and have different values, things + * will get weird. Don't do that. */ + if ((strcmp(pname, "phandle") == 0) || + (strcmp(pname, "linux,phandle") == 0)) { if (np->phandle == 0) np->phandle = *((u32 *)*p); } + /* And we process the "ibm,phandle" property + * used in pSeries dynamic device tree + * stuff */ if (strcmp(pname, "ibm,phandle") == 0) np->phandle = *((u32 *)*p); pp->name = pname; -- cgit v1.2.3 From 4ef7b373df330bc0ff037dc4792d373c9346375f Mon Sep 17 00:00:00 2001 From: Jeremy Kerr Date: Sun, 14 Feb 2010 07:13:47 -0700 Subject: of/flattree: Don't assume HAVE_LMB We don't always have lmb available, so make arches provide an early_init_dt_alloc_memory_arch() to handle the allocation of memory in the fdt code. When we don't have lmb.h included, we need asm/page.h for __va. Signed-off-by: Jeremy Kerr Signed-off-by: Grant Likely Acked-by: Benjamin Herrenschmidt Acked-by: Michal Simek --- arch/microblaze/kernel/prom.c | 5 +++++ arch/powerpc/kernel/prom.c | 5 +++++ drivers/of/fdt.c | 9 ++++++--- include/linux/of_fdt.h | 1 + 4 files changed, 17 insertions(+), 3 deletions(-) (limited to 'drivers/of/fdt.c') diff --git a/arch/microblaze/kernel/prom.c b/arch/microblaze/kernel/prom.c index 050b7993c51c..a7dcaf092200 100644 --- a/arch/microblaze/kernel/prom.c +++ b/arch/microblaze/kernel/prom.c @@ -55,6 +55,11 @@ void __init early_init_dt_add_memory_arch(u64 base, u64 size) lmb_add(base, size); } +u64 __init early_init_dt_alloc_memory_arch(u64 size, u64 align) +{ + return lmb_alloc(size, align); +} + #ifdef CONFIG_EARLY_PRINTK /* MS this is Microblaze specifig function */ static int __init early_init_dt_scan_serial(unsigned long node, diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 43c78d74ddcb..5bbbdb29f603 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -510,6 +510,11 @@ void __init early_init_dt_add_memory_arch(u64 base, u64 size) memstart_addr = min((u64)memstart_addr, base); } +u64 __init early_init_dt_alloc_memory_arch(u64 size, u64 align) +{ + return lmb_alloc(size, align); +} + #ifdef CONFIG_BLK_DEV_INITRD void __init early_init_dt_setup_initrd_arch(unsigned long start, unsigned long end) diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index b51f797d9d9d..406757a9d7ea 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -10,16 +10,18 @@ */ #include -#include #include #include #include - +#include +#include #ifdef CONFIG_PPC #include #endif /* CONFIG_PPC */ +#include + int __initdata dt_root_addr_cells; int __initdata dt_root_size_cells; @@ -560,7 +562,8 @@ void __init unflatten_device_tree(void) pr_debug(" size is %lx, allocating...\n", size); /* Allocate memory for the expanded device tree */ - mem = lmb_alloc(size + 4, __alignof__(struct device_node)); + mem = early_init_dt_alloc_memory_arch(size + 4, + __alignof__(struct device_node)); mem = (unsigned long) __va(mem); ((__be32 *)mem)[size / 4] = cpu_to_be32(0xdeadbeef); diff --git a/include/linux/of_fdt.h b/include/linux/of_fdt.h index c9cb8a7bc065..a1ca92ccb0ff 100644 --- a/include/linux/of_fdt.h +++ b/include/linux/of_fdt.h @@ -78,6 +78,7 @@ extern void early_init_dt_check_for_initrd(unsigned long node); extern int early_init_dt_scan_memory(unsigned long node, const char *uname, int depth, void *data); extern void early_init_dt_add_memory_arch(u64 base, u64 size); +extern u64 early_init_dt_alloc_memory_arch(u64 size, u64 align); extern u64 dt_mem_next_cell(int s, __be32 **cellp); /* -- cgit v1.2.3