Patchwork [U-Boot,v3,6/6] fdt: add decode helper library

login
register
mail settings
Submitter Simon Glass
Date Oct. 11, 2011, 10:26 p.m.
Message ID <1318371971-4457-7-git-send-email-sjg@chromium.org>
Download mbox | patch
Permalink /patch/119081/
State New, archived
Headers show

Comments

Simon Glass - Oct. 11, 2011, 10:26 p.m.
This library provides useful functions to drivers which want to use
the fdt to control their operation. Functions are provided to:

- look up and enumerate a device type (for example assigning i2c bus 0,
 i2c bus 1, etc.)
- decode basic types from the fdt, like addresses and integers

While this library is not strictly necessary, it helps to minimise the
changes to a driver, in order to make it work under fdt control. Less
code is required, and so the barrier to switch drivers over is lower.

Additional functions to read arrays and GPIOs could be made available
here also.

Signed-off-by: Simon Glass <sjg@chromium.org>
---
Changes in v2:
- Add example proposed decode helper library

Changes in v3:
- Simplify decode library to remove provide only primitive functions
- Remove i2c decode function
- Rename fdt_decode to fdtdec, since it will be used a lot
- Moved fdt_decode.c to /lib
- Export almost all functions from fdtdec, to allow widespread use
- Remove use of FDT_ERR_MISSING which is not strictly needed now

 include/fdtdec.h |  122 ++++++++++++++++++++++++++++++++++++++++++++++++++
 lib/Makefile     |    1 +
 lib/fdtdec.c     |  131 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 254 insertions(+), 0 deletions(-)
 create mode 100644 include/fdtdec.h
 create mode 100644 lib/fdtdec.c
Mike Frysinger - Oct. 13, 2011, 8:33 p.m.
On Tuesday 11 October 2011 18:26:11 Simon Glass wrote:
> --- /dev/null
> +++ b/include/fdtdec.h
>
> +/*
> + * A typedef for a physical address. Note that fdt data is always big
> + * endian even on a litle endian machine.
> + */
> +#ifdef CONFIG_PHYS_64BIT
> +typedef u64 addr_t;
> +#define ADDR_T_NONE (-1ULL)
> +#define addr_to_cpu(reg) be64_to_cpu(reg)
> +#else
> +typedef u32 addr_t;
> +#define ADDR_T_NONE (-1U)
> +#define addr_to_cpu(reg) be32_to_cpu(reg)
> +#endif

"addr" is fairly generic.  how about "fdt_addr" instead ?

> --- /dev/null
> +++ b/lib/fdtdec.c
>
> +/* we need a generic GPIO interface here */
> +#include <asm/arch/gpio.h>

we have asm/gpio.h now, although i don't see this code using anything from the 
gpio header to need this include ...

> +static const char *compat_names[COMPAT_COUNT] = {

static const char * const compat_names[COMPAT_COUNT] = {

> +int fdtdec_next_alias(const void *blob, const char *name,
> +		enum fdt_compat_id id, int *upto)
> +{
> +#define MAX_STR_LEN 20
> +	char str[MAX_STR_LEN + 20];
> +	int node, err;
> +
> +	sprintf(str, "%.*s%d", MAX_STR_LEN, name, *upto);

where's that "20" coming from ?  just arbitrarily defined ?  might want to add 
an assert(strlen(name) <= MAX_STR_LEN).
-mike
Simon Glass - Oct. 13, 2011, 9:28 p.m.
Hi Mike,

On Thu, Oct 13, 2011 at 1:33 PM, Mike Frysinger <vapier@gentoo.org> wrote:
> On Tuesday 11 October 2011 18:26:11 Simon Glass wrote:
>> --- /dev/null
>> +++ b/include/fdtdec.h
>>
>> +/*
>> + * A typedef for a physical address. Note that fdt data is always big
>> + * endian even on a litle endian machine.
>> + */
>> +#ifdef CONFIG_PHYS_64BIT
>> +typedef u64 addr_t;
>> +#define ADDR_T_NONE (-1ULL)
>> +#define addr_to_cpu(reg) be64_to_cpu(reg)
>> +#else
>> +typedef u32 addr_t;
>> +#define ADDR_T_NONE (-1U)
>> +#define addr_to_cpu(reg) be32_to_cpu(reg)
>> +#endif
>
> "addr" is fairly generic.  how about "fdt_addr" instead ?

OK

>
>> --- /dev/null
>> +++ b/lib/fdtdec.c
>>
>> +/* we need a generic GPIO interface here */
>> +#include <asm/arch/gpio.h>
>
> we have asm/gpio.h now, although i don't see this code using anything from the
> gpio header to need this include ...

Will remove it.

>
>> +static const char *compat_names[COMPAT_COUNT] = {
>
> static const char * const compat_names[COMPAT_COUNT] = {
>
>> +int fdtdec_next_alias(const void *blob, const char *name,
>> +             enum fdt_compat_id id, int *upto)
>> +{
>> +#define MAX_STR_LEN 20
>> +     char str[MAX_STR_LEN + 20];
>> +     int node, err;
>> +
>> +     sprintf(str, "%.*s%d", MAX_STR_LEN, name, *upto);
>
> where's that "20" coming from ?  just arbitrarily defined ?  might want to add
> an assert(strlen(name) <= MAX_STR_LEN).
> -mike
>

OK. Of course I would like to use snprintf()...

Regards,
Simon
Mike Frysinger - Oct. 13, 2011, 11:01 p.m.
On Thursday 13 October 2011 17:28:10 Simon Glass wrote:
> On Thu, Oct 13, 2011 at 1:33 PM, Mike Frysinger wrote:
> > On Tuesday 11 October 2011 18:26:11 Simon Glass wrote:
> >> +int fdtdec_next_alias(const void *blob, const char *name,
> >> +             enum fdt_compat_id id, int *upto)
> >> +{
> >> +#define MAX_STR_LEN 20
> >> +     char str[MAX_STR_LEN + 20];
> >> +     int node, err;
> >> +
> >> +     sprintf(str, "%.*s%d", MAX_STR_LEN, name, *upto);
> > 
> > where's that "20" coming from ?  just arbitrarily defined ?  might want
> > to add an assert(strlen(name) <= MAX_STR_LEN).
> 
> OK. Of course I would like to use snprintf()...

i think that might be nicer anyways than %.*s

	char str[40];	/* an arbitrary len */
	snprintf(str, sizeof(str), "%s%d", name, *upto);
-mike
Simon Glass - Oct. 13, 2011, 11:16 p.m.
Hi Mike,

On Thu, Oct 13, 2011 at 4:01 PM, Mike Frysinger <vapier@gentoo.org> wrote:
> On Thursday 13 October 2011 17:28:10 Simon Glass wrote:
>> On Thu, Oct 13, 2011 at 1:33 PM, Mike Frysinger wrote:
>> > On Tuesday 11 October 2011 18:26:11 Simon Glass wrote:
>> >> +int fdtdec_next_alias(const void *blob, const char *name,
>> >> +             enum fdt_compat_id id, int *upto)
>> >> +{
>> >> +#define MAX_STR_LEN 20
>> >> +     char str[MAX_STR_LEN + 20];
>> >> +     int node, err;
>> >> +
>> >> +     sprintf(str, "%.*s%d", MAX_STR_LEN, name, *upto);
>> >
>> > where's that "20" coming from ?  just arbitrarily defined ?  might want
>> > to add an assert(strlen(name) <= MAX_STR_LEN).
>>
>> OK. Of course I would like to use snprintf()...
>
> i think that might be nicer anyways than %.*s
>
>        char str[40];   /* an arbitrary len */
>        snprintf(str, sizeof(str), "%s%d", name, *upto);
> -mike
>

Yes I agree, but we have the minor issue that snprintf() is not merged yet :-(

Regards,
Simon
Mike Frysinger - Oct. 13, 2011, 11:32 p.m.
On Thursday 13 October 2011 19:16:52 Simon Glass wrote:
> On Thu, Oct 13, 2011 at 4:01 PM, Mike Frysinger wrote:
> >        char str[40];   /* an arbitrary len */
> >        snprintf(str, sizeof(str), "%s%d", name, *upto);
> 
> Yes I agree, but we have the minor issue that snprintf() is not merged yet

ah, good point.  obviously didn't realize :).
-mike
Kumar Gala - Oct. 14, 2011, 6:12 p.m.
On Oct 11, 2011, at 5:26 PM, Simon Glass wrote:

> This library provides useful functions to drivers which want to use
> the fdt to control their operation. Functions are provided to:
> 
> - look up and enumerate a device type (for example assigning i2c bus 0,
> i2c bus 1, etc.)
> - decode basic types from the fdt, like addresses and integers
> 
> While this library is not strictly necessary, it helps to minimise the
> changes to a driver, in order to make it work under fdt control. Less
> code is required, and so the barrier to switch drivers over is lower.
> 
> Additional functions to read arrays and GPIOs could be made available
> here also.
> 
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
> Changes in v2:
> - Add example proposed decode helper library
> 
> Changes in v3:
> - Simplify decode library to remove provide only primitive functions
> - Remove i2c decode function
> - Rename fdt_decode to fdtdec, since it will be used a lot
> - Moved fdt_decode.c to /lib
> - Export almost all functions from fdtdec, to allow widespread use
> - Remove use of FDT_ERR_MISSING which is not strictly needed now
> 
> include/fdtdec.h |  122 ++++++++++++++++++++++++++++++++++++++++++++++++++
> lib/Makefile     |    1 +
> lib/fdtdec.c     |  131 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 254 insertions(+), 0 deletions(-)
> create mode 100644 include/fdtdec.h
> create mode 100644 lib/fdtdec.c

I think this is the wrong approach.  If we intend to go down the path of embedded a device tree we should look at produce a live tree structure that can be used like Linux has.

There are a lot of places we are manipulate device tree blobs that would be more efficient if we had a live tree structure in place.

I think that will only get worse with the addition of embedding a tree.

- k
Simon Glass - Oct. 14, 2011, 6:21 p.m.
Hi Kumar,

On Fri, Oct 14, 2011 at 11:12 AM, Kumar Gala <galak@kernel.crashing.org> wrote:
>
> On Oct 11, 2011, at 5:26 PM, Simon Glass wrote:
>
>> This library provides useful functions to drivers which want to use
>> the fdt to control their operation. Functions are provided to:
>>
>> - look up and enumerate a device type (for example assigning i2c bus 0,
>> i2c bus 1, etc.)
>> - decode basic types from the fdt, like addresses and integers
>>
>> While this library is not strictly necessary, it helps to minimise the
>> changes to a driver, in order to make it work under fdt control. Less
>> code is required, and so the barrier to switch drivers over is lower.
>>
>> Additional functions to read arrays and GPIOs could be made available
>> here also.
>>
>> Signed-off-by: Simon Glass <sjg@chromium.org>
>> ---
>> Changes in v2:
>> - Add example proposed decode helper library
>>
>> Changes in v3:
>> - Simplify decode library to remove provide only primitive functions
>> - Remove i2c decode function
>> - Rename fdt_decode to fdtdec, since it will be used a lot
>> - Moved fdt_decode.c to /lib
>> - Export almost all functions from fdtdec, to allow widespread use
>> - Remove use of FDT_ERR_MISSING which is not strictly needed now
>>
>> include/fdtdec.h |  122 ++++++++++++++++++++++++++++++++++++++++++++++++++
>> lib/Makefile     |    1 +
>> lib/fdtdec.c     |  131 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
>> 3 files changed, 254 insertions(+), 0 deletions(-)
>> create mode 100644 include/fdtdec.h
>> create mode 100644 lib/fdtdec.c
>
> I think this is the wrong approach.  If we intend to go down the path of embedded a device tree we should look at produce a live tree structure that can be used like Linux has.

The intent of this patch set is to provide U-Boot with a simple
run-time configuration system.

Can you please explain why you want a live tree for use by U-Boot?
U-Boot already has one that it passes on to Linux, and this is under
control of scripts, etc., quite separate from this.

This fdt is for configuration of devices used by U-Boot itself.

What can U-Boot find out that it would want to put into this private
fdt? Are you thinking of probing for devices early on and then using
them later in U-Boot? If so, surely no code can exist which does this
now, since this patch set is new.

>
> There are a lot of places we are manipulate device tree blobs that would be more efficient if we had a live tree structure in place.

Please can you point to these? Are you sure you are not referring to
the working_fdt? As I understand it this is already a live structure.

>
> I think that will only get worse with the addition of embedding a tree.

I need a bit more info / understanding before I can respond to this
email properly.

Regards,
Simon

>
> - k
>
>
Aaron Williams - Oct. 15, 2011, 1:42 a.m.
Hi,

On Friday, October 14, 2011 11:21:54 AM Simon Glass wrote:
> Hi Kumar,
> 
> On Fri, Oct 14, 2011 at 11:12 AM, Kumar Gala <galak@kernel.crashing.org> 
wrote:
> > On Oct 11, 2011, at 5:26 PM, Simon Glass wrote:
> >> This library provides useful functions to drivers which want to use
> >> the fdt to control their operation. Functions are provided to:
> >> 
> >> - look up and enumerate a device type (for example assigning i2c bus 0,
> >> i2c bus 1, etc.)
> >> - decode basic types from the fdt, like addresses and integers
> >> 
> >> While this library is not strictly necessary, it helps to minimise the
> >> changes to a driver, in order to make it work under fdt control. Less
> >> code is required, and so the barrier to switch drivers over is lower.
> >> 
> >> Additional functions to read arrays and GPIOs could be made available
> >> here also.
> >> 
> >> Signed-off-by: Simon Glass <sjg@chromium.org>
> >> ---
> >> Changes in v2:
> >> - Add example proposed decode helper library
> >> 
> >> Changes in v3:
> >> - Simplify decode library to remove provide only primitive functions
> >> - Remove i2c decode function
> >> - Rename fdt_decode to fdtdec, since it will be used a lot
> >> - Moved fdt_decode.c to /lib
> >> - Export almost all functions from fdtdec, to allow widespread use
> >> - Remove use of FDT_ERR_MISSING which is not strictly needed now
> >> 
> >> include/fdtdec.h |  122
> >> ++++++++++++++++++++++++++++++++++++++++++++++++++ lib/Makefile     |  
> >>  1 +
> >> lib/fdtdec.c     |  131
> >> ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed,
> >> 254 insertions(+), 0 deletions(-)
> >> create mode 100644 include/fdtdec.h
> >> create mode 100644 lib/fdtdec.c
> > 
> > I think this is the wrong approach.  If we intend to go down the path of
> > embedded a device tree we should look at produce a live tree structure
> > that can be used like Linux has.
> 
> The intent of this patch set is to provide U-Boot with a simple
> run-time configuration system.
> 
> Can you please explain why you want a live tree for use by U-Boot?
> U-Boot already has one that it passes on to Linux, and this is under
> control of scripts, etc., quite separate from this.
> 
> This fdt is for configuration of devices used by U-Boot itself.
> 
> What can U-Boot find out that it would want to put into this private
> fdt? Are you thinking of probing for devices early on and then using
> them later in U-Boot? If so, surely no code can exist which does this
> now, since this patch set is new.
> 
> > There are a lot of places we are manipulate device tree blobs that would
> > be more efficient if we had a live tree structure in place.
> 
> Please can you point to these? Are you sure you are not referring to
> the working_fdt? As I understand it this is already a live structure.
> 
> > I think that will only get worse with the addition of embedding a tree.
> 
> I need a bit more info / understanding before I can respond to this
> email properly.
> 
> Regards,
> Simon
> 
> > - k
> 
This would actually be helpful for us. We have switched our bootloader to make 
use of the FDT and use it both within our common SOC code which is linked to 
our U-Boot image as well as what we pass to the Linux kernel.

We use a single FDT image for both.

We currently have our FDT for each board contain all possible options and then 
at runtime trim the parts that are not detected at runtime. Many of our boards 
have pluggable networking modules for example which are supported by our U-
Boot image.

-Aaron
Simon Glass - Oct. 15, 2011, 2:16 a.m.
Hi Aaron,

On Fri, Oct 14, 2011 at 6:42 PM, Aaron Williams
<Aaron.Williams@cavium.com> wrote:
> Hi,
>
> On Friday, October 14, 2011 11:21:54 AM Simon Glass wrote:
>> Hi Kumar,
>>
>> On Fri, Oct 14, 2011 at 11:12 AM, Kumar Gala <galak@kernel.crashing.org>
> wrote:
>> > On Oct 11, 2011, at 5:26 PM, Simon Glass wrote:
>> >> This library provides useful functions to drivers which want to use
>> >> the fdt to control their operation. Functions are provided to:
>> >>
>> >> - look up and enumerate a device type (for example assigning i2c bus 0,
>> >> i2c bus 1, etc.)
>> >> - decode basic types from the fdt, like addresses and integers
>> >>
>> >> While this library is not strictly necessary, it helps to minimise the
>> >> changes to a driver, in order to make it work under fdt control. Less
>> >> code is required, and so the barrier to switch drivers over is lower.
>> >>
>> >> Additional functions to read arrays and GPIOs could be made available
>> >> here also.
>> >>
>> >> Signed-off-by: Simon Glass <sjg@chromium.org>
>> >> ---
>> >> Changes in v2:
>> >> - Add example proposed decode helper library
>> >>
>> >> Changes in v3:
>> >> - Simplify decode library to remove provide only primitive functions
>> >> - Remove i2c decode function
>> >> - Rename fdt_decode to fdtdec, since it will be used a lot
>> >> - Moved fdt_decode.c to /lib
>> >> - Export almost all functions from fdtdec, to allow widespread use
>> >> - Remove use of FDT_ERR_MISSING which is not strictly needed now
>> >>
>> >> include/fdtdec.h |  122
>> >> ++++++++++++++++++++++++++++++++++++++++++++++++++ lib/Makefile     |
>> >>  1 +
>> >> lib/fdtdec.c     |  131
>> >> ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed,
>> >> 254 insertions(+), 0 deletions(-)
>> >> create mode 100644 include/fdtdec.h
>> >> create mode 100644 lib/fdtdec.c
>> >
>> > I think this is the wrong approach.  If we intend to go down the path of
>> > embedded a device tree we should look at produce a live tree structure
>> > that can be used like Linux has.
>>
>> The intent of this patch set is to provide U-Boot with a simple
>> run-time configuration system.
>>
>> Can you please explain why you want a live tree for use by U-Boot?
>> U-Boot already has one that it passes on to Linux, and this is under
>> control of scripts, etc., quite separate from this.
>>
>> This fdt is for configuration of devices used by U-Boot itself.
>>
>> What can U-Boot find out that it would want to put into this private
>> fdt? Are you thinking of probing for devices early on and then using
>> them later in U-Boot? If so, surely no code can exist which does this
>> now, since this patch set is new.
>>
>> > There are a lot of places we are manipulate device tree blobs that would
>> > be more efficient if we had a live tree structure in place.
>>
>> Please can you point to these? Are you sure you are not referring to
>> the working_fdt? As I understand it this is already a live structure.
>>
>> > I think that will only get worse with the addition of embedding a tree.
>>
>> I need a bit more info / understanding before I can respond to this
>> email properly.
>>
>> Regards,
>> Simon
>>
>> > - k
>>
> This would actually be helpful for us. We have switched our bootloader to make
> use of the FDT and use it both within our common SOC code which is linked to
> our U-Boot image as well as what we pass to the Linux kernel.

Do you like the fdt with U-Boot or find it in flash somewhere?

>
> We use a single FDT image for both.

This is easy enough with the current patch set in that the build
system can provide the same fdt to both U-Boot and the kernel. It
would also be possible to make a copy of the U-Boot one (through some
new 'fdt' command), update it and pass it to the kernel. It might be a
little early to do that though - at least on the ARM side many fdt
things in the kernel are still in flux and there might be a desire to
limit the U-Boot changes (dealing with changed fdt definitions for
peripherals, etc.) forced by changes in the kernel.

>
> We currently have our FDT for each board contain all possible options and then
> at runtime trim the parts that are not detected at runtime. Many of our boards
> have pluggable networking modules for example which are supported by our U-
> Boot image.

Sounds great. On ARM SOCs there is often not much interest in probing
since it either isn't possible or isn't useful (since things are known
at build time anyway). So far my patch set does not deal with a
dynamic fdt - it is just a basic implementation to get started. I'm
sure it can expand as need dictates.

Regards,
Simon

>
> -Aaron
>
> --
> Aaron Williams <Aaron.Williams@cavium.com>
>  (408) 943-7198
>

Patch

diff --git a/include/fdtdec.h b/include/fdtdec.h
new file mode 100644
index 0000000..b38f48c
--- /dev/null
+++ b/include/fdtdec.h
@@ -0,0 +1,122 @@ 
+/*
+ * Copyright (c) 2011 The Chromium OS Authors.
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+
+/*
+ * This file contains convenience functions for decoding useful and
+ * enlightening information from FDTs. It is intended to be used by device
+ * drivers and board-specific code within U-Boot. It aims to reduce the
+ * amount of FDT munging required within U-Boot itself, so that driver code
+ * changes to support FDT are minimized.
+ */
+
+#include <libfdt.h>
+
+/*
+ * A typedef for a physical address. Note that fdt data is always big
+ * endian even on a litle endian machine.
+ */
+#ifdef CONFIG_PHYS_64BIT
+typedef u64 addr_t;
+#define ADDR_T_NONE (-1ULL)
+#define addr_to_cpu(reg) be64_to_cpu(reg)
+#else
+typedef u32 addr_t;
+#define ADDR_T_NONE (-1U)
+#define addr_to_cpu(reg) be32_to_cpu(reg)
+#endif
+
+/* Information obtained about memory from the FDT */
+struct fdt_memory {
+	addr_t start;
+	addr_t end;
+};
+
+/**
+ * Compat types that we know about and for which we might have drivers.
+ * Each is named COMPAT_<dir>_<filename> where <dir> is the directory
+ * within drivers.
+ */
+enum fdt_compat_id {
+	COMPAT_UNKNOWN,
+
+	COMPAT_COUNT,
+};
+
+/**
+ * Find the next numbered alias for a peripheral. This is used to enumerate
+ * all the peripherals of a certain type.
+ *
+ * Do the first call with *upto = 0. Assuming /aliases/<name>0 exists then
+ * this function will return a pointer to the node the alias points to, and
+ * then update *upto to 1. Next time you call this function, the next node
+ * will be returned.
+ *
+ * All nodes returned will match the compatible ID, as it is assumed that
+ * all peripherals use the same driver.
+ *
+ * @param blob		FDT blob to use
+ * @param name		Root name of alias to search for
+ * @param id		Compatible ID to look for
+ * @return offset of next compatible node, or -FDT_ERR_NOTFOUND if no more
+ */
+int fdtdec_next_alias(const void *blob, const char *name,
+		enum fdt_compat_id id, int *upto);
+
+/**
+ * Look up an address property in a node and return it as an address.
+ * The property must hold either one address with no trailing data or
+ * one address with a length. This is only tested on 32-bit machines.
+ *
+ * @param blob	FDT blob
+ * @param node	node to examine
+ * @param prop_name	name of property to find
+ * @return address, if found, or ADDR_T_NONE if not
+ */
+addr_t fdtdec_get_addr(const void *blob, int node,
+		const char *prop_name);
+
+/**
+ * Look up a 32-bit integer property in a node and return it. The property
+ * must have at least 4 bytes of data. The value of the first cell is
+ * returned.
+ *
+ * @param blob	FDT blob
+ * @param node	node to examine
+ * @param prop_name	name of property to find
+ * @param default_val	default value to return if the property is not found
+ * @return integer value, if found, or default_val if not
+ */
+s32 fdtdec_get_int(const void *blob, int node, const char *prop_name,
+		s32 default_val);
+
+/**
+ * Checks whether a node is enabled.
+ * This looks for a 'status' property. If this exists, then returns 1 if
+ * the status is 'ok' and 0 otherwise. If there is no status property,
+ * it returns the default value.
+ *
+ * @param blob	FDT blob
+ * @param node	node to examine
+ * @param default_val	default value to return if no 'status' property exists
+ * @return integer value 0/1, if found, or default_val if not
+ */
+int fdtdec_get_is_enabled(const void *blob, int node, int default_val);
diff --git a/lib/Makefile b/lib/Makefile
index 884f64c..3b901c9 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -38,6 +38,7 @@  COBJS-y += crc16.o
 COBJS-y += crc32.o
 COBJS-y += display_options.o
 COBJS-y += errno.o
+COBJS-$(CONFIG_OF_CONTROL) += fdtdec.o
 COBJS-$(CONFIG_GZIP) += gunzip.o
 COBJS-y += hashtable.o
 COBJS-$(CONFIG_LMB) += lmb.o
diff --git a/lib/fdtdec.c b/lib/fdtdec.c
new file mode 100644
index 0000000..c33b3ed
--- /dev/null
+++ b/lib/fdtdec.c
@@ -0,0 +1,131 @@ 
+/*
+ * Copyright (c) 2011 The Chromium OS Authors.
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <serial.h>
+#include <libfdt.h>
+#include <fdtdec.h>
+
+/* we need a generic GPIO interface here */
+#include <asm/arch/gpio.h>
+
+/*
+ * Here are the type we know about. One day we might allow drivers to
+ * register. For now we just put them here. The COMPAT macro allows us to
+ * turn this into a sparse list later, and keeps the ID with the name.
+ */
+#define COMPAT(id, name) name
+static const char *compat_names[COMPAT_COUNT] = {
+};
+
+/**
+ * Look in the FDT for an alias with the given name and return its node.
+ *
+ * @param blob	FDT blob
+ * @param name	alias name to look up
+ * @return node offset if found, or an error code < 0 otherwise
+ */
+static int find_alias_node(const void *blob, const char *name)
+{
+	const char *path;
+	int alias_node;
+
+	debug("find_alias_node: %s\n", name);
+	alias_node = fdt_path_offset(blob, "/aliases");
+	if (alias_node < 0)
+		return alias_node;
+	path = fdt_getprop(blob, alias_node, name, NULL);
+	if (!path)
+		return -FDT_ERR_NOTFOUND;
+	return fdt_path_offset(blob, path);
+}
+
+addr_t fdtdec_get_addr(const void *blob, int node,
+		const char *prop_name)
+{
+	const addr_t *cell;
+	int len;
+
+	debug("get_addr: %s\n", prop_name);
+	cell = fdt_getprop(blob, node, prop_name, &len);
+	if (cell && (len == sizeof(addr_t) || len == sizeof(addr_t) * 2))
+		return addr_to_cpu(*cell);
+	return ADDR_T_NONE;
+}
+
+s32 fdtdec_get_int(const void *blob, int node, const char *prop_name,
+		s32 default_val)
+{
+	const s32 *cell;
+	int len;
+
+	debug("get_size: %s\n", prop_name);
+	cell = fdt_getprop(blob, node, prop_name, &len);
+	if (cell && len >= sizeof(s32))
+		return fdt32_to_cpu(cell[0]);
+	return default_val;
+}
+
+int fdtdec_get_is_enabled(const void *blob, int node, int default_val)
+{
+	const char *cell;
+
+	cell = fdt_getprop(blob, node, "status", NULL);
+	if (cell)
+		return 0 == strcmp(cell, "ok");
+	return default_val;
+}
+
+enum fdt_compat_id fd_dec_lookup(const void *blob, int node)
+{
+	enum fdt_compat_id id;
+
+	/* Search our drivers */
+	for (id = COMPAT_UNKNOWN; id < COMPAT_COUNT; id++)
+		if (0 == fdt_node_check_compatible(blob, node,
+				compat_names[id]))
+			return id;
+	return COMPAT_UNKNOWN;
+}
+
+int fdtdec_next_compatible(const void *blob, int node,
+		enum fdt_compat_id id)
+{
+	return fdt_node_offset_by_compatible(blob, node, compat_names[id]);
+}
+
+int fdtdec_next_alias(const void *blob, const char *name,
+		enum fdt_compat_id id, int *upto)
+{
+#define MAX_STR_LEN 20
+	char str[MAX_STR_LEN + 20];
+	int node, err;
+
+	sprintf(str, "%.*s%d", MAX_STR_LEN, name, *upto);
+	(*upto)++;
+	node = find_alias_node(blob, str);
+	if (node < 0)
+		return node;
+	err = fdt_node_check_compatible(blob, node, compat_names[id]);
+	if (err < 0)
+		return err;
+	return err ? -FDT_ERR_NOTFOUND : node;
+}